From c7509fac9a4976b833928ce96d563ca54407af28 Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Wed, 13 Dec 2017 21:12:09 -0600 Subject: [PATCH 1/8] Added now playing members. --- gui/MainWindow.cpp | 20 +++++++++++++++----- gui/MainWindow.h | 5 +++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index ac1d1f4c..a8aabade 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -20,9 +20,6 @@ #include "FilterWidget.h" #include "MainWindow.h" #include "NetworkAwareFileDialog.h" -#if TODO -#include "SettingsDialog.h" -#endif #include "MDITreeViewBase.h" #include "MDILibraryView.h" @@ -765,8 +762,21 @@ void MainWindow::writeLibSettings(QSettings& settings) void MainWindow::loadFiles() { - /// @todo - changeIconTheme(QIcon::themeName()); + /// @todo This is doing more than loading files, rename it. + // Change the Icon Theme. + changeIconTheme(QIcon::themeName()); + + // Create the "Now Playing" playlist. + auto wins = createMdiChildPlaylist(); + m_now_playing_playlist_view = wins.first; + QMdiSubWindow* mdisubwindow = wins.second; + + m_now_playing_playlist_view->newFile(); + + setActiveSubWindow(mdisubwindow); + statusBar()->showMessage(QString("Opened new Playlist '%1'").arg(m_now_playing_playlist_view->windowTitle())); + + m_now_playing_playlist_view->show(); qDebug() << QString("Loading files from last session..."); QSettings settings; diff --git a/gui/MainWindow.h b/gui/MainWindow.h index a2aaa6f6..992ba915 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -166,6 +166,11 @@ private slots: /// The library models. std::vector> m_libmodels; + /// The "Now Playing" playlist. + QPointer m_now_playing_playlist_model; + QPointer m_now_playing_playlist_view; + + /// The list of PlaylistModels. std::vector m_playlist_models; From b66dc08da36cc6be8a754518c37613e00226c683 Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Thu, 14 Dec 2017 19:54:06 -0600 Subject: [PATCH 2/8] Interim. --- gui/MDILibraryView.cpp | 52 +++++++++++++++++++++++++++++++++++++++++ gui/MDILibraryView.h | 11 +++++++++ gui/MDIPlaylistView.h | 11 ++++----- gui/MDITreeViewBase.cpp | 11 +++++++++ gui/MDITreeViewBase.h | 6 +++++ gui/MainWindow.cpp | 18 ++++++++------ gui/MainWindow.h | 2 +- 7 files changed, 97 insertions(+), 14 deletions(-) diff --git a/gui/MDILibraryView.cpp b/gui/MDILibraryView.cpp index c10ee6a2..67e7f9f6 100644 --- a/gui/MDILibraryView.cpp +++ b/gui/MDILibraryView.cpp @@ -30,6 +30,7 @@ #include #include #include +#include MDILibraryView::MDILibraryView(QWidget* parent) : MDITreeViewBase(parent) { @@ -50,6 +51,9 @@ MDILibraryView::MDILibraryView(QWidget* parent) : MDITreeViewBase(parent) // Configure selection. setSelectionMode(QAbstractItemView::ExtendedSelection); + // Hook up double-click handler. + connect(this, &MDILibraryView::doubleClicked, this, &MDILibraryView::onDoubleClicked); + // Configure drag and drop. //// Libraries can't have items dragged around inside them. setDragEnabled(false); @@ -148,6 +152,20 @@ bool MDILibraryView::onBlankAreaToolTip(QHelpEvent* event) return true; } +QModelIndex MDILibraryView::to_underlying_qmodelindex(const QModelIndex &proxy_index) +{ + auto underlying_model_index = qobject_cast(model())->mapToSource(proxy_index); + Q_ASSERT(underlying_model_index.isValid()); + + return underlying_model_index; +} + +QModelIndex MDILibraryView::from_underlying_qmodelindex(const QModelIndex &underlying_index) +{ + auto proxy_model_index = qobject_cast(model())->mapFromSource(underlying_index); + return proxy_model_index; +} + void MDILibraryView::addSendToMenuActions(QMenu* menu) { auto playlistviews = getAllMdiPlaylistViews(); @@ -216,6 +234,40 @@ void MDILibraryView::onContextMenu(QPoint pos) } } +/** + * Handler which gets invoked by a double-click on a Library Model item. + * Sends the clicked-on item to the "Now Playing" playlist to be played. + */ +void MDILibraryView::onDoubleClicked(const QModelIndex &index) +{ + // Should always be valid. + Q_ASSERT(index.isValid()); + +M_WARNING("TODO: Fix assumptions"); + if(true) // we're the playlist connected to the player. + { + // Tell the player to start playing the song at index. + qDebug() << "Double-clicked index:" << index; + auto underlying_model_index = to_underlying_qmodelindex(index); + + Q_ASSERT(underlying_model_index.isValid()); + + qDebug() << "Underlying index:" << underlying_model_index; + + // Since m_underlying_model->qmplaylist() is connected to the player, we should only have to setCurrentIndex() to + // start the song. + /// @note See "jump()" etc in the Qt5 MediaPlyer example. + +// m_underlying_model->qmplaylist()->setCurrentIndex(underlying_model_index.row()); + + // If the player isn't already playing, the index change above won't start it. Send a signal to it to + // make sure it starts. +// emit play(); + } + +} + + std::vector MDILibraryView::getAllMdiPlaylistViews() { auto subwindows = getQMdiSubWindow()->mdiArea()->subWindowList(QMdiArea::ActivationHistoryOrder); diff --git a/gui/MDILibraryView.h b/gui/MDILibraryView.h index 063978ef..bc90c859 100644 --- a/gui/MDILibraryView.h +++ b/gui/MDILibraryView.h @@ -73,10 +73,21 @@ class MDILibraryView : public MDITreeViewBase virtual bool onBlankAreaToolTip(QHelpEvent* event) override; + /// Helper function to convert from incoming proxy QModelIndexes to actual underlying model indexes. + QModelIndex to_underlying_qmodelindex(const QModelIndex &proxy_index) override; + /// Helper function to convert from underlying model indexes to proxy QModelIndexes. + QModelIndex from_underlying_qmodelindex(const QModelIndex& underlying_index) override; + protected slots: virtual void onContextMenu(QPoint pos); + /// Invoked when user double-clicks on an entry. + /// According to Qt5 docs, index will always be valid: + /// http://doc.qt.io/qt-5/qabstractitemview.html#doubleClicked: + /// "The [doubleClicked] signal is only emitted when the index is valid." + void onDoubleClicked(const QModelIndex &index); + private: Q_DISABLE_COPY(MDILibraryView) diff --git a/gui/MDIPlaylistView.h b/gui/MDIPlaylistView.h index 5a045c2f..992c5911 100644 --- a/gui/MDIPlaylistView.h +++ b/gui/MDIPlaylistView.h @@ -70,6 +70,11 @@ public slots: /// Drag and Drop virtual void dropEvent(QDropEvent* event) override; + /// Helper function to convert from incoming proxy QModelIndexes to actual underlying model indexes. + QModelIndex to_underlying_qmodelindex(const QModelIndex &proxy_index) override; + /// Helper function to convert from underlying model indexes to proxy QModelIndexes. + QModelIndex from_underlying_qmodelindex(const QModelIndex& underlying_index) override; + protected slots: virtual void playlistPositionChanged(qint64 position); @@ -87,12 +92,6 @@ private slots: bool dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex); - /// Helper function to convert from incoming proxy QModelIndexes to actual underlying model indexes. - QModelIndex to_underlying_qmodelindex(const QModelIndex& proxy_index); - /// Helper function to convert from underlying model indexes to proxy QModelIndexes. - QModelIndex from_underlying_qmodelindex(const QModelIndex& underlying_index); - - PlaylistModel* m_underlying_model; LibrarySortFilterProxyModel* m_sortfilter_model; ItemDelegateLength* m_length_delegate; diff --git a/gui/MDITreeViewBase.cpp b/gui/MDITreeViewBase.cpp index b1df9db8..5cc8786c 100644 --- a/gui/MDITreeViewBase.cpp +++ b/gui/MDITreeViewBase.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "gui/NetworkAwareFileDialog.h" @@ -77,14 +78,24 @@ MDITreeViewBase::MDITreeViewBase(QWidget* parent) : QTreeView(parent) connect(header(), &QHeaderView::customContextMenuRequested, this, &MDITreeViewBase::headerMenu); } +/** + * Called by the MainWindow immediately after a new, empty MDI child window is created. + */ void MDITreeViewBase::newFile() { static qint64 sequenceNumber = 0; + // We don't have an actual title yet. m_isUntitled = true; + + // Create a default filename. m_current_url = QUrl(getNewFilenameTemplate().arg(sequenceNumber)); sequenceNumber += 1; + + // Set the window title to the default filename, plus the Qt "is modified" placeholder. setWindowTitle(userFriendlyCurrentFile() + "[*]"); + + /// @todo Connect a contentsChanged signal to a docWasModified slot here? } bool MDITreeViewBase::loadFile(QUrl load_url) diff --git a/gui/MDITreeViewBase.h b/gui/MDITreeViewBase.h index da8a93f1..2d992b22 100644 --- a/gui/MDITreeViewBase.h +++ b/gui/MDITreeViewBase.h @@ -103,6 +103,12 @@ protected slots: QMdiSubWindow* getQMdiSubWindow() const; + /// Helper function to convert from incoming proxy QModelIndexes to actual underlying model indexes. + virtual QModelIndex to_underlying_qmodelindex(const QModelIndex &proxy_index) = 0; + + /// Helper function to convert from underlying model indexes to proxy QModelIndexes. + virtual QModelIndex from_underlying_qmodelindex(const QModelIndex& underlying_index) = 0; + private: Q_DISABLE_COPY(MDITreeViewBase) diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index a8aabade..d9ad998d 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -132,7 +132,7 @@ M_WARNING("TODO: ifdef this to development only") setUnifiedTitleAndToolBarOnMac(true); // Send ourself a message to re-load the files we had open last time we were closed. - QTimer::singleShot(0, this, &MainWindow::loadFiles); + QTimer::singleShot(0, this, &MainWindow::onStartup); } @@ -759,11 +759,12 @@ void MainWindow::writeLibSettings(QSettings& settings) qDebug() << "writeLibSettings() end"; } - -void MainWindow::loadFiles() +/** + * Called by a "timer(0)" started in the constructor. + */ +void MainWindow::onStartup() { - /// @todo This is doing more than loading files, rename it. - // Change the Icon Theme. + // Set the Icon Theme. changeIconTheme(QIcon::themeName()); // Create the "Now Playing" playlist. @@ -774,10 +775,11 @@ void MainWindow::loadFiles() m_now_playing_playlist_view->newFile(); setActiveSubWindow(mdisubwindow); - statusBar()->showMessage(QString("Opened new Playlist '%1'").arg(m_now_playing_playlist_view->windowTitle())); + statusBar()->showMessage(QString("Opened 'Now Playing' Playlist '%1'").arg(m_now_playing_playlist_view->windowTitle())); m_now_playing_playlist_view->show(); + // Load any files which were opened at the time the last session was closed. qDebug() << QString("Loading files from last session..."); QSettings settings; readLibSettings(settings); @@ -949,7 +951,9 @@ void MainWindow::onRemoveDirFromLibrary(LibraryModel* libmodel) /// @todo ??? } -// Top-level action for creating a new, empty playlist. +/** + * Top-level menu/toolbar action for creating a new, empty playlist. + */ void MainWindow::newPlaylist() { auto wins = createMdiChildPlaylist(); diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 992ba915..c4224e89 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -124,7 +124,7 @@ private slots: /// Reads the primary settings. void readSettings(); - void loadFiles(); + void onStartup(); void openWindows(); void writeSettings(); void writeLibSettings(QSettings& settings); From 433a5fc91b3e2c4dbfc47d3d42cd0f68dc06e777 Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Thu, 14 Dec 2017 20:12:31 -0600 Subject: [PATCH 3/8] Interim. --- gui/MDILibraryView.cpp | 1 + gui/MDITreeViewBase.h | 3 +++ gui/MainWindow.cpp | 6 ++++++ gui/MainWindow.h | 2 ++ 4 files changed, 12 insertions(+) diff --git a/gui/MDILibraryView.cpp b/gui/MDILibraryView.cpp index 67e7f9f6..fec5bcd0 100644 --- a/gui/MDILibraryView.cpp +++ b/gui/MDILibraryView.cpp @@ -145,6 +145,7 @@ bool MDILibraryView::onBlankAreaToolTip(QHelpEvent* event) { // Return True if you handle it, False if you don't. // Blank-area tooltip, for debugging. +M_WARNING("TODO: Get/print library stats") QToolTip::showText(event->globalPos(), QString("Debug Info
" "Num items in model: %1\n" diff --git a/gui/MDITreeViewBase.h b/gui/MDITreeViewBase.h index 2d992b22..2f22ded6 100644 --- a/gui/MDITreeViewBase.h +++ b/gui/MDITreeViewBase.h @@ -101,6 +101,9 @@ protected slots: virtual bool maybeSave(); + /** + * Returns the QMdiSubwindow instance holding this MDITreeViewBase-derived instance. + */ QMdiSubWindow* getQMdiSubWindow() const; /// Helper function to convert from incoming proxy QModelIndexes to actual underlying model indexes. diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index d9ad998d..f4d5b2db 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -450,6 +450,11 @@ void MainWindow::connectLibraryToActivityProgressWidget(LibraryModel* lm, Activi lm->connectProgressToActivityProgressWidget(apw); } +void MainWindow::connectLibraryViewAndMainWindow(MDILibraryView *lv) +{ + //connect(); +} + void MainWindow::updateConnections() { if(activeMdiChild() != nullptr) @@ -1181,6 +1186,7 @@ void MainWindow::onStatusSignal(LibState state, qint64 current, qint64 max) #endif } + #if 0 @pyqtSlot() diff --git a/gui/MainWindow.h b/gui/MainWindow.h index c4224e89..45b93404 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -111,6 +111,8 @@ private slots: void connectPlayerControlsAndPlaylistView(PlayerControls *m_controls, MDIPlaylistView *playlist_view); void connectLibraryToActivityProgressWidget(LibraryModel* lm, ActivityProgressWidget* apw); + + void connectLibraryViewAndMainWindow(MDILibraryView* lv); ///@} void stopAllBackgroundThreads(); From 9c9f5d0b85efbdeeae16df7e15612da02f7373d0 Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Thu, 14 Dec 2017 20:24:26 -0600 Subject: [PATCH 4/8] Interim. --- gui/MDILibraryView.h | 1 + gui/MainWindow.cpp | 11 ++++++++--- gui/MainWindow.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/gui/MDILibraryView.h b/gui/MDILibraryView.h index bc90c859..c2f58755 100644 --- a/gui/MDILibraryView.h +++ b/gui/MDILibraryView.h @@ -45,6 +45,7 @@ class MDILibraryView : public MDITreeViewBase signals: void sendEntryToPlaylist(std::shared_ptr, std::shared_ptr); + void sendToNowPlaying(std::shared_ptr); void playTrackNowSignal(QUrl); protected: diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index f4d5b2db..54897d82 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -452,7 +452,8 @@ void MainWindow::connectLibraryToActivityProgressWidget(LibraryModel* lm, Activi void MainWindow::connectLibraryViewAndMainWindow(MDILibraryView *lv) { - //connect(); + connect(lv, &MDILibraryView::sendEntryToPlaylist, this, &MainWindow::onSendEntryToPlaylist); + connect(lv, &MDILibraryView::sendToNowPlaying, this, &MainWindow::onSendToNowPlaying); } void MainWindow::updateConnections() @@ -891,7 +892,7 @@ std::tuple MainWindow::createMdiChildLibraryVie auto child = new MDILibraryView(this); auto mdisubwindow = m_mdi_area->addSubWindow(child); - connect(child, &MDILibraryView::sendEntryToPlaylist, this, &MainWindow::onSendEntryToPlaylist); + connectLibraryViewAndMainWindow(child); return std::make_tuple(child, mdisubwindow); } @@ -993,6 +994,11 @@ void MainWindow::onSendEntryToPlaylist(std::shared_ptr libentry, s } } +void MainWindow::onSendToNowPlaying(std::shared_ptr libentry) +{ + Q_ASSERT(0); +} + std::pair MainWindow::createMdiChildPlaylist() { // Create a new playlist model. @@ -1186,7 +1192,6 @@ void MainWindow::onStatusSignal(LibState state, qint64 current, qint64 max) #endif } - #if 0 @pyqtSlot() diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 45b93404..6cf7cfb3 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -86,6 +86,7 @@ private slots: void onPlayTrackNowSignal(QUrl url); void onSendEntryToPlaylist(std::shared_ptr libentry, std::shared_ptr playlist_model); + void onSendToNowPlaying(std::shared_ptr libentry); void doExperiment(); From 1fa3d7a335bc32d8a668230053530e489fadf94a Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Thu, 14 Dec 2017 23:07:24 -0600 Subject: [PATCH 5/8] Adding to "Now Playing" correctly, but not starting the correct song. --- gui/MDILibraryView.cpp | 27 ++++++++++----------------- gui/MDIPlaylistView.cpp | 28 ++++++++++++++++++++++++++++ gui/MDIPlaylistView.h | 2 ++ gui/MainWindow.cpp | 11 ++++++++++- gui/MainWindow.h | 2 ++ logic/PlaylistModel.cpp | 2 +- 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/gui/MDILibraryView.cpp b/gui/MDILibraryView.cpp index fec5bcd0..bddd8e36 100644 --- a/gui/MDILibraryView.cpp +++ b/gui/MDILibraryView.cpp @@ -244,28 +244,21 @@ void MDILibraryView::onDoubleClicked(const QModelIndex &index) // Should always be valid. Q_ASSERT(index.isValid()); -M_WARNING("TODO: Fix assumptions"); - if(true) // we're the playlist connected to the player. - { - // Tell the player to start playing the song at index. - qDebug() << "Double-clicked index:" << index; - auto underlying_model_index = to_underlying_qmodelindex(index); - - Q_ASSERT(underlying_model_index.isValid()); + // Tell the player to start playing the song at index. + qDebug() << "Double-clicked index:" << index; + auto underlying_model_index = to_underlying_qmodelindex(index); - qDebug() << "Underlying index:" << underlying_model_index; + Q_ASSERT(underlying_model_index.isValid()); - // Since m_underlying_model->qmplaylist() is connected to the player, we should only have to setCurrentIndex() to - // start the song. - /// @note See "jump()" etc in the Qt5 MediaPlyer example. + qDebug() << "Underlying index:" << underlying_model_index; -// m_underlying_model->qmplaylist()->setCurrentIndex(underlying_model_index.row()); + // Get the item that was double clicked. + auto item = m_underlying_model->getItem(underlying_model_index); - // If the player isn't already playing, the index change above won't start it. Send a signal to it to - // make sure it starts. -// emit play(); - } + Q_ASSERT(item != nullptr); + // Send it to the "Now Playing" playlist, by way of MainWindow. + emit sendToNowPlaying(item); } diff --git a/gui/MDIPlaylistView.cpp b/gui/MDIPlaylistView.cpp index 877915e2..8d5d69d3 100644 --- a/gui/MDIPlaylistView.cpp +++ b/gui/MDIPlaylistView.cpp @@ -344,6 +344,10 @@ PlaylistModel* MDIPlaylistView::underlyingModel() const return m_underlying_model; } +// +// Public slots +// + void MDIPlaylistView::next() { // Forward to the QMediaPlaylist. @@ -356,6 +360,29 @@ void MDIPlaylistView::previous() m_underlying_model->qmplaylist()->previous(); } +/** + * Slot which appends the incoming library entry and starts playing it. + */ +void MDIPlaylistView::onSendToNowPlaying(std::shared_ptr new_libentry) +{ +M_WARNING("TODO: Dedup") + + // We first need to convert the LibraryEntry to a PlaylistModelItem. + // Create a new PlaylistModelItem to put in the model. + std::shared_ptr new_playlist_entry = PlaylistModelItem::createFromLibraryEntry(new_libentry); + +Q_ASSERT(new_playlist_entry != nullptr); + + // Append to underlying model. + m_underlying_model->appendRow(new_playlist_entry); + + // Find the last row of the underlying model in top-proxy-model coordinates. + auto proxy_index = from_underlying_qmodelindex(m_underlying_model->index(std::min(0, m_underlying_model->rowCount()-1), 0)); + + // Pretend the user double-clicked on it. + emit onDoubleClicked(proxy_index); +} + void MDIPlaylistView::onContextMenu(QPoint pos) { M_WARNING("@todo Implement a playlist context menu."); @@ -431,3 +458,4 @@ QModelIndex MDIPlaylistView::from_underlying_qmodelindex(const QModelIndex &unde auto proxy_model_index = qobject_cast(model())->mapFromSource(underlying_index); return proxy_model_index; } + diff --git a/gui/MDIPlaylistView.h b/gui/MDIPlaylistView.h index 992c5911..07792128 100644 --- a/gui/MDIPlaylistView.h +++ b/gui/MDIPlaylistView.h @@ -50,6 +50,8 @@ public slots: void next(); void previous(); + void onSendToNowPlaying(std::shared_ptr); + protected: /// diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 54897d82..81bb78d2 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -456,6 +456,11 @@ void MainWindow::connectLibraryViewAndMainWindow(MDILibraryView *lv) connect(lv, &MDILibraryView::sendToNowPlaying, this, &MainWindow::onSendToNowPlaying); } +void MainWindow::connectNowPlayingViewAndMainWindow(MDIPlaylistView* plv) +{ + connect(this, &MainWindow::sendToNowPlaying, plv, &MDIPlaylistView::onSendToNowPlaying); +} + void MainWindow::updateConnections() { if(activeMdiChild() != nullptr) @@ -778,8 +783,11 @@ void MainWindow::onStartup() m_now_playing_playlist_view = wins.first; QMdiSubWindow* mdisubwindow = wins.second; +M_WARNING("TODO: Specify a temp/cache file?") m_now_playing_playlist_view->newFile(); + connectNowPlayingViewAndMainWindow(m_now_playing_playlist_view); + setActiveSubWindow(mdisubwindow); statusBar()->showMessage(QString("Opened 'Now Playing' Playlist '%1'").arg(m_now_playing_playlist_view->windowTitle())); @@ -996,7 +1004,8 @@ void MainWindow::onSendEntryToPlaylist(std::shared_ptr libentry, s void MainWindow::onSendToNowPlaying(std::shared_ptr libentry) { - Q_ASSERT(0); + // Resend the entry to the "Now Playing" playlist view. + emit sendToNowPlaying(libentry); } std::pair MainWindow::createMdiChildPlaylist() diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 6cf7cfb3..1146cfc8 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -58,6 +58,7 @@ class MainWindow: public QMainWindow ~MainWindow() override; signals: + void sendToNowPlaying(std::shared_ptr); protected: void closeEvent(QCloseEvent* event) override; @@ -114,6 +115,7 @@ private slots: void connectLibraryToActivityProgressWidget(LibraryModel* lm, ActivityProgressWidget* apw); void connectLibraryViewAndMainWindow(MDILibraryView* lv); + void connectNowPlayingViewAndMainWindow(MDIPlaylistView* plv); ///@} void stopAllBackgroundThreads(); diff --git a/logic/PlaylistModel.cpp b/logic/PlaylistModel.cpp index 5221f78a..0b3c9f19 100644 --- a/logic/PlaylistModel.cpp +++ b/logic/PlaylistModel.cpp @@ -131,7 +131,7 @@ std::shared_ptr PlaylistModel::getItem(const QModelIndex& index) c auto playlist_model_item = std::dynamic_pointer_cast(libmodel_item); if(!playlist_model_item) { - qCritical() << "LibraryModelItem not a PlaylistModelItem"; + qCritical() << "libmodel_item not a PlaylistModelItem"; } Q_ASSERT(playlist_model_item != nullptr); From 10e91a3d293e49d8e97f08deffd860883d6cbcf1 Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Thu, 14 Dec 2017 23:13:15 -0600 Subject: [PATCH 6/8] Now starting the correct song. --- gui/MDIPlaylistView.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/MDIPlaylistView.cpp b/gui/MDIPlaylistView.cpp index 8d5d69d3..012ba911 100644 --- a/gui/MDIPlaylistView.cpp +++ b/gui/MDIPlaylistView.cpp @@ -377,7 +377,9 @@ Q_ASSERT(new_playlist_entry != nullptr); m_underlying_model->appendRow(new_playlist_entry); // Find the last row of the underlying model in top-proxy-model coordinates. - auto proxy_index = from_underlying_qmodelindex(m_underlying_model->index(std::min(0, m_underlying_model->rowCount()-1), 0)); + auto proxy_index = from_underlying_qmodelindex(m_underlying_model->index(std::max(0, m_underlying_model->rowCount()-1), 0)); + + qDebug() << "Proxy index:" << proxy_index; // Pretend the user double-clicked on it. emit onDoubleClicked(proxy_index); From 15fd5112de543e0268d7093b8f6ad02e8f2f42fb Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Fri, 15 Dec 2017 00:06:35 -0600 Subject: [PATCH 7/8] Initial commit of MDINowPlayingView. Hooked up and working. --- CMakeLists.txt | 2 +- gui/MDINowPlayingView.cpp | 25 +++++++++++++++++++ gui/MDINowPlayingView.h | 35 +++++++++++++++++++++++++++ gui/MDIPlaylistView.h | 4 +++ gui/MDITreeViewBase.h | 9 +++++++ gui/MainWindow.cpp | 51 +++++++++++++++++++++++++++++---------- gui/MainWindow.h | 2 ++ 7 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 gui/MDINowPlayingView.cpp create mode 100644 gui/MDINowPlayingView.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 69e08e45..158b2d30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -323,7 +323,7 @@ set(SOURCE_FILES gui/settings/SettingsDialog.cpp gui/settings/SettingsDialogPageBase.cpp gui/settings/SettingsDialogPageBase.h gui/settings/SDPageAppearance.cpp gui/settings/SDPageAppearance.h - gui/settings/SettingsDialogSideWidget.cpp gui/settings/SDPageLibrary.cpp gui/settings/SDPageLibrary.h) + gui/settings/SettingsDialogSideWidget.cpp gui/settings/SDPageLibrary.cpp gui/settings/SDPageLibrary.h gui/MDINowPlayingView.cpp gui/MDINowPlayingView.h) # This function sets up the variable META_FILES_TO_INCLUDE to the extra files # needed for a windows build (essentially just the configured .rc file). diff --git a/gui/MDINowPlayingView.cpp b/gui/MDINowPlayingView.cpp new file mode 100644 index 00000000..ed79a97c --- /dev/null +++ b/gui/MDINowPlayingView.cpp @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Gary R. Van Sickle (grvs@users.sourceforge.net). + * + * This file is part of AwesomeMediaLibraryManager. + * + * AwesomeMediaLibraryManager 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. + * + * AwesomeMediaLibraryManager 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 AwesomeMediaLibraryManager. If not, see . + */ + +#include "MDINowPlayingView.h" + +MDINowPlayingView::MDINowPlayingView(QWidget *parent) : MDIPlaylistView(parent) +{ + +} diff --git a/gui/MDINowPlayingView.h b/gui/MDINowPlayingView.h new file mode 100644 index 00000000..933c5b6a --- /dev/null +++ b/gui/MDINowPlayingView.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Gary R. Van Sickle (grvs@users.sourceforge.net). + * + * This file is part of AwesomeMediaLibraryManager. + * + * AwesomeMediaLibraryManager 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. + * + * AwesomeMediaLibraryManager 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 AwesomeMediaLibraryManager. If not, see . + */ + +#ifndef AWESOMEMEDIALIBRARYMANAGER_MDINOWPLAYINGVIEW_H +#define AWESOMEMEDIALIBRARYMANAGER_MDINOWPLAYINGVIEW_H + + +#include "MDIPlaylistView.h" + +class MDINowPlayingView : public MDIPlaylistView +{ + Q_OBJECT + +public: + MDINowPlayingView(QWidget *parent); +}; + + +#endif //AWESOMEMEDIALIBRARYMANAGER_MDINOWPLAYINGVIEW_H diff --git a/gui/MDIPlaylistView.h b/gui/MDIPlaylistView.h index 07792128..8cb9a58a 100644 --- a/gui/MDIPlaylistView.h +++ b/gui/MDIPlaylistView.h @@ -50,6 +50,10 @@ public slots: void next(); void previous(); + /** + * Slot which appends the incoming library entry and starts playing it. + * Intended for use primarily on the single "Now Playing" playlist. + */ void onSendToNowPlaying(std::shared_ptr); protected: diff --git a/gui/MDITreeViewBase.h b/gui/MDITreeViewBase.h index 2f22ded6..0786ed38 100644 --- a/gui/MDITreeViewBase.h +++ b/gui/MDITreeViewBase.h @@ -45,7 +45,10 @@ class MDITreeViewBase : public QTreeView bool saveAs(); bool saveFile(QUrl save_url, QString filter); + /// Returns the current basename of this window's backing file. QString userFriendlyCurrentFile() const; + + /// Returns the full URL of this window's backing file. QUrl getCurrentUrl() const; protected: @@ -55,6 +58,7 @@ class MDITreeViewBase : public QTreeView bool m_isUntitled = true; /// Protected function which is used to set the view's filename properties on a save or load. + /// Called by loadFile() and saveFile(). void setCurrentFile(QUrl url); virtual void closeEvent(QCloseEvent* event) override; @@ -99,6 +103,11 @@ protected slots: /// Return True if you handle it, False if you don't. virtual bool onBlankAreaToolTip(QHelpEvent* event); + /** + * Called by closeEvent(). If document shows as modified, pops up a "Do you want to save?" box, + * then calls save() or not depending on the user's choice. + * @return false if file was modified and user cancelled, true otherwise. + */ virtual bool maybeSave(); /** diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 81bb78d2..5a5111ee 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -459,6 +459,9 @@ void MainWindow::connectLibraryViewAndMainWindow(MDILibraryView *lv) void MainWindow::connectNowPlayingViewAndMainWindow(MDIPlaylistView* plv) { connect(this, &MainWindow::sendToNowPlaying, plv, &MDIPlaylistView::onSendToNowPlaying); + + connectPlayerAndPlaylistView(&m_player, plv); + connectPlayerControlsAndPlaylistView(m_controls, plv); } void MainWindow::updateConnections() @@ -473,26 +476,23 @@ void MainWindow::updateConnections() if(childIsLibrary != nullptr) { auto connection_handle = connect(activeMdiChild()->selectionModel(), &QItemSelectionModel::selectionChanged, - m_metadataDockWidget, &MetadataDockWidget::playlistSelectionChanged, - Qt::ConnectionType(Qt::AutoConnection | Qt::UniqueConnection)); - if(!connection_handle) + m_metadataDockWidget, &MetadataDockWidget::playlistSelectionChanged, + Qt::ConnectionType(Qt::AutoConnection | Qt::UniqueConnection)); + if (!connection_handle) { qDebug() << "Connection failed: already connected?"; } - connection_handle = connect(childIsLibrary, &MDILibraryView::playTrackNowSignal, - this, &MainWindow::onPlayTrackNowSignal, Qt::ConnectionType(Qt::AutoConnection | Qt::UniqueConnection)); - if(!connection_handle) + connection_handle = connect(childIsLibrary, + &MDILibraryView::playTrackNowSignal, + this, + &MainWindow::onPlayTrackNowSignal, + Qt::ConnectionType(Qt::AutoConnection | Qt::UniqueConnection)); + if (!connection_handle) { qDebug() << "Connection failed: already connected?"; } } - - if(childIsPlaylist != nullptr) - { - connectPlayerAndPlaylistView(&m_player, childIsPlaylist); - connectPlayerControlsAndPlaylistView(m_controls, childIsPlaylist); - } } } @@ -779,7 +779,7 @@ void MainWindow::onStartup() changeIconTheme(QIcon::themeName()); // Create the "Now Playing" playlist. - auto wins = createMdiChildPlaylist(); + auto wins = createMdiNowPlayingView(); m_now_playing_playlist_view = wins.first; QMdiSubWindow* mdisubwindow = wins.second; @@ -1031,6 +1031,31 @@ std::pair MainWindow::createMdiChildPlaylist() return std::make_pair(child, mdisubwindow); } +std::pair MainWindow::createMdiNowPlayingView() +{ + // Create a new "Now Playing" playlist model. + auto new_playlist_model = new PlaylistModel(this); + + // TODO REMOVE + m_playlist_models.push_back(new_playlist_model); + m_now_playing_playlist_model = new_playlist_model; + + MDINowPlayingView* child = new MDINowPlayingView(this); + child->setModel(new_playlist_model); + auto mdisubwindow = m_mdi_area->addSubWindow(child); + + // child.undoAvailable.connect(editUndoAct.setEnabled) + // child.redoAvailable.connect(redoAct.setEnabled) + // child.copyAvailable.connect(cutAct.setEnabled) + // child.copyAvailable.connect(copyAct.setEnabled) + + // Connect signals. + //child.cursorPositionChanged.connect(cursorPosChanged) + + // Add the new playlist to the collection doc widget. + m_libraryDockWidget->addPlaylist(new PlaylistItem(child)); + return std::make_pair(child, mdisubwindow); +} // Top-level "saveAs" action handler for "Save playlist as..." void MainWindow::savePlaylistAs() diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 1146cfc8..b3154e55 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -22,6 +22,7 @@ #include "MDIPlaylistView.h" #include "MDITreeViewBase.h" #include "PlayerControls.h" +#include "MDINowPlayingView.h" #include #include @@ -144,6 +145,7 @@ private slots: MDITreeViewBase* activeMdiChild(); QMdiSubWindow* findSubWindow(QUrl url); std::pair createMdiChildPlaylist(); + std::pair createMdiNowPlayingView(); QSharedPointer openLibraryModelOnUrl(QUrl url); void openMDILibraryViewOnModel(LibraryModel* libmodel); From a2efa9149d8b6047fdffd1872d80de1a53a783b7 Mon Sep 17 00:00:00 2001 From: "Gary R. Van Sickle" Date: Fri, 15 Dec 2017 00:25:51 -0600 Subject: [PATCH 8/8] Seems to be working well. --- gui/CollectionDockWidget.h | 3 +-- gui/MDINowPlayingView.cpp | 5 +++++ gui/MDINowPlayingView.h | 2 ++ gui/MDITreeViewBase.cpp | 11 ++++++++--- gui/MDITreeViewBase.h | 4 ++++ 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/gui/CollectionDockWidget.h b/gui/CollectionDockWidget.h index e15dfce3..e809fbdf 100644 --- a/gui/CollectionDockWidget.h +++ b/gui/CollectionDockWidget.h @@ -72,7 +72,6 @@ class PlaylistItem: public QStandardItem public: PlaylistItem(MDIPlaylistView* view) { - //playlist_model: PlaylistModel = model; playlist_view = view; setData(QIcon::fromTheme("folder"), Qt::DecorationRole); @@ -83,7 +82,7 @@ class PlaylistItem: public QStandardItem // Get the data we need from the model we're connected to if(role == Qt::EditRole || role == Qt::DisplayRole) { - return QVariant(playlist_view->userFriendlyCurrentFile()); + return QVariant(playlist_view->getDisplayName()); } else if(role == Qt::ToolTipRole) { diff --git a/gui/MDINowPlayingView.cpp b/gui/MDINowPlayingView.cpp index ed79a97c..20f89bdb 100644 --- a/gui/MDINowPlayingView.cpp +++ b/gui/MDINowPlayingView.cpp @@ -23,3 +23,8 @@ MDINowPlayingView::MDINowPlayingView(QWidget *parent) : MDIPlaylistView(parent) { } + +QString MDINowPlayingView::getDisplayName() const +{ + return "Now Playing"; +} diff --git a/gui/MDINowPlayingView.h b/gui/MDINowPlayingView.h index 933c5b6a..1fe63fc0 100644 --- a/gui/MDINowPlayingView.h +++ b/gui/MDINowPlayingView.h @@ -29,6 +29,8 @@ class MDINowPlayingView : public MDIPlaylistView public: MDINowPlayingView(QWidget *parent); + + QString getDisplayName() const override; }; diff --git a/gui/MDITreeViewBase.cpp b/gui/MDITreeViewBase.cpp index 5cc8786c..6d108a42 100644 --- a/gui/MDITreeViewBase.cpp +++ b/gui/MDITreeViewBase.cpp @@ -92,8 +92,8 @@ static qint64 sequenceNumber = 0; m_current_url = QUrl(getNewFilenameTemplate().arg(sequenceNumber)); sequenceNumber += 1; - // Set the window title to the default filename, plus the Qt "is modified" placeholder. - setWindowTitle(userFriendlyCurrentFile() + "[*]"); + // Set the window title to the Display Name, which defaults to the filename, plus the Qt "is modified" placeholder. + setWindowTitle(getDisplayName() + "[*]"); /// @todo Connect a contentsChanged signal to a docWasModified slot here? } @@ -196,7 +196,12 @@ void MDITreeViewBase::setCurrentFile(QUrl url) m_isUntitled = false; setWindowFilePath(url.toString()); setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); + setWindowTitle(getDisplayName() + "[*]"); +} + +QString MDITreeViewBase::getDisplayName() const +{ + return userFriendlyCurrentFile(); } void MDITreeViewBase::closeEvent(QCloseEvent* event) diff --git a/gui/MDITreeViewBase.h b/gui/MDITreeViewBase.h index 0786ed38..9b15568d 100644 --- a/gui/MDITreeViewBase.h +++ b/gui/MDITreeViewBase.h @@ -51,6 +51,10 @@ class MDITreeViewBase : public QTreeView /// Returns the full URL of this window's backing file. QUrl getCurrentUrl() const; + /// Returns the name to be displayed as this view's windowTitle(), e.g. in tabs. + /// Default implementation returns userFriendlyCurrentFile(). + virtual QString getDisplayName() const; + protected: QUrl m_current_url;