diff --git a/build/depends.py b/build/depends.py index 38e9fdf07e79..633265cbf803 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/cratehighlightdelegate.cpp", "library/browse/browsetablemodel.cpp", "library/browse/browsethread.cpp", 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/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 84334f8a6ebe..7509521c0859 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() { @@ -560,9 +560,6 @@ 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); } @@ -596,21 +593,18 @@ QModelIndex BasePlaylistFeature::indexFromPlaylistId(int playlistId) { return QModelIndex(); } -void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { - m_pSelectedTrack = pTrack; - int trackId = pTrack.isNull() ? -1 : pTrack->getId(); +bool BasePlaylistFeature::isTrackInChildModel(const int trackId, + const QVariant dataPath) { + return m_playlistDao.isTrackInPlaylist(trackId, dataPath.toInt()); +} - // 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); +TrackPointer BasePlaylistFeature::getSelectedTrack() { + return m_pSelectedTrack; +} - bool shouldBold = m_playlistDao.isTrackInPlaylist(trackId, playlistId); - m_childModel.setData(index, shouldBold, TreeItemModel::kBoldRole); - } +void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) { + m_pSelectedTrack = pTrack; + m_childModel.triggerRepaint(); } diff --git a/src/library/baseplaylistfeature.h b/src/library/baseplaylistfeature.h index f1f999ec5074..f0731be189f7 100644 --- a/src/library/baseplaylistfeature.h +++ b/src/library/baseplaylistfeature.h @@ -35,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); @@ -92,14 +95,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/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/cratefeature.cpp b/src/library/cratefeature.cpp index ba7762e593ab..80ae234d42e5 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,6 +120,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) { @@ -515,8 +520,6 @@ 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); } @@ -712,23 +715,16 @@ QString CrateFeature::getRootViewHtml() const { return html; } +TrackPointer CrateFeature::getSelectedTrack() { + return m_pSelectedTrack; +} + void CrateFeature::slotTrackSelected(TrackPointer pTrack) { m_pSelectedTrack = pTrack; - 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); - } + m_childModel.triggerRepaint(); } void CrateFeature::slotResetSelectedTrack() { slotTrackSelected(TrackPointer()); } + diff --git a/src/library/cratefeature.h b/src/library/cratefeature.h index fcc9af5f8b6c..8a82e3ba5f6e 100644 --- a/src/library/cratefeature.h +++ b/src/library/cratefeature.h @@ -40,6 +40,9 @@ class CrateFeature : public LibraryFeature { TreeItemModel* getChildModel(); + TrackPointer getSelectedTrack(); + virtual bool isTrackInChildModel(const int trackId, const QVariant dataPath); + signals: void analyzeTracks(QList); @@ -62,10 +65,6 @@ 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); @@ -92,6 +91,10 @@ 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/cratehighlightdelegate.cpp b/src/library/cratehighlightdelegate.cpp new file mode 100644 index 000000000000..c8c2d12977c3 --- /dev/null +++ b/src/library/cratehighlightdelegate.cpp @@ -0,0 +1,45 @@ +#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 new file mode 100644 index 000000000000..a0076660c6b8 --- /dev/null +++ b/src/library/cratehighlightdelegate.h @@ -0,0 +1,9 @@ +#include + +class CrateHighlightDelegate : public QStyledItemDelegate { + +public: + 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 b353cc3b5e9e..ba7e9260ca36 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -58,6 +58,14 @@ 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 @@ -95,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/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(); diff --git a/src/library/sidebarmodel.cpp b/src/library/sidebarmodel.cpp index a87aaa44c601..5c52edf005d4 100644 --- a/src/library/sidebarmodel.cpp +++ b/src/library/sidebarmodel.cpp @@ -197,13 +197,9 @@ QVariant SidebarModel::data(const QModelIndex& index, int role) const { } else { return tree_item->dataPath(); } - } else if (role == TreeItemModel::kDataPathRole) { + } else if (role == Qt::UserRole) { // 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(); } diff --git a/src/library/treeitem.cpp b/src/library/treeitem.cpp index 2985373fcb92..ca715938c8bb 100644 --- a/src/library/treeitem.cpp +++ b/src/library/treeitem.cpp @@ -35,7 +35,6 @@ TreeItem::TreeItem(const QString &data, const QString &data_path, m_dataPath = data_path; m_parentItem = parent; m_feature = feature; - m_bold = false; } TreeItem::TreeItem() { @@ -43,7 +42,6 @@ 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 d56c38cc243d..a8b24a46405d 100644 --- a/src/library/treeitem.h +++ b/src/library/treeitem.h @@ -49,14 +49,6 @@ 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(); @@ -65,7 +57,6 @@ 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 10a703bd5e6a..9572118aeca7 100644 --- a/src/library/treeitemmodel.cpp +++ b/src/library/treeitemmodel.cpp @@ -45,22 +45,20 @@ QVariant TreeItemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); - if (role != Qt::DisplayRole && role != kDataPathRole && role != kBoldRole) + if (role != Qt::DisplayRole && role != Qt::UserRole) return QVariant(); TreeItem *item = static_cast(index.internalPointer()); // We use Qt::UserRole to ask for the datapath. - if (role == kDataPathRole) { + if (role == Qt::UserRole) { 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) { @@ -72,12 +70,9 @@ bool TreeItemModel::setData(const QModelIndex &a_rIndex, case Qt::DisplayRole: pItem->setData(a_rValue, pItem->dataPath()); break; - case kDataPathRole: + case Qt::UserRole: pItem->setData(pItem->data(), a_rValue); break; - case kBoldRole: - pItem->setBold(a_rValue.toBool()); - break; default: return false; } @@ -198,3 +193,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..34d0019723e7 100644 --- a/src/library/treeitemmodel.h +++ b/src/library/treeitemmodel.h @@ -11,9 +11,6 @@ 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(); @@ -35,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 a32f02173205..d9c44dffe233 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -27,9 +27,13 @@ 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 6c8c538cdebe..fdab0fe3c028 100644 --- a/src/widget/wlibrarysidebar.h +++ b/src/widget/wlibrarysidebar.h @@ -13,6 +13,7 @@ #include #include "widget/wbasewidget.h" +#include "library/cratehighlightdelegate.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; + CrateHighlightDelegate *m_delegate; }; #endif /* WLIBRARYSIDEBAR_H */