Undo and redo actions for the playlist. Note that undoing a sort or a shuffle doesn't work yet. Fixes issue #152
This commit is contained in:
parent
9d0541a53b
commit
b2236bfd1e
|
@ -81,5 +81,7 @@
|
|||
<file>schema-7.sql</file>
|
||||
<file>tiny-pause.png</file>
|
||||
<file>tiny-start.png</file>
|
||||
<file>edit-redo.png</file>
|
||||
<file>edit-undo.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -75,6 +75,7 @@ set(CLEMENTINE-SOURCES
|
|||
settingsprovider.cpp
|
||||
libraryplaylistitem.cpp
|
||||
scopedtransaction.cpp
|
||||
playlistundocommands.cpp
|
||||
)
|
||||
|
||||
# Header files that have Q_OBJECT in
|
||||
|
|
|
@ -310,11 +310,22 @@ MainWindow::MainWindow(QNetworkAccessManager* network, Engine::Type engine, QWid
|
|||
connect(library_config_dialog_.get(), SIGNAL(accepted()), ui_.library_view, SLOT(ReloadSettings()));
|
||||
|
||||
// Playlist menu
|
||||
QAction* playlist_undo = playlist_->undo_stack()->createUndoAction(this);
|
||||
QAction* playlist_redo = playlist_->undo_stack()->createRedoAction(this);
|
||||
playlist_undo->setIcon(QIcon(":edit-undo.png"));
|
||||
playlist_undo->setShortcut(QKeySequence::Undo);
|
||||
playlist_redo->setIcon(QIcon(":edit-redo.png"));
|
||||
playlist_redo->setShortcut(QKeySequence::Redo);
|
||||
addAction(playlist_undo); // These seem to be required to get the keyboard
|
||||
addAction(playlist_redo); // shortcuts to work
|
||||
|
||||
playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay()));
|
||||
playlist_menu_->addAction(ui_.action_stop);
|
||||
playlist_stop_after_ = playlist_menu_->addAction(QIcon(":media-playback-stop.png"), tr("Stop after this track"), this, SLOT(PlaylistStopAfter()));
|
||||
playlist_menu_->addSeparator();
|
||||
playlist_menu_->addAction(ui_.action_remove_from_playlist);
|
||||
playlist_menu_->addAction(playlist_undo);
|
||||
playlist_menu_->addAction(playlist_redo);
|
||||
playlist_menu_->addSeparator();
|
||||
playlist_menu_->addAction(ui_.action_edit_track);
|
||||
playlist_menu_->addAction(ui_.action_edit_value);
|
||||
|
|
199
src/playlist.cpp
199
src/playlist.cpp
|
@ -23,6 +23,7 @@
|
|||
#include "savedradio.h"
|
||||
#include "librarybackend.h"
|
||||
#include "libraryplaylistitem.h"
|
||||
#include "playlistundocommands.h"
|
||||
|
||||
#include <QtDebug>
|
||||
#include <QMimeData>
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include <QSettings>
|
||||
#include <QFileInfo>
|
||||
#include <QDirIterator>
|
||||
#include <QUndoStack>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <algorithm>
|
||||
|
@ -50,7 +52,8 @@ Playlist::Playlist(QObject *parent, SettingsProvider* settings)
|
|||
scrobble_point_(-1),
|
||||
has_scrobbled_(false),
|
||||
playlist_sequence_(NULL),
|
||||
ignore_sorting_(false)
|
||||
ignore_sorting_(false),
|
||||
undo_stack_(new QUndoStack(this))
|
||||
{
|
||||
settings_->set_group(kSettingsGroup);
|
||||
|
||||
|
@ -352,48 +355,7 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action, int ro
|
|||
stream >> source_rows;
|
||||
qStableSort(source_rows); // Make sure we take them in order
|
||||
|
||||
layoutAboutToBeChanged();
|
||||
PlaylistItemList moved_items;
|
||||
|
||||
// Take the items out of the list first, keeping track of whether the
|
||||
// insertion point changes
|
||||
int offset = 0;
|
||||
foreach (int source_row, source_rows) {
|
||||
moved_items << items_.takeAt(source_row-offset);
|
||||
if (row != -1 && row >= source_row)
|
||||
row --;
|
||||
offset++;
|
||||
}
|
||||
|
||||
// Put the items back in
|
||||
const int start = row == -1 ? items_.count() : row;
|
||||
for (int i=start ; i<start+moved_items.count() ; ++i) {
|
||||
items_.insert(i, moved_items[i - start]);
|
||||
}
|
||||
|
||||
// Update persistent indexes
|
||||
foreach (const QModelIndex& pidx, persistentIndexList()) {
|
||||
const int dest_offset = source_rows.indexOf(pidx.row());
|
||||
if (dest_offset != -1) {
|
||||
// This index was moved
|
||||
changePersistentIndex(pidx, index(start + dest_offset, pidx.column(), QModelIndex()));
|
||||
} else {
|
||||
int d = 0;
|
||||
foreach (int source_row, source_rows) {
|
||||
if (pidx.row() > source_row)
|
||||
d --;
|
||||
}
|
||||
if (pidx.row() + d >= start)
|
||||
d += source_rows.count();
|
||||
|
||||
changePersistentIndex(pidx, index(pidx.row() + d, pidx.column(), QModelIndex()));
|
||||
}
|
||||
}
|
||||
current_virtual_index_ = virtual_items_.indexOf(current_index());
|
||||
|
||||
layoutChanged();
|
||||
Save();
|
||||
|
||||
undo_stack_->push(new PlaylistUndoCommands::MoveItems(this, source_rows, row));
|
||||
} else if (data->hasUrls()) {
|
||||
// URL list dragged from the file list or some other app
|
||||
InsertPaths(data->urls(), row);
|
||||
|
@ -402,7 +364,95 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action, int ro
|
|||
return true;
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertPaths(QList<QUrl> urls, int after) {
|
||||
void Playlist::MoveItemsWithoutUndo(const QList<int> &source_rows, int pos) {
|
||||
layoutAboutToBeChanged();
|
||||
PlaylistItemList moved_items;
|
||||
|
||||
// Take the items out of the list first, keeping track of whether the
|
||||
// insertion point changes
|
||||
int offset = 0;
|
||||
foreach (int source_row, source_rows) {
|
||||
moved_items << items_.takeAt(source_row-offset);
|
||||
if (pos != -1 && pos >= source_row)
|
||||
pos --;
|
||||
offset++;
|
||||
}
|
||||
|
||||
// Put the items back in
|
||||
const int start = pos == -1 ? items_.count() : pos;
|
||||
for (int i=start ; i<start+moved_items.count() ; ++i) {
|
||||
items_.insert(i, moved_items[i - start]);
|
||||
}
|
||||
|
||||
// Update persistent indexes
|
||||
foreach (const QModelIndex& pidx, persistentIndexList()) {
|
||||
const int dest_offset = source_rows.indexOf(pidx.row());
|
||||
if (dest_offset != -1) {
|
||||
// This index was moved
|
||||
changePersistentIndex(pidx, index(start + dest_offset, pidx.column(), QModelIndex()));
|
||||
} else {
|
||||
int d = 0;
|
||||
foreach (int source_row, source_rows) {
|
||||
if (pidx.row() > source_row)
|
||||
d --;
|
||||
}
|
||||
if (pidx.row() + d >= start)
|
||||
d += source_rows.count();
|
||||
|
||||
changePersistentIndex(pidx, index(pidx.row() + d, pidx.column(), QModelIndex()));
|
||||
}
|
||||
}
|
||||
current_virtual_index_ = virtual_items_.indexOf(current_index());
|
||||
|
||||
layoutChanged();
|
||||
Save();
|
||||
}
|
||||
|
||||
void Playlist::MoveItemsWithoutUndo(int start, const QList<int>& dest_rows) {
|
||||
layoutAboutToBeChanged();
|
||||
PlaylistItemList moved_items;
|
||||
|
||||
if (start == -1)
|
||||
start = items_.count() - dest_rows.count();
|
||||
|
||||
// Take the items out of the list first, keeping track of whether the
|
||||
// insertion point changes
|
||||
for (int i=start ; i<start + dest_rows.count() ; ++i)
|
||||
moved_items << items_.takeAt(start);
|
||||
|
||||
// Put the items back in
|
||||
int offset = 0;
|
||||
foreach (int dest_row, dest_rows) {
|
||||
items_.insert(dest_row, moved_items[offset]);
|
||||
offset ++;
|
||||
}
|
||||
|
||||
// Update persistent indexes
|
||||
foreach (const QModelIndex& pidx, persistentIndexList()) {
|
||||
if (pidx.row() >= start && pidx.row() < start + dest_rows.count()) {
|
||||
// This index was moved
|
||||
const int i = pidx.row() - start;
|
||||
changePersistentIndex(pidx, index(dest_rows[i], pidx.column(), QModelIndex()));
|
||||
} else {
|
||||
int d = 0;
|
||||
if (pidx.row() >= start + dest_rows.count())
|
||||
d -= dest_rows.count();
|
||||
|
||||
foreach (int dest_row, dest_rows) {
|
||||
if (pidx.row() + d > dest_row)
|
||||
d ++;
|
||||
}
|
||||
|
||||
changePersistentIndex(pidx, index(pidx.row() + d, pidx.column(), QModelIndex()));
|
||||
}
|
||||
}
|
||||
current_virtual_index_ = virtual_items_.indexOf(current_index());
|
||||
|
||||
layoutChanged();
|
||||
Save();
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertPaths(QList<QUrl> urls, int pos) {
|
||||
SongList songs;
|
||||
for (int i=0 ; i<urls.count() ; ++i) {
|
||||
QUrl url(urls[i]);
|
||||
|
@ -438,14 +488,25 @@ QModelIndex Playlist::InsertPaths(QList<QUrl> urls, int after) {
|
|||
}
|
||||
}
|
||||
|
||||
return InsertSongs(songs, after);
|
||||
return InsertSongs(songs, pos);
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertItems(const PlaylistItemList& items, int after) {
|
||||
QModelIndex Playlist::InsertItems(const PlaylistItemList& items, int pos) {
|
||||
if (items.isEmpty())
|
||||
return QModelIndex();
|
||||
|
||||
const int start = after == -1 ? items_.count() : after;
|
||||
const int start = pos == -1 ? items_.count() : pos;
|
||||
undo_stack_->push(new PlaylistUndoCommands::InsertItems(this, items, pos));
|
||||
|
||||
return index(start, 0);
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertItemsWithoutUndo(const PlaylistItemList& items,
|
||||
int pos) {
|
||||
if (items.isEmpty())
|
||||
return QModelIndex();
|
||||
|
||||
const int start = pos == -1 ? items_.count() : pos;
|
||||
const int end = start + items.count() - 1;
|
||||
|
||||
beginInsertRows(QModelIndex(), start, end);
|
||||
|
@ -461,23 +522,23 @@ QModelIndex Playlist::InsertItems(const PlaylistItemList& items, int after) {
|
|||
return index(start, 0);
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertLibraryItems(const SongList& songs, int after) {
|
||||
QModelIndex Playlist::InsertLibraryItems(const SongList& songs, int pos) {
|
||||
PlaylistItemList items;
|
||||
foreach (const Song& song, songs) {
|
||||
items << shared_ptr<PlaylistItem>(new LibraryPlaylistItem(song));
|
||||
}
|
||||
return InsertItems(items, after);
|
||||
return InsertItems(items, pos);
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertSongs(const SongList& songs, int after) {
|
||||
QModelIndex Playlist::InsertSongs(const SongList& songs, int pos) {
|
||||
PlaylistItemList items;
|
||||
foreach (const Song& song, songs) {
|
||||
items << shared_ptr<PlaylistItem>(new SongPlaylistItem(song));
|
||||
}
|
||||
return InsertItems(items, after);
|
||||
return InsertItems(items, pos);
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertRadioStations(const QList<RadioItem*>& items, int after) {
|
||||
QModelIndex Playlist::InsertRadioStations(const QList<RadioItem*>& items, int pos) {
|
||||
PlaylistItemList playlist_items;
|
||||
foreach (RadioItem* item, items) {
|
||||
if (!item->playable)
|
||||
|
@ -486,16 +547,16 @@ QModelIndex Playlist::InsertRadioStations(const QList<RadioItem*>& items, int af
|
|||
playlist_items << shared_ptr<PlaylistItem>(
|
||||
new RadioPlaylistItem(item->service, item->Url(), item->Title(), item->Artist()));
|
||||
}
|
||||
return InsertItems(playlist_items, after);
|
||||
return InsertItems(playlist_items, pos);
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertStreamUrls(const QList<QUrl>& urls, int after) {
|
||||
QModelIndex Playlist::InsertStreamUrls(const QList<QUrl>& urls, int pos) {
|
||||
PlaylistItemList playlist_items;
|
||||
foreach (const QUrl& url, urls) {
|
||||
playlist_items << shared_ptr<PlaylistItem>(new RadioPlaylistItem(
|
||||
RadioModel::ServiceByName(SavedRadio::kServiceName), url.toString(), url.toString(), QString()));
|
||||
}
|
||||
return InsertItems(playlist_items, after);
|
||||
return InsertItems(playlist_items, pos);
|
||||
}
|
||||
|
||||
QMimeData* Playlist::mimeData(const QModelIndexList& indexes) const {
|
||||
|
@ -613,6 +674,9 @@ void Playlist::sort(int column, Qt::SortOrder order) {
|
|||
|
||||
layoutChanged();
|
||||
|
||||
// TODO
|
||||
undo_stack_->clear();
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
|
@ -676,11 +740,21 @@ bool Playlist::removeRows(int row, int count, const QModelIndex& parent) {
|
|||
if (row < 0 || row >= items_.size() || row + count > items_.size()) {
|
||||
return false;
|
||||
}
|
||||
beginRemoveRows(parent, row, row+count-1);
|
||||
|
||||
undo_stack_->push(new PlaylistUndoCommands::RemoveItems(this, row, count));
|
||||
return true;
|
||||
}
|
||||
|
||||
PlaylistItemList Playlist::RemoveItemsWithoutUndo(int row, int count) {
|
||||
if (row < 0 || row >= items_.size() || row + count > items_.size()) {
|
||||
return PlaylistItemList();
|
||||
}
|
||||
beginRemoveRows(QModelIndex(), row, row+count-1);
|
||||
|
||||
// Remove items
|
||||
PlaylistItemList ret;
|
||||
for (int i=0 ; i<count ; ++i)
|
||||
items_.removeAt(row);
|
||||
ret << items_.takeAt(row);
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
|
@ -701,7 +775,7 @@ bool Playlist::removeRows(int row, int count, const QModelIndex& parent) {
|
|||
current_virtual_index_ = virtual_items_.indexOf(current_index());
|
||||
|
||||
Save();
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Playlist::StopAfter(int row) {
|
||||
|
@ -787,11 +861,7 @@ void Playlist::UpdateScrobblePoint() {
|
|||
}
|
||||
|
||||
void Playlist::Clear() {
|
||||
items_.clear();
|
||||
virtual_items_.clear();
|
||||
reset();
|
||||
|
||||
current_virtual_index_ = -1;
|
||||
undo_stack_->push(new PlaylistUndoCommands::RemoveItems(this, 0, items_.count()));
|
||||
|
||||
Save();
|
||||
}
|
||||
|
@ -822,6 +892,9 @@ void Playlist::Shuffle() {
|
|||
|
||||
layoutChanged();
|
||||
|
||||
// TODO
|
||||
undo_stack_->clear();
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
|
|
|
@ -31,9 +31,21 @@
|
|||
class RadioService;
|
||||
class LibraryBackendInterface;
|
||||
|
||||
class QUndoStack;
|
||||
|
||||
namespace PlaylistUndoCommands {
|
||||
class InsertItems;
|
||||
class RemoveItems;
|
||||
class MoveItems;
|
||||
}
|
||||
|
||||
class Playlist : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
friend class PlaylistUndoCommands::InsertItems;
|
||||
friend class PlaylistUndoCommands::RemoveItems;
|
||||
friend class PlaylistUndoCommands::MoveItems;
|
||||
|
||||
public:
|
||||
Playlist(QObject* parent = 0, SettingsProvider* settings = NULL);
|
||||
~Playlist();
|
||||
|
@ -100,18 +112,20 @@ class Playlist : public QAbstractListModel {
|
|||
void set_sequence(PlaylistSequence* v);
|
||||
PlaylistSequence* sequence() const { return playlist_sequence_; }
|
||||
|
||||
QUndoStack* undo_stack() const { return undo_stack_; }
|
||||
|
||||
// Scrobbling
|
||||
int scrobble_point() const { return scrobble_point_; }
|
||||
bool has_scrobbled() const { return has_scrobbled_; }
|
||||
void set_scrobbled(bool v) { has_scrobbled_ = v; }
|
||||
|
||||
// Changing the playlist
|
||||
QModelIndex InsertItems(const PlaylistItemList& items, int after = -1);
|
||||
QModelIndex InsertLibraryItems(const SongList& items, int after = -1);
|
||||
QModelIndex InsertSongs(const SongList& items, int after = -1);
|
||||
QModelIndex InsertRadioStations(const QList<RadioItem*>& items, int after = -1);
|
||||
QModelIndex InsertStreamUrls(const QList<QUrl>& urls, int after = -1);
|
||||
QModelIndex InsertPaths(QList<QUrl> urls, int after = -1);
|
||||
QModelIndex InsertItems(const PlaylistItemList& items, int pos = -1);
|
||||
QModelIndex InsertLibraryItems(const SongList& items, int pos = -1);
|
||||
QModelIndex InsertSongs(const SongList& items, int pos = -1);
|
||||
QModelIndex InsertRadioStations(const QList<RadioItem*>& items, int pos = -1);
|
||||
QModelIndex InsertStreamUrls(const QList<QUrl>& urls, int pos = -1);
|
||||
QModelIndex InsertPaths(QList<QUrl> urls, int pos = -1);
|
||||
void StopAfter(int row);
|
||||
void ReloadItems(const QList<int>& rows);
|
||||
|
||||
|
@ -159,6 +173,13 @@ class Playlist : public QAbstractListModel {
|
|||
void ReshuffleIndices();
|
||||
int NextVirtualIndex(int i) const;
|
||||
|
||||
// Modify the playlist without changing the undo stack. These are used by
|
||||
// our friends in PlaylistUndoCommands
|
||||
QModelIndex InsertItemsWithoutUndo(const PlaylistItemList& items, int pos);
|
||||
PlaylistItemList RemoveItemsWithoutUndo(int pos, int count);
|
||||
void MoveItemsWithoutUndo(const QList<int>& source_rows, int pos);
|
||||
void MoveItemsWithoutUndo(int start, const QList<int>& dest_rows);
|
||||
|
||||
private:
|
||||
boost::scoped_ptr<SettingsProvider> settings_;
|
||||
|
||||
|
@ -183,6 +204,8 @@ class Playlist : public QAbstractListModel {
|
|||
|
||||
// Hack to stop QTreeView::setModel sorting the playlist
|
||||
bool ignore_sorting_;
|
||||
|
||||
QUndoStack* undo_stack_;
|
||||
};
|
||||
|
||||
#endif // PLAYLIST_H
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "playlistundocommands.h"
|
||||
#include "playlist.h"
|
||||
|
||||
namespace PlaylistUndoCommands {
|
||||
|
||||
Base::Base(Playlist *playlist)
|
||||
: QUndoCommand(0),
|
||||
playlist_(playlist)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
InsertItems::InsertItems(Playlist *playlist, const PlaylistItemList &items, int pos)
|
||||
: Base(playlist),
|
||||
items_(items),
|
||||
pos_(pos)
|
||||
{
|
||||
setText(tr("add %n songs", "", items_.count()));
|
||||
}
|
||||
|
||||
void InsertItems::redo() {
|
||||
playlist_->InsertItemsWithoutUndo(items_, pos_);
|
||||
}
|
||||
|
||||
void InsertItems::undo() {
|
||||
const int start = pos_ == -1 ?
|
||||
playlist_->rowCount() - items_.count() : pos_;
|
||||
playlist_->RemoveItemsWithoutUndo(start, items_.count());
|
||||
}
|
||||
|
||||
|
||||
RemoveItems::RemoveItems(Playlist *playlist, int pos, int count)
|
||||
: Base(playlist),
|
||||
pos_(pos),
|
||||
count_(count)
|
||||
{
|
||||
setText(tr("remove %n songs", "", count_));
|
||||
}
|
||||
|
||||
void RemoveItems::redo() {
|
||||
items_ = playlist_->RemoveItemsWithoutUndo(pos_, count_);
|
||||
}
|
||||
|
||||
void RemoveItems::undo() {
|
||||
playlist_->InsertItemsWithoutUndo(items_, pos_);
|
||||
}
|
||||
|
||||
|
||||
MoveItems::MoveItems(Playlist *playlist, const QList<int> &source_rows, int pos)
|
||||
: Base(playlist),
|
||||
source_rows_(source_rows),
|
||||
pos_(pos)
|
||||
{
|
||||
setText(tr("move songs", "", source_rows.count()));
|
||||
}
|
||||
|
||||
void MoveItems::redo() {
|
||||
playlist_->MoveItemsWithoutUndo(source_rows_, pos_);
|
||||
}
|
||||
|
||||
void MoveItems::undo() {
|
||||
playlist_->MoveItemsWithoutUndo(pos_, source_rows_);
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,76 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PLAYLISTUNDOCOMMANDS_H
|
||||
#define PLAYLISTUNDOCOMMANDS_H
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "playlistitem.h"
|
||||
|
||||
class Playlist;
|
||||
|
||||
namespace PlaylistUndoCommands {
|
||||
class Base : public QUndoCommand {
|
||||
Q_DECLARE_TR_FUNCTIONS(PlaylistUndoCommands);
|
||||
|
||||
public:
|
||||
Base(Playlist* playlist);
|
||||
|
||||
protected:
|
||||
Playlist* playlist_;
|
||||
};
|
||||
|
||||
class InsertItems : public Base {
|
||||
public:
|
||||
InsertItems(Playlist* playlist, const PlaylistItemList& items, int pos);
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
private:
|
||||
PlaylistItemList items_;
|
||||
int pos_;
|
||||
};
|
||||
|
||||
class RemoveItems : public Base {
|
||||
public:
|
||||
RemoveItems(Playlist* playlist, int pos, int count);
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
private:
|
||||
int pos_;
|
||||
int count_;
|
||||
PlaylistItemList items_;
|
||||
};
|
||||
|
||||
class MoveItems : public Base {
|
||||
public:
|
||||
MoveItems(Playlist* playlist, const QList<int>& source_rows, int pos);
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
private:
|
||||
QList<int> source_rows_;
|
||||
int pos_;
|
||||
};
|
||||
} //namespace
|
||||
|
||||
#endif // PLAYLISTUNDOCOMMANDS_H
|
|
@ -564,6 +564,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Další skladba"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -985,6 +996,10 @@ msgstr ""
|
|||
msgid "Enable equalizer"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Další skladba"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "Sousedství uživatele %1"
|
||||
|
||||
|
|
|
@ -568,6 +568,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "%n Stücke bearbeiten"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -992,5 +1003,9 @@ msgstr ""
|
|||
msgid "Enable equalizer"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "%n Stücke bearbeiten"
|
||||
|
||||
#~ msgid "%1's Library"
|
||||
#~ msgstr "%1s Musiksammlung"
|
||||
|
|
|
@ -566,6 +566,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Τροποποίηση %n κομματιών"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -989,6 +1000,10 @@ msgstr "Προκαθορισμένα:"
|
|||
msgid "Enable equalizer"
|
||||
msgstr "Ενεργοποίηση του ισοσταθμιστή"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Τροποποίηση %n κομματιών"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "%1's Συνοικιακά"
|
||||
|
||||
|
|
|
@ -550,6 +550,17 @@ msgstr "Select engine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr "Unknown audio engine \"%1\". Choices are:"
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Editing %n tracks"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -969,3 +980,7 @@ msgstr "Preset:"
|
|||
|
||||
msgid "Enable equalizer"
|
||||
msgstr "Enable equalizer"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Editing %n tracks"
|
||||
|
|
|
@ -566,6 +566,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Editando %n pistas"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -993,6 +1004,10 @@ msgstr "Preconfiguración:"
|
|||
msgid "Enable equalizer"
|
||||
msgstr "Habilitar el ecualizador"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Editando %n pistas"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "Vecinos de %1"
|
||||
|
||||
|
|
|
@ -567,6 +567,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Editer %n pistes"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -993,6 +1004,10 @@ msgstr ""
|
|||
msgid "Enable equalizer"
|
||||
msgstr "Activer l'égaliseur"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Editer %n pistes"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "Voisinnage de %1"
|
||||
|
||||
|
|
|
@ -571,6 +571,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Endrer %n spor"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -993,6 +1004,10 @@ msgstr "Forhåndsinnstillinger:"
|
|||
msgid "Enable equalizer"
|
||||
msgstr "Slå på equalizer"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Endrer %n spor"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "%1s nabolag"
|
||||
|
||||
|
|
|
@ -563,6 +563,17 @@ msgstr ""
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Następny utwór"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr ""
|
||||
|
||||
|
@ -982,6 +993,10 @@ msgstr ""
|
|||
msgid "Enable equalizer"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Następny utwór"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "%1 sąsiada"
|
||||
|
||||
|
|
|
@ -566,6 +566,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Editando %n faixas"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -988,6 +999,10 @@ msgstr "Predefinição:"
|
|||
msgid "Enable equalizer"
|
||||
msgstr "Activar o equalizador"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Editando %n faixas"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "Vizinhos da %1's"
|
||||
|
||||
|
|
|
@ -558,6 +558,17 @@ msgstr ""
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -564,6 +564,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Редактирую %n треков"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -986,6 +997,10 @@ msgstr "Настройка:"
|
|||
msgid "Enable equalizer"
|
||||
msgstr "Включить эквалайзер"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Редактирую %n треков"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "Соседи %1"
|
||||
|
||||
|
|
|
@ -564,6 +564,17 @@ msgstr ""
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Nesledujca skladba"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr ""
|
||||
|
||||
|
@ -985,6 +996,10 @@ msgstr ""
|
|||
msgid "Enable equalizer"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Nesledujca skladba"
|
||||
|
||||
#~ msgid "%1's Neighborhood"
|
||||
#~ msgstr "%1 susedia"
|
||||
|
||||
|
|
|
@ -562,6 +562,17 @@ msgstr "Clementine"
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr "Redigerar %n spår"
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr "Clementine"
|
||||
|
||||
|
@ -985,3 +996,7 @@ msgstr "Förval:"
|
|||
|
||||
msgid "Enable equalizer"
|
||||
msgstr "Aktivera equalizer"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "insert %n tracks"
|
||||
#~ msgstr "Redigerar %n spår"
|
||||
|
|
|
@ -558,6 +558,17 @@ msgstr ""
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -549,6 +549,17 @@ msgstr ""
|
|||
msgid "Unknown audio engine \"%1\". Choices are:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "add %n songs"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "remove %n songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "move songs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clementine"
|
||||
msgstr ""
|
||||
|
||||
|
|
Loading…
Reference in New Issue