xref: /haiku/src/apps/mediaplayer/playlist/RemovePLItemsCommand.cpp (revision 6e434fd80e4640c64031faf5e49720c5672fc470)
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_TRANSLATE_CONTEXT
20 #define B_TRANSLATE_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 			(new BAlert(B_TRANSLATE("Move Into Trash Error"), message.String(),
122 				B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
123 				B_WARNING_ALERT))->Go(NULL);
124 		}
125 	}
126 
127 	return B_OK;
128 }
129 
130 
131 status_t
132 RemovePLItemsCommand::Undo()
133 {
134 	BAutolock _(fPlaylist);
135 
136 	fItemsRemoved = false;
137 
138 	if (fMoveFilesToTrash) {
139 		for (int32 i = 0; i < fCount; i++) {
140 			fItems[i]->RestoreFromTrash();
141 		}
142 	}
143 
144 	// remember currently playling item in case we move it
145 	PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
146 
147 	// add items to playlist at remembered indices
148 	status_t ret = B_OK;
149 	for (int32 i = 0; i < fCount; i++) {
150 		if (!fPlaylist->AddItem(fItems[i], fIndices[i])) {
151 			ret = B_NO_MEMORY;
152 			break;
153 		}
154 	}
155 	if (ret < B_OK)
156 		return ret;
157 
158 	// take care about currently played ref
159 	if (current != NULL)
160 		fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current), false);
161 
162 	return B_OK;
163 }
164 
165 
166 void
167 RemovePLItemsCommand::GetName(BString& name)
168 {
169 	if (fMoveFilesToTrash) {
170 		if (fCount > 1)
171 			name << B_TRANSLATE("Remove Entries into Trash");
172 		else
173 			name << B_TRANSLATE("Remove Entry into Trash");
174 	}
175 	else
176 	{
177 		if (fCount > 1)
178 			name << B_TRANSLATE("Remove Entries");
179 		else
180 			name << B_TRANSLATE("Remove Entry");
181 	}
182 }
183