diff --git a/src/library/trackset/baseplaylistfeature.cpp b/src/library/trackset/baseplaylistfeature.cpp
index 970a2f98722..efa722620f8 100644
--- a/src/library/trackset/baseplaylistfeature.cpp
+++ b/src/library/trackset/baseplaylistfeature.cpp
@@ -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);
}
}
@@ -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 %1?")
@@ -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() {
@@ -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());
}
diff --git a/src/library/trackset/crate/cratefeature.cpp b/src/library/trackset/crate/cratefeature.cpp
index 7db9e7700cc..9845e13bb68 100644
--- a/src/library/trackset/crate/cratefeature.cpp
+++ b/src/library/trackset/crate/cratefeature.cpp
@@ -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);
@@ -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);
@@ -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 %1?")
@@ -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() {
@@ -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 {
diff --git a/src/library/trackset/playlistfeature.cpp b/src/library/trackset/playlistfeature.cpp
index 92015e90316..bf6a1c56a32 100644
--- a/src/library/trackset/playlistfeature.cpp
+++ b/src/library/trackset/playlistfeature.cpp
@@ -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);
+ }
}
}
diff --git a/src/library/trackset/setlogfeature.cpp b/src/library/trackset/setlogfeature.cpp
index f3d57b512a0..355b6639090 100644
--- a/src/library/trackset/setlogfeature.cpp
+++ b/src/library/trackset/setlogfeature.cpp
@@ -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 groups;
-
QList itemList;
// Generous estimate (number of years the db is used ;))
itemList.reserve(kNumToplevelHistoryEntries + 15);
@@ -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);
@@ -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));
@@ -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) {
@@ -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);
}
}
}
@@ -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);
}
}
@@ -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);
}
@@ -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);
}
}
diff --git a/src/library/trackset/setlogfeature.h b/src/library/trackset/setlogfeature.h
index fc6e4dfeb52..84f9f159d0a 100644
--- a/src/library/trackset/setlogfeature.h
+++ b/src/library/trackset/setlogfeature.h
@@ -45,7 +45,6 @@ class SetlogFeature : public BasePlaylistFeature {
private:
void deleteAllUnlockedPlaylistsWithFewerTracks();
- void reloadChildModel(int playlistId);
QString getRootViewHtml() const override;
std::list m_recentTracks;