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 "MovePLItemsCommand.h" 7 8 #include <new> 9 #include <stdio.h> 10 11 #include <Autolock.h> 12 #include <Catalog.h> 13 #include <Locale.h> 14 15 #include "Playlist.h" 16 17 18 #undef B_TRANSLATION_CONTEXT 19 #define B_TRANSLATION_CONTEXT "MediaPlayer-MovePLItemsCmd" 20 21 22 using std::nothrow; 23 24 25 MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist, 26 BList indices, int32 toIndex) 27 : 28 PLItemsCommand(), 29 fPlaylist(playlist), 30 fCount(indices.CountItems()), 31 fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL), 32 fIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL), 33 fToIndex(toIndex) 34 { 35 if (indices.IsEmpty()) { 36 // indicate a bad object state 37 delete[] fItems; 38 fItems = NULL; 39 return; 40 } 41 42 memset(fItems, 0, sizeof(PlaylistItem*) * fCount); 43 44 // init original entry indices and 45 // adjust toIndex compensating for items that 46 // are removed before that index 47 int32 itemsBeforeIndex = 0; 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 // indicate a bad object state 53 delete[] fItems; 54 fItems = NULL; 55 return; 56 } 57 if (fIndices[i] < fToIndex) 58 itemsBeforeIndex++; 59 } 60 fToIndex -= itemsBeforeIndex; 61 } 62 63 64 MovePLItemsCommand::~MovePLItemsCommand() 65 { 66 delete[] fItems; 67 delete[] fIndices; 68 } 69 70 71 status_t 72 MovePLItemsCommand::InitCheck() 73 { 74 if (!fItems) 75 return B_NO_INIT; 76 77 // analyse the move, don't return B_OK in case 78 // the container state does not change... 79 80 int32 index = fIndices[0]; 81 // NOTE: fIndices == NULL if fCount < 1 82 83 if (index != fToIndex) { 84 // a change is guaranteed 85 return B_OK; 86 } 87 88 // the insertion index is the same as the index of the first 89 // moved item, a change only occures if the indices of the 90 // moved items is not contiguous 91 bool isContiguous = true; 92 for (int32 i = 1; i < fCount; i++) { 93 if (fIndices[i] != index + 1) { 94 isContiguous = false; 95 break; 96 } 97 index = fIndices[i]; 98 } 99 if (isContiguous) { 100 // the container state will not change because of the move 101 return B_ERROR; 102 } 103 104 return B_OK; 105 } 106 107 108 status_t 109 MovePLItemsCommand::Perform() 110 { 111 BAutolock _(fPlaylist); 112 113 status_t ret = B_OK; 114 115 // remember currently playling item in case we move it 116 PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex()); 117 118 // remove refs from playlist 119 for (int32 i = 0; i < fCount; i++) { 120 // "- i" to account for the items already removed 121 fPlaylist->RemoveItem(fIndices[i] - i, false); 122 } 123 124 // add refs to playlist at the insertion index 125 int32 index = fToIndex; 126 for (int32 i = 0; i < fCount; i++) { 127 if (!fPlaylist->AddItem(fItems[i], index++)) { 128 ret = B_NO_MEMORY; 129 break; 130 } 131 } 132 if (ret < B_OK) 133 return ret; 134 135 // take care about currently played item 136 if (current != NULL) 137 fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current), false); 138 139 return B_OK; 140 } 141 142 143 status_t 144 MovePLItemsCommand::Undo() 145 { 146 BAutolock _(fPlaylist); 147 148 status_t ret = B_OK; 149 150 // remember currently playling item in case we move it 151 PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex()); 152 153 // remove refs from playlist 154 int32 index = fToIndex; 155 for (int32 i = 0; i < fCount; i++) { 156 fPlaylist->RemoveItem(index++, false); 157 } 158 159 // add ref to playlist at remembered indices 160 for (int32 i = 0; i < fCount; i++) { 161 if (!fPlaylist->AddItem(fItems[i], fIndices[i])) { 162 ret = B_NO_MEMORY; 163 break; 164 } 165 } 166 if (ret < B_OK) 167 return ret; 168 169 // take care about currently played item 170 if (current != NULL) 171 fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current), false); 172 173 return B_OK; 174 } 175 176 177 void 178 MovePLItemsCommand::GetName(BString& name) 179 { 180 if (fCount > 1) 181 name << B_TRANSLATE("Move Entries"); 182 else 183 name << B_TRANSLATE("Move Entry"); 184 } 185