From eb5cf7eeb9c6a34e8973858af6e84b6942cdbb26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Thu, 28 May 2015 20:35:34 +0200 Subject: [PATCH 01/24] Highlight Crates a Track is in. Still some work to do --- build/depends.py | 1 + src/library/backgroundcolordelegate.cpp | 28 +++++++++++++++++++++++++ src/library/backgroundcolordelegate.h | 12 +++++++++++ src/library/cratefeature.cpp | 18 ++++++++++++++-- src/library/cratefeature.h | 11 +++++++++- src/library/dao/cratedao.cpp | 14 +++++++++++++ src/library/dao/cratedao.h | 1 + src/library/libraryfeature.h | 3 +++ src/widget/wlibrarysidebar.cpp | 3 +++ src/widget/wlibrarysidebar.h | 2 ++ 10 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/library/backgroundcolordelegate.cpp create mode 100644 src/library/backgroundcolordelegate.h diff --git a/build/depends.py b/build/depends.py index 38e9fdf07e79..136956e22c85 100644 --- a/build/depends.py +++ b/build/depends.py @@ -743,6 +743,7 @@ def sources(self, build): "library/baseplaylistfeature.cpp", "library/playlistfeature.cpp", "library/setlogfeature.cpp", + "library/backgroundcolordelegate.cpp", "library/browse/browsetablemodel.cpp", "library/browse/browsethread.cpp", diff --git a/src/library/backgroundcolordelegate.cpp b/src/library/backgroundcolordelegate.cpp new file mode 100644 index 000000000000..29a732c0b969 --- /dev/null +++ b/src/library/backgroundcolordelegate.cpp @@ -0,0 +1,28 @@ +#include "library/backgroundcolordelegate.h" +#include "library/treeitem.h" +#include "trackinfoobject.h" +#include "libraryfeature.h" +#include "cratefeature.h" + + +void BackgroundColorDelegate::initStyleOption(QStyleOptionViewItem *option, + const QModelIndex &index) const{ + QStyledItemDelegate::initStyleOption(option, index); + QStyleOptionViewItemV4 *optionV4 = qstyleoption_cast(option); + + TreeItem *item = static_cast(index.internalPointer()); + LibraryFeature* pFeature = static_cast(item->getFeature()); + if (pFeature){ + TrackPointer pTrack = pFeature->getSelectedTrack(); + if (pTrack){ + CrateFeature* pCrateFeature = static_cast(pFeature); + if (pCrateFeature){ + if (pCrateFeature->getCrateDao().isTrackInCrate(pTrack->getId(), item->dataPath().toInt())){ + optionV4->font.setBold(true); + //Todo: now trigger repaint of the widget so that it will be applyed + } + } + + } + } +} diff --git a/src/library/backgroundcolordelegate.h b/src/library/backgroundcolordelegate.h new file mode 100644 index 000000000000..518eb4379171 --- /dev/null +++ b/src/library/backgroundcolordelegate.h @@ -0,0 +1,12 @@ +#include + +class BackgroundColorDelegate : public QStyledItemDelegate { + +public: + BackgroundColorDelegate(QObject *parent = 0) + : QStyledItemDelegate(parent) + { + } + + void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const; +}; diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index 99c3aafaf646..d27bbcd8266a 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -24,14 +24,13 @@ #include "util/dnd.h" #include "util/time.h" -CrateFeature::CrateFeature(QObject* parent, +CrateFeature::CrateFeature(Library* pLibrary, TrackCollection* pTrackCollection, ConfigObject* pConfig) : m_pTrackCollection(pTrackCollection), m_crateDao(pTrackCollection->getCrateDAO()), m_crateTableModel(this, pTrackCollection), m_pConfig(pConfig) { - Q_UNUSED(parent); m_pCreateCrateAction = new QAction(tr("Create New Crate"),this); connect(m_pCreateCrateAction, SIGNAL(triggered()), this, SLOT(slotCreateCrate())); @@ -92,6 +91,9 @@ CrateFeature::CrateFeature(QObject* parent, TreeItem *rootItem = new TreeItem(); m_childModel.setRootItem(rootItem); constructChildModel(-1); + + connect(pLibrary, SIGNAL(trackSelected(TrackPointer)), + this, SLOT(slotTrackSelected(TrackPointer))); } CrateFeature::~CrateFeature() { @@ -705,3 +707,15 @@ QString CrateFeature::getRootViewHtml() const { html.append(""); return html; } + +TrackPointer CrateFeature::getSelectedTrack() { + return this->m_pSelectedTrack; +} + +CrateDAO& CrateFeature::getCrateDao() { + return m_crateDao; +} + +void CrateFeature::slotTrackSelected(TrackPointer pTrack) { + m_pSelectedTrack = pTrack; +} diff --git a/src/library/cratefeature.h b/src/library/cratefeature.h index 1a77807889df..7c71c1255426 100644 --- a/src/library/cratefeature.h +++ b/src/library/cratefeature.h @@ -12,16 +12,18 @@ #include "library/libraryfeature.h" #include "library/cratetablemodel.h" +#include "library/library.h" #include "treeitemmodel.h" #include "configobject.h" +#include "trackinfoobject.h" class TrackCollection; class CrateFeature : public LibraryFeature { Q_OBJECT public: - CrateFeature(QObject* parent, + CrateFeature(Library* pLibrary, TrackCollection* pTrackCollection, ConfigObject* pConfig); virtual ~CrateFeature(); @@ -38,6 +40,9 @@ class CrateFeature : public LibraryFeature { TreeItemModel* getChildModel(); + TrackPointer getSelectedTrack(); + CrateDAO& getCrateDao(); + signals: void analyzeTracks(QList); @@ -85,6 +90,10 @@ class CrateFeature : public LibraryFeature { QModelIndex m_lastRightClickedIndex; TreeItemModel m_childModel; ConfigObject* m_pConfig; + TrackPointer m_pSelectedTrack; + + private slots: + void slotTrackSelected(TrackPointer pTrack); }; #endif /* CRATEFEATURE_H */ diff --git a/src/library/dao/cratedao.cpp b/src/library/dao/cratedao.cpp index 0b07fbcdec1f..64b6909811f6 100644 --- a/src/library/dao/cratedao.cpp +++ b/src/library/dao/cratedao.cpp @@ -422,3 +422,17 @@ void CrateDAO::removeTracksFromCrates(const QList& ids) { // emit(trackRemoved(crateId, trackId)); // emit(changed(crateId)); } + +bool CrateDAO::isTrackInCrate(const int trackId, const int crateId) { + QSqlQuery query(m_database); + query.prepare("SELECT track_id FROM " CRATE_TRACKS_TABLE " WHERE " + "crate_id = :crate_id AND track_id = :track_id"); + query.bindValue(":crate_id", crateId); + query.bindValue(":track_id", trackId); + + if (!query.exec()) { + LOG_FAILED_QUERY(query); + return false; + } + return query.next(); +} diff --git a/src/library/dao/cratedao.h b/src/library/dao/cratedao.h index dcef3ad05ba4..7a4befc121e4 100644 --- a/src/library/dao/cratedao.h +++ b/src/library/dao/cratedao.h @@ -61,6 +61,7 @@ class CrateDAO : public QObject, public virtual DAO { bool removeTracksFromCrate(const QList& ids, const int crateId); // remove tracks from all crates void removeTracksFromCrates(const QList& ids); + bool isTrackInCrate(const int trackId, const int crateId); signals: void added(int crateId); diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index b353cc3b5e9e..9f45c9f324ec 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -58,6 +58,9 @@ class LibraryFeature : public QObject { virtual void bindWidget(WLibrary* /* libraryWidget */, MixxxKeyboard* /* keyboard */) {} virtual TreeItemModel* getChildModel() = 0; + virtual TrackPointer getSelectedTrack(){ + return TrackPointer(); + }; public slots: // called when you single click on the root item diff --git a/src/widget/wlibrarysidebar.cpp b/src/widget/wlibrarysidebar.cpp index a32f02173205..6d3c5617dc21 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -27,6 +27,9 @@ WLibrarySidebar::WLibrarySidebar(QWidget* parent) header()->setStretchLastSection(false); header()->setResizeMode(QHeaderView::ResizeToContents); header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); + + m_delegate = new BackgroundColorDelegate(); + this->setItemDelegate(m_delegate); } WLibrarySidebar::~WLibrarySidebar() { diff --git a/src/widget/wlibrarysidebar.h b/src/widget/wlibrarysidebar.h index 6c8c538cdebe..c395d2403a08 100644 --- a/src/widget/wlibrarysidebar.h +++ b/src/widget/wlibrarysidebar.h @@ -13,6 +13,7 @@ #include #include "widget/wbasewidget.h" +#include "library/backgroundcolordelegate.h" class WLibrarySidebar : public QTreeView, public WBaseWidget { Q_OBJECT @@ -41,6 +42,7 @@ class WLibrarySidebar : public QTreeView, public WBaseWidget { private: QBasicTimer m_expandTimer; QModelIndex m_hoverIndex; + BackgroundColorDelegate *m_delegate; }; #endif /* WLIBRARYSIDEBAR_H */ From 3832e4110242ef21122083ad61fee37149200f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Thu, 28 May 2015 20:47:43 +0200 Subject: [PATCH 02/24] Rename delegate according to his function --- build/depends.py | 2 +- ...backgroundcolordelegate.cpp => cratehighlightdelegate.cpp} | 4 ++-- .../{backgroundcolordelegate.h => cratehighlightdelegate.h} | 4 ++-- src/widget/wlibrarysidebar.cpp | 2 +- src/widget/wlibrarysidebar.h | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) rename src/library/{backgroundcolordelegate.cpp => cratehighlightdelegate.cpp} (89%) rename src/library/{backgroundcolordelegate.h => cratehighlightdelegate.h} (62%) diff --git a/build/depends.py b/build/depends.py index 136956e22c85..633265cbf803 100644 --- a/build/depends.py +++ b/build/depends.py @@ -743,7 +743,7 @@ def sources(self, build): "library/baseplaylistfeature.cpp", "library/playlistfeature.cpp", "library/setlogfeature.cpp", - "library/backgroundcolordelegate.cpp", + "library/cratehighlightdelegate.cpp", "library/browse/browsetablemodel.cpp", "library/browse/browsethread.cpp", diff --git a/src/library/backgroundcolordelegate.cpp b/src/library/cratehighlightdelegate.cpp similarity index 89% rename from src/library/backgroundcolordelegate.cpp rename to src/library/cratehighlightdelegate.cpp index 29a732c0b969..f214d338732e 100644 --- a/src/library/backgroundcolordelegate.cpp +++ b/src/library/cratehighlightdelegate.cpp @@ -1,11 +1,11 @@ -#include "library/backgroundcolordelegate.h" +#include "library/cratehighlightdelegate.h" #include "library/treeitem.h" #include "trackinfoobject.h" #include "libraryfeature.h" #include "cratefeature.h" -void BackgroundColorDelegate::initStyleOption(QStyleOptionViewItem *option, +void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const{ QStyledItemDelegate::initStyleOption(option, index); QStyleOptionViewItemV4 *optionV4 = qstyleoption_cast(option); diff --git a/src/library/backgroundcolordelegate.h b/src/library/cratehighlightdelegate.h similarity index 62% rename from src/library/backgroundcolordelegate.h rename to src/library/cratehighlightdelegate.h index 518eb4379171..098c4b366412 100644 --- a/src/library/backgroundcolordelegate.h +++ b/src/library/cratehighlightdelegate.h @@ -1,9 +1,9 @@ #include -class BackgroundColorDelegate : public QStyledItemDelegate { +class CrateHighlightDelegate : public QStyledItemDelegate { public: - BackgroundColorDelegate(QObject *parent = 0) + CrateHighlightDelegate(QObject *parent = 0) : QStyledItemDelegate(parent) { } diff --git a/src/widget/wlibrarysidebar.cpp b/src/widget/wlibrarysidebar.cpp index 6d3c5617dc21..28cb1b9e60d7 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -28,7 +28,7 @@ WLibrarySidebar::WLibrarySidebar(QWidget* parent) header()->setResizeMode(QHeaderView::ResizeToContents); header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); - m_delegate = new BackgroundColorDelegate(); + m_delegate = new CrateHighlightDelegate(); this->setItemDelegate(m_delegate); } diff --git a/src/widget/wlibrarysidebar.h b/src/widget/wlibrarysidebar.h index c395d2403a08..fdab0fe3c028 100644 --- a/src/widget/wlibrarysidebar.h +++ b/src/widget/wlibrarysidebar.h @@ -13,7 +13,7 @@ #include #include "widget/wbasewidget.h" -#include "library/backgroundcolordelegate.h" +#include "library/cratehighlightdelegate.h" class WLibrarySidebar : public QTreeView, public WBaseWidget { Q_OBJECT @@ -42,7 +42,7 @@ class WLibrarySidebar : public QTreeView, public WBaseWidget { private: QBasicTimer m_expandTimer; QModelIndex m_hoverIndex; - BackgroundColorDelegate *m_delegate; + CrateHighlightDelegate *m_delegate; }; #endif /* WLIBRARYSIDEBAR_H */ From dccb51974c4583af918d14f461d8a2e67271169e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 12:36:38 +0200 Subject: [PATCH 03/24] Highlighting crates the selected track is in works now --- src/library/cratefeature.cpp | 12 +++++++----- src/library/cratefeature.h | 2 +- src/library/cratehighlightdelegate.cpp | 23 +++++++++++------------ src/library/cratehighlightdelegate.h | 4 ++-- src/library/dao/cratedao.cpp | 1 + src/library/libraryfeature.h | 8 ++++++-- src/library/treeitemmodel.cpp | 6 ++++++ src/library/treeitemmodel.h | 2 ++ src/widget/wlibrarysidebar.cpp | 2 +- 9 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index d27bbcd8266a..54f475919aed 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -118,6 +118,11 @@ QIcon CrateFeature::getIcon() { return QIcon(":/images/library/ic_library_crates.png"); } +bool CrateFeature::isTrackInChildModel(const int trackId, + const QVariant dataPath) { + return m_crateDao.isTrackInCrate(trackId, dataPath.toInt()); +} + int CrateFeature::crateIdFromIndex(QModelIndex index) { TreeItem* item = static_cast(index.internalPointer()); if (item == NULL) { @@ -709,13 +714,10 @@ QString CrateFeature::getRootViewHtml() const { } TrackPointer CrateFeature::getSelectedTrack() { - return this->m_pSelectedTrack; -} - -CrateDAO& CrateFeature::getCrateDao() { - return m_crateDao; + return m_pSelectedTrack; } void CrateFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; + m_childModel.triggerRepaint(); } diff --git a/src/library/cratefeature.h b/src/library/cratefeature.h index 7c71c1255426..000389e0a4be 100644 --- a/src/library/cratefeature.h +++ b/src/library/cratefeature.h @@ -41,7 +41,7 @@ class CrateFeature : public LibraryFeature { TreeItemModel* getChildModel(); TrackPointer getSelectedTrack(); - CrateDAO& getCrateDao(); + virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath); signals: void analyzeTracks(QList); diff --git a/src/library/cratehighlightdelegate.cpp b/src/library/cratehighlightdelegate.cpp index f214d338732e..8af0c687fe53 100644 --- a/src/library/cratehighlightdelegate.cpp +++ b/src/library/cratehighlightdelegate.cpp @@ -5,24 +5,23 @@ #include "cratefeature.h" -void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem *option, - const QModelIndex &index) const{ +void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem* option, + const QModelIndex& index) const{ + if (!index.isValid()){ + return; + } + QStyledItemDelegate::initStyleOption(option, index); QStyleOptionViewItemV4 *optionV4 = qstyleoption_cast(option); TreeItem *item = static_cast(index.internalPointer()); - LibraryFeature* pFeature = static_cast(item->getFeature()); - if (pFeature){ + LibraryFeature* pFeature = item->getFeature(); + if (pFeature) { TrackPointer pTrack = pFeature->getSelectedTrack(); - if (pTrack){ - CrateFeature* pCrateFeature = static_cast(pFeature); - if (pCrateFeature){ - if (pCrateFeature->getCrateDao().isTrackInCrate(pTrack->getId(), item->dataPath().toInt())){ - optionV4->font.setBold(true); - //Todo: now trigger repaint of the widget so that it will be applyed - } + if (pTrack) { + if (pFeature->isTrackInChildModel(pTrack->getId(), item->dataPath())){ + optionV4->font.setBold(true); } - } } } diff --git a/src/library/cratehighlightdelegate.h b/src/library/cratehighlightdelegate.h index 098c4b366412..001b4934663f 100644 --- a/src/library/cratehighlightdelegate.h +++ b/src/library/cratehighlightdelegate.h @@ -3,10 +3,10 @@ class CrateHighlightDelegate : public QStyledItemDelegate { public: - CrateHighlightDelegate(QObject *parent = 0) + CrateHighlightDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) { } - void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const; + void initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const; }; diff --git a/src/library/dao/cratedao.cpp b/src/library/dao/cratedao.cpp index 64b6909811f6..59a3b7fef0d1 100644 --- a/src/library/dao/cratedao.cpp +++ b/src/library/dao/cratedao.cpp @@ -434,5 +434,6 @@ bool CrateDAO::isTrackInCrate(const int trackId, const int crateId) { LOG_FAILED_QUERY(query); return false; } + // query.next() is null if the result was empty which will lead to false as needed. return query.next(); } diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index 9f45c9f324ec..9d8bcb443c3c 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -60,7 +60,12 @@ class LibraryFeature : public QObject { virtual TreeItemModel* getChildModel() = 0; virtual TrackPointer getSelectedTrack(){ return TrackPointer(); - }; + } + virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath){ + Q_UNUSED(trackId); + Q_UNUSED(dataPath); + return false; + } public slots: // called when you single click on the root item @@ -98,7 +103,6 @@ class LibraryFeature : public QObject { void featureSelect(LibraryFeature* pFeature, const QModelIndex& index); // emit this signal to enable/disable the cover art widget void enableCoverArtDisplay(bool); - void trackSelected(TrackPointer pTrack); }; #endif /* LIBRARYFEATURE_H */ diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp index 26c0391bfd41..ad81f8965c81 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -193,3 +193,9 @@ TreeItem* TreeItemModel::getItem(const QModelIndex &index) const { } return m_pRootItem; } + +void TreeItemModel::triggerRepaint() { + //todo: find a nicer way to do this. Works as it should but kind of hackish + beginInsertRows(QModelIndex().parent(), QModelIndex().row(), QModelIndex().row()); + endInsertRows(); +} diff --git a/src/library/treeitemmodel.h b/src/library/treeitemmodel.h index c8ad95984834..34d0019723e7 100644 --- a/src/library/treeitemmodel.h +++ b/src/library/treeitemmodel.h @@ -32,6 +32,8 @@ class TreeItemModel : public QAbstractItemModel { // If the index is invalid, the root item is returned. TreeItem* getItem(const QModelIndex &index) const; + void triggerRepaint(); + private: TreeItem *m_pRootItem; }; diff --git a/src/widget/wlibrarysidebar.cpp b/src/widget/wlibrarysidebar.cpp index 28cb1b9e60d7..98c6e8b256a6 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -29,7 +29,7 @@ WLibrarySidebar::WLibrarySidebar(QWidget* parent) header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_delegate = new CrateHighlightDelegate(); - this->setItemDelegate(m_delegate); + setItemDelegate(m_delegate); } WLibrarySidebar::~WLibrarySidebar() { From c48d33a76e3a1054e083be775b7fa40b8fab1503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 12:45:11 +0200 Subject: [PATCH 04/24] Some minor code-style fixes --- src/library/cratehighlightdelegate.cpp | 8 ++++++-- src/library/cratehighlightdelegate.h | 5 +---- src/library/libraryfeature.h | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/library/cratehighlightdelegate.cpp b/src/library/cratehighlightdelegate.cpp index 8af0c687fe53..f35ab9f09968 100644 --- a/src/library/cratehighlightdelegate.cpp +++ b/src/library/cratehighlightdelegate.cpp @@ -4,10 +4,14 @@ #include "libraryfeature.h" #include "cratefeature.h" +CrateHighlightDelegate::CrateHighlightDelegate(QObject* parent) + : QStyledItemDelegate(parent) { + +} void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem* option, - const QModelIndex& index) const{ - if (!index.isValid()){ + const QModelIndex& index) const { + if (!index.isValid()) { return; } diff --git a/src/library/cratehighlightdelegate.h b/src/library/cratehighlightdelegate.h index 001b4934663f..a0076660c6b8 100644 --- a/src/library/cratehighlightdelegate.h +++ b/src/library/cratehighlightdelegate.h @@ -3,10 +3,7 @@ class CrateHighlightDelegate : public QStyledItemDelegate { public: - CrateHighlightDelegate(QObject* parent = 0) - : QStyledItemDelegate(parent) - { - } + CrateHighlightDelegate(QObject* parent = 0); void initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const; }; diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index 9d8bcb443c3c..ba7e9260ca36 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -58,10 +58,10 @@ class LibraryFeature : public QObject { virtual void bindWidget(WLibrary* /* libraryWidget */, MixxxKeyboard* /* keyboard */) {} virtual TreeItemModel* getChildModel() = 0; - virtual TrackPointer getSelectedTrack(){ + virtual TrackPointer getSelectedTrack() { return TrackPointer(); } - virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath){ + virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath) { Q_UNUSED(trackId); Q_UNUSED(dataPath); return false; From a096fb68a61ce8734953fa6b1606bb06fafdcaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 12:46:30 +0200 Subject: [PATCH 05/24] Added comment to CrateHighlightDelegate::initStyleOption --- src/library/cratehighlightdelegate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/library/cratehighlightdelegate.cpp b/src/library/cratehighlightdelegate.cpp index f35ab9f09968..7a6d7ec937b0 100644 --- a/src/library/cratehighlightdelegate.cpp +++ b/src/library/cratehighlightdelegate.cpp @@ -9,6 +9,7 @@ CrateHighlightDelegate::CrateHighlightDelegate(QObject* parent) } +// This will be called to by Qt before painting the TreeView-Item. Set up styles here void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const { if (!index.isValid()) { From ca3f01198eb451a00f5eef2e11d68ac77f896fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 14:03:10 +0200 Subject: [PATCH 06/24] Added highlighting of playlists --- src/library/baseplaylistfeature.cpp | 19 +++++++++++++++++++ src/library/baseplaylistfeature.h | 8 ++++++++ src/library/dao/playlistdao.cpp | 15 +++++++++++++++ src/library/dao/playlistdao.h | 1 + 4 files changed, 43 insertions(+) diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index a843389785c7..1721cdd71a8a 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -5,6 +5,7 @@ #include #include +#include "library/library.h" #include "library/parser.h" #include "library/parserm3u.h" #include "library/parserpls.h" @@ -82,6 +83,10 @@ BasePlaylistFeature::BasePlaylistFeature(QObject* parent, connect(&m_playlistDao, SIGNAL(lockChanged(int)), this, SLOT(slotPlaylistTableChanged(int))); + + Library* pLibrary = static_cast(parent); + connect(pLibrary, SIGNAL(trackSelected(TrackPointer)), + this, SLOT(slotTrackSelected(TrackPointer))); } BasePlaylistFeature::~BasePlaylistFeature() { @@ -585,3 +590,17 @@ QModelIndex BasePlaylistFeature::indexFromPlaylistId(int playlistId) { } return QModelIndex(); } + +bool BasePlaylistFeature::isTrackInChildModel(const int trackId, + const QVariant dataPath) { + return m_playlistDao.isTrackInPlaylist(trackId, dataPath.toInt()); +} + +TrackPointer BasePlaylistFeature::getSelectedTrack() { + return m_pSelectedTrack; +} + +void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { + m_pSelectedTrack = pTrack; + m_childModel.triggerRepaint(); +} diff --git a/src/library/baseplaylistfeature.h b/src/library/baseplaylistfeature.h index 4100ec27ca98..cea0323f95a1 100644 --- a/src/library/baseplaylistfeature.h +++ b/src/library/baseplaylistfeature.h @@ -13,6 +13,7 @@ #include "library/libraryfeature.h" #include "library/dao/playlistdao.h" #include "library/dao/trackdao.h" +#include "trackinfoobject.h" class WLibrary; class MixxxKeyboard; @@ -34,6 +35,9 @@ class BasePlaylistFeature : public LibraryFeature { void bindWidget(WLibrary* libraryWidget, MixxxKeyboard* keyboard); + TrackPointer getSelectedTrack(); + virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath); + signals: void showPage(const QUrl& page); void analyzeTracks(QList); @@ -89,11 +93,15 @@ class BasePlaylistFeature : public LibraryFeature { QList > m_playlistList; QModelIndex m_lastRightClickedIndex; TreeItemModel m_childModel; + TrackPointer m_pSelectedTrack; private: virtual QString getRootViewHtml() const = 0; QString m_rootViewName; + + private slots: + void slotTrackSelected(TrackPointer pTrack); }; #endif /* BASEPLAYLISTFEATURE_H */ diff --git a/src/library/dao/playlistdao.cpp b/src/library/dao/playlistdao.cpp index b34c7623dc70..a9aca564b580 100644 --- a/src/library/dao/playlistdao.cpp +++ b/src/library/dao/playlistdao.cpp @@ -942,3 +942,18 @@ void PlaylistDAO::shuffleTracks(const int playlistId, const QList& position transaction.commit(); emit(changed(playlistId)); } + +bool PlaylistDAO::isTrackInPlaylist(const int trackId, const int playlistId) { + QSqlQuery query(m_database); + query.prepare("SELECT track_id FROM PlaylistTracks " + "WHERE playlist_id = :playlist_id AND track_id = :track_id"); + query.bindValue(":playlist_id", playlistId); + query.bindValue(":track_id", trackId); + + if (!query.exec()) { + LOG_FAILED_QUERY(query); + return false; + } + // query.next() is null if the result was empty which will lead to false as needed. + return query.next(); +} diff --git a/src/library/dao/playlistdao.h b/src/library/dao/playlistdao.h index 2a8e789b5953..97799ebf4f3e 100644 --- a/src/library/dao/playlistdao.h +++ b/src/library/dao/playlistdao.h @@ -99,6 +99,7 @@ class PlaylistDAO : public QObject, public virtual DAO { const int oldPosition, const int newPosition); // shuffles all tracks in the position List void shuffleTracks(const int playlistId, const QList& positions, const QHash& allIds); + bool isTrackInPlaylist(const int trackId, const int playlistId); signals: void added(int playlistId); From 34ce420a0d9ee3ae39cf6fce636b788ed20ca7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 14:50:03 +0200 Subject: [PATCH 07/24] Another aproach for Repainting preventing the selection to move --- src/library/treeitemmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp index ad81f8965c81..bac8308a2687 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -196,6 +196,6 @@ TreeItem* TreeItemModel::getItem(const QModelIndex &index) const { void TreeItemModel::triggerRepaint() { //todo: find a nicer way to do this. Works as it should but kind of hackish - beginInsertRows(QModelIndex().parent(), QModelIndex().row(), QModelIndex().row()); + beginInsertRows(QModelIndex(), rowCount(), rowCount()); endInsertRows(); } From 5d09cfaf97d8243dc66b63a9723f30d40bfe2107 Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Fri, 29 May 2015 10:07:40 -0400 Subject: [PATCH 08/24] Ignore QModelIndex's that don't have TreeItem internal pointers in CrateHighlightDelegate. --- src/library/cratehighlightdelegate.cpp | 33 ++++++++++++++++++-------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/library/cratehighlightdelegate.cpp b/src/library/cratehighlightdelegate.cpp index 7a6d7ec937b0..c8c2d12977c3 100644 --- a/src/library/cratehighlightdelegate.cpp +++ b/src/library/cratehighlightdelegate.cpp @@ -6,12 +6,11 @@ CrateHighlightDelegate::CrateHighlightDelegate(QObject* parent) : QStyledItemDelegate(parent) { - } // This will be called to by Qt before painting the TreeView-Item. Set up styles here void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem* option, - const QModelIndex& index) const { + const QModelIndex& index) const { if (!index.isValid()) { return; } @@ -19,14 +18,28 @@ void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem* option, QStyledItemDelegate::initStyleOption(option, index); QStyleOptionViewItemV4 *optionV4 = qstyleoption_cast(option); - TreeItem *item = static_cast(index.internalPointer()); + // If the item has no parent then it is a top-level sidebar item and its + // internalPointer is of type SidebarModel*, not TreeItem*. + if (!index.parent().isValid()) { + return; + } + + TreeItem* item = static_cast(index.internalPointer()); + if (item == NULL) { + return; + } + LibraryFeature* pFeature = item->getFeature(); - if (pFeature) { - TrackPointer pTrack = pFeature->getSelectedTrack(); - if (pTrack) { - if (pFeature->isTrackInChildModel(pTrack->getId(), item->dataPath())){ - optionV4->font.setBold(true); - } - } + if (pFeature == NULL) { + return; + } + + TrackPointer pTrack = pFeature->getSelectedTrack(); + if (pTrack.isNull()) { + return; + } + + if (pFeature->isTrackInChildModel(pTrack->getId(), item->dataPath())){ + optionV4->font.setBold(true); } } From 915c682c8df387cc7580ae9aab7a110dd395618f Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Fri, 29 May 2015 10:09:02 -0400 Subject: [PATCH 09/24] Fix SidebarModel handling of child models' dataChanged signals. --- src/library/sidebarmodel.cpp | 5 +++-- src/library/treeitemmodel.cpp | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/library/sidebarmodel.cpp b/src/library/sidebarmodel.cpp index 9d2cd31efd17..5c52edf005d4 100644 --- a/src/library/sidebarmodel.cpp +++ b/src/library/sidebarmodel.cpp @@ -333,9 +333,10 @@ QModelIndex SidebarModel::translateSourceIndex(const QModelIndex& index) { } void SidebarModel::slotDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { - Q_UNUSED(topLeft); - Q_UNUSED(bottomRight); //qDebug() << "slotDataChanged topLeft:" << topLeft << "bottomRight:" << bottomRight; + QModelIndex topLeftTranslated = translateSourceIndex(topLeft); + QModelIndex bottomRightTranslated = translateSourceIndex(bottomRight); + emit(dataChanged(topLeftTranslated, bottomRightTranslated)); } void SidebarModel::slotRowsAboutToBeInserted(const QModelIndex& parent, int start, int end) { diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp index bac8308a2687..9572118aeca7 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -195,7 +195,7 @@ TreeItem* TreeItemModel::getItem(const QModelIndex &index) const { } void TreeItemModel::triggerRepaint() { - //todo: find a nicer way to do this. Works as it should but kind of hackish - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - endInsertRows(); + QModelIndex left = index(0, 0); + QModelIndex right = index(rowCount() - 1, columnCount() - 1); + emit(dataChanged(left, right)); } From 8f27dc3ebdb0bdc82d2e95804024715a8ad6b655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 16:35:58 +0200 Subject: [PATCH 10/24] Holding Track-Crate relation in memory for faster highlighting --- src/library/dao/cratedao.cpp | 47 +++++++++++++++++++++++++++--------- src/library/dao/cratedao.h | 2 ++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/library/dao/cratedao.cpp b/src/library/dao/cratedao.cpp index 59a3b7fef0d1..a571f0d94867 100644 --- a/src/library/dao/cratedao.cpp +++ b/src/library/dao/cratedao.cpp @@ -18,6 +18,32 @@ CrateDAO::~CrateDAO() { void CrateDAO::initialize() { qDebug() << "CrateDAO::initialize()"; + + //get the count to allocate HashMap + int tracksInCratesCount = 0; + QSqlQuery query(m_database); + query.prepare("SELECT COUNT(*) from " CRATE_TRACKS_TABLE); + + if (!query.exec()) { + LOG_FAILED_QUERY(query); + } + + tracksInCratesCount = query.value(0).toInt(); + + m_cratesTrackIsIn.reserve(tracksInCratesCount); + + //now fetch all Tracks from all crates and insert them into the hashmap + query.prepare("SELECT track_id, crate_id from " CRATE_TRACKS_TABLE); + if (!query.exec()) { + LOG_FAILED_QUERY(query); + } + + const int trackIdColumn = query.record().indexOf("track_id"); + const int crateIdColumn = query.record().indexOf("crate_id"); + while (query.next()) { + m_cratesTrackIsIn.insert(query.value(crateIdColumn).toInt(), + query.value(trackIdColumn).toInt()); + } } unsigned int CrateDAO::crateCount() { @@ -236,6 +262,9 @@ bool CrateDAO::deleteCrate(const int crateId) { transaction.commit(); emit(deleted(crateId)); + + //Update in-memory map + m_cratesTrackIsIn.remove(crateId); return true; } @@ -334,6 +363,7 @@ bool CrateDAO::addTrackToCrate(const int trackId, const int crateId) { emit(trackAdded(crateId, trackId)); emit(changed(crateId)); + m_cratesTrackIsIn.insert(crateId, trackId); return true; } @@ -359,6 +389,7 @@ int CrateDAO::addTracksToCrate(const int crateId, QList* trackIdList) { // Emitting the trackAdded signals for each trackID outside the transaction foreach(int trackId, *trackIdList) { emit(trackAdded(crateId, trackId)); + m_cratesTrackIsIn.insert(crateId, trackId); } emit(changed(crateId)); @@ -381,6 +412,7 @@ bool CrateDAO::removeTrackFromCrate(const int trackId, const int crateId) { emit(trackRemoved(crateId, trackId)); emit(changed(crateId)); + m_cratesTrackIsIn.remove(crateId, trackId); return true; } @@ -401,6 +433,7 @@ bool CrateDAO::removeTracksFromCrate(const QList& ids, const int crateId) { } foreach (int trackId, ids) { emit(trackRemoved(crateId, trackId)); + m_cratesTrackIsIn.remove(crateId, trackId); } emit(changed(crateId)); return true; @@ -421,19 +454,9 @@ void CrateDAO::removeTracksFromCrates(const QList& ids) { // TODO(XXX) should we emit this for all crates? // emit(trackRemoved(crateId, trackId)); // emit(changed(crateId)); + // remove those tracks from memory-map } bool CrateDAO::isTrackInCrate(const int trackId, const int crateId) { - QSqlQuery query(m_database); - query.prepare("SELECT track_id FROM " CRATE_TRACKS_TABLE " WHERE " - "crate_id = :crate_id AND track_id = :track_id"); - query.bindValue(":crate_id", crateId); - query.bindValue(":track_id", trackId); - - if (!query.exec()) { - LOG_FAILED_QUERY(query); - return false; - } - // query.next() is null if the result was empty which will lead to false as needed. - return query.next(); + return m_cratesTrackIsIn.contains(crateId, trackId); } diff --git a/src/library/dao/cratedao.h b/src/library/dao/cratedao.h index 7a4befc121e4..7775e0fc6383 100644 --- a/src/library/dao/cratedao.h +++ b/src/library/dao/cratedao.h @@ -6,6 +6,7 @@ #include #include +#include #include #include "library/dao/dao.h" @@ -75,6 +76,7 @@ class CrateDAO : public QObject, public virtual DAO { private: QSqlDatabase& m_database; + QMultiHash m_cratesTrackIsIn; DISALLOW_COPY_AND_ASSIGN(CrateDAO); }; From 4dbc7ac60f8bddb48234290b2da939892af1d791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 16:55:35 +0200 Subject: [PATCH 11/24] Holding Track-Playlist relation in memory for faster highlighting --- src/library/dao/playlistdao.cpp | 46 ++++++++++++++++++++++++--------- src/library/dao/playlistdao.h | 1 + 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/library/dao/playlistdao.cpp b/src/library/dao/playlistdao.cpp index a9aca564b580..3f5d7ed980a6 100644 --- a/src/library/dao/playlistdao.cpp +++ b/src/library/dao/playlistdao.cpp @@ -15,6 +15,31 @@ PlaylistDAO::~PlaylistDAO() { } void PlaylistDAO::initialize() { + //get the count to allocate HashMap + int tracksInPlaylistsCount = 0; + QSqlQuery query(m_database); + query.prepare("SELECT COUNT(*) from " PLAYLIST_TRACKS_TABLE); + + if (!query.exec()) { + LOG_FAILED_QUERY(query); + } + + tracksInPlaylistsCount = query.value(0).toInt(); + + m_playlistsTrackIsIn.reserve(tracksInPlaylistsCount); + + //now fetch all Tracks from all playlists and insert them into the hashmap + query.prepare("SELECT track_id, playlist_id from " PLAYLIST_TRACKS_TABLE); + if (!query.exec()) { + LOG_FAILED_QUERY(query); + } + + const int trackIdColumn = query.record().indexOf(PLAYLISTTRACKSTABLE_TRACKID); + const int playlistIdColumn = query.record().indexOf(PLAYLISTTRACKSTABLE_PLAYLISTID); + while (query.next()) { + m_playlistsTrackIsIn.insert(query.value(playlistIdColumn).toInt(), + query.value(trackIdColumn).toInt()); + } } int PlaylistDAO::createPlaylist(const QString& name, const HiddenType hidden) { @@ -162,6 +187,7 @@ void PlaylistDAO::deletePlaylist(const int playlistId) { transaction.commit(); //TODO: Crap, we need to shuffle the positions of all the playlists? + m_playlistsTrackIsIn.remove(playlistId); emit(deleted(playlistId)); } @@ -245,6 +271,7 @@ bool PlaylistDAO::appendTracksToPlaylist(const QList& trackIds, const int p foreach (int trackId, trackIds) { // TODO(XXX) don't emit if the track didn't add successfully. emit(trackAdded(playlistId, trackId, insertPosition++)); + m_playlistsTrackIsIn.insert(playlistId, trackId); } emit(changed(playlistId)); return true; @@ -372,6 +399,7 @@ void PlaylistDAO::removeTrackFromPlaylist(const int playlistId, const int positi emit(trackRemoved(playlistId, trackId, position)); emit(changed(playlistId)); + m_playlistsTrackIsIn.remove(playlistId, trackId); } void PlaylistDAO::removeTracksFromPlaylist(const int playlistId, QList& positions) { @@ -421,6 +449,7 @@ void PlaylistDAO::removeTracksFromPlaylist(const int playlistId, QList& pos } emit(trackRemoved(playlistId, trackId, position)); + m_playlistsTrackIsIn.remove(playlistId, trackId); } transaction.commit(); emit(changed(playlistId)); @@ -467,6 +496,7 @@ bool PlaylistDAO::insertTrackIntoPlaylist(const int trackId, const int playlistI emit(trackAdded(playlistId, trackId, position)); emit(changed(playlistId)); + m_playlistsTrackIsIn.insert(playlistId, trackId); return true; } @@ -525,6 +555,7 @@ int PlaylistDAO::insertTracksIntoPlaylist(const QList& trackIds, foreach (int trackId, trackIds) { // TODO(XXX) The position is wrong if any track failed to insert. emit(trackAdded(playlistId, trackId, insertPositon++)); + m_playlistsTrackIsIn.insert(playlistId, trackId); } emit(changed(playlistId)); return tracksAdded; @@ -637,6 +668,7 @@ bool PlaylistDAO::copyPlaylistTracks(const int sourcePlaylistID, const int targe int copiedTrackId = query.value(0).toInt(); int copiedPosition = query.value(1).toInt(); emit(trackAdded(targetPlaylistID, copiedTrackId, copiedPosition)); + m_playlistsTrackIsIn.insert(targetPlaylistID, copiedTrackId); } emit(changed(targetPlaylistID)); return true; @@ -704,6 +736,7 @@ void PlaylistDAO::removeTracksFromPlaylistsInner(const QStringList& trackIdList) foreach (int playlistId, removedTracksPlaylistIds) { emit(changed(playlistId)); } + //Todo: update the internal memoryMap m_playlistsTrackIsIn - only used for track deletions therefore ok for now } int PlaylistDAO::tracksInPlaylist(const int playlistId) const { @@ -944,16 +977,5 @@ void PlaylistDAO::shuffleTracks(const int playlistId, const QList& position } bool PlaylistDAO::isTrackInPlaylist(const int trackId, const int playlistId) { - QSqlQuery query(m_database); - query.prepare("SELECT track_id FROM PlaylistTracks " - "WHERE playlist_id = :playlist_id AND track_id = :track_id"); - query.bindValue(":playlist_id", playlistId); - query.bindValue(":track_id", trackId); - - if (!query.exec()) { - LOG_FAILED_QUERY(query); - return false; - } - // query.next() is null if the result was empty which will lead to false as needed. - return query.next(); + return m_playlistsTrackIsIn.contains(playlistId,trackId); } diff --git a/src/library/dao/playlistdao.h b/src/library/dao/playlistdao.h index 97799ebf4f3e..66dec24a0a04 100644 --- a/src/library/dao/playlistdao.h +++ b/src/library/dao/playlistdao.h @@ -121,6 +121,7 @@ class PlaylistDAO : public QObject, public virtual DAO { int* pTrackDistance); QSqlDatabase& m_database; + QMultiHash m_playlistsTrackIsIn; DISALLOW_COPY_AND_ASSIGN(PlaylistDAO); }; From d9c3db3f14588b08a55a2ac51819aba9acdb1d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 17:18:25 +0200 Subject: [PATCH 12/24] Clean up used memory --- src/widget/wlibrarysidebar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widget/wlibrarysidebar.cpp b/src/widget/wlibrarysidebar.cpp index 98c6e8b256a6..d9c44dffe233 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -33,6 +33,7 @@ WLibrarySidebar::WLibrarySidebar(QWidget* parent) } WLibrarySidebar::~WLibrarySidebar() { + delete m_delegate; } From 29cd09ad7a299359116d35af06c5c7fafebf8e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 17:48:59 +0200 Subject: [PATCH 13/24] fix missing signals --- src/library/analysisfeature.h | 2 ++ src/library/autodj/autodjfeature.h | 4 ++++ src/library/browse/browsefeature.h | 2 ++ src/library/mixxxlibraryfeature.h | 3 +++ 4 files changed, 11 insertions(+) diff --git a/src/library/analysisfeature.h b/src/library/analysisfeature.h index e481262e48c9..29f6d67dc196 100644 --- a/src/library/analysisfeature.h +++ b/src/library/analysisfeature.h @@ -16,6 +16,7 @@ #include "configobject.h" #include "treeitemmodel.h" #include "dlganalysis.h" +#include "trackinfoobject.h" class AnalyserQueue; class TrackCollection; @@ -42,6 +43,7 @@ class AnalysisFeature : public LibraryFeature { signals: void analysisActive(bool bActive); void trackAnalysisStarted(int size); + void trackSelected(TrackPointer); public slots: void activate(); diff --git a/src/library/autodj/autodjfeature.h b/src/library/autodj/autodjfeature.h index 48d4d0a6e60a..90f4f436cca0 100644 --- a/src/library/autodj/autodjfeature.h +++ b/src/library/autodj/autodjfeature.h @@ -19,6 +19,7 @@ #include "library/libraryfeature.h" #include "configobject.h" #include "library/treeitemmodel.h" +#include "trackinfoobject.h" #ifdef __AUTODJCRATES__ #include "library/dao/autodjcratesdao.h" @@ -50,6 +51,9 @@ class AutoDJFeature : public LibraryFeature { TreeItemModel* getChildModel(); + signals: + void trackSelected(TrackPointer); + public slots: void activate(); diff --git a/src/library/browse/browsefeature.h b/src/library/browse/browsefeature.h index 027f42b9df20..68cd56f7ee70 100644 --- a/src/library/browse/browsefeature.h +++ b/src/library/browse/browsefeature.h @@ -14,6 +14,7 @@ #include #include "configobject.h" +#include "trackinfoobject.h" #include "library/browse/browsetablemodel.h" #include "library/browse/foldertreemodel.h" #include "library/libraryfeature.h" @@ -56,6 +57,7 @@ class BrowseFeature : public LibraryFeature { void setRootIndex(const QModelIndex&); void requestAddDir(QString); void scanLibrary(); + void trackSelected(TrackPointer); private: QString getRootViewHtml() const; diff --git a/src/library/mixxxlibraryfeature.h b/src/library/mixxxlibraryfeature.h index 01604b5d424f..12fb5ec1ac4e 100644 --- a/src/library/mixxxlibraryfeature.h +++ b/src/library/mixxxlibraryfeature.h @@ -18,6 +18,7 @@ #include "library/dao/trackdao.h" #include "treeitemmodel.h" #include "configobject.h" +#include "trackinfoobject.h" class DlgHidden; class DlgMissing; @@ -41,6 +42,8 @@ class MixxxLibraryFeature : public LibraryFeature { TreeItemModel* getChildModel(); void bindWidget(WLibrary* pLibrary, MixxxKeyboard* pKeyboard); + signals: + void trackSelected(TrackPointer); public slots: void activate(); From dc1f573d27e3b972167a17804b7ce10ab9866076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kl=C3=B6sges?= Date: Fri, 29 May 2015 17:57:45 +0200 Subject: [PATCH 14/24] Clear selected Playlists/Crates on viewChange --- src/library/baseplaylistfeature.cpp | 7 +++++++ src/library/baseplaylistfeature.h | 1 + src/library/cratefeature.cpp | 7 +++++++ src/library/cratefeature.h | 1 + 4 files changed, 16 insertions(+) diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 1721cdd71a8a..7509521c0859 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -87,6 +87,8 @@ BasePlaylistFeature::BasePlaylistFeature(QObject* parent, Library* pLibrary = static_cast(parent); connect(pLibrary, SIGNAL(trackSelected(TrackPointer)), this, SLOT(slotTrackSelected(TrackPointer))); + connect(pLibrary, SIGNAL(switchToView(const QString&)), + this, SLOT(slotResetSelectedTrack())); } BasePlaylistFeature::~BasePlaylistFeature() { @@ -604,3 +606,8 @@ void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; m_childModel.triggerRepaint(); } + + +void BasePlaylistFeature::slotResetSelectedTrack() { + slotTrackSelected(TrackPointer()); +} diff --git a/src/library/baseplaylistfeature.h b/src/library/baseplaylistfeature.h index cea0323f95a1..f0731be189f7 100644 --- a/src/library/baseplaylistfeature.h +++ b/src/library/baseplaylistfeature.h @@ -102,6 +102,7 @@ class BasePlaylistFeature : public LibraryFeature { private slots: void slotTrackSelected(TrackPointer pTrack); + void slotResetSelectedTrack(); }; #endif /* BASEPLAYLISTFEATURE_H */ diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index 54f475919aed..80ae234d42e5 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -94,6 +94,8 @@ CrateFeature::CrateFeature(Library* pLibrary, connect(pLibrary, SIGNAL(trackSelected(TrackPointer)), this, SLOT(slotTrackSelected(TrackPointer))); + connect(pLibrary, SIGNAL(switchToView(const QString&)), + this, SLOT(slotResetSelectedTrack())); } CrateFeature::~CrateFeature() { @@ -721,3 +723,8 @@ void CrateFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; m_childModel.triggerRepaint(); } + +void CrateFeature::slotResetSelectedTrack() { + slotTrackSelected(TrackPointer()); +} + diff --git a/src/library/cratefeature.h b/src/library/cratefeature.h index 000389e0a4be..8a82e3ba5f6e 100644 --- a/src/library/cratefeature.h +++ b/src/library/cratefeature.h @@ -94,6 +94,7 @@ class CrateFeature : public LibraryFeature { private slots: void slotTrackSelected(TrackPointer pTrack); + void slotResetSelectedTrack(); }; #endif /* CRATEFEATURE_H */ From dbb60d823599eb6cf2d072ba5cbe4dd2350b4bd3 Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Sat, 30 May 2015 15:40:10 -0400 Subject: [PATCH 15/24] Remove CrateHighlightDelegate. --- build/depends.py | 1 - src/library/cratehighlightdelegate.cpp | 45 -------------------------- src/library/cratehighlightdelegate.h | 9 ------ src/widget/wlibrarysidebar.cpp | 4 --- src/widget/wlibrarysidebar.h | 2 -- 5 files changed, 61 deletions(-) delete mode 100644 src/library/cratehighlightdelegate.cpp delete mode 100644 src/library/cratehighlightdelegate.h diff --git a/build/depends.py b/build/depends.py index 633265cbf803..38e9fdf07e79 100644 --- a/build/depends.py +++ b/build/depends.py @@ -743,7 +743,6 @@ def sources(self, build): "library/baseplaylistfeature.cpp", "library/playlistfeature.cpp", "library/setlogfeature.cpp", - "library/cratehighlightdelegate.cpp", "library/browse/browsetablemodel.cpp", "library/browse/browsethread.cpp", diff --git a/src/library/cratehighlightdelegate.cpp b/src/library/cratehighlightdelegate.cpp deleted file mode 100644 index c8c2d12977c3..000000000000 --- a/src/library/cratehighlightdelegate.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "library/cratehighlightdelegate.h" -#include "library/treeitem.h" -#include "trackinfoobject.h" -#include "libraryfeature.h" -#include "cratefeature.h" - -CrateHighlightDelegate::CrateHighlightDelegate(QObject* parent) - : QStyledItemDelegate(parent) { -} - -// This will be called to by Qt before painting the TreeView-Item. Set up styles here -void CrateHighlightDelegate::initStyleOption(QStyleOptionViewItem* option, - const QModelIndex& index) const { - if (!index.isValid()) { - return; - } - - QStyledItemDelegate::initStyleOption(option, index); - QStyleOptionViewItemV4 *optionV4 = qstyleoption_cast(option); - - // If the item has no parent then it is a top-level sidebar item and its - // internalPointer is of type SidebarModel*, not TreeItem*. - if (!index.parent().isValid()) { - return; - } - - TreeItem* item = static_cast(index.internalPointer()); - if (item == NULL) { - return; - } - - LibraryFeature* pFeature = item->getFeature(); - if (pFeature == NULL) { - return; - } - - TrackPointer pTrack = pFeature->getSelectedTrack(); - if (pTrack.isNull()) { - return; - } - - if (pFeature->isTrackInChildModel(pTrack->getId(), item->dataPath())){ - optionV4->font.setBold(true); - } -} diff --git a/src/library/cratehighlightdelegate.h b/src/library/cratehighlightdelegate.h deleted file mode 100644 index a0076660c6b8..000000000000 --- a/src/library/cratehighlightdelegate.h +++ /dev/null @@ -1,9 +0,0 @@ -#include - -class CrateHighlightDelegate : public QStyledItemDelegate { - -public: - CrateHighlightDelegate(QObject* parent = 0); - - void initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const; -}; diff --git a/src/widget/wlibrarysidebar.cpp b/src/widget/wlibrarysidebar.cpp index d9c44dffe233..a32f02173205 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -27,13 +27,9 @@ WLibrarySidebar::WLibrarySidebar(QWidget* parent) header()->setStretchLastSection(false); header()->setResizeMode(QHeaderView::ResizeToContents); header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); - - m_delegate = new CrateHighlightDelegate(); - setItemDelegate(m_delegate); } WLibrarySidebar::~WLibrarySidebar() { - delete m_delegate; } diff --git a/src/widget/wlibrarysidebar.h b/src/widget/wlibrarysidebar.h index fdab0fe3c028..6c8c538cdebe 100644 --- a/src/widget/wlibrarysidebar.h +++ b/src/widget/wlibrarysidebar.h @@ -13,7 +13,6 @@ #include #include "widget/wbasewidget.h" -#include "library/cratehighlightdelegate.h" class WLibrarySidebar : public QTreeView, public WBaseWidget { Q_OBJECT @@ -42,7 +41,6 @@ class WLibrarySidebar : public QTreeView, public WBaseWidget { private: QBasicTimer m_expandTimer; QModelIndex m_hoverIndex; - CrateHighlightDelegate *m_delegate; }; #endif /* WLIBRARYSIDEBAR_H */ From 655266760fb53f6362381d2e393f94dcbb9994df Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Sat, 30 May 2015 15:41:57 -0400 Subject: [PATCH 16/24] Add bold attribute to TreeItem. --- src/library/treeitem.cpp | 2 ++ src/library/treeitem.h | 9 +++++++++ src/library/treeitemmodel.cpp | 15 ++++++++++----- src/library/treeitemmodel.h | 3 +++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/library/treeitem.cpp b/src/library/treeitem.cpp index ca715938c8bb..2985373fcb92 100644 --- a/src/library/treeitem.cpp +++ b/src/library/treeitem.cpp @@ -35,6 +35,7 @@ TreeItem::TreeItem(const QString &data, const QString &data_path, m_dataPath = data_path; m_parentItem = parent; m_feature = feature; + m_bold = false; } TreeItem::TreeItem() { @@ -42,6 +43,7 @@ TreeItem::TreeItem() { m_dataPath = "$root"; m_parentItem = NULL; m_feature = NULL; + m_bold = false; } TreeItem::~TreeItem() { diff --git a/src/library/treeitem.h b/src/library/treeitem.h index a8b24a46405d..d56c38cc243d 100644 --- a/src/library/treeitem.h +++ b/src/library/treeitem.h @@ -49,6 +49,14 @@ class TreeItem { /* Returns the Library feature object to which an item belongs to */ LibraryFeature* getFeature(); + void setBold(bool bold) { + m_bold = bold; + } + bool isBold() const { + return m_bold; + } + + void setIcon(const QIcon& icon); QIcon getIcon(); @@ -57,6 +65,7 @@ class TreeItem { QString m_dataPath; QString m_data; LibraryFeature* m_feature; + bool m_bold; TreeItem *m_parentItem; QIcon m_icon; diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp index 9572118aeca7..cd9824c3a67e 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -45,20 +45,22 @@ QVariant TreeItemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); - if (role != Qt::DisplayRole && role != Qt::UserRole) + if (role != Qt::DisplayRole && role != kDataPathRole && role != kBoldRole) return QVariant(); TreeItem *item = static_cast(index.internalPointer()); // We use Qt::UserRole to ask for the datapath. - if (role == Qt::UserRole) { + if (role == kDataPathRole) { return item->dataPath(); + } else if (role == kBoldRole) { + return item->isBold(); } return item->data(); } -bool TreeItemModel::setData (const QModelIndex &a_rIndex, - const QVariant &a_rValue, int a_iRole) { +bool TreeItemModel::setData(const QModelIndex &a_rIndex, + const QVariant &a_rValue, int a_iRole) { // Get the item referred to by this index. TreeItem *pItem = static_cast(a_rIndex.internalPointer()); if (pItem == NULL) { @@ -70,9 +72,12 @@ bool TreeItemModel::setData (const QModelIndex &a_rIndex, case Qt::DisplayRole: pItem->setData(a_rValue, pItem->dataPath()); break; - case Qt::UserRole: + case kDataPathRole: pItem->setData(pItem->data(), a_rValue); break; + case kBoldRole: + pItem->setBold(a_rValue.toBool()); + break; default: return false; } diff --git a/src/library/treeitemmodel.h b/src/library/treeitemmodel.h index 34d0019723e7..3aa28de27bf2 100644 --- a/src/library/treeitemmodel.h +++ b/src/library/treeitemmodel.h @@ -11,6 +11,9 @@ class TreeItem; class TreeItemModel : public QAbstractItemModel { Q_OBJECT public: + static const int kDataPathRole = Qt::UserRole; + static const int kBoldRole = Qt::UserRole + 1; + TreeItemModel(QObject *parent = 0); virtual ~TreeItemModel(); From d6692f076564a433ccb3a62b2e2d355e7f0554da Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Sat, 30 May 2015 15:51:38 -0400 Subject: [PATCH 17/24] Restore LibraryFeature::trackSelected signal. I think this was why we had to add signals to each individual feature. --- src/library/analysisfeature.h | 2 -- src/library/autodj/autodjfeature.h | 4 ---- src/library/browse/browsefeature.h | 2 -- src/library/libraryfeature.h | 1 + src/library/mixxxlibraryfeature.h | 3 --- 5 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/library/analysisfeature.h b/src/library/analysisfeature.h index 29f6d67dc196..e481262e48c9 100644 --- a/src/library/analysisfeature.h +++ b/src/library/analysisfeature.h @@ -16,7 +16,6 @@ #include "configobject.h" #include "treeitemmodel.h" #include "dlganalysis.h" -#include "trackinfoobject.h" class AnalyserQueue; class TrackCollection; @@ -43,7 +42,6 @@ class AnalysisFeature : public LibraryFeature { signals: void analysisActive(bool bActive); void trackAnalysisStarted(int size); - void trackSelected(TrackPointer); public slots: void activate(); diff --git a/src/library/autodj/autodjfeature.h b/src/library/autodj/autodjfeature.h index 90f4f436cca0..48d4d0a6e60a 100644 --- a/src/library/autodj/autodjfeature.h +++ b/src/library/autodj/autodjfeature.h @@ -19,7 +19,6 @@ #include "library/libraryfeature.h" #include "configobject.h" #include "library/treeitemmodel.h" -#include "trackinfoobject.h" #ifdef __AUTODJCRATES__ #include "library/dao/autodjcratesdao.h" @@ -51,9 +50,6 @@ class AutoDJFeature : public LibraryFeature { TreeItemModel* getChildModel(); - signals: - void trackSelected(TrackPointer); - public slots: void activate(); diff --git a/src/library/browse/browsefeature.h b/src/library/browse/browsefeature.h index 68cd56f7ee70..027f42b9df20 100644 --- a/src/library/browse/browsefeature.h +++ b/src/library/browse/browsefeature.h @@ -14,7 +14,6 @@ #include #include "configobject.h" -#include "trackinfoobject.h" #include "library/browse/browsetablemodel.h" #include "library/browse/foldertreemodel.h" #include "library/libraryfeature.h" @@ -57,7 +56,6 @@ class BrowseFeature : public LibraryFeature { void setRootIndex(const QModelIndex&); void requestAddDir(QString); void scanLibrary(); - void trackSelected(TrackPointer); private: QString getRootViewHtml() const; diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index ba7e9260ca36..2697736043b3 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -103,6 +103,7 @@ class LibraryFeature : public QObject { void featureSelect(LibraryFeature* pFeature, const QModelIndex& index); // emit this signal to enable/disable the cover art widget void enableCoverArtDisplay(bool); + void trackSelected(TrackPointer pTrack); }; #endif /* LIBRARYFEATURE_H */ diff --git a/src/library/mixxxlibraryfeature.h b/src/library/mixxxlibraryfeature.h index 12fb5ec1ac4e..01604b5d424f 100644 --- a/src/library/mixxxlibraryfeature.h +++ b/src/library/mixxxlibraryfeature.h @@ -18,7 +18,6 @@ #include "library/dao/trackdao.h" #include "treeitemmodel.h" #include "configobject.h" -#include "trackinfoobject.h" class DlgHidden; class DlgMissing; @@ -42,8 +41,6 @@ class MixxxLibraryFeature : public LibraryFeature { TreeItemModel* getChildModel(); void bindWidget(WLibrary* pLibrary, MixxxKeyboard* pKeyboard); - signals: - void trackSelected(TrackPointer); public slots: void activate(); From 89e3ad388bdf6abba364468f58b0abdaabe6bda6 Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Sat, 30 May 2015 15:53:09 -0400 Subject: [PATCH 18/24] Respond to Qt::FontRole in SidebarModel. --- src/library/sidebarmodel.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/library/sidebarmodel.cpp b/src/library/sidebarmodel.cpp index 5c52edf005d4..a87aaa44c601 100644 --- a/src/library/sidebarmodel.cpp +++ b/src/library/sidebarmodel.cpp @@ -197,9 +197,13 @@ QVariant SidebarModel::data(const QModelIndex& index, int role) const { } else { return tree_item->dataPath(); } - } else if (role == Qt::UserRole) { + } else if (role == TreeItemModel::kDataPathRole) { // We use Qt::UserRole to ask for the datapath. return tree_item->dataPath(); + } else if (role == Qt::FontRole) { + QFont font; + font.setBold(tree_item->isBold()); + return font; } else if (role == Qt::DecorationRole) { return tree_item->getIcon(); } From 986013dab60723a3509ba45b87baff59322aff07 Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Sat, 30 May 2015 15:56:26 -0400 Subject: [PATCH 19/24] Populate playlist and crate TreeItems with bold attribute when track selection changes. --- src/library/baseplaylistfeature.cpp | 27 +++++++++++++++------------ src/library/baseplaylistfeature.h | 11 ++++------- src/library/cratefeature.cpp | 28 +++++++++++++++------------- src/library/cratefeature.h | 11 ++++------- src/library/libraryfeature.h | 8 -------- src/library/treeitemmodel.cpp | 6 ------ src/library/treeitemmodel.h | 2 -- 7 files changed, 38 insertions(+), 55 deletions(-) diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 7509521c0859..17068bf19dd1 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -86,9 +86,9 @@ BasePlaylistFeature::BasePlaylistFeature(QObject* parent, Library* pLibrary = static_cast(parent); connect(pLibrary, SIGNAL(trackSelected(TrackPointer)), - this, SLOT(slotTrackSelected(TrackPointer))); + this, SLOT(slotTrackSelected(TrackPointer))); connect(pLibrary, SIGNAL(switchToView(const QString&)), - this, SLOT(slotResetSelectedTrack())); + this, SLOT(slotResetSelectedTrack())); } BasePlaylistFeature::~BasePlaylistFeature() { @@ -593,18 +593,21 @@ QModelIndex BasePlaylistFeature::indexFromPlaylistId(int playlistId) { return QModelIndex(); } -bool BasePlaylistFeature::isTrackInChildModel(const int trackId, - const QVariant dataPath) { - return m_playlistDao.isTrackInPlaylist(trackId, dataPath.toInt()); -} - -TrackPointer BasePlaylistFeature::getSelectedTrack() { - return m_pSelectedTrack; -} - void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; - m_childModel.triggerRepaint(); + int trackId = pTrack.isNull() ? -1 : pTrack->getId(); + + // Set all playlists the track is in bold (or if there is no track selected, + // clear all the bolding). + int row = 0; + for (QList >::const_iterator it = m_playlistList.begin(); + it != m_playlistList.end(); ++it, ++row) { + int playlistId = it->first; + QModelIndex index = m_childModel.index(row, 0); + + bool shouldBold = m_playlistDao.isTrackInPlaylist(trackId, playlistId); + m_childModel.setData(index, shouldBold, TreeItemModel::kBoldRole); + } } diff --git a/src/library/baseplaylistfeature.h b/src/library/baseplaylistfeature.h index f0731be189f7..f1f999ec5074 100644 --- a/src/library/baseplaylistfeature.h +++ b/src/library/baseplaylistfeature.h @@ -35,9 +35,6 @@ class BasePlaylistFeature : public LibraryFeature { void bindWidget(WLibrary* libraryWidget, MixxxKeyboard* keyboard); - TrackPointer getSelectedTrack(); - virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath); - signals: void showPage(const QUrl& page); void analyzeTracks(QList); @@ -95,14 +92,14 @@ class BasePlaylistFeature : public LibraryFeature { TreeItemModel m_childModel; TrackPointer m_pSelectedTrack; + private slots: + void slotTrackSelected(TrackPointer pTrack); + void slotResetSelectedTrack(); + private: virtual QString getRootViewHtml() const = 0; QString m_rootViewName; - - private slots: - void slotTrackSelected(TrackPointer pTrack); - void slotResetSelectedTrack(); }; #endif /* BASEPLAYLISTFEATURE_H */ diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index 80ae234d42e5..f8ac4b1dfa2b 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -93,9 +93,9 @@ CrateFeature::CrateFeature(Library* pLibrary, constructChildModel(-1); connect(pLibrary, SIGNAL(trackSelected(TrackPointer)), - this, SLOT(slotTrackSelected(TrackPointer))); + this, SLOT(slotTrackSelected(TrackPointer))); connect(pLibrary, SIGNAL(switchToView(const QString&)), - this, SLOT(slotResetSelectedTrack())); + this, SLOT(slotResetSelectedTrack())); } CrateFeature::~CrateFeature() { @@ -120,11 +120,6 @@ QIcon CrateFeature::getIcon() { return QIcon(":/images/library/ic_library_crates.png"); } -bool CrateFeature::isTrackInChildModel(const int trackId, - const QVariant dataPath) { - return m_crateDao.isTrackInCrate(trackId, dataPath.toInt()); -} - int CrateFeature::crateIdFromIndex(QModelIndex index) { TreeItem* item = static_cast(index.internalPointer()); if (item == NULL) { @@ -715,16 +710,23 @@ QString CrateFeature::getRootViewHtml() const { return html; } -TrackPointer CrateFeature::getSelectedTrack() { - return m_pSelectedTrack; -} - void CrateFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; - m_childModel.triggerRepaint(); + int trackId = pTrack.isNull() ? -1 : pTrack->getId(); + + // Set all crates the track is in bold (or if there is no track selected, + // clear all the bolding). + int row = 0; + for (QList >::const_iterator it = m_crateList.begin(); + it != m_crateList.end(); ++it, ++row) { + int crateId = it->first; + QModelIndex index = m_childModel.index(row, 0); + + bool shouldBold = m_crateDao.isTrackInCrate(trackId, crateId); + m_childModel.setData(index, shouldBold, TreeItemModel::kBoldRole); + } } void CrateFeature::slotResetSelectedTrack() { slotTrackSelected(TrackPointer()); } - diff --git a/src/library/cratefeature.h b/src/library/cratefeature.h index 8a82e3ba5f6e..fcc9af5f8b6c 100644 --- a/src/library/cratefeature.h +++ b/src/library/cratefeature.h @@ -40,9 +40,6 @@ class CrateFeature : public LibraryFeature { TreeItemModel* getChildModel(); - TrackPointer getSelectedTrack(); - virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath); - signals: void analyzeTracks(QList); @@ -65,6 +62,10 @@ class CrateFeature : public LibraryFeature { void slotCrateTableRenamed(int playlistId, QString a_strName); void htmlLinkClicked(const QUrl& link); + private slots: + void slotTrackSelected(TrackPointer pTrack); + void slotResetSelectedTrack(); + private: QString getRootViewHtml() const; QModelIndex constructChildModel(int selected_id); @@ -91,10 +92,6 @@ class CrateFeature : public LibraryFeature { TreeItemModel m_childModel; ConfigObject* m_pConfig; TrackPointer m_pSelectedTrack; - - private slots: - void slotTrackSelected(TrackPointer pTrack); - void slotResetSelectedTrack(); }; #endif /* CRATEFEATURE_H */ diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index 2697736043b3..b353cc3b5e9e 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -58,14 +58,6 @@ class LibraryFeature : public QObject { virtual void bindWidget(WLibrary* /* libraryWidget */, MixxxKeyboard* /* keyboard */) {} virtual TreeItemModel* getChildModel() = 0; - virtual TrackPointer getSelectedTrack() { - return TrackPointer(); - } - virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath) { - Q_UNUSED(trackId); - Q_UNUSED(dataPath); - return false; - } public slots: // called when you single click on the root item diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp index cd9824c3a67e..10a703bd5e6a 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -198,9 +198,3 @@ TreeItem* TreeItemModel::getItem(const QModelIndex &index) const { } return m_pRootItem; } - -void TreeItemModel::triggerRepaint() { - QModelIndex left = index(0, 0); - QModelIndex right = index(rowCount() - 1, columnCount() - 1); - emit(dataChanged(left, right)); -} diff --git a/src/library/treeitemmodel.h b/src/library/treeitemmodel.h index 3aa28de27bf2..8dc23db7d3f6 100644 --- a/src/library/treeitemmodel.h +++ b/src/library/treeitemmodel.h @@ -35,8 +35,6 @@ class TreeItemModel : public QAbstractItemModel { // If the index is invalid, the root item is returned. TreeItem* getItem(const QModelIndex &index) const; - void triggerRepaint(); - private: TreeItem *m_pRootItem; }; From 939428f85494aac697595a8dbad52d95183180fb Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Sat, 30 May 2015 15:57:39 -0400 Subject: [PATCH 20/24] Populate TreeItem state when re-building the child model. This supports bolding/unbolding the playlist/crate when a track is added/removed. --- src/library/baseplaylistfeature.cpp | 3 +++ src/library/cratefeature.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 17068bf19dd1..84334f8a6ebe 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -560,6 +560,9 @@ QModelIndex BasePlaylistFeature::constructChildModel(int selected_id) { // Create the TreeItem whose parent is the invisible root item TreeItem* item = new TreeItem(playlist_name, QString::number(playlist_id), this, root); + item->setBold(m_pSelectedTrack && m_playlistDao.isTrackInPlaylist( + m_pSelectedTrack->getId(), playlist_id)); + decorateChild(item, playlist_id); data_list.append(item); } diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index f8ac4b1dfa2b..ba7762e593ab 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -515,6 +515,8 @@ QModelIndex CrateFeature::constructChildModel(int selected_id) { TreeItem* item = new TreeItem(crate_name, QString::number(crate_id), this, root); bool locked = m_crateDao.isCrateLocked(crate_id); item->setIcon(locked ? QIcon(":/images/library/ic_library_locked.png") : QIcon()); + item->setBold(m_pSelectedTrack && m_crateDao.isTrackInCrate( + m_pSelectedTrack->getId(), crate_id)); data_list.append(item); } From 55381bf26f01f20cf1c5f0a6e107dd97b895f76c Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Tue, 2 Jun 2015 14:57:36 -0400 Subject: [PATCH 21/24] Swap key/value pairing of crate/playlist membership cache in CrateDAO/PlaylistDAO. Also add a method to fetch all the playlists/crates a track is in. --- src/library/dao/cratedao.cpp | 49 +++++++++++++++++++++------- src/library/dao/cratedao.h | 4 +++ src/library/dao/playlistdao.cpp | 58 +++++++++++++++++++++++++-------- src/library/dao/playlistdao.h | 6 +++- 4 files changed, 90 insertions(+), 27 deletions(-) diff --git a/src/library/dao/cratedao.cpp b/src/library/dao/cratedao.cpp index a571f0d94867..dacc2caa8b1c 100644 --- a/src/library/dao/cratedao.cpp +++ b/src/library/dao/cratedao.cpp @@ -19,7 +19,11 @@ CrateDAO::~CrateDAO() { void CrateDAO::initialize() { qDebug() << "CrateDAO::initialize()"; - //get the count to allocate HashMap + populateCrateMembershipCache(); +} + +void CrateDAO::populateCrateMembershipCache() { + // get the count to allocate HashMap int tracksInCratesCount = 0; QSqlQuery query(m_database); query.prepare("SELECT COUNT(*) from " CRATE_TRACKS_TABLE); @@ -32,7 +36,7 @@ void CrateDAO::initialize() { m_cratesTrackIsIn.reserve(tracksInCratesCount); - //now fetch all Tracks from all crates and insert them into the hashmap + // now fetch all Tracks from all crates and insert them into the hashmap query.prepare("SELECT track_id, crate_id from " CRATE_TRACKS_TABLE); if (!query.exec()) { LOG_FAILED_QUERY(query); @@ -41,8 +45,8 @@ void CrateDAO::initialize() { const int trackIdColumn = query.record().indexOf("track_id"); const int crateIdColumn = query.record().indexOf("crate_id"); while (query.next()) { - m_cratesTrackIsIn.insert(query.value(crateIdColumn).toInt(), - query.value(trackIdColumn).toInt()); + m_cratesTrackIsIn.insert(query.value(trackIdColumn).toInt(), + query.value(crateIdColumn).toInt()); } } @@ -263,8 +267,16 @@ bool CrateDAO::deleteCrate(const int crateId) { emit(deleted(crateId)); - //Update in-memory map - m_cratesTrackIsIn.remove(crateId); + // Update in-memory map + for (QMultiHash::iterator it = m_cratesTrackIsIn.begin(); + it != m_cratesTrackIsIn.end();) { + if (it.value() == crateId) { + it = m_cratesTrackIsIn.erase(it); + } else { + it++; + } + } + return true; } @@ -361,9 +373,9 @@ bool CrateDAO::addTrackToCrate(const int trackId, const int crateId) { return false; } + m_cratesTrackIsIn.insert(trackId, crateId); emit(trackAdded(crateId, trackId)); emit(changed(crateId)); - m_cratesTrackIsIn.insert(crateId, trackId); return true; } @@ -388,8 +400,8 @@ int CrateDAO::addTracksToCrate(const int crateId, QList* trackIdList) { // Emitting the trackAdded signals for each trackID outside the transaction foreach(int trackId, *trackIdList) { + m_cratesTrackIsIn.insert(trackId, crateId); emit(trackAdded(crateId, trackId)); - m_cratesTrackIsIn.insert(crateId, trackId); } emit(changed(crateId)); @@ -410,9 +422,9 @@ bool CrateDAO::removeTrackFromCrate(const int trackId, const int crateId) { return false; } + m_cratesTrackIsIn.remove(trackId, crateId); emit(trackRemoved(crateId, trackId)); emit(changed(crateId)); - m_cratesTrackIsIn.remove(crateId, trackId); return true; } @@ -432,8 +444,8 @@ bool CrateDAO::removeTracksFromCrate(const QList& ids, const int crateId) { return false; } foreach (int trackId, ids) { + m_cratesTrackIsIn.remove(trackId, crateId); emit(trackRemoved(crateId, trackId)); - m_cratesTrackIsIn.remove(crateId, trackId); } emit(changed(crateId)); return true; @@ -451,12 +463,25 @@ void CrateDAO::removeTracksFromCrates(const QList& ids) { LOG_FAILED_QUERY(query); } + // remove those tracks from memory-map + foreach (int trackId, ids) { + m_cratesTrackIsIn.remove(trackId); + } + // TODO(XXX) should we emit this for all crates? // emit(trackRemoved(crateId, trackId)); // emit(changed(crateId)); - // remove those tracks from memory-map } bool CrateDAO::isTrackInCrate(const int trackId, const int crateId) { - return m_cratesTrackIsIn.contains(crateId, trackId); + return m_cratesTrackIsIn.contains(trackId, crateId); +} + +void CrateDAO::getCratesTrackIsIn(const int trackId, + QSet* crateSet) const { + crateSet->clear(); + for (QHash::const_iterator it = m_cratesTrackIsIn.find(trackId); + it != m_cratesTrackIsIn.end(); ++it) { + crateSet->insert(it.value()); + } } diff --git a/src/library/dao/cratedao.h b/src/library/dao/cratedao.h index 7775e0fc6383..1bcfc3f10c67 100644 --- a/src/library/dao/cratedao.h +++ b/src/library/dao/cratedao.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "library/dao/dao.h" #include "util.h" @@ -63,6 +64,7 @@ class CrateDAO : public QObject, public virtual DAO { // remove tracks from all crates void removeTracksFromCrates(const QList& ids); bool isTrackInCrate(const int trackId, const int crateId); + void getCratesTrackIsIn(const int trackId, QSet* crateSet) const; signals: void added(int crateId); @@ -75,6 +77,8 @@ class CrateDAO : public QObject, public virtual DAO { void autoDjChanged(int a_iCrateId, bool a_bIn); private: + void populateCrateMembershipCache(); + QSqlDatabase& m_database; QMultiHash m_cratesTrackIsIn; DISALLOW_COPY_AND_ASSIGN(CrateDAO); diff --git a/src/library/dao/playlistdao.cpp b/src/library/dao/playlistdao.cpp index 3f5d7ed980a6..5193e60f0260 100644 --- a/src/library/dao/playlistdao.cpp +++ b/src/library/dao/playlistdao.cpp @@ -15,7 +15,11 @@ PlaylistDAO::~PlaylistDAO() { } void PlaylistDAO::initialize() { - //get the count to allocate HashMap + populatePlaylistMembershipCache(); +} + +void PlaylistDAO::populatePlaylistMembershipCache() { + // get the count to allocate HashMap int tracksInPlaylistsCount = 0; QSqlQuery query(m_database); query.prepare("SELECT COUNT(*) from " PLAYLIST_TRACKS_TABLE); @@ -28,7 +32,7 @@ void PlaylistDAO::initialize() { m_playlistsTrackIsIn.reserve(tracksInPlaylistsCount); - //now fetch all Tracks from all playlists and insert them into the hashmap + // now fetch all Tracks from all playlists and insert them into the hashmap query.prepare("SELECT track_id, playlist_id from " PLAYLIST_TRACKS_TABLE); if (!query.exec()) { LOG_FAILED_QUERY(query); @@ -37,8 +41,9 @@ void PlaylistDAO::initialize() { const int trackIdColumn = query.record().indexOf(PLAYLISTTRACKSTABLE_TRACKID); const int playlistIdColumn = query.record().indexOf(PLAYLISTTRACKSTABLE_PLAYLISTID); while (query.next()) { - m_playlistsTrackIsIn.insert(query.value(playlistIdColumn).toInt(), - query.value(trackIdColumn).toInt()); + m_playlistsTrackIsIn.insert(query.value(trackIdColumn).toInt(), + query.value(playlistIdColumn).toInt()); + } } @@ -187,7 +192,15 @@ void PlaylistDAO::deletePlaylist(const int playlistId) { transaction.commit(); //TODO: Crap, we need to shuffle the positions of all the playlists? - m_playlistsTrackIsIn.remove(playlistId); + for (QMultiHash::iterator it = m_playlistsTrackIsIn.begin(); + it != m_playlistsTrackIsIn.end();) { + if (it.value() == playlistId) { + it = m_playlistsTrackIsIn.erase(it); + } else { + it++; + } + } + emit(deleted(playlistId)); } @@ -269,9 +282,9 @@ bool PlaylistDAO::appendTracksToPlaylist(const QList& trackIds, const int p insertPosition = position; foreach (int trackId, trackIds) { + m_playlistsTrackIsIn.insert(trackId, playlistId); // TODO(XXX) don't emit if the track didn't add successfully. emit(trackAdded(playlistId, trackId, insertPosition++)); - m_playlistsTrackIsIn.insert(playlistId, trackId); } emit(changed(playlistId)); return true; @@ -397,9 +410,11 @@ void PlaylistDAO::removeTrackFromPlaylist(const int playlistId, const int positi } transaction.commit(); + m_playlistsTrackIsIn.remove(trackId, playlistId); + emit(trackRemoved(playlistId, trackId, position)); emit(changed(playlistId)); - m_playlistsTrackIsIn.remove(playlistId, trackId); + } void PlaylistDAO::removeTracksFromPlaylist(const int playlistId, QList& positions) { @@ -448,8 +463,8 @@ void PlaylistDAO::removeTracksFromPlaylist(const int playlistId, QList& pos LOG_FAILED_QUERY(query); } + m_playlistsTrackIsIn.remove(trackId, playlistId); emit(trackRemoved(playlistId, trackId, position)); - m_playlistsTrackIsIn.remove(playlistId, trackId); } transaction.commit(); emit(changed(playlistId)); @@ -494,9 +509,9 @@ bool PlaylistDAO::insertTrackIntoPlaylist(const int trackId, const int playlistI } transaction.commit(); + m_playlistsTrackIsIn.insert(trackId, playlistId); emit(trackAdded(playlistId, trackId, position)); emit(changed(playlistId)); - m_playlistsTrackIsIn.insert(playlistId, trackId); return true; } @@ -553,9 +568,9 @@ int PlaylistDAO::insertTracksIntoPlaylist(const QList& trackIds, insertPositon = position; foreach (int trackId, trackIds) { + m_playlistsTrackIsIn.insert(trackId, playlistId); // TODO(XXX) The position is wrong if any track failed to insert. emit(trackAdded(playlistId, trackId, insertPositon++)); - m_playlistsTrackIsIn.insert(playlistId, trackId); } emit(changed(playlistId)); return tracksAdded; @@ -667,8 +682,8 @@ bool PlaylistDAO::copyPlaylistTracks(const int sourcePlaylistID, const int targe while (query.next()) { int copiedTrackId = query.value(0).toInt(); int copiedPosition = query.value(1).toInt(); + m_playlistsTrackIsIn.insert(copiedTrackId, targetPlaylistID); emit(trackAdded(targetPlaylistID, copiedTrackId, copiedPosition)); - m_playlistsTrackIsIn.insert(targetPlaylistID, copiedTrackId); } emit(changed(targetPlaylistID)); return true; @@ -707,6 +722,13 @@ void PlaylistDAO::removeTracksFromPlaylists(const QList& trackIds) { trackIdList << QString::number(id); } removeTracksFromPlaylistsInner(trackIdList); + + // Update the in-memory hash. TODO(XXX) this assumes all the removes + // succeeded. + foreach (int trackId, trackIds) { + m_playlistsTrackIsIn.remove(trackId); + } + } void PlaylistDAO::removeTracksFromPlaylistsInner(const QStringList& trackIdList) { @@ -736,7 +758,6 @@ void PlaylistDAO::removeTracksFromPlaylistsInner(const QStringList& trackIdList) foreach (int playlistId, removedTracksPlaylistIds) { emit(changed(playlistId)); } - //Todo: update the internal memoryMap m_playlistsTrackIsIn - only used for track deletions therefore ok for now } int PlaylistDAO::tracksInPlaylist(const int playlistId) const { @@ -976,6 +997,15 @@ void PlaylistDAO::shuffleTracks(const int playlistId, const QList& position emit(changed(playlistId)); } -bool PlaylistDAO::isTrackInPlaylist(const int trackId, const int playlistId) { - return m_playlistsTrackIsIn.contains(playlistId,trackId); +bool PlaylistDAO::isTrackInPlaylist(const int trackId, const int playlistId) const { + return m_playlistsTrackIsIn.contains(trackId, playlistId); +} + +void PlaylistDAO::getPlaylistsTrackIsIn(const int trackId, + QSet* playlistSet) const { + playlistSet->clear(); + for (QHash::const_iterator it = m_playlistsTrackIsIn.find(trackId); + it != m_playlistsTrackIsIn.end(); ++it) { + playlistSet->insert(it.value()); + } } diff --git a/src/library/dao/playlistdao.h b/src/library/dao/playlistdao.h index 66dec24a0a04..c158ef66b8b6 100644 --- a/src/library/dao/playlistdao.h +++ b/src/library/dao/playlistdao.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "library/dao/dao.h" #include "util.h" @@ -99,7 +100,9 @@ class PlaylistDAO : public QObject, public virtual DAO { const int oldPosition, const int newPosition); // shuffles all tracks in the position List void shuffleTracks(const int playlistId, const QList& positions, const QHash& allIds); - bool isTrackInPlaylist(const int trackId, const int playlistId); + bool isTrackInPlaylist(const int trackId, const int playlistId) const; + + void getPlaylistsTrackIsIn(const int trackId, QSet* playlistSet) const; signals: void added(int playlistId); @@ -119,6 +122,7 @@ class PlaylistDAO : public QObject, public virtual DAO { const int otherTrackPosition, const QHash* pTrackPositionIds, int* pTrackDistance); + void populatePlaylistMembershipCache(); QSqlDatabase& m_database; QMultiHash m_playlistsTrackIsIn; From 1176128aaaac66ec5eb8acf20c1f6ef68e889007 Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Wed, 3 Jun 2015 09:36:17 -0400 Subject: [PATCH 22/24] Fetch playlist / crate membership set on track selection. Avoids repeatedly asking the DAO for pair-wise membership (requires linear hash table lookups). --- src/library/baseplaylistfeature.cpp | 6 +++--- src/library/baseplaylistfeature.h | 2 ++ src/library/cratefeature.cpp | 7 +++---- src/library/cratefeature.h | 2 ++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 84334f8a6ebe..553e38163523 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -560,8 +560,7 @@ QModelIndex BasePlaylistFeature::constructChildModel(int selected_id) { // Create the TreeItem whose parent is the invisible root item TreeItem* item = new TreeItem(playlist_name, QString::number(playlist_id), this, root); - item->setBold(m_pSelectedTrack && m_playlistDao.isTrackInPlaylist( - m_pSelectedTrack->getId(), playlist_id)); + item->setBold(m_playlistsSelectedTrackIsIn.contains(playlist_id)); decorateChild(item, playlist_id); data_list.append(item); @@ -599,6 +598,7 @@ QModelIndex BasePlaylistFeature::indexFromPlaylistId(int playlistId) { void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; int trackId = pTrack.isNull() ? -1 : pTrack->getId(); + m_playlistDao.getPlaylistsTrackIsIn(trackId, &m_playlistsSelectedTrackIsIn); // Set all playlists the track is in bold (or if there is no track selected, // clear all the bolding). @@ -608,7 +608,7 @@ void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { int playlistId = it->first; QModelIndex index = m_childModel.index(row, 0); - bool shouldBold = m_playlistDao.isTrackInPlaylist(trackId, playlistId); + bool shouldBold = m_playlistsSelectedTrackIsIn.contains(playlistId); m_childModel.setData(index, shouldBold, TreeItemModel::kBoldRole); } } diff --git a/src/library/baseplaylistfeature.h b/src/library/baseplaylistfeature.h index f1f999ec5074..4fc9f1d2fe86 100644 --- a/src/library/baseplaylistfeature.h +++ b/src/library/baseplaylistfeature.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "library/libraryfeature.h" @@ -99,6 +100,7 @@ class BasePlaylistFeature : public LibraryFeature { private: virtual QString getRootViewHtml() const = 0; + QSet m_playlistsSelectedTrackIsIn; QString m_rootViewName; }; diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index ba7762e593ab..78ba35ba158a 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -515,8 +515,7 @@ QModelIndex CrateFeature::constructChildModel(int selected_id) { TreeItem* item = new TreeItem(crate_name, QString::number(crate_id), this, root); bool locked = m_crateDao.isCrateLocked(crate_id); item->setIcon(locked ? QIcon(":/images/library/ic_library_locked.png") : QIcon()); - item->setBold(m_pSelectedTrack && m_crateDao.isTrackInCrate( - m_pSelectedTrack->getId(), crate_id)); + item->setBold(m_cratesSelectedTrackIsIn.contains(crate_id)); data_list.append(item); } @@ -715,6 +714,7 @@ QString CrateFeature::getRootViewHtml() const { void CrateFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; int trackId = pTrack.isNull() ? -1 : pTrack->getId(); + m_crateDao.getCratesTrackIsIn(trackId, &m_cratesSelectedTrackIsIn); // Set all crates the track is in bold (or if there is no track selected, // clear all the bolding). @@ -723,8 +723,7 @@ void CrateFeature::slotTrackSelected(TrackPointer pTrack) { it != m_crateList.end(); ++it, ++row) { int crateId = it->first; QModelIndex index = m_childModel.index(row, 0); - - bool shouldBold = m_crateDao.isTrackInCrate(trackId, crateId); + bool shouldBold = m_cratesSelectedTrackIsIn.contains(crateId); m_childModel.setData(index, shouldBold, TreeItemModel::kBoldRole); } } diff --git a/src/library/cratefeature.h b/src/library/cratefeature.h index fcc9af5f8b6c..6b1e7a1be9ce 100644 --- a/src/library/cratefeature.h +++ b/src/library/cratefeature.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "library/libraryfeature.h" #include "library/cratetablemodel.h" @@ -92,6 +93,7 @@ class CrateFeature : public LibraryFeature { TreeItemModel m_childModel; ConfigObject* m_pConfig; TrackPointer m_pSelectedTrack; + QSet m_cratesSelectedTrackIsIn; }; #endif /* CRATEFEATURE_H */ From 41c5fa5965a2828ebcf66e6ede51fc87c8ae0689 Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Wed, 10 Jun 2015 09:02:35 -0400 Subject: [PATCH 23/24] Fix crate/playlist membership fetchers. --- src/library/dao/cratedao.cpp | 2 +- src/library/dao/playlistdao.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/dao/cratedao.cpp b/src/library/dao/cratedao.cpp index dacc2caa8b1c..1e8bd897f022 100644 --- a/src/library/dao/cratedao.cpp +++ b/src/library/dao/cratedao.cpp @@ -481,7 +481,7 @@ void CrateDAO::getCratesTrackIsIn(const int trackId, QSet* crateSet) const { crateSet->clear(); for (QHash::const_iterator it = m_cratesTrackIsIn.find(trackId); - it != m_cratesTrackIsIn.end(); ++it) { + it != m_cratesTrackIsIn.end() && it.key() == trackId; ++it) { crateSet->insert(it.value()); } } diff --git a/src/library/dao/playlistdao.cpp b/src/library/dao/playlistdao.cpp index 5193e60f0260..374b21088571 100644 --- a/src/library/dao/playlistdao.cpp +++ b/src/library/dao/playlistdao.cpp @@ -1005,7 +1005,7 @@ void PlaylistDAO::getPlaylistsTrackIsIn(const int trackId, QSet* playlistSet) const { playlistSet->clear(); for (QHash::const_iterator it = m_playlistsTrackIsIn.find(trackId); - it != m_playlistsTrackIsIn.end(); ++it) { + it != m_playlistsTrackIsIn.end() && it.key() == trackId; ++it) { playlistSet->insert(it.value()); } } From de3e581f5fe1d232f20726a6a328bb13d0cd7760 Mon Sep 17 00:00:00 2001 From: RJ Ryan Date: Wed, 10 Jun 2015 10:47:53 -0400 Subject: [PATCH 24/24] Don't call TreeItemModel::setData in a loop. This caused severe performance issues since it triggered a repaint on every loop iteration. --- src/library/baseplaylistfeature.cpp | 16 +++++++++++++--- src/library/cratefeature.cpp | 14 ++++++++++++-- src/library/treeitemmodel.cpp | 6 ++++++ src/library/treeitemmodel.h | 2 ++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 553e38163523..2bc38238f9a0 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -600,17 +600,27 @@ void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { int trackId = pTrack.isNull() ? -1 : pTrack->getId(); m_playlistDao.getPlaylistsTrackIsIn(trackId, &m_playlistsSelectedTrackIsIn); + TreeItem* rootItem = m_childModel.getItem(QModelIndex()); + if (rootItem == nullptr) { + return; + } + // Set all playlists the track is in bold (or if there is no track selected, // clear all the bolding). int row = 0; for (QList >::const_iterator it = m_playlistList.begin(); it != m_playlistList.end(); ++it, ++row) { - int playlistId = it->first; - QModelIndex index = m_childModel.index(row, 0); + TreeItem* playlist = rootItem->child(row); + if (playlist == nullptr) { + continue; + } + int playlistId = it->first; bool shouldBold = m_playlistsSelectedTrackIsIn.contains(playlistId); - m_childModel.setData(index, shouldBold, TreeItemModel::kBoldRole); + playlist->setBold(shouldBold); } + + m_childModel.triggerRepaint(); } diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index 78ba35ba158a..0d4ea3bb37e8 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -716,16 +716,26 @@ void CrateFeature::slotTrackSelected(TrackPointer pTrack) { int trackId = pTrack.isNull() ? -1 : pTrack->getId(); m_crateDao.getCratesTrackIsIn(trackId, &m_cratesSelectedTrackIsIn); + TreeItem* rootItem = m_childModel.getItem(QModelIndex()); + if (rootItem == nullptr) { + return; + } + // Set all crates the track is in bold (or if there is no track selected, // clear all the bolding). int row = 0; for (QList >::const_iterator it = m_crateList.begin(); it != m_crateList.end(); ++it, ++row) { + TreeItem* crate = rootItem->child(row); + if (crate == nullptr) { + continue; + } int crateId = it->first; - QModelIndex index = m_childModel.index(row, 0); bool shouldBold = m_cratesSelectedTrackIsIn.contains(crateId); - m_childModel.setData(index, shouldBold, TreeItemModel::kBoldRole); + crate->setBold(shouldBold); } + + m_childModel.triggerRepaint(); } void CrateFeature::slotResetSelectedTrack() { diff --git a/src/library/treeitemmodel.cpp b/src/library/treeitemmodel.cpp index 10a703bd5e6a..cd9824c3a67e 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -198,3 +198,9 @@ TreeItem* TreeItemModel::getItem(const QModelIndex &index) const { } return m_pRootItem; } + +void TreeItemModel::triggerRepaint() { + QModelIndex left = index(0, 0); + QModelIndex right = index(rowCount() - 1, columnCount() - 1); + emit(dataChanged(left, right)); +} diff --git a/src/library/treeitemmodel.h b/src/library/treeitemmodel.h index 8dc23db7d3f6..3aa28de27bf2 100644 --- a/src/library/treeitemmodel.h +++ b/src/library/treeitemmodel.h @@ -35,6 +35,8 @@ class TreeItemModel : public QAbstractItemModel { // If the index is invalid, the root item is returned. TreeItem* getItem(const QModelIndex &index) const; + void triggerRepaint(); + private: TreeItem *m_pRootItem; };