xref: /haiku/src/apps/mediaplayer/playlist/RemovePLItemsCommand.cpp (revision 99d027cd0238c1d86da86d7c3f4200509ccc61a6)
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