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