Skip to content

Commit

Permalink
Merge pull request mixxxdj#617 from rryan/sidebar-highlight
Browse files Browse the repository at this point in the history
Highlight Crates a Track is in
  • Loading branch information
rryan committed Jun 10, 2015
2 parents eca1adc + de3e581 commit 4a103da
Show file tree
Hide file tree
Showing 13 changed files with 281 additions and 11 deletions.
42 changes: 42 additions & 0 deletions src/library/baseplaylistfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <QFileInfo>
#include <QDesktopServices>

#include "library/library.h"
#include "library/parser.h"
#include "library/parserm3u.h"
#include "library/parserpls.h"
Expand Down Expand Up @@ -82,6 +83,12 @@ BasePlaylistFeature::BasePlaylistFeature(QObject* parent,

connect(&m_playlistDao, SIGNAL(lockChanged(int)),
this, SLOT(slotPlaylistTableChanged(int)));

Library* pLibrary = static_cast<Library*>(parent);
connect(pLibrary, SIGNAL(trackSelected(TrackPointer)),
this, SLOT(slotTrackSelected(TrackPointer)));
connect(pLibrary, SIGNAL(switchToView(const QString&)),
this, SLOT(slotResetSelectedTrack()));
}

BasePlaylistFeature::~BasePlaylistFeature() {
Expand Down Expand Up @@ -553,6 +560,8 @@ 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_playlistsSelectedTrackIsIn.contains(playlist_id));

decorateChild(item, playlist_id);
data_list.append(item);
}
Expand Down Expand Up @@ -585,3 +594,36 @@ QModelIndex BasePlaylistFeature::indexFromPlaylistId(int playlistId) {
}
return QModelIndex();
}

void BasePlaylistFeature::slotTrackSelected(TrackPointer pTrack) {
m_pSelectedTrack = 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<QPair<int, QString> >::const_iterator it = m_playlistList.begin();
it != m_playlistList.end(); ++it, ++row) {
TreeItem* playlist = rootItem->child(row);
if (playlist == nullptr) {
continue;
}

int playlistId = it->first;
bool shouldBold = m_playlistsSelectedTrackIsIn.contains(playlistId);
playlist->setBold(shouldBold);
}

m_childModel.triggerRepaint();
}


void BasePlaylistFeature::slotResetSelectedTrack() {
slotTrackSelected(TrackPointer());
}
8 changes: 8 additions & 0 deletions src/library/baseplaylistfeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
#include <QAction>
#include <QList>
#include <QPair>
#include <QSet>
#include <QString>

#include "library/libraryfeature.h"
#include "library/dao/playlistdao.h"
#include "library/dao/trackdao.h"
#include "trackinfoobject.h"

class WLibrary;
class MixxxKeyboard;
Expand Down Expand Up @@ -89,10 +91,16 @@ class BasePlaylistFeature : public LibraryFeature {
QList<QPair<int, QString> > m_playlistList;
QModelIndex m_lastRightClickedIndex;
TreeItemModel m_childModel;
TrackPointer m_pSelectedTrack;

private slots:
void slotTrackSelected(TrackPointer pTrack);
void slotResetSelectedTrack();

private:
virtual QString getRootViewHtml() const = 0;

QSet<int> m_playlistsSelectedTrackIsIn;
QString m_rootViewName;
};

Expand Down
40 changes: 38 additions & 2 deletions src/library/cratefeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@
#include "util/dnd.h"
#include "util/time.h"

CrateFeature::CrateFeature(QObject* parent,
CrateFeature::CrateFeature(Library* pLibrary,
TrackCollection* pTrackCollection,
ConfigObject<ConfigValue>* 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()));
Expand Down Expand Up @@ -92,6 +91,11 @@ CrateFeature::CrateFeature(QObject* parent,
TreeItem *rootItem = new TreeItem();
m_childModel.setRootItem(rootItem);
constructChildModel(-1);

connect(pLibrary, SIGNAL(trackSelected(TrackPointer)),
this, SLOT(slotTrackSelected(TrackPointer)));
connect(pLibrary, SIGNAL(switchToView(const QString&)),
this, SLOT(slotResetSelectedTrack()));
}

CrateFeature::~CrateFeature() {
Expand Down Expand Up @@ -510,6 +514,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_cratesSelectedTrackIsIn.contains(crate_id));
data_list.append(item);
}

Expand Down Expand Up @@ -704,3 +709,34 @@ QString CrateFeature::getRootViewHtml() const {
html.append("</td></tr></table>");
return html;
}

void CrateFeature::slotTrackSelected(TrackPointer pTrack) {
m_pSelectedTrack = 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<QPair<int, QString> >::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;
bool shouldBold = m_cratesSelectedTrackIsIn.contains(crateId);
crate->setBold(shouldBold);
}

