mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-15 10:48:33 +01:00
Allow inline editing of tags in the playlist. Thanks christoph.gysin
This commit is contained in:
parent
11bd9966d1
commit
766429c860
@ -133,6 +133,7 @@ MainWindow::MainWindow(QNetworkAccessManager* network, QWidget *parent)
|
||||
connect(ui_.action_edit_track, SIGNAL(triggered()), SLOT(EditTracks()));
|
||||
connect(ui_.action_renumber_tracks, SIGNAL(triggered()), SLOT(RenumberTracks()));
|
||||
connect(ui_.action_selection_set_value, SIGNAL(triggered()), SLOT(SelectionSetValue()));
|
||||
connect(ui_.action_edit_value, SIGNAL(triggered()), SLOT(EditValue()));
|
||||
connect(ui_.action_configure, SIGNAL(triggered()), settings_dialog_, SLOT(show()));
|
||||
connect(ui_.action_about, SIGNAL(triggered()), about_dialog_, SLOT(show()));
|
||||
connect(ui_.action_shuffle, SIGNAL(triggered()), playlist_, SLOT(Shuffle()));
|
||||
@ -244,6 +245,7 @@ MainWindow::MainWindow(QNetworkAccessManager* network, QWidget *parent)
|
||||
playlist_menu_->addAction(ui_.action_remove_from_playlist);
|
||||
playlist_menu_->addSeparator();
|
||||
playlist_menu_->addAction(ui_.action_edit_track);
|
||||
playlist_menu_->addAction(ui_.action_edit_value);
|
||||
playlist_menu_->addAction(ui_.action_renumber_tracks);
|
||||
playlist_menu_->addAction(ui_.action_selection_set_value);
|
||||
playlist_menu_->addSeparator();
|
||||
@ -587,17 +589,22 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex&
|
||||
}
|
||||
}
|
||||
ui_.action_edit_track->setEnabled(editable);
|
||||
ui_.action_renumber_tracks->setEnabled(editable);
|
||||
ui_.action_selection_set_value->setEnabled(editable >= 2);
|
||||
ui_.action_renumber_tracks->setVisible(editable);
|
||||
ui_.action_selection_set_value->setVisible(editable >= 2);
|
||||
ui_.action_edit_value->setVisible(editable);
|
||||
ui_.action_remove_from_playlist->setEnabled(!selection.isEmpty());
|
||||
|
||||
if (!index.isValid()) {
|
||||
ui_.action_selection_set_value->setVisible(false);
|
||||
ui_.action_edit_value->setVisible(false);
|
||||
} else {
|
||||
Playlist::Column column = (Playlist::Column)index.column();
|
||||
bool editable = Playlist::column_is_editable(column);
|
||||
|
||||
ui_.action_selection_set_value->setVisible(
|
||||
column <= Playlist::Column_Genre &&
|
||||
column != Playlist::Column_Length);
|
||||
ui_.action_selection_set_value->isVisible() && editable);
|
||||
ui_.action_edit_value->setVisible(
|
||||
ui_.action_edit_value->isVisible() && editable);
|
||||
|
||||
QString column_name = Playlist::column_name(column);
|
||||
QString column_value = playlist_->data(index).toString();
|
||||
@ -606,6 +613,7 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex&
|
||||
|
||||
ui_.action_selection_set_value->setText(tr("Set %1 to \"%2\"...")
|
||||
.arg(column_name.toLower()).arg(column_value));
|
||||
ui_.action_edit_value->setText(tr("Edit tag \"%1\"...").arg(column_name));
|
||||
}
|
||||
|
||||
playlist_menu_->popup(global_pos);
|
||||
@ -685,44 +693,17 @@ void MainWindow::SelectionSetValue() {
|
||||
int row = index.row();
|
||||
Song song = playlist_->item_at(row)->Metadata();
|
||||
|
||||
if (song.IsEditable()) {
|
||||
switch(column) {
|
||||
case Playlist::Column_Title:
|
||||
song.set_title(column_value.toString());
|
||||
break;
|
||||
case Playlist::Column_Artist:
|
||||
song.set_artist(column_value.toString());
|
||||
break;
|
||||
case Playlist::Column_Album:
|
||||
song.set_album(column_value.toString());
|
||||
break;
|
||||
case Playlist::Column_AlbumArtist:
|
||||
song.set_albumartist(column_value.toString());
|
||||
break;
|
||||
case Playlist::Column_Composer:
|
||||
song.set_composer(column_value.toString());
|
||||
break;
|
||||
case Playlist::Column_Track:
|
||||
song.set_track(column_value.toInt());
|
||||
break;
|
||||
case Playlist::Column_Disc:
|
||||
song.set_disc(column_value.toInt());
|
||||
break;
|
||||
case Playlist::Column_Year:
|
||||
song.set_year(column_value.toInt());
|
||||
break;
|
||||
case Playlist::Column_Genre:
|
||||
song.set_genre(column_value.toString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(Playlist::set_column_value(song, column, column_value)) {
|
||||
song.Save();
|
||||
playlist_->item_at(row)->Reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::EditValue() {
|
||||
ui_.playlist->edit(playlist_menu_index_);
|
||||
}
|
||||
|
||||
void MainWindow::LibraryScanStarted() {
|
||||
multi_loading_indicator_->TaskStarted(MultiLoadingIndicator::UpdatingLibrary);
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ class MainWindow : public QMainWindow {
|
||||
void EditTracks();
|
||||
void RenumberTracks();
|
||||
void SelectionSetValue();
|
||||
void EditValue();
|
||||
|
||||
void PlayIndex(const QModelIndex& index);
|
||||
void StopAfterCurrent();
|
||||
|
@ -40,6 +40,9 @@
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::SelectedClicked|QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -665,6 +668,11 @@
|
||||
<string>Set value for all selected tracks...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_edit_value">
|
||||
<property name="text">
|
||||
<string>Edit tag...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_configure">
|
||||
<property name="icon">
|
||||
<iconset resource="../data/data.qrc">
|
||||
|
@ -66,6 +66,64 @@ QVariant Playlist::headerData(int section, Qt::Orientation, int role) const {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool Playlist::column_is_editable(Playlist::Column column) {
|
||||
switch(column) {
|
||||
case Column_Title:
|
||||
case Column_Artist:
|
||||
case Column_Album:
|
||||
case Column_AlbumArtist:
|
||||
case Column_Composer:
|
||||
case Column_Track:
|
||||
case Column_Disc:
|
||||
case Column_Year:
|
||||
case Column_Genre:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Playlist::set_column_value(Song& song, Playlist::Column column,
|
||||
const QVariant& value) {
|
||||
|
||||
if (!song.IsEditable())
|
||||
return false;
|
||||
|
||||
switch(column) {
|
||||
case Playlist::Column_Title:
|
||||
song.set_title(value.toString());
|
||||
break;
|
||||
case Playlist::Column_Artist:
|
||||
song.set_artist(value.toString());
|
||||
break;
|
||||
case Playlist::Column_Album:
|
||||
song.set_album(value.toString());
|
||||
break;
|
||||
case Playlist::Column_AlbumArtist:
|
||||
song.set_albumartist(value.toString());
|
||||
break;
|
||||
case Playlist::Column_Composer:
|
||||
song.set_composer(value.toString());
|
||||
break;
|
||||
case Playlist::Column_Track:
|
||||
song.set_track(value.toInt());
|
||||
break;
|
||||
case Playlist::Column_Disc:
|
||||
song.set_disc(value.toInt());
|
||||
break;
|
||||
case Playlist::Column_Year:
|
||||
song.set_year(value.toInt());
|
||||
break;
|
||||
case Playlist::Column_Genre:
|
||||
song.set_genre(value.toString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant Playlist::data(const QModelIndex& index, int role) const {
|
||||
switch (role) {
|
||||
case Role_IsCurrent:
|
||||
@ -77,6 +135,7 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
|
||||
case Role_StopAfter:
|
||||
return stop_after_.isValid() && stop_after_.row() == index.row();
|
||||
|
||||
case Qt::EditRole:
|
||||
case Qt::DisplayRole: {
|
||||
PlaylistItem* item = items_[index.row()];
|
||||
Song song = item->Metadata();
|
||||
@ -112,6 +171,18 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool Playlist::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
int row = index.row();
|
||||
Song song = item_at(row)->Metadata();
|
||||
|
||||
if(!set_column_value(song, (Column)index.column(), value))
|
||||
return false;
|
||||
|
||||
song.Save();
|
||||
item_at(row)->Reload();
|
||||
return true;
|
||||
}
|
||||
|
||||
int Playlist::current_index() const {
|
||||
return current_item_.isValid() ? current_item_.row() : -1;
|
||||
}
|
||||
@ -222,9 +293,16 @@ void Playlist::set_current_index(int i) {
|
||||
}
|
||||
|
||||
Qt::ItemFlags Playlist::flags(const QModelIndex &index) const {
|
||||
|
||||
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
|
||||
if(column_is_editable((Column)index.column()))
|
||||
flags |= Qt::ItemIsEditable;
|
||||
|
||||
if (index.isValid())
|
||||
return Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
return Qt::ItemIsDropEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
return flags | Qt::ItemIsDragEnabled;
|
||||
|
||||
return Qt::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
QStringList Playlist::mimeTypes() const {
|
||||
|
@ -72,6 +72,8 @@ class Playlist : public QAbstractListModel {
|
||||
const PlaylistItem* a, const PlaylistItem* b);
|
||||
|
||||
static QString column_name(Column column);
|
||||
static bool column_is_editable(Playlist::Column column);
|
||||
static bool set_column_value(Song& song, Column column, const QVariant& value);
|
||||
|
||||
// Persistence
|
||||
void Save() const;
|
||||
@ -110,6 +112,7 @@ class Playlist : public QAbstractListModel {
|
||||
int rowCount(const QModelIndex& = QModelIndex()) const { return items_.count(); }
|
||||
int columnCount(const QModelIndex& = QModelIndex()) const { return ColumnCount; }
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QStringList mimeTypes() const;
|
||||
|
@ -349,10 +349,9 @@ bool CompareSelectionRanges(const QItemSelectionRange& a, const QItemSelectionRa
|
||||
void PlaylistView::keyPressEvent(QKeyEvent* event) {
|
||||
if (!model()) {
|
||||
QTreeView::keyPressEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->matches(QKeySequence::Delete) ||
|
||||
} else if (state() == QAbstractItemView::EditingState) {
|
||||
QTreeView::keyPressEvent(event);
|
||||
} else if (event->matches(QKeySequence::Delete) ||
|
||||
event->key() == Qt::Key_Backspace) {
|
||||
RemoveSelected();
|
||||
event->accept();
|
||||
@ -390,3 +389,71 @@ void PlaylistView::RemoveSelected() {
|
||||
currentIndex().sibling(currentIndex().row(), model()->columnCount()-1)),
|
||||
QItemSelectionModel::Select);
|
||||
}
|
||||
|
||||
QList<int> PlaylistView::GetEditableColumns() {
|
||||
QList<int> columns;
|
||||
QHeaderView* h = header();
|
||||
for (int col=0; col<h->count(); col++) {
|
||||
if (h->isSectionHidden(col))
|
||||
continue;
|
||||
QModelIndex index = model()->index(0, col);
|
||||
if (index.flags() & Qt::ItemIsEditable)
|
||||
columns << h->visualIndex(col);
|
||||
}
|
||||
qSort(columns);
|
||||
return columns;
|
||||
}
|
||||
|
||||
QModelIndex PlaylistView::NextEditableIndex(const QModelIndex& current) {
|
||||
QList<int> columns = GetEditableColumns();
|
||||
QHeaderView* h = header();
|
||||
int col = h->visualIndex(current.column());
|
||||
QList<int> columns_left = columns.mid(columns.indexOf(col)+1);
|
||||
|
||||
QModelIndex index;
|
||||
if(columns_left.empty())
|
||||
index = model()->index(current.row()+1, h->logicalIndex(columns.first()));
|
||||
else
|
||||
index = model()->index(current.row(), h->logicalIndex(columns_left.first()));
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
QModelIndex PlaylistView::PrevEditableIndex(const QModelIndex& current) {
|
||||
QList<int> columns = GetEditableColumns();
|
||||
QHeaderView* h = header();
|
||||
int col = h->visualIndex(current.column());
|
||||
QList<int> columns_left = columns.mid(0, columns.indexOf(col));
|
||||
|
||||
QModelIndex index;
|
||||
if(columns_left.empty())
|
||||
index = model()->index(current.row()-1, h->logicalIndex(columns.last()));
|
||||
else
|
||||
index = model()->index(current.row(), h->logicalIndex(columns_left.last()));
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void PlaylistView::closeEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint) {
|
||||
if (hint == QAbstractItemDelegate::NoHint) {
|
||||
QTreeView::closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);
|
||||
} else if (hint == QAbstractItemDelegate::EditNextItem ||
|
||||
hint == QAbstractItemDelegate::EditPreviousItem) {
|
||||
|
||||
QModelIndex index;
|
||||
if (hint == QAbstractItemDelegate::EditNextItem)
|
||||
index = NextEditableIndex(currentIndex());
|
||||
else
|
||||
index = PrevEditableIndex(currentIndex());
|
||||
|
||||
if (!index.isValid()) {
|
||||
QTreeView::closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);
|
||||
} else {
|
||||
QTreeView::closeEditor(editor, QAbstractItemDelegate::NoHint);
|
||||
setCurrentIndex(index);
|
||||
edit(index);
|
||||
}
|
||||
} else {
|
||||
QTreeView::closeEditor(editor, hint);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
class RadioLoadingIndicator;
|
||||
|
||||
class PlaylistDelegateBase : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PlaylistDelegateBase(QTreeView* view);
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
@ -78,6 +79,7 @@ class PlaylistView : public QTreeView {
|
||||
public slots:
|
||||
void StopGlowing();
|
||||
void StartGlowing();
|
||||
void closeEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint);
|
||||
|
||||
signals:
|
||||
void PlayPauseItem(const QModelIndex& index);
|
||||
@ -100,6 +102,10 @@ class PlaylistView : public QTreeView {
|
||||
static const char* kSettingsGroup;
|
||||
static const int kGlowIntensitySteps;
|
||||
|
||||
QList<int> GetEditableColumns();
|
||||
QModelIndex NextEditableIndex(const QModelIndex& current);
|
||||
QModelIndex PrevEditableIndex(const QModelIndex& current);
|
||||
|
||||
bool glow_enabled_;
|
||||
QTimer* glow_timer_;
|
||||
int glow_intensity_step_;
|
||||
|
Loading…
Reference in New Issue
Block a user