@@ -45,6 +45,9 @@ namespace {
4545
4646const mixxx::Logger kLogger (" Library" );
4747
48+ const ConfigKey kLastSelectedTrackIdConfigKey =
49+ ConfigKey (QStringLiteral(" [Library]" ), QStringLiteral(" last_selected_track_id" ));
50+
4851} // namespace
4952
5053using namespace mixxx ::library::prefs;
@@ -81,6 +84,12 @@ Library::Library(
8184 this ,
8285 &Library::slotRefreshLibraryModels);
8386
87+ // Save the selected track ID on exit so the latest selection is persisted
88+ connect (QCoreApplication::instance (),
89+ &QCoreApplication::aboutToQuit,
90+ this ,
91+ &Library::slotSaveSelectedTrackId);
92+
8493 // TODO(rryan) -- turn this construction / adding of features into a static
8594 // method or something -- CreateDefaultLibrary
8695 m_pMixxxLibraryFeature = make_parented<MixxxLibraryFeature>(
@@ -366,6 +375,10 @@ void Library::bindSidebarWidget(WLibrarySidebar* pSidebarWidget) {
366375 &WLibrarySidebar::expanded,
367376 m_pSidebarModel,
368377 &SidebarModel::doubleClicked);
378+ connect (m_pSidebarModel,
379+ &SidebarModel::selectionSaved,
380+ this ,
381+ &Library::slotSaveSelectedTrackId);
369382
370383 connect (pSidebarWidget,
371384 &WLibrarySidebar::rightClicked,
@@ -617,6 +630,11 @@ void Library::onSkinLoadFinished() {
617630 // Enable the default selection when a new skin is loaded.
618631 m_pSidebarModel->activateDefaultSelection ();
619632 }
633+
634+ // Restore the selected track after the track model has had time to load.
635+ // The track model populates asynchronously after activateChild is called,
636+ // and a model reset clears the selection. We retry with increasing delays.
637+ QTimer::singleShot (1000 , this , &Library::slotRestoreSelectedTrackId);
620638}
621639
622640bool Library::requestAddDir (const QString& dir) {
@@ -825,3 +843,62 @@ LibraryTableModel* Library::trackTableModel() const {
825843
826844 return m_pMixxxLibraryFeature->trackTableModel ();
827845}
846+
847+ void Library::slotSaveSelectedTrackId () {
848+ if (!m_pConfig || !m_pLibraryWidget) {
849+ return ;
850+ }
851+ WTrackTableView* pView = m_pLibraryWidget->getCurrentTrackTableView ();
852+ if (pView) {
853+ TrackId trackId = pView->getCurrentTrackId ();
854+ if (trackId.isValid ()) {
855+ m_pConfig->set (kLastSelectedTrackIdConfigKey ,
856+ ConfigValue (trackId.toVariant ().toString ()));
857+ } else {
858+ m_pConfig->set (kLastSelectedTrackIdConfigKey , ConfigValue ());
859+ }
860+ }
861+ }
862+
863+ void Library::slotRestoreSelectedTrackId () {
864+ if (!m_pConfig || !m_pLibraryWidget) {
865+ return ;
866+ }
867+ QString trackIdStr = m_pConfig->getValue (kLastSelectedTrackIdConfigKey );
868+ if (trackIdStr.isEmpty ()) {
869+ return ;
870+ }
871+ TrackId trackId{QVariant (trackIdStr)};
872+ if (!trackId.isValid ()) {
873+ return ;
874+ }
875+
876+ // setCurrentTrackId calls selectRow then setCurrentIndex with SelectCurrent,
877+ // which clears the row selection. Re-select the row after it succeeds.
878+ auto selectAndReselect = [](WTrackTableView* pView, const TrackId& id) {
879+ if (pView->setCurrentTrackId (id, 0 , true )) {
880+ QModelIndex idx = pView->currentIndex ();
881+ if (idx.isValid ()) {
882+ pView->selectRow (idx.row ());
883+ }
884+ return true ;
885+ }
886+ return false ;
887+ };
888+
889+ WTrackTableView* pView = m_pLibraryWidget->getCurrentTrackTableView ();
890+ if (pView) {
891+ if (!selectAndReselect (pView, trackId)) {
892+ qDebug () << " Library: track" << trackId
893+ << " not in current view, will retry in 1s" ;
894+ QTimer::singleShot (1000 , this , [this , trackId, selectAndReselect]() {
895+ if (m_pLibraryWidget) {
896+ WTrackTableView* pView = m_pLibraryWidget->getCurrentTrackTableView ();
897+ if (pView) {
898+ selectAndReselect (pView, trackId);
899+ }
900+ }
901+ });
902+ }
903+ }
904+ }
0 commit comments