Skip to content

Commit

Permalink
Merge branch 'feature/ISSUE4-AddNowPlayingPlaylist'
Browse files Browse the repository at this point in the history
  • Loading branch information
gvansickle committed Dec 15, 2017
2 parents bedbbdb + a2efa91 commit 4cc3053
Show file tree
Hide file tree
Showing 13 changed files with 303 additions and 35 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
3 changes: 1 addition & 2 deletions gui/CollectionDockWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
{
Expand Down
46 changes: 46 additions & 0 deletions gui/MDILibraryView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <gui/MDIPlaylistView.h>
#include <logic/LibraryModel.h>
#include <logic/PlaylistModel.h>
#include <utils/DebugHelpers.h>

MDILibraryView::MDILibraryView(QWidget* parent) : MDITreeViewBase(parent)
{
Expand All @@ -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);
Expand Down Expand Up @@ -141,13 +145,28 @@ 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("<b>Debug Info</b><hr>"
"Num items in model: %1\n"
"rowCount: %2").arg(m_underlying_model->getLibraryNumEntries()).arg(model()->rowCount()));
return true;
}

QModelIndex MDILibraryView::to_underlying_qmodelindex(const QModelIndex &proxy_index)
{
auto underlying_model_index = qobject_cast<LibrarySortFilterProxyModel*>(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<LibrarySortFilterProxyModel*>(model())->mapFromSource(underlying_index);
return proxy_model_index;
}

void MDILibraryView::addSendToMenuActions(QMenu* menu)
{
auto playlistviews = getAllMdiPlaylistViews();
Expand Down Expand Up @@ -216,6 +235,33 @@ 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());

// 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;

// Get the item that was double clicked.
auto item = m_underlying_model->getItem(underlying_model_index);

Q_ASSERT(item != nullptr);

// Send it to the "Now Playing" playlist, by way of MainWindow.
emit sendToNowPlaying(item);
}


std::vector<MDIPlaylistView*> MDILibraryView::getAllMdiPlaylistViews()
{
auto subwindows = getQMdiSubWindow()->mdiArea()->subWindowList(QMdiArea::ActivationHistoryOrder);
Expand Down
12 changes: 12 additions & 0 deletions gui/MDILibraryView.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class MDILibraryView : public MDITreeViewBase

signals:
void sendEntryToPlaylist(std::shared_ptr<LibraryEntry>, std::shared_ptr<PlaylistModel>);
void sendToNowPlaying(std::shared_ptr<LibraryEntry>);
void playTrackNowSignal(QUrl);

protected:
Expand Down Expand Up @@ -73,10 +74,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)

Expand Down
30 changes: 30 additions & 0 deletions gui/MDINowPlayingView.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2017 Gary R. Van Sickle ([email protected]).
*
* 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 <http://www.gnu.org/licenses/>.
*/

#include "MDINowPlayingView.h"

MDINowPlayingView::MDINowPlayingView(QWidget *parent) : MDIPlaylistView(parent)
{

}

QString MDINowPlayingView::getDisplayName() const
{
return "Now Playing";
}
37 changes: 37 additions & 0 deletions gui/MDINowPlayingView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2017 Gary R. Van Sickle ([email protected]).
*
* 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 <http://www.gnu.org/licenses/>.
*/

#ifndef AWESOMEMEDIALIBRARYMANAGER_MDINOWPLAYINGVIEW_H
#define AWESOMEMEDIALIBRARYMANAGER_MDINOWPLAYINGVIEW_H


#include "MDIPlaylistView.h"

class MDINowPlayingView : public MDIPlaylistView
{
Q_OBJECT

public:
MDINowPlayingView(QWidget *parent);

QString getDisplayName() const override;
};


#endif //AWESOMEMEDIALIBRARYMANAGER_MDINOWPLAYINGVIEW_H
30 changes: 30 additions & 0 deletions gui/MDIPlaylistView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ PlaylistModel* MDIPlaylistView::underlyingModel() const
return m_underlying_model;
}

//
// Public slots
//

void MDIPlaylistView::next()
{
// Forward to the QMediaPlaylist.
Expand All @@ -356,6 +360,31 @@ 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<LibraryEntry> 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<PlaylistModelItem> 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::max(0, m_underlying_model->rowCount()-1), 0));

qDebug() << "Proxy index:" << proxy_index;

// Pretend the user double-clicked on it.
emit onDoubleClicked(proxy_index);
}

void MDIPlaylistView::onContextMenu(QPoint pos)
{
M_WARNING("@todo Implement a playlist context menu.");
Expand Down Expand Up @@ -431,3 +460,4 @@ QModelIndex MDIPlaylistView::from_underlying_qmodelindex(const QModelIndex &unde
auto proxy_model_index = qobject_cast<LibrarySortFilterProxyModel*>(model())->mapFromSource(underlying_index);
return proxy_model_index;
}

17 changes: 11 additions & 6 deletions gui/MDIPlaylistView.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ 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<LibraryEntry>);

protected:

///
Expand All @@ -70,6 +76,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);

Expand All @@ -87,12 +98,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;
Expand Down
20 changes: 18 additions & 2 deletions gui/MDITreeViewBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <QAction>
#include <QHeaderView>
#include <QSaveFile>
#include <logic/LibrarySortFilterProxyModel.h>

#include "gui/NetworkAwareFileDialog.h"

Expand Down Expand Up @@ -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;
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?
}

bool MDITreeViewBase::loadFile(QUrl load_url)
Expand Down Expand Up @@ -185,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)
Expand Down
22 changes: 22 additions & 0 deletions gui/MDITreeViewBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,24 @@ 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;

/// 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;
QString m_current_filter;
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;
Expand Down Expand Up @@ -99,10 +107,24 @@ 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();

/**
* 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.
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)

Expand Down
Loading

0 comments on commit 4cc3053

Please sign in to comment.