Skip to content

Commit

Permalink
Library sidebar: handle item selection in DAO callback slots ...
Browse files Browse the repository at this point in the history
not in preceeding action slots, since this is easier to maintain and more robust,
i.e. consistent right-click & select UX
  • Loading branch information
ronso0 committed Jan 30, 2023
1 parent b2a61f6 commit 11a3f5e
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 74 deletions.
27 changes: 4 additions & 23 deletions src/library/trackset/baseplaylistfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,8 @@ void BasePlaylistFeature::slotDuplicatePlaylist() {

int newPlaylistId = m_playlistDao.createPlaylist(name);

if (newPlaylistId != kInvalidPlaylistId &&
m_playlistDao.copyPlaylistTracks(oldPlaylistId, newPlaylistId)) {
// Note: this assumes the sidebar model was already updated by slotPlaylisttableChanged
// and the sidebar scrolled to the new playlist
activatePlaylist(oldPlaylistId);
if (newPlaylistId != kInvalidPlaylistId) {
m_playlistDao.copyPlaylistTracks(oldPlaylistId, newPlaylistId);
}
}

Expand Down Expand Up @@ -420,21 +417,12 @@ void BasePlaylistFeature::slotDeletePlaylist() {
return;
}

// we will switch to the sibling if the deleted playlist is currently active
bool wasActive = m_pPlaylistTableModel->getPlaylist() == playlistId;

VERIFY_OR_DEBUG_ASSERT(playlistId >= 0) {
return;
}

bool locked = m_playlistDao.isPlaylistLocked(playlistId);
if (locked) {
qDebug() << "Skipping playlist deletion because playlist" << playlistId << "is locked.";
return;
}

int siblingId = getSiblingPlaylistIdOf(m_lastRightClickedIndex);

QMessageBox::StandardButton btn = QMessageBox::question(nullptr,
tr("Confirm Deletion"),
tr("Do you really want to delete playlist <b>%1</b>?")
Expand All @@ -446,15 +434,6 @@ void BasePlaylistFeature::slotDeletePlaylist() {
}

m_playlistDao.deletePlaylist(playlistId);

if (siblingId == kInvalidPlaylistId) {
return;
}
if (wasActive) {
activatePlaylist(siblingId);
} else if (m_pSidebarWidget) {
m_pSidebarWidget->selectChildIndex(indexFromPlaylistId(siblingId), false);
}
}

void BasePlaylistFeature::slotImportPlaylist() {
Expand Down Expand Up @@ -755,6 +734,8 @@ void BasePlaylistFeature::updateChildModel(int playlistId) {

/// Clears the child model dynamically, but the invisible root item remains
void BasePlaylistFeature::clearChildModel() {
m_lastClickedIndex = QModelIndex();
m_lastRightClickedIndex = QModelIndex();
m_pSidebarModel->removeRows(0, m_pSidebarModel->rowCount());
}

Expand Down
36 changes: 19 additions & 17 deletions src/library/trackset/crate/cratefeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,14 @@ void CrateFeature::activate() {
}

void CrateFeature::activateChild(const QModelIndex& index) {
//qDebug() << "CrateFeature::activateChild()" << index;
qDebug() << " CrateFeature::activateChild()" << index;
CrateId crateId(crateIdFromIndex(index));
VERIFY_OR_DEBUG_ASSERT(crateId.isValid()) {
return;
}
m_lastClickedIndex = index;
m_lastRightClickedIndex = QModelIndex();
m_prevSiblingCrate = CrateId();
emit saveModelState();
m_crateTableModel.selectCrate(crateId);
emit showTrackModel(&m_crateTableModel);
Expand All @@ -323,9 +324,10 @@ bool CrateFeature::activateCrate(CrateId crateId) {
VERIFY_OR_DEBUG_ASSERT(index.isValid()) {
return false;
}
emit saveModelState();
m_lastClickedIndex = index;
m_lastRightClickedIndex = QModelIndex();
m_prevSiblingCrate = CrateId();
emit saveModelState();
m_crateTableModel.selectCrate(crateId);
emit showTrackModel(&m_crateTableModel);
emit enableCoverArtDisplay(true);
Expand Down Expand Up @@ -434,7 +436,11 @@ void CrateFeature::slotDeleteCrate() {
CrateId crateId = crate.getId();
// Store sibling id to restore selection after crate was deleted
// to avoid the scroll position being reset to Crate root item.
storePrevSiblingCrateId(crateId);
m_prevSiblingCrate = CrateId();
if (isChildIndexSelectedInSidebar(m_lastRightClickedIndex)) {
storePrevSiblingCrateId(crateId);
}

QMessageBox::StandardButton btn = QMessageBox::question(nullptr,
tr("Confirm Deletion"),
tr("Do you really want to delete crate <b>%1</b>?")
Expand Down Expand Up @@ -509,13 +515,10 @@ void CrateFeature::slotDuplicateCrate() {
.duplicateCrate(crate);
if (newCrateId.isValid()) {
qDebug() << "Duplicate crate" << crate << ", new crate:" << newCrateId;
// expand Crates and scroll to new crate
m_pSidebarWidget->selectChildIndex(indexFromCrateId(newCrateId), false);
activateCrate(crate.getId());
return;
}
} else {
qDebug() << "Failed to duplicate selected crate";
}
qDebug() << "Failed to duplicate selected crate";
}

void CrateFeature::slotToggleCrateLock() {
Expand Down Expand Up @@ -856,15 +859,14 @@ void CrateFeature::storePrevSiblingCrateId(CrateId crateId) {
}

void CrateFeature::slotCrateTableChanged(CrateId crateId) {
if (m_lastRightClickedIndex.isValid() &&
(crateIdFromIndex(m_lastRightClickedIndex) == crateId)) {
// Try to restore previous selection
m_lastRightClickedIndex = rebuildChildModel(crateId);
if (m_lastRightClickedIndex.isValid()) {
// Select last active crate
activateCrate(crateId);
} else if (m_prevSiblingCrate.isValid()) {
// Select neighbour of deleted crate
Q_UNUSED(crateId);
if (isChildIndexSelectedInSidebar(m_lastClickedIndex)) {
// If the previously selected crate was loaded to the tracks table and
// selected in the sidebar try to activate that or a sibling
rebuildChildModel();
if (!activateCrate(m_crateTableModel.selectedCrate())) {
// probably last clicked crate was deleted, try to
// select the stored sibling
activateCrate(m_prevSiblingCrate);
}
} else {
Expand Down
23 changes: 22 additions & 1 deletion src/library/trackset/playlistfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,29 @@ void PlaylistFeature::slotPlaylistTableChanged(int playlistId) {
enum PlaylistDAO::HiddenType type = m_playlistDao.getHiddenType(playlistId);
if (type == PlaylistDAO::PLHT_NOT_HIDDEN ||
type == PlaylistDAO::PLHT_UNKNOWN) { // In case of a deleted Playlist
// Store current selection
int selectedPlaylistId = kInvalidPlaylistId;
if (isChildIndexSelectedInSidebar(m_lastClickedIndex)) {
if (playlistId == playlistIdFromIndex(m_lastClickedIndex) &&
type == PlaylistDAO::PLHT_UNKNOWN) {
// if the selected playlist was deleted, find a sibling to select
selectedPlaylistId = getSiblingPlaylistIdOf(m_lastClickedIndex);
} else {
// just restore the current selection
selectedPlaylistId = playlistIdFromIndex(m_lastClickedIndex);
}
}

clearChildModel();
m_lastRightClickedIndex = constructChildModel(playlistId);
QModelIndex newIndex = constructChildModel(selectedPlaylistId);
if (newIndex.isValid()) {
// If a child index was selected and we got a new valid index select that.
// Else (root item was selected or for some reason no index could be created)
// there's nothing to do: either no child was selected earlier, or the root
// was selected and will remain selected after the child model was rebuilt.
activateChild(newIndex);
emit featureSelect(this, newIndex);
}
}
}

Expand Down
114 changes: 82 additions & 32 deletions src/library/trackset/setlogfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,9 @@ QModelIndex SetlogFeature::constructChildModel(int selectedId) {
int idColumn = record.indexOf("id");
int createdColumn = record.indexOf("date_created");

// Nice to have: restore previous expanded/collapsed state of YEAR items
clearChildModel();
QMap<int, TreeItem*> groups;

QList<TreeItem*> itemList;
// Generous estimate (number of years the db is used ;))
itemList.reserve(kNumToplevelHistoryEntries + 15);
Expand All @@ -229,16 +230,19 @@ QModelIndex SetlogFeature::constructChildModel(int selectedId) {
.toDateTime();

// Create the TreeItem whose parent is the invisible root item
// Show only [kNumToplevelHistoryEntries -1] recent playlists at the top
// level before grouping them by year.
// Show only [kNumToplevelHistoryEntries] recent playlists at the top level
// before grouping them by year.
if (row >= kNumToplevelHistoryEntries) {
// group by year
int yearCreated = dateCreated.date().year();

auto i = groups.find(yearCreated);
TreeItem* groupItem;
if (i != groups.end() && i.key() == yearCreated) {
// get YEAR item the playlist will sorted into
groupItem = i.value();
} else {
// create YEAR item the playlist will sorted into
// store id of empty placeholder playlist
groupItem = new TreeItem(QString::number(yearCreated), m_placeholderId);
groups.insert(yearCreated, groupItem);
Expand All @@ -252,6 +256,7 @@ QModelIndex SetlogFeature::constructChildModel(int selectedId) {

groupItem->appendChild(std::move(item));
} else {
// add most recent top-level playlist
TreeItem* item = new TreeItem(name, id);
item->setBold(m_playlistIdsOfSelectedTrack.contains(id));

Expand All @@ -264,10 +269,7 @@ QModelIndex SetlogFeature::constructChildModel(int selectedId) {
// Append all the newly created TreeItems in a dynamic way to the childmodel
m_pSidebarModel->insertTreeItemRows(itemList, 0);

if (selectedId) {
return indexFromPlaylistId(selectedId);
}
return QModelIndex();
return indexFromPlaylistId(selectedId);
}

QString SetlogFeature::fetchPlaylistLabel(int playlistId) {
Expand Down Expand Up @@ -384,11 +386,7 @@ void SetlogFeature::slotJoinWithPrevious() {
<< " previous:" << previousPlaylistId;
if (m_playlistDao.copyPlaylistTracks(
currentPlaylistId, previousPlaylistId)) {
m_lastRightClickedIndex = constructChildModel(previousPlaylistId);
m_playlistDao.deletePlaylist(currentPlaylistId);
reloadChildModel(previousPlaylistId); // For moving selection
emit showTrackModel(m_pPlaylistTableModel);
activatePlaylist(previousPlaylistId);
}
}
}
Expand Down Expand Up @@ -523,16 +521,61 @@ void SetlogFeature::slotPlayingTrackChanged(TrackPointer currentPlayingTrack) {
}

void SetlogFeature::slotPlaylistTableChanged(int playlistId) {
reloadChildModel(playlistId);
}

void SetlogFeature::reloadChildModel(int playlistId) {
//qDebug() << "updateChildModel() playlistId:" << playlistId;
PlaylistDAO::HiddenType type = m_playlistDao.getHiddenType(playlistId);
if (type == PlaylistDAO::PLHT_SET_LOG ||
type == PlaylistDAO::PLHT_UNKNOWN) { // In case of a deleted Playlist
clearChildModel();
m_lastRightClickedIndex = constructChildModel(playlistId);
if (type != PlaylistDAO::PLHT_SET_LOG &&
type != PlaylistDAO::PLHT_UNKNOWN) { // deleted Playlist
return;
}

// save currently selected History sidebar item (if any)
int selectedYearIndexRow = -1;
int selectedPlaylistId = kInvalidPlaylistId;
bool rootWasSelected = false;
if (isChildIndexSelectedInSidebar(m_lastClickedIndex)) {
// a child index was selected (actual playlist or YEAR item)
int lastClickedPlaylistId = m_pPlaylistTableModel->getPlaylist();
if (lastClickedPlaylistId == m_placeholderId) {
// a YEAR item was selected
selectedYearIndexRow = m_lastClickedIndex.row();
} else if (playlistId == lastClickedPlaylistId &&
type == PlaylistDAO::PLHT_UNKNOWN) {
// selected playlist was deleted, find a sibling.
// prev/next works here because history playlists are always
// sorted by date of creation.
selectedPlaylistId = m_playlistDao.getPreviousPlaylist(
lastClickedPlaylistId,
PlaylistDAO::PLHT_SET_LOG);
if (selectedPlaylistId == kInvalidPlaylistId) {
// no previous playlist, try to get the next playlist
selectedPlaylistId = m_playlistDao.getNextPlaylist(
lastClickedPlaylistId,
PlaylistDAO::PLHT_SET_LOG);
}
} else {
selectedPlaylistId = lastClickedPlaylistId;
}
} else {
rootWasSelected = m_pSidebarWidget &&
m_pSidebarWidget->isFeatureRootIndexSelected(this);
}

QModelIndex newIndex = constructChildModel(selectedPlaylistId);

// restore selection
if (selectedYearIndexRow != -1) {
// if row is valid this means newIndex is invalid anyway
newIndex = m_pSidebarModel->index(selectedYearIndexRow, 0);
if (!newIndex.isValid()) {
// seems like we deleted the oldest (bottom) YEAR node while it was
// selected. Try to pick the row above
newIndex = m_pSidebarModel->index(selectedYearIndexRow - 1, 0);
}
}
if (newIndex.isValid() || rootWasSelected) {
// calling featureSelect with invalid index will select the root item
emit featureSelect(this, newIndex);
activateChild(newIndex);
}
}

Expand Down Expand Up @@ -561,7 +604,7 @@ void SetlogFeature::slotPlaylistTableRenamed(int playlistId, const QString& newN

void SetlogFeature::activate() {
// The root item was clicked, so actuvate the current playlist.
m_lastClickedIndex = QModelIndex();
m_lastClickedIndex = m_pSidebarModel->getRootIndex();
activatePlaylist(m_playlistId);
}

Expand All @@ -571,18 +614,25 @@ void SetlogFeature::activatePlaylist(int playlistId) {
return;
}
QModelIndex index = indexFromPlaylistId(playlistId);
if (index.isValid()) {
emit saveModelState();
m_pPlaylistTableModel->setTableModel(playlistId);
emit showTrackModel(m_pPlaylistTableModel);
emit enableCoverArtDisplay(true);
// Update sidebar selection only if this is a child, incl. current playlist.
// indexFromPlaylistId() can't be used because, in case the root item was
// selected, that would switch to the 'current' child.
if (m_lastClickedIndex.isValid()) {
emit featureSelect(this, index);
activateChild(index);
}
VERIFY_OR_DEBUG_ASSERT(index.isValid()) {
return;
}
emit saveModelState();
m_pPlaylistTableModel->setTableModel(playlistId);
emit showTrackModel(m_pPlaylistTableModel);
emit enableCoverArtDisplay(true);
// Update sidebar selection only if this is a child, incl. current playlist.
// indexFromPlaylistId() can't be used because, in case the root item was
// selected, that would switch to the 'current' child.
if (m_lastClickedIndex != m_pSidebarModel->getRootIndex()) {
m_lastClickedIndex = index;
emit featureSelect(this, index);
// redundant
// activateChild(index);

// TODO(ronso0) Disable search for YEAR items
// emit disableSearch();
// emit enableCoverArtDisplay(false);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/library/trackset/setlogfeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class SetlogFeature : public BasePlaylistFeature {

private:
void deleteAllUnlockedPlaylistsWithFewerTracks();
void reloadChildModel(int playlistId);
QString getRootViewHtml() const override;

std::list<TrackId> m_recentTracks;
Expand Down

0 comments on commit 11a3f5e

Please sign in to comment.