1 /* 2 * Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT license. 4 */ 5 6 #include "RemovePLItemsCommand.h" 7 8 #include <new> 9 #include <stdio.h> 10 11 #include <Alert.h> 12 #include <Autolock.h> 13 #include <Catalog.h> 14 #include <Locale.h> 15 16 #include "Playlist.h" 17 18 19 #undef B_TRANSLATION_CONTEXT 20 #define B_TRANSLATION_CONTEXT "MediaPlayer-RemovePLItemsCmd" 21 22 23 using std::nothrow; 24 25 26 RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist, 27 const int32* indices, int32 count, bool moveFilesToTrash) 28 : 29 PLItemsCommand(), 30 fPlaylist(playlist), 31 fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL), 32 fIndices(count > 0 ? new (nothrow) int32[count] : NULL), 33 fCount(count), 34 fMoveFilesToTrash(moveFilesToTrash), 35 fMoveErrorShown(false), 36 fItemsRemoved(false) 37 { 38 if (!indices || !fPlaylist || !fItems || !fIndices) { 39 // indicate a bad object state 40 delete[] fItems; 41 fItems = NULL; 42 return; 43 } 44 45 memcpy(fIndices, indices, fCount * sizeof(int32)); 46 memset(fItems, 0, fCount * sizeof(PlaylistItem*)); 47 48 // init original entry indices 49 for (int32 i = 0; i < fCount; i++) { 50 fItems[i] = fPlaylist->ItemAt(fIndices[i]); 51 if (fItems[i] == NULL) { 52 delete[] fItems; 53 fItems = NULL; 54 return; 55 } 56 } 57 } 58 59 60 RemovePLItemsCommand::~RemovePLItemsCommand() 61 { 62 _CleanUp(fItems, fCount, fItemsRemoved); 63 delete[] fIndices; 64 } 65 66 67 status_t 68 RemovePLItemsCommand::InitCheck() 69 { 70 if (!fPlaylist || !fItems || !fIndices) 71 return B_NO_INIT; 72 return B_OK; 73 } 74 75 76 status_t 77 RemovePLItemsCommand::Perform() 78 { 79 BAutolock _(fPlaylist); 80 81 fItemsRemoved = true; 82 83 int32 lastRemovedIndex = -1; 84 85 // remove refs from playlist 86 for (int32 i = 0; i < fCount; i++) { 87 // "- i" to account for the items already removed 88 lastRemovedIndex = fIndices[i] - i; 89 fPlaylist->RemoveItem(lastRemovedIndex); 90 } 91 92 // in case we removed the currently playing file 93 if (fPlaylist->CurrentItemIndex() == -1) 94 fPlaylist->SetCurrentItemIndex(lastRemovedIndex); 95 96 if (fMoveFilesToTrash) { 97 BString errorFiles; 98 status_t moveError = B_OK; 99 bool errorOnAllFiles = true; 100 for (int32 i = 0; i < fCount; i++) { 101 status_t err = fItems[i]->MoveIntoTrash(); 102 if (err != B_OK) { 103 moveError = err; 104 if (errorFiles.Length() > 0) 105 errorFiles << ' '; 106 errorFiles << fItems[i]->Name(); 107 } else 108 errorOnAllFiles = false; 109 } 110 // Show an error alert if necessary 111 if (!fMoveErrorShown && moveError != B_OK) { 112 fMoveErrorShown = true; 113 BString message; 114 if (errorOnAllFiles) 115 message << 116 B_TRANSLATE("All files could not be moved into Trash."); 117 else 118 message << 119 B_TRANSLATE("Some files could not be moved into Trash."); 120 message << "\n\n" << B_TRANSLATE("Error: ") << strerror(moveError); 121 BAlert* alert = new BAlert(B_TRANSLATE("Move into trash error"), 122 message.String(), B_TRANSLATE("OK"), NULL, NULL, 123 B_WIDTH_AS_USUAL, B_WARNING_ALERT); 124 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 125 alert->Go(NULL); 126 } 127 } 128 129 return B_OK; 130 } 131 132 133 status_t 134 RemovePLItemsCommand::Undo() 135 { 136 BAutolock _(fPlaylist); 137 138 fItemsRemoved = false; 139 140 if (fMoveFilesToTrash) { 141 for (int32 i = 0; i < fCount; i++) { 142 fItems[i]->RestoreFromTrash(); 143 } 144 } 145 146 // remember currently playling item in case we move it 147 PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex()); 148 149 // add items to playlist at remembered indices 150 status_t ret = B_OK; 151 for (int32 i = 0; i < fCount; i++) { 152 if (!fPlaylist->AddItem(fItems[i], fIndices[i])) { 153 ret = B_NO_MEMORY; 154 break; 155 } 156 } 157 if (ret < B_OK) 158 return ret; 159 160 // take care about currently played ref 161 if (current != NULL) 162 fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current), false); 163 164 return B_OK; 165 } 166 167 168 void 169 RemovePLItemsCommand::GetName(BString& name) 170 { 171 if (fMoveFilesToTrash) { 172 if (fCount > 1) 173 name << B_TRANSLATE("Remove Entries into Trash"); 174 else 175 name << B_TRANSLATE("Remove Entry into Trash"); 176 } 177 else 178 { 179 if (fCount > 1) 180 name << B_TRANSLATE("Remove Entries"); 181 else 182 name << B_TRANSLATE("Remove Entry"); 183 } 184 } 185