From c2445edad521b99ef530f07b841bd3fede1cfa3d Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 6 Mar 2011 14:07:41 +0000 Subject: [PATCH] Add a "complete tags automatically" shortcut to the playlist context menu. Fixes issue #1532 --- data/data.qrc | 1 + data/providers/musicbrainz.png | Bin 0 -> 1611 bytes src/core/tagfetcher.cpp | 1 - src/ui/edittagdialog.cpp | 7 ++-- src/ui/edittagdialog.h | 2 +- src/ui/edittagdialog.ui | 12 ++++++- src/ui/mainwindow.cpp | 53 +++++++++++++++++++++++++++ src/ui/mainwindow.h | 7 ++++ src/ui/mainwindow.ui | 14 +++++++- src/ui/trackselectiondialog.cpp | 59 ++++++++++++++++++++++++++++-- src/ui/trackselectiondialog.h | 18 +++++++--- src/ui/trackselectiondialog.ui | 61 ++++++++++++++++++++++++-------- 12 files changed, 207 insertions(+), 28 deletions(-) create mode 100644 data/providers/musicbrainz.png diff --git a/data/data.qrc b/data/data.qrc index d2ad63238..404a55eee 100644 --- a/data/data.qrc +++ b/data/data.qrc @@ -302,5 +302,6 @@ icons/22x22/network-server.png icons/32x32/network-server.png icons/48x48/network-server.png + providers/musicbrainz.png diff --git a/data/providers/musicbrainz.png b/data/providers/musicbrainz.png new file mode 100644 index 0000000000000000000000000000000000000000..f56ef9194588270ddd5d8943abae6901fb3cbdb5 GIT binary patch literal 1611 zcmV-R2DJH!P)4hzSP(000JJOGiWi{{a60|De66lK=n!32;bRa{vGf6951U69E94oEQKA1=vYM zK~zY`y;f;VR96&s5E!shL=mJ42#Dp3?MVyz-r+naoO_r7`W-EY2g&UfyN8UN2% zNT?;e{9k-rhah{(cU1&;g8Eq!dX7*-7$C_11u-W=|ju`hJRG0Or|p$Mr0~V4ndQ+0alCLu)2B}tEx_76oT0sl^BLkA>1mF0Tf_0?$z<#(^}tLW*{D?Uj~!-`@kKs@nB086?LcY4 z9ucmH&;mgsL$d`z{^=+y+>4^zP88<6B1mf!*JEU32yPE0;lsnr@zIgx_-r5n&3UeP zyCWJ+SN@WK+})7}^kwOWPyBRr$-gbU}iv^H#rF%o73^iYtS|ESWElDnctkGrswY zQnHymETx{Fyg4`^9VrQo6uJ?(Iz=KcvkkQ?kAqb#%Iy*%&ChB_#Igdcts52_c9eUG z9Q&O@$g17yPry%aYVrQQcofCkiu-3(f}Kqd(pFZ4BFS6>ALqQxxR4iK?#dA+!S=xFuun0G%Ce&(uf{{Xvg9ya zog*iRu_|AWBu|8l^X;3{8Zl=wY$5Dz{c8hJon${uTe%S&Cle`+U7e7@i)BGsgPhcE z&QYMbAizZYeN#kr=4R|bmbL{xo+>C~Yv}iV_{pN=jaVU9@sWj}r9cy%T^_%M}PY7b{_}S^(U^d?dIT_nU0hpWF!E~M# z4CJ#>UEViAjGdnPBHV1|z<23f^bvt;J+bh%HxcS_h4OPhpG}8cPp5gtbcddcIzd~~GB>$TBFt%LiGFD$TB>akv)W=IL43_hY8##9dZdK`;%@c~D zElRYWQ=39?hg4&=?v83vuW=Bq>3ce9+^4P(;cmvw-1t!&{{><&8Nl&S96|s9002ov JPDHLkV1hl;|40A; literal 0 HcmV?d00001 diff --git a/src/core/tagfetcher.cpp b/src/core/tagfetcher.cpp index a906d5bac..53df16aac 100644 --- a/src/core/tagfetcher.cpp +++ b/src/core/tagfetcher.cpp @@ -57,7 +57,6 @@ TagFetcher::TagFetcher(QObject *parent) } TagFetcher::~TagFetcher() { - delete network_; tp_Delete(pimp_); } diff --git a/src/ui/edittagdialog.cpp b/src/ui/edittagdialog.cpp index 019f22796..b83586597 100644 --- a/src/ui/edittagdialog.cpp +++ b/src/ui/edittagdialog.cpp @@ -64,8 +64,8 @@ EditTagDialog::EditTagDialog(QWidget* parent) connect(tag_fetcher_, SIGNAL(FetchFinished(QString, SongList)), results_dialog_, SLOT(FetchTagFinished(QString, SongList)), Qt::QueuedConnection); - connect(results_dialog_, SIGNAL(SongChosen(QString, Song)), - SLOT(FetchTagSongChosen(QString, Song))); + connect(results_dialog_, SIGNAL(SongChosen(Song, Song)), + SLOT(FetchTagSongChosen(Song, Song))); #endif ui_->setupUi(this); @@ -708,7 +708,8 @@ void EditTagDialog::FetchTag() { #endif } -void EditTagDialog::FetchTagSongChosen(const QString& filename, const Song& new_metadata) { +void EditTagDialog::FetchTagSongChosen(const Song& original_song, const Song& new_metadata) { + const QString filename = original_song.filename(); // Find the song with this filename for (int i=0 ; i - 0 + 1 @@ -823,6 +823,16 @@ Complete tags automatically + + + :/providers/musicbrainz.png:/providers/musicbrainz.png + + + + 38 + 22 + + diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index e27273e70..cff2aec2a 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -32,6 +32,7 @@ #include "core/player.h" #include "core/songloader.h" #include "core/stylesheetloader.h" +#include "core/tagfetcher.h" #include "core/taskmanager.h" #include "devices/devicemanager.h" #include "devices/devicestatefiltermodel.h" @@ -78,6 +79,7 @@ #include "ui/qtsystemtrayicon.h" #include "ui/settingsdialog.h" #include "ui/systemtrayicon.h" +#include "ui/trackselectiondialog.h" #include "ui/windows7thumbbar.h" #include "version.h" #include "widgets/errordialog.h" @@ -296,6 +298,7 @@ MainWindow::MainWindow( ui_->action_full_library_scan->setIcon(IconLoader::Load("view-refresh")); ui_->action_rain->setIcon(IconLoader::Load("weather-showers-scattered")); + // File view connections connect(file_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*))); connect(file_view_, SIGNAL(PathChanged(QString)), SLOT(FilePathChanged(QString))); @@ -322,6 +325,7 @@ MainWindow::MainWindow( 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_auto_complete_tags, SIGNAL(triggered()), SLOT(AutoCompleteTags())); connect(ui_->action_configure, SIGNAL(triggered()), SLOT(OpenSettingsDialog())); connect(ui_->action_about, SIGNAL(triggered()), SLOT(ShowAboutDialog())); connect(ui_->action_about_qt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); @@ -471,6 +475,9 @@ MainWindow::MainWindow( playlist_menu_->addAction(ui_->action_edit_value); playlist_menu_->addAction(ui_->action_renumber_tracks); playlist_menu_->addAction(ui_->action_selection_set_value); +#ifdef HAVE_LIBTUNEPIMP + playlist_menu_->addAction(ui_->action_auto_complete_tags); +#endif playlist_menu_->addSeparator(); playlist_copy_to_library_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to library..."), this, SLOT(PlaylistCopyToLibrary())); playlist_move_to_library_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to library..."), this, SLOT(PlaylistMoveToLibrary())); @@ -1108,6 +1115,8 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex& // those is not CUE related ui_->action_edit_track->setEnabled(editable); ui_->action_edit_track->setVisible(editable); + ui_->action_auto_complete_tags->setEnabled(editable); + ui_->action_auto_complete_tags->setVisible(editable); // the rest of the read / write actions work only when there are no CUEs // involved if(cue_selected) @@ -1871,3 +1880,47 @@ void MainWindow::Exit() { } qApp->quit(); } + +void MainWindow::AutoCompleteTags() { + // Create the tag fetching stuff if it hasn't been already + if (!tag_fetcher_) { + tag_fetcher_.reset(new TagFetcher); + track_selection_dialog_.reset(new TrackSelectionDialog); + track_selection_dialog_->set_save_on_close(true); + + connect(tag_fetcher_.get(), SIGNAL(FetchFinished(QString, SongList)), + track_selection_dialog_.get(), SLOT(FetchTagFinished(QString, SongList)), + Qt::QueuedConnection); + connect(track_selection_dialog_.get(), SIGNAL(accepted()), + SLOT(AutoCompleteTagsAccepted())); + } + + // Get the selected songs and start fetching tags for them + SongList songs; + autocomplete_tag_items_.clear(); + foreach (const QModelIndex& index, + ui_->playlist->view()->selectionModel()->selection().indexes()) { + if (index.column() != 0) + continue; + int row = playlists_->current()->proxy()->mapToSource(index).row(); + PlaylistItemPtr item(playlists_->current()->item_at(row)); + Song song = item->Metadata(); + + if (song.IsEditable()) { + songs << song; + autocomplete_tag_items_ << item; + tag_fetcher_->FetchFromFile(song.filename()); + } + } + + track_selection_dialog_->Init(songs); + track_selection_dialog_->show(); +} +void MainWindow::AutoCompleteTagsAccepted() { + foreach (PlaylistItemPtr item, autocomplete_tag_items_) { + item->Reload(); + } + + // This is really lame but we don't know what rows have changed + ui_->playlist->view()->update(); +} diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index a44d02634..b5f5be072 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -66,7 +66,9 @@ class Song; class SongInfoBase; class SongInfoView; class SystemTrayIcon; +class TagFetcher; class TaskManager; +class TrackSelectionDialog; class TranscodeDialog; class VisualisationContainer; class WiimotedevShortcuts; @@ -157,6 +159,8 @@ class MainWindow : public QMainWindow, public PlatformInterface { void RenumberTracks(); void SelectionSetValue(); void EditValue(); + void AutoCompleteTags(); + void AutoCompleteTagsAccepted(); void PlaylistUndoRedoChanged(QAction* undo, QAction* redo); void PlaylistCopyToLibrary(); @@ -283,6 +287,9 @@ class MainWindow : public QMainWindow, public PlatformInterface { boost::scoped_ptr organise_dialog_; boost::scoped_ptr queue_manager_; + boost::scoped_ptr tag_fetcher_; + boost::scoped_ptr track_selection_dialog_; + PlaylistItemList autocomplete_tag_items_; #ifdef ENABLE_VISUALISATIONS boost::scoped_ptr visualisation_; diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index fc13129f7..2b07cdbd6 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -390,7 +390,7 @@ 0 0 1131 - 25 + 23 @@ -764,6 +764,18 @@ Do a full library rescan + + + + :/providers/musicbrainz.png:/providers/musicbrainz.png + + + Complete tags automatically... + + + Ctrl+T + + diff --git a/src/ui/trackselectiondialog.cpp b/src/ui/trackselectiondialog.cpp index 04ffc8174..33a1a6e99 100644 --- a/src/ui/trackselectiondialog.cpp +++ b/src/ui/trackselectiondialog.cpp @@ -19,13 +19,16 @@ #include "trackselectiondialog.h" #include +#include #include #include +#include #include TrackSelectionDialog::TrackSelectionDialog(QWidget *parent) : QDialog(parent), - ui_(new Ui_TrackSelectionDialog) + ui_(new Ui_TrackSelectionDialog), + save_on_close_(false) { // Setup dialog window ui_->setupUi(this); @@ -35,6 +38,7 @@ TrackSelectionDialog::TrackSelectionDialog(QWidget *parent) SLOT(ResultSelected())); ui_->splitter->setSizes(QList() << 200 << width() - 200); + SetLoading(QString()); // Add the next/previous buttons previous_button_ = new QPushButton(IconLoader::Load("go-previous"), tr("Previous"), this); @@ -188,17 +192,68 @@ void TrackSelectionDialog::ResultSelected() { data_[song_row].selected_result_ = result_index; } +void TrackSelectionDialog::SetLoading(const QString& message) { + const bool loading = !message.isEmpty(); + + ui_->loading_container->setVisible(loading); + ui_->button_box->setEnabled(!loading); + ui_->splitter->setEnabled(!loading); + ui_->loading_label->setText(message); +} + +void TrackSelectionDialog::SaveData(const QList& data) { + for (int i=0 ; i future = QtConcurrent::run(&TrackSelectionDialog::SaveData, data_); + QFutureWatcher* watcher = new QFutureWatcher(this); + watcher->setFuture(future); + connect(watcher, SIGNAL(finished()), SLOT(AcceptFinished())); + + return; + } + QDialog::accept(); foreach (const Data& data, data_) { if (data.pending_ || data.results_.isEmpty() || data.selected_result_ == -1) continue; - emit SongChosen(data.original_song_.filename(), data.results_[data.selected_result_]); + const Song& new_metadata = data.results_[data.selected_result_]; + + emit SongChosen(data.original_song_, new_metadata); } } +void TrackSelectionDialog::AcceptFinished() { + QFutureWatcher* watcher = dynamic_cast*>(sender()); + if (!watcher) + return; + watcher->deleteLater(); + + SetLoading(QString()); + QDialog::accept(); +} + void TrackSelectionDialog::NextSong() { int row = (ui_->song_list->currentRow() + 1) % ui_->song_list->count(); ui_->song_list->setCurrentRow(row); diff --git a/src/ui/trackselectiondialog.h b/src/ui/trackselectiondialog.h index 1eb863024..111788060 100644 --- a/src/ui/trackselectiondialog.h +++ b/src/ui/trackselectiondialog.h @@ -32,6 +32,8 @@ public: TrackSelectionDialog(QWidget *parent = 0); ~TrackSelectionDialog(); + void set_save_on_close(bool save_on_close) { save_on_close_ = save_on_close; } + void Init(const SongList& songs); public slots: @@ -41,7 +43,7 @@ public slots: void accept(); signals: - void SongChosen(const QString& filename, const Song& song); + void SongChosen(const Song& original_song, const Song& new_metadata); private slots: void UpdateStack(); @@ -50,10 +52,7 @@ private slots: void PreviousSong(); void ResultSelected(); - -private: - void AddDivider(const QString& text, QTreeWidget* parent) const; - void AddSong(const Song& song, int result_index, QTreeWidget* parent) const; + void AcceptFinished(); private: Ui_TrackSelectionDialog* ui_; @@ -67,10 +66,19 @@ private: int selected_result_; }; + void AddDivider(const QString& text, QTreeWidget* parent) const; + void AddSong(const Song& song, int result_index, QTreeWidget* parent) const; + + void SetLoading(const QString& message); + static void SaveData(const QList& data); + +private: QList data_; QPushButton* previous_button_; QPushButton* next_button_; + + bool save_on_close_; }; #endif // TRACKSELECTIONDIALOG_H diff --git a/src/ui/trackselectiondialog.ui b/src/ui/trackselectiondialog.ui index 86d3fd147..ec3375336 100644 --- a/src/ui/trackselectiondialog.ui +++ b/src/ui/trackselectiondialog.ui @@ -221,20 +221,53 @@ - - - - 0 - 0 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + + + + + 0 + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + +