From 7bf0cda47b80943342d99d1eb10c281f0028cc09 Mon Sep 17 00:00:00 2001 From: Daniel Poelzleithner Date: Wed, 25 Apr 2018 12:38:49 +0200 Subject: [PATCH 1/2] [WIP] crates widget Adds a new widget that shows the crates the selected tracks are in. The new library redesign makes it impossible to see the crates the selection is in. Even the old design had problems with many crates. Known Bugs: - Only LateNight and Deer skin. Needs more styling. - The Crates that are not in all selected tracks should be displayed differently, but current solution seems not to work as expected. --- build/depends.py | 1 + res/skins/Deere/library.xml | 53 ++++++++-- res/skins/LateNight/library.xml | 51 +++++++-- res/skins/LateNight/skin.xml | 1 + res/skins/LateNight/style.qss | 51 ++++++++- src/controllers/controlpickermenu.cpp | 3 + src/library/crate/crate.h | 1 + src/library/crate/cratesummary.h | 1 + src/library/library.cpp | 2 + src/library/library.h | 6 ++ src/library/libraryfeature.cpp | 2 + src/library/libraryfeature.h | 1 + src/library/trackcollection.cpp | 2 +- src/skin/legacyskinparser.cpp | 42 ++++++++ src/skin/legacyskinparser.h | 1 + src/skin/tooltips.cpp | 4 + src/track/track.h | 3 + src/widget/wcratelist.cpp | 146 ++++++++++++++++++++++++++ src/widget/wcratelist.h | 85 +++++++++++++++ src/widget/wlibrarytableview.h | 1 + src/widget/wmainmenubar.cpp | 16 +++ src/widget/wtrackproperty.cpp | 1 + src/widget/wtracktableview.cpp | 10 ++ 23 files changed, 463 insertions(+), 21 deletions(-) create mode 100644 src/widget/wcratelist.cpp create mode 100644 src/widget/wcratelist.h diff --git a/build/depends.py b/build/depends.py index 5f00bd6cb038..b41036439363 100644 --- a/build/depends.py +++ b/build/depends.py @@ -886,6 +886,7 @@ def sources(self, build): "widget/wcombobox.cpp", "widget/wsplitter.cpp", "widget/wcoverart.cpp", + "widget/wcratelist.cpp", "widget/wcoverartlabel.cpp", "widget/wcoverartmenu.cpp", "widget/wsingletoncontainer.cpp", diff --git a/res/skins/Deere/library.xml b/res/skins/Deere/library.xml index decee8764402..e35e4e59fc2f 100644 --- a/res/skins/Deere/library.xml +++ b/res/skins/Deere/library.xml @@ -147,16 +147,49 @@ - - LibraryCoverArt - coverart - me,me - 30,30 - - [Library],show_coverart - visible - - + + + + CratesSplitter + me,me + 1,1 + [LateNight],CratesSplitSize + horizontal + 0,0 + + + vertical + min,me + 100,-1 + + [Library],show_coverart + visible + + + + me,me + 40,40 + + + + + vertical + min,me + 100,-1 + + [Library],show_crates + visible + + + + me,me + 40,40 + [Library] + + + + + diff --git a/res/skins/LateNight/library.xml b/res/skins/LateNight/library.xml index f25f1ffc519f..9c6d8a76edc5 100644 --- a/res/skins/LateNight/library.xml +++ b/res/skins/LateNight/library.xml @@ -45,15 +45,48 @@ - - - me,me - 40,40 - - [Library],show_coverart - visible - - + + + CratesSplitter + me,me + 1,1 + [LateNight],CratesSplitSize + horizontal + 0,0 + + + vertical + min,me + 100,-1 + + [Library],show_coverart + visible + + + + me,me + 40,40 + + + + + vertical + min,me + 100,-1 + + [Library],show_crates + visible + + + + me,me + 40,40 + [Library] + + + + + diff --git a/res/skins/LateNight/skin.xml b/res/skins/LateNight/skin.xml index 8f7d5df78c03..4d10bd1996f9 100644 --- a/res/skins/LateNight/skin.xml +++ b/res/skins/LateNight/skin.xml @@ -48,6 +48,7 @@ 1 1 1 + 0 0 0 1 diff --git a/res/skins/LateNight/style.qss b/res/skins/LateNight/style.qss index e2659217fe89..6e4a020e70ac 100644 --- a/res/skins/LateNight/style.qss +++ b/res/skins/LateNight/style.qss @@ -1507,13 +1507,19 @@ WBaseLibrary QLabel { margin: 0px; } -QTreeView::item:selected:active, +QListView::item { + color: #cfb32c; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, QTableView::item:selected:active { color: #cfb32c; background-color: #725309; } QTreeView::item:selected:!active, +QListView::item:selected:!active, QTableView::item:selected:!active { color: #cfb32c; background-color: #4c3b11; @@ -1677,6 +1683,15 @@ WCoverArt { color: #ACACAC; } +WCrateList { + border-left: 2px solid #585858; + background-color: #0e0e0e; + padding-top: 2px; + padding-bottom: 2px; + /*border-top: 1px solid #585858;*/ +} + + /* splitter between treeview and library */ #LibrarySplitter::handle { image: url(skin:/style/style_handle_unchecked.png); @@ -1840,3 +1855,37 @@ QToolTip { border: 1px solid #333; border-radius: 2px; } + +/* Spacing between treeview and searchbar */ +QListView { margin: 10px 0px 0px 0px; } +QListView:focus { border: 1px solid #8E5C00; } + +/* triangle for closed/opened branches in treeview */ +QListView { show-decoration-selected: 0; background-color: #151515; } /* Suppresses that selected sidebar items branch indicator shows wrong color when out of focus ; lp:880588 */ +QListView::branch:has-children:!has-siblings:closed, +QListView::branch:closed:has-children:has-siblings { border-image: none; image: url(skin:/style/style_branch_closed.png); + background-color:#0f0f0f; +} +QListView::branch:open:has-children:!has-siblings, +QListView::branch:open:has-children:has-siblings { border-image: none; image: url(skin:/style/style_branch_open.png); + background-color:#0f0f0f; +} +QListView::branch:has-children:!has-siblings:closed:selected, +QListView::branch:closed:has-children:has-siblings:selected { border-image: none; image: url(skin:/style/style_branch_closed.png); + background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #585858, stop:1 #0f0f0f); +} +QListView::branch:open:has-children:!has-siblings:selected, +QListView::branch:open:has-children:has-siblings:selected { border-image: none; image: url(skin:/style/style_branch_open.png); + background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #585858, stop:1 #0f0f0f); +} + +QListView WCrateItemSome { + background-color: #FF0000; + color: black; +} + +QListView WCrateItemSome { + background-color: #FF0000; + color: black; +} + diff --git a/src/controllers/controlpickermenu.cpp b/src/controllers/controlpickermenu.cpp index e0a4b5cde4aa..4bb9decd5eb4 100644 --- a/src/controllers/controlpickermenu.cpp +++ b/src/controllers/controlpickermenu.cpp @@ -786,6 +786,9 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent) addControl("[Master]", "maximize_library", tr("Library Maximize/Restore"), tr("Maximize the track library to take up all the available screen space."), guiMenu); + addControl("[Library]", "show_crates", + tr("Crates List Show/Hide"), + tr("Show/hide list of crates"), guiMenu); QString spinnyTitle = tr("Vinyl Spinner Show/Hide"); QString spinnyDescription = tr("Show/hide spinning vinyl widget"); diff --git a/src/library/crate/crate.h b/src/library/crate/crate.h index 9eed1016437a..3bf42314b478 100644 --- a/src/library/crate/crate.h +++ b/src/library/crate/crate.h @@ -35,5 +35,6 @@ class Crate: public DbNamedEntity { bool m_autoDjSource; }; +Q_DECLARE_METATYPE(Crate); #endif // MIXXX_CRATE_H diff --git a/src/library/crate/cratesummary.h b/src/library/crate/cratesummary.h index 4318a9ee40b7..ae63d9e67117 100644 --- a/src/library/crate/cratesummary.h +++ b/src/library/crate/cratesummary.h @@ -42,5 +42,6 @@ class CrateSummary: public Crate { double m_trackDuration; }; +Q_DECLARE_METATYPE(CrateSummary); #endif // MIXXX_CRATESUMMARY_H diff --git a/src/library/library.cpp b/src/library/library.cpp index f13599305e11..69976374acd4 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -255,6 +255,8 @@ void Library::addFeature(LibraryFeature* feature) { this, SIGNAL(enableCoverArtDisplay(bool))); connect(feature, SIGNAL(trackSelected(TrackPointer)), this, SIGNAL(trackSelected(TrackPointer))); + connect(feature, SIGNAL(trackSelection(QList)), + this, SIGNAL(trackSelection(QList))); connect(feature, SIGNAL(hovered(LibraryFeature*)), this, SLOT(slotSetHoveredFeature(LibraryFeature*))); diff --git a/src/library/library.h b/src/library/library.h index e26a31ca91d6..cf137838e137 100644 --- a/src/library/library.h +++ b/src/library/library.h @@ -37,6 +37,7 @@ class WBaseLibrary; class WLibraryPane; class WLibrarySidebar; class WLibraryBreadCrumb; +class WCrateList; class WButtonBar; class WSearchLineEdit; class TreeItem; @@ -92,6 +93,10 @@ class Library: public QObject, return m_trackTableFont; } + inline TrackCollection* getTrackCollection() { + return m_pTrackCollection; + } + void switchToFeature(LibraryFeature* pFeature); void showBreadCrumb(int paneId, TreeItem* pTree); void showBreadCrumb(int paneId, const QString& text, const QIcon& icon); @@ -142,6 +147,7 @@ class Library: public QObject, // emit this signal to enable/disable the cover art widget void enableCoverArtDisplay(bool); void trackSelected(TrackPointer pTrack); + void trackSelection(QList pTrack); void setTrackTableFont(const QFont& font); void setTrackTableRowHeight(int rowHeight); diff --git a/src/library/libraryfeature.cpp b/src/library/libraryfeature.cpp index 6e5de569cb5e..d5c1a724fb4b 100644 --- a/src/library/libraryfeature.cpp +++ b/src/library/libraryfeature.cpp @@ -191,6 +191,8 @@ parented_ptr LibraryFeature::createTableWidget(int paneId, QWid this, SIGNAL(loadTrackToPlayer(TrackPointer, QString, bool))); connect(pTrackTableView.get(), SIGNAL(trackSelected(TrackPointer)), this, SIGNAL(trackSelected(TrackPointer))); + connect(pTrackTableView.get(), SIGNAL(trackSelection(QList)), + this, SIGNAL(trackSelection(QList))); connect(pTrackTableView.get(), SIGNAL(tableChanged()), this, SLOT(restoreSaveButton())); diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index 560681d38530..3388d0818559 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -123,6 +123,7 @@ class LibraryFeature : public QObject { // emit this signal to enable/disable the cover art widget void enableCoverArtDisplay(bool); void trackSelected(TrackPointer); + void trackSelection(QList); void hovered(LibraryFeature* pLibraryFeature); void leaved(LibraryFeature* pLibraryFeature); diff --git a/src/library/trackcollection.cpp b/src/library/trackcollection.cpp index 3b19cb99fb1c..82d9582a4205 100644 --- a/src/library/trackcollection.cpp +++ b/src/library/trackcollection.cpp @@ -20,7 +20,7 @@ TrackCollection::TrackCollection( : m_pConfig(pConfig), m_analysisDao(pConfig), m_trackDao(m_cueDao, m_playlistDao, - m_analysisDao, m_libraryHashDao, pConfig) { + m_analysisDao, m_libraryHashDao, pConfig) { } TrackCollection::~TrackCollection() { diff --git a/src/skin/legacyskinparser.cpp b/src/skin/legacyskinparser.cpp index 2fcae8ce8574..f4263814473d 100644 --- a/src/skin/legacyskinparser.cpp +++ b/src/skin/legacyskinparser.cpp @@ -39,6 +39,7 @@ #include "widget/controlwidgetconnection.h" #include "widget/wbasewidget.h" #include "widget/wcoverart.h" +#include "widget/wcratelist.h" #include "widget/wwidget.h" #include "widget/wknob.h" #include "widget/wknobcomposed.h" @@ -534,6 +535,8 @@ QList LegacySkinParser::parseNode(const QDomElement& node) { result = wrapWidget(parseText(node)); } else if (nodeName == "TrackProperty") { result = wrapWidget(parseTrackProperty(node)); + } else if (nodeName == "CrateList") { + result = wrapWidget(parseCrateList(node)); } else if (nodeName == "StarRating") { result = wrapWidget(parseStarRating(node)); } else if (nodeName == "VuMeter") { @@ -1225,6 +1228,7 @@ QWidget* LegacySkinParser::parseSearchBox(const QDomElement& node) { QWidget* LegacySkinParser::parseCoverArt(const QDomElement& node) { QString channel = lookupNodeGroup(node); + BaseTrackPlayer* pPlayer = m_pPlayerManager->getPlayer(channel); WCoverArt* pCoverArt = new WCoverArt(m_pParent, m_pConfig, channel, pPlayer); @@ -1246,6 +1250,44 @@ QWidget* LegacySkinParser::parseCoverArt(const QDomElement& node) { return pCoverArt; } + +QWidget* LegacySkinParser::parseCrateList(const QDomElement& node) { + QString channelStr = lookupNodeGroup(node); + const char* pSafeChannelStr = safeChannelString(channelStr); + + BaseTrackPlayer* pPlayer = m_pPlayerManager->getPlayer(channelStr); + + if (!pPlayer && channelStr.compare("[Library]", Qt::CaseInsensitive) != 0) { + SKIN_WARNING(node, *m_pContext) + << "CrateList widget requires a Deck or Library group"; + return NULL; + } + + WCrateList* p = new WCrateList(pSafeChannelStr, m_pConfig, m_pLibrary->getTrackCollection(), m_pParent); + + commonWidgetSetup(node, p); + p->setup(node, *m_pContext); + + if (pPlayer) { + connect(pPlayer, SIGNAL(newTrackLoaded(TrackPointer)), + p, SLOT(slotTrackLoaded(TrackPointer))); + connect(pPlayer, SIGNAL(loadingTrack(TrackPointer, TrackPointer)), + p, SLOT(slotTrackLoaded(TrackPointer))); + + TrackPointer pTrack = pPlayer->getLoadedTrack(); + if (pTrack) { + p->slotTrackLoaded(pTrack); + } + } else { + // hookup to library + connect(m_pLibrary, SIGNAL(switchToView(const QString&)), + p, SLOT(slotReset())); + connect(m_pLibrary, SIGNAL(trackSelection(QList)), + p, SLOT(slotTrackSelection(QList))); + } + return p; +} + void LegacySkinParser::parseSingletonDefinition(const QDomElement& node) { QString objectName = m_pContext->selectString(node, "ObjectName"); if (objectName.isEmpty()) { diff --git a/src/skin/legacyskinparser.h b/src/skin/legacyskinparser.h index ade7445c4d3c..369d1c9876ab 100644 --- a/src/skin/legacyskinparser.h +++ b/src/skin/legacyskinparser.h @@ -76,6 +76,7 @@ class LegacySkinParser : public QObject, public SkinParser { void setupLabelWidget(const QDomElement& element, WLabel* pLabel); QWidget* parseText(const QDomElement& node); QWidget* parseTrackProperty(const QDomElement& node); + QWidget* parseCrateList(const QDomElement& node); QWidget* parseStarRating(const QDomElement& node); QWidget* parseNumberRate(const QDomElement& node); QWidget* parseNumberPos(const QDomElement& node); diff --git a/src/skin/tooltips.cpp b/src/skin/tooltips.cpp index 785ff46cb11c..84c58bef8cf9 100644 --- a/src/skin/tooltips.cpp +++ b/src/skin/tooltips.cpp @@ -230,6 +230,10 @@ void Tooltips::addStandardTooltips() { << tr("Cover Art") << tr("Show/hide Cover Art."); + add("show_crates") + << tr("Crates List") + << tr("Show/hide Crates List."); + add("toggle_4decks") << tr("Toggle 4 Decks") << tr("Switches between showing 2 decks and 4 decks."); diff --git a/src/track/track.h b/src/track/track.h index 21b65b3317ff..5681a8a8469f 100644 --- a/src/track/track.h +++ b/src/track/track.h @@ -376,6 +376,9 @@ class Track : public QObject { // The list of cue points for the track QList m_cuePoints; + // A resolved list of the crates the track is in + QStringList m_cratesList; + // Storage for the track's beats BeatsPointer m_pBeats; diff --git a/src/widget/wcratelist.cpp b/src/widget/wcratelist.cpp new file mode 100644 index 000000000000..adc282ed2c81 --- /dev/null +++ b/src/widget/wcratelist.cpp @@ -0,0 +1,146 @@ + +#include +#include +#include +#include +#include +#include + +#include "control/controlobject.h" +#include "widget/wcratelist.h" +#include "util/dnd.h" + + +WCrateListWorker::WCrateListWorker(QObject* parent, const TrackCollection* pCollection): + QObject(parent) { + DEBUG_ASSERT(pCollection != nullptr); + + m_pTrackCollection = pCollection; + +} + +WCrateItem::WCrateItem(const QString &text, QListWidget *parent): + QListWidgetItem(text, parent, QListWidgetItem::UserType) {} + +WCrateItemSome::WCrateItemSome(const QString &text, QListWidget *parent): + QListWidgetItem(text, parent, QListWidgetItem::UserType) {} + + +void WCrateListWorker::query(int query, QList trackIds) { + QString where = QString(" WHERE %1 > 0 ").arg("track_count"); + + QList rv = QList(); + rv.reserve(trackIds.length()); + + CrateSummarySelectResult results = m_pTrackCollection->crates().selectCratesWithTrackCount(trackIds); + + CrateSummary crate; + while (results.populateNext(&crate)) { + if (crate.getTrackCount() == 0) + continue; + rv.append(crate); + } + emit(result(query, trackIds.length(), rv)); +} + +QThread* WCrateList::s_worker_thread = nullptr; //QThread(); + +WCrateList::WCrateList(const char* group, UserSettingsPointer pConfig, + const TrackCollection* pCollection, QWidget* pParent) + : QListWidget(pParent), WBaseWidget(pParent), + m_pGroup(group), + m_pConfig(pConfig), + m_pCollection(pCollection) { + + // FIXME(poelzi): does it make sense to allow drops of certain stuff ??? + setAcceptDrops(false); + + // initilize the shared worker thread + if (s_worker_thread == nullptr) { + // initialize the worker thread shared between all widgets on first use + s_worker_thread = new QThread(nullptr); + s_worker_thread->setObjectName("wcratelistworker"); + s_worker_thread->start(QThread::LowPriority); + qDebug() << "worker thread initialized"; + } + m_pWorker = new WCrateListWorker(this, pCollection); + m_pWorker->moveToThread(s_worker_thread); + + connect(m_pWorker, SIGNAL(result(int, uint, QList)), + this, SLOT(receiveResults(int, uint, QList))); + connect(this, SIGNAL(query(int, QList)), + m_pWorker, SLOT(query(int, QList))); +} + +// generates unique id's for all worker requests +int WCrateList::s_last_id = 0; + +int WCrateList::generateId() { + return ++s_last_id; +} + +void WCrateList::receiveResults(int query, uint total, QList crates) { + // we are only interested in results we requested last + if (query != m_id) { + return; + } + + foreach (CrateSummary crate, crates) { + if (crate.getTrackCount() == total) { + WCrateItem *item = new WCrateItem(crate.getName(), this); + addItem(item); + } else { + WCrateItemSome *item = new WCrateItemSome(crate.getName(), this); + addItem(item); + } + + } +} + +void WCrateList::slotTrackLoaded(TrackPointer track) { + clear(); + if (track == nullptr) { + return; + } + m_id = generateId(); + + QList lst = QList(); + lst.append(track->getId()); + emit query(m_id, lst); +} + +void WCrateList::slotTrackSelection(QList tracks) { + clear(); + + m_id = generateId(); + + QList lst = QList(); + lst.reserve(tracks.size()); + + foreach (auto track, tracks) { + if (track != nullptr) { + lst.append(track->getId()); + } + } + + emit query(m_id, lst); +} + +void WCrateList::setup(const QDomNode& node, const SkinContext& context) { + Q_UNUSED(node); + Q_UNUSED(context); +} + +void WCrateList::mouseMoveEvent(QMouseEvent *event) { + if ((event->buttons() & Qt::LeftButton) && m_pCurrentTrack) { + DragAndDropHelper::dragTrack(m_pCurrentTrack, this, m_pGroup); + } +} + +void WCrateList::dragEnterEvent(QDragEnterEvent *event) { + event->ignore(); +} + +void WCrateList::dropEvent(QDropEvent *event) { + event->ignore(); +} diff --git a/src/widget/wcratelist.h b/src/widget/wcratelist.h new file mode 100644 index 000000000000..c9da374b7e9b --- /dev/null +++ b/src/widget/wcratelist.h @@ -0,0 +1,85 @@ +#ifndef WCrateList_H +#define WCrateList_H + +#include +#include +#include +#include +#include +#include + +#include "preferences/usersettings.h" +#include "skin/skincontext.h" +#include "track/track.h" +#include "library/features/crates/cratestorage.h" +#include "library/trackcollection.h" +#include "widget/wlabel.h" + + + +class WCrateListWorker : public QObject { + Q_OBJECT +public: + WCrateListWorker(QObject* parent, const TrackCollection* collection); + ~WCrateListWorker() = default; +public slots: + void query(int query, QList); +signals: + void result(int query, uint total, QList); +private: + // add your variables here + const TrackCollection* m_pTrackCollection; +}; + +class WCrateItem : public QListWidgetItem { +public: + WCrateItem(const QString &text, QListWidget *parent); +}; + +class WCrateItemSome : public QListWidgetItem { +public: + WCrateItemSome(const QString &text, QListWidget *parent); +}; + +class WCrateList : public QListWidget, public WBaseWidget { + Q_OBJECT + public: + WCrateList(const char* group, UserSettingsPointer pConfig, const TrackCollection* collection, QWidget* pParent); + + void setup(const QDomNode& node, const SkinContext& context); + int generateId(); + + signals: + void trackDropped(QString filename, QString group); + void query(int query, QList); + + public slots: + void slotTrackLoaded(TrackPointer track); + void slotTrackSelection(QList tracks); + //void slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldTrack); + + private slots: + //void updateLabel(Track*); + void receiveResults(int query, uint total, QList); + + private: + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + + const char* m_pGroup; + UserSettingsPointer m_pConfig; + TrackPointer m_pCurrentTrack; + //QString m_property; + //QString m_seperator; + const TrackCollection* m_pCollection; + //const CrateStorage* m_cratestore; + int m_id; + WCrateListWorker* m_pWorker; + + // shared worker thread + static QThread* s_worker_thread; + // id generation + static int s_last_id; +}; +#endif /* WCrateList_H */ diff --git a/src/widget/wlibrarytableview.h b/src/widget/wlibrarytableview.h index 08093e96c8ce..8ad87ef62f65 100644 --- a/src/widget/wlibrarytableview.h +++ b/src/widget/wlibrarytableview.h @@ -48,6 +48,7 @@ class WLibraryTableView : public QTableView, public virtual LibraryView { void loadTrackToPlayer(TrackPointer pTrack, QString group, bool play = false); void trackSelected(TrackPointer pTrack); + void trackSelection(QList); void onlyCachedCoverArt(bool); void scrollValueChanged(int); diff --git a/src/widget/wmainmenubar.cpp b/src/widget/wmainmenubar.cpp index 9032e5885fdf..6483cddd4960 100644 --- a/src/widget/wmainmenubar.cpp +++ b/src/widget/wmainmenubar.cpp @@ -241,6 +241,22 @@ void WMainMenuBar::initialize() { createVisibilityControl(pLibraryText, ConfigKey("[Library]", "show_icon_text")); pViewMenu->addAction(pLibraryText); + + QString showCratesTitle = tr("Show Crates List"); + QString showCratesText = tr("Show a list with crates the selection is in") + + " " + mayNotBeSupported; + auto pViewShowCrates = new QAction(showCratesTitle, this); + pViewShowCrates->setCheckable(true); + pViewShowCrates->setShortcut( + QKeySequence(m_pKbdConfig->getValue( + ConfigKey("[KeyboardShortcuts]", "ViewMenu_ShowCrates"), + tr("Ctrl+7", "Menubar|View|Show Crates Section")))); + pViewShowCrates->setStatusTip(showCratesText); + pViewShowCrates->setWhatsThis(buildWhatsThis(showCratesTitle, showCratesText)); + createVisibilityControl(pViewShowCrates, ConfigKey("[Library]", "show_crates")); + pViewMenu->addAction(pViewShowCrates); + + QString maximizeLibraryTitle = tr("Maximize Library"); QString maximizeLibraryText = tr("Maximize the track library to take up all the available screen space.") + " " + mayNotBeSupported; diff --git a/src/widget/wtrackproperty.cpp b/src/widget/wtrackproperty.cpp index a03acc3c0cb4..cffc50adeb3a 100644 --- a/src/widget/wtrackproperty.cpp +++ b/src/widget/wtrackproperty.cpp @@ -1,6 +1,7 @@ #include #include +#include #include "control/controlobject.h" #include "widget/wtrackproperty.h" diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp index 2c745acd209a..410939e57018 100644 --- a/src/widget/wtracktableview.cpp +++ b/src/widget/wtracktableview.cpp @@ -217,6 +217,16 @@ void WTrackTableView::slotGuiTick50ms(double /*unused*/) { if (pTrack) { emit(trackSelected(pTrack)); } + // emit list of all selected track + auto signal_data = QList(); + signal_data.reserve(indices.size()); + foreach (auto track, indices) { + pTrack = trackModel->getTrack(track); + if (pTrack) { + signal_data.append(pTrack); + } + } + emit(trackSelection(signal_data)); } } else { emit(trackSelected(TrackPointer())); From 6897508acc90809015343812599bd259d009ec0b Mon Sep 17 00:00:00 2001 From: Daniel Poelzleithner Date: Wed, 2 May 2018 08:50:57 +0200 Subject: [PATCH 2/2] undo whitespace change --- src/library/trackcollection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/trackcollection.cpp b/src/library/trackcollection.cpp index 82d9582a4205..3b19cb99fb1c 100644 --- a/src/library/trackcollection.cpp +++ b/src/library/trackcollection.cpp @@ -20,7 +20,7 @@ TrackCollection::TrackCollection( : m_pConfig(pConfig), m_analysisDao(pConfig), m_trackDao(m_cueDao, m_playlistDao, - m_analysisDao, m_libraryHashDao, pConfig) { + m_analysisDao, m_libraryHashDao, pConfig) { } TrackCollection::~TrackCollection() {