m_childModel.triggerRepaint();
}

void CrateFeature::slotResetSelectedTrack() {
slotTrackSelected(TrackPointer());
}
11 changes: 10 additions & 1 deletion src/library/cratefeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,22 @@
#include <QUrl>
#include <QIcon>
#include <QPoint>
#include <QSet>

#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<ConfigValue>* pConfig);
virtual ~CrateFeature();
Expand Down Expand Up @@ -60,6 +63,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);
Expand All @@ -85,6 +92,8 @@ class CrateFeature : public LibraryFeature {
QModelIndex m_lastRightClickedIndex;
TreeItemModel m_childModel;
ConfigObject<ConfigValue>* m_pConfig;
TrackPointer m_pSelectedTrack;
QSet<int> m_cratesSelectedTrackIsIn;
};

#endif /* CRATEFEATURE_H */
63 changes: 63 additions & 0 deletions src/library/dao/cratedao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,36 @@ CrateDAO::~CrateDAO() {

void CrateDAO::initialize() {
qDebug() << "CrateDAO::initialize()";

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

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(trackIdColumn).toInt(),
query.value(crateIdColumn).toInt());
}
}

unsigned int CrateDAO::crateCount() {
Expand Down Expand Up @@ -236,6 +266,17 @@ bool CrateDAO::deleteCrate(const int crateId) {
transaction.commit();

emit(deleted(crateId));

// Update in-memory map
for (QMultiHash<int, int>::iterator it = m_cratesTrackIsIn.begin();
it != m_cratesTrackIsIn.end();) {
if (it.value() == crateId) {
it = m_cratesTrackIsIn.erase(it);
} else {
it++;
}
}

return true;
}

Expand Down Expand Up @@ -332,6 +373,7 @@ bool CrateDAO::addTrackToCrate(const int trackId, const int crateId) {
return false;
}

m_cratesTrackIsIn.insert(trackId, crateId);
emit(trackAdded(crateId, trackId));
emit(changed(crateId));
return true;
Expand All @@ -358,6 +400,7 @@ int CrateDAO::addTracksToCrate(const int crateId, QList<int>* trackIdList) {

// Emitting the trackAdded signals for each trackID outside the transaction
foreach(int trackId, *trackIdList) {
m_cratesTrackIsIn.insert(trackId, crateId);
emit(trackAdded(crateId, trackId));
}

Expand All @@ -379,6 +422,7 @@ bool CrateDAO::removeTrackFromCrate(const int trackId, const int crateId) {
return false;
}

m_cratesTrackIsIn.remove(trackId, crateId);
emit(trackRemoved(crateId, trackId));
emit(changed(crateId));
return true;
Expand All @@ -400,6 +444,7 @@ bool CrateDAO::removeTracksFromCrate(const QList<int>& ids, const int crateId) {
return false;
}
foreach (int trackId, ids) {
m_cratesTrackIsIn.remove(trackId, crateId);
emit(trackRemoved(crateId, trackId));
}
emit(changed(crateId));
Expand All @@ -418,7 +463,25 @@ void CrateDAO::removeTracksFromCrates(const QList<int>& 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));
}

bool CrateDAO::isTrackInCrate(const int trackId, const int crateId) {
return m_cratesTrackIsIn.contains(trackId, crateId);
}

void CrateDAO::getCratesTrackIsIn(const int trackId,
QSet<int>* crateSet) const {
crateSet->clear();
for (QHash<int, int>::const_iterator it = m_cratesTrackIsIn.find(trackId);
it != m_cratesTrackIsIn.end() && it.key() == trackId; ++it) {
crateSet->insert(it.value());
}
}
7 changes: 7 additions & 0 deletions src/library/dao/cratedao.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

#include <QObject>
#include <QMap>
#include <QMultiHash>
#include <QSqlDatabase>
#include <QSet>

#include "library/dao/dao.h"
#include "util.h"
Expand Down Expand Up @@ -61,6 +63,8 @@ class CrateDAO : public QObject, public virtual DAO {
bool removeTracksFromCrate(const QList<int>& ids, const int crateId);
// remove tracks from all crates
void removeTracksFromCrates(const QList<int>& ids);
bool isTrackInCrate(const int trackId, const int crateId);
void getCratesTrackIsIn(const int trackId, QSet<int>* crateSet) const;

signals:
void added(int crateId);
Expand All @@ -73,7 +77,10 @@ class CrateDAO : public QObject, public virtual DAO {
void autoDjChanged(int a_iCrateId, bool a_bIn);

private:
void populateCrateMembershipCache();

QSqlDatabase& m_database;
QMultiHash<int,int> m_cratesTrackIsIn;
DISALLOW_COPY_AND_ASSIGN(CrateDAO);
};

Expand Down
Loading

0 comments on commit 4a103da

Please sign in to comment.