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
RemovePLItemsCommand(Playlist * playlist,BList indices,bool moveFilesToTrash)26 RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
27 BList indices, bool moveFilesToTrash)
28 :
29 PLItemsCommand(),
30 fPlaylist(playlist),
31 fCount(indices.CountItems()),
32 fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
33 fIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL),
34 fMoveFilesToTrash(moveFilesToTrash),
35 fMoveErrorShown(false),
36 fItemsRemoved(false)
37 {
38 if (indices.IsEmpty()) {
39 // indicate a bad object state
40 delete[] fItems;
41 fItems = NULL;
42 return;
43 }
44
45 memset(fItems, 0, fCount * sizeof(PlaylistItem*));
46
47 // init original entry indices
48 for (int32 i = 0; i < fCount; i++) {
49 fIndices[i] = (int32)(addr_t)indices.ItemAt(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
~RemovePLItemsCommand()60 RemovePLItemsCommand::~RemovePLItemsCommand()
61 {
62 _CleanUp(fItems, fCount, fItemsRemoved);
63 delete[] fIndices;
64 }
65
66
67 status_t
InitCheck()68 RemovePLItemsCommand::InitCheck()
69 {
70 if (!fPlaylist || !fItems || !fIndices)
71 return B_NO_INIT;
72 return B_OK;
73 }
74
75
76 status_t
Perform()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
Undo()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
GetName(BString & name)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