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