From fcf96cb6ffee937568ae7042d1bbe74efb1c1baa Mon Sep 17 00:00:00 2001 From: vaterlangen Date: Mon, 18 Jun 2018 15:21:44 +0200 Subject: [PATCH] Queue size and duration is now displayed in queue manager && Album Cover Popup fixes (#6086) --- dist/format.py | 2 +- src/core/player.h | 2 +- src/playlist/queue.cpp | 47 ++++++++++++++++++++++++++- src/playlist/queue.h | 15 ++++++++- src/playlist/queuemanager.cpp | 6 ++++ src/playlist/queuemanager.ui | 29 ++++++++++++----- src/ui/albumcoverchoicecontroller.cpp | 29 ++++++++++++++++- src/ui/albumcoverchoicecontroller.h | 7 +++- src/widgets/nowplayingwidget.cpp | 2 +- 9 files changed, 123 insertions(+), 16 deletions(-) diff --git a/dist/format.py b/dist/format.py index c3c964cc0..616802b54 100755 --- a/dist/format.py +++ b/dist/format.py @@ -12,7 +12,7 @@ def main(): description='Reformats C++ source files that have changed from a given ' 'git ref.') parser.add_argument('--url', - default='http://clang.clementine-player.org/format', + default='https://clang.clementine-player.org/format', help='a URL of a Clang-in-the-cloud service') parser.add_argument('--ref', default='origin/master', help='the git-ref to compare against') diff --git a/src/core/player.h b/src/core/player.h index 19c2821b4..7dd141965 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -110,7 +110,7 @@ signals: // The toggle parameter is true when user requests to toggle visibility for // Pretty OSD - void ForceShowOSD(Song, bool toogle); + void ForceShowOSD(Song, bool toggle); }; class Player : public PlayerInterface { diff --git a/src/playlist/queue.cpp b/src/playlist/queue.cpp index d66e3e03f..898acd9d4 100644 --- a/src/playlist/queue.cpp +++ b/src/playlist/queue.cpp @@ -21,9 +21,17 @@ #include #include +#include "core/utilities.h" + const char* Queue::kRowsMimetype = "application/x-clementine-queue-rows"; -Queue::Queue(QObject* parent) : QAbstractProxyModel(parent) {} +Queue::Queue(Playlist* parent) + : QAbstractProxyModel(parent), playlist_(parent), total_length_ns_(0) { + connect(this, SIGNAL(ItemCountChanged(int)), SLOT(UpdateTotalLength())); + connect(this, SIGNAL(TotalLengthChanged(quint64)), SLOT(UpdateSummaryText())); + + UpdateSummaryText(); +} QModelIndex Queue::mapFromSource(const QModelIndex& source_index) const { if (!source_index.isValid()) return QModelIndex(); @@ -77,6 +85,7 @@ void Queue::SourceDataChanged(const QModelIndex& top_left, emit dataChanged(proxy_index, proxy_index); } + emit ItemCountChanged(this->ItemCount()); } void Queue::SourceLayoutChanged() { @@ -89,6 +98,7 @@ void Queue::SourceLayoutChanged() { --i; } } + emit ItemCountChanged(this->ItemCount()); } QModelIndex Queue::index(int row, int column, const QModelIndex& parent) const { @@ -180,6 +190,41 @@ int Queue::PositionOf(const QModelIndex& source_index) const { bool Queue::is_empty() const { return source_indexes_.isEmpty(); } +int Queue::ItemCount() const { return source_indexes_.length(); } + +quint64 Queue::GetTotalLength() const { return total_length_ns_; } + +void Queue::UpdateTotalLength() { + quint64 total = 0; + + for (QPersistentModelIndex row : source_indexes_) { + int id = row.row(); + + Q_ASSERT(playlist_->has_item_at(id)); + + quint64 length = playlist_->item_at(id)->Metadata().length_nanosec(); + if (length > 0) total += length; + } + + total_length_ns_ = total; + + emit TotalLengthChanged(total); +} + +void Queue::UpdateSummaryText() { + QString summary; + int tracks = this->ItemCount(); + quint64 nanoseconds = this->GetTotalLength(); + + // TODO: Make the plurals translatable + summary += tracks == 1 ? tr("1 track") : tr("%1 tracks").arg(tracks); + + if (nanoseconds) + summary += " - [ " + Utilities::WordyTimeNanosec(nanoseconds) + " ]"; + + emit SummaryTextChanged(summary); +} + void Queue::Clear() { if (source_indexes_.isEmpty()) return; diff --git a/src/playlist/queue.h b/src/playlist/queue.h index 77751f0f5..f840e733e 100644 --- a/src/playlist/queue.h +++ b/src/playlist/queue.h @@ -26,7 +26,7 @@ class Queue : public QAbstractProxyModel { Q_OBJECT public: - Queue(QObject* parent = nullptr); + Queue(Playlist* parent); static const char* kRowsMimetype; @@ -35,6 +35,8 @@ class Queue : public QAbstractProxyModel { int PositionOf(const QModelIndex& source_index) const; bool ContainsSourceRow(int source_row) const; int PeekNext() const; + int ItemCount() const; + quint64 GetTotalLength() const; // Modify the queue int TakeNext(); @@ -66,13 +68,24 @@ class Queue : public QAbstractProxyModel { int column, const QModelIndex& parent); Qt::ItemFlags flags(const QModelIndex& index) const; + public slots: + void UpdateSummaryText(); + + signals: + void TotalLengthChanged(const quint64 length); + void ItemCountChanged(const int count); + void SummaryTextChanged(const QString& message); + private slots: void SourceDataChanged(const QModelIndex& top_left, const QModelIndex& bottom_right); void SourceLayoutChanged(); + void UpdateTotalLength(); private: QList source_indexes_; + const Playlist* playlist_; + quint64 total_length_ns_; }; #endif // QUEUE_H diff --git a/src/playlist/queuemanager.cpp b/src/playlist/queuemanager.cpp index 55520d64f..b44f4d4fc 100644 --- a/src/playlist/queuemanager.cpp +++ b/src/playlist/queuemanager.cpp @@ -73,6 +73,8 @@ void QueueManager::CurrentPlaylistChanged(Playlist* playlist) { SLOT(UpdateButtonState())); disconnect(current_playlist_->queue(), SIGNAL(layoutChanged()), this, SLOT(UpdateButtonState())); + disconnect(current_playlist_->queue(), SIGNAL(SummaryTextChanged(QString)), + ui_->queue_summary, SLOT(setText(QString))); disconnect(current_playlist_, SIGNAL(destroyed()), this, SLOT(PlaylistDestroyed())); } @@ -87,6 +89,8 @@ void QueueManager::CurrentPlaylistChanged(Playlist* playlist) { SLOT(UpdateButtonState())); connect(current_playlist_->queue(), SIGNAL(layoutChanged()), this, SLOT(UpdateButtonState())); + connect(current_playlist_->queue(), SIGNAL(SummaryTextChanged(QString)), + ui_->queue_summary, SLOT(setText(QString))); connect(current_playlist_, SIGNAL(destroyed()), this, SLOT(PlaylistDestroyed())); @@ -95,6 +99,8 @@ void QueueManager::CurrentPlaylistChanged(Playlist* playlist) { connect(ui_->list->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(UpdateButtonState())); + + QTimer::singleShot(0, current_playlist_->queue(), SLOT(UpdateSummaryText())); } void QueueManager::MoveUp() { diff --git a/src/playlist/queuemanager.ui b/src/playlist/queuemanager.ui index 3203f8027..89147c240 100644 --- a/src/playlist/queuemanager.ui +++ b/src/playlist/queuemanager.ui @@ -17,7 +17,7 @@ :/icon.png:/icon.png - + @@ -144,14 +144,25 @@ - - - Qt::Horizontal - - - QDialogButtonBox::Close - - + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + diff --git a/src/ui/albumcoverchoicecontroller.cpp b/src/ui/albumcoverchoicecontroller.cpp index ed78208c9..c00cd5919 100644 --- a/src/ui/albumcoverchoicecontroller.cpp +++ b/src/ui/albumcoverchoicecontroller.cpp @@ -55,7 +55,8 @@ AlbumCoverChoiceController::AlbumCoverChoiceController(QWidget* parent) cover_searcher_(nullptr), cover_fetcher_(nullptr), save_file_dialog_(nullptr), - cover_from_url_dialog_(nullptr) { + cover_from_url_dialog_(nullptr), + album_cover_popup_(nullptr) { cover_from_file_ = new QAction(IconLoader::Load("document-open", IconLoader::Base), tr("Load cover from disk..."), this); @@ -203,7 +204,27 @@ QString AlbumCoverChoiceController::UnsetCover(Song* song) { return cover; } +bool AlbumCoverChoiceController::ToggleCover(const Song& song) { + if (album_cover_popup_ != nullptr) { + album_cover_popup_->accept(); + album_cover_popup_ = nullptr; + return false; + } + + album_cover_popup_ = ShowCoverPrivate(song); + + // keep track of our window to prevent endless stacking + connect(album_cover_popup_, SIGNAL(finished(int)), this, + SLOT(AlbumCoverPopupClosed())); + + return true; +} + void AlbumCoverChoiceController::ShowCover(const Song& song) { + ShowCoverPrivate(song); +} + +QDialog* AlbumCoverChoiceController::ShowCoverPrivate(const Song& song) { QDialog* dialog = new QDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose, true); @@ -245,6 +266,12 @@ void AlbumCoverChoiceController::ShowCover(const Song& song) { dialog->setWindowTitle(title_text); dialog->setFixedSize(label->pixmap()->size()); dialog->show(); + + return dialog; +} + +void AlbumCoverChoiceController::AlbumCoverPopupClosed() { + album_cover_popup_ = nullptr; } void AlbumCoverChoiceController::SearchCoverAutomatically(const Song& song) { diff --git a/src/ui/albumcoverchoicecontroller.h b/src/ui/albumcoverchoicecontroller.h index c71a4f5c7..529783fcf 100644 --- a/src/ui/albumcoverchoicecontroller.h +++ b/src/ui/albumcoverchoicecontroller.h @@ -96,6 +96,7 @@ class AlbumCoverChoiceController : public QWidget { // Shows the cover of given song in it's original size. void ShowCover(const Song& song); + bool ToggleCover(const Song& song); // Search for covers automatically void SearchCoverAutomatically(const Song& song); @@ -113,14 +114,16 @@ class AlbumCoverChoiceController : public QWidget { static bool CanAcceptDrag(const QDragEnterEvent* e); -signals: + signals: void AutomaticCoverSearchDone(); private slots: void AlbumCoverFetched(quint64 id, const QImage& image, const CoverSearchStatistics& statistics); + void AlbumCoverPopupClosed(); private: + QDialog* ShowCoverPrivate(const Song& song); QString GetInitialPathForFileDialog(const Song& song, const QString& filename); @@ -144,6 +147,8 @@ signals: QAction* search_cover_auto_; QMap cover_fetching_tasks_; + + QDialog* album_cover_popup_; }; #endif // ALBUMCOVERCHOICECONTROLLER_H diff --git a/src/widgets/nowplayingwidget.cpp b/src/widgets/nowplayingwidget.cpp index b62b5b671..502a7801d 100644 --- a/src/widgets/nowplayingwidget.cpp +++ b/src/widgets/nowplayingwidget.cpp @@ -641,7 +641,7 @@ void NowPlayingWidget::UnsetCover() { } void NowPlayingWidget::ShowCover() { - album_cover_choice_controller_->ShowCover(metadata_); + album_cover_choice_controller_->ToggleCover(metadata_); } void NowPlayingWidget::SearchCoverAutomatically() {