@@ -1307,7 +1307,19 @@ void WTrackTableView::doSortByColumn(int headerSection, Qt::SortOrder sortOrder)
13071307 }
13081308
13091309 // Save the selection
1310- const QList<TrackId> selectedTrackIds = getSelectedTrackIds ();
1310+ // If this is track model that may contain a track multiple times (a playlist),
1311+ // we store the positions in order to reselect only the current selection,
1312+ // not all occurrences of selected tracks.
1313+ QList<TrackId> selectedTrackIds;
1314+ QList<int > selectedTrackPositions;
1315+ bool usePositions = pTrackModel->hasCapabilities (TrackModel::Capability::Reorder);
1316+ if (usePositions) {
1317+ const QModelIndexList indices = getSelectedRows ();
1318+ selectedTrackPositions = pTrackModel->getSelectedPositions (indices);
1319+ } else {
1320+ selectedTrackIds = getSelectedTrackIds ();
1321+ }
1322+
13111323 int savedHScrollBarPos = horizontalScrollBar ()->value ();
13121324 // Save the column of focused table cell.
13131325 // The cell is not necessarily part of the selection, but even if it's
@@ -1320,13 +1332,56 @@ void WTrackTableView::doSortByColumn(int headerSection, Qt::SortOrder sortOrder)
13201332
13211333 sortByColumn (headerSection, sortOrder);
13221334
1323- selectTracksById (selectedTrackIds, prevColumn);
1335+ if (usePositions) {
1336+ selectTracksByPosition (selectedTrackPositions, prevColumn);
1337+ } else {
1338+ selectTracksById (selectedTrackIds, prevColumn);
1339+ }
13241340
13251341 // This seems to be broken since at least Qt 5.12: no scrolling is issued
13261342 // scrollTo(first, QAbstractItemView::EnsureVisible);
13271343 horizontalScrollBar ()->setValue (savedHScrollBarPos);
13281344}
13291345
1346+ void WTrackTableView::selectTracksByPosition (const QList<int >& positions, int prevColumn) {
1347+ if (positions.isEmpty ()) {
1348+ return ;
1349+ }
1350+ TrackModel* pTrackModel = getTrackModel ();
1351+ QItemSelectionModel* pSelectionModel = selectionModel ();
1352+ pSelectionModel->reset (); // remove current selection
1353+
1354+ // Find previously selected tracks and store respective rows for reselection.
1355+ QList<int > rows;
1356+ for (int pos : positions) {
1357+ rows.append (pTrackModel->getTrackRowByPosition (pos));
1358+ }
1359+
1360+ // Select the first row of the previous selection.
1361+ // This scrolls to that row and with the leftmost cell being focused we have
1362+ // a starting point (currentIndex) for navigation with Up/Down keys.
1363+ // Replaces broken scrollTo() (see comment below)
1364+ if (!rows.isEmpty ()) {
1365+ selectRow (rows.first ());
1366+ }
1367+
1368+ // Refocus the cell in the column that was focused before sorting.
1369+ // With this, any Up/Down key press moves the selection and keeps the
1370+ // horizontal scrollbar position we will restore below.
1371+ QModelIndex restoreIndex = model ()->index (currentIndex ().row (), prevColumn);
1372+ if (restoreIndex.isValid ()) {
1373+ setCurrentIndex (restoreIndex);
1374+ }
1375+
1376+ // Restore previous selection (doesn't affect focused cell).
1377+ for (int row : rows) {
1378+ pSelectionModel->select (model ()->index (row, prevColumn),
1379+ QItemSelectionModel::Select | QItemSelectionModel::Rows);
1380+ }
1381+ }
1382+
1383+ // Don't use this on playlists since they may contain a TrackId multiple times.
1384+ // See doSortByColumn.
13301385void WTrackTableView::selectTracksById (const QList<TrackId>& trackIds, int prevColum) {
13311386 TrackModel* pTrackModel = getTrackModel ();
13321387 QAbstractItemModel* pItemModel = model ();
@@ -1337,14 +1392,6 @@ void WTrackTableView::selectTracksById(const QList<TrackId>& trackIds, int prevC
13371392 // Find previously selected tracks and store respective rows for reselection.
13381393 QMap<int , int > selectedRows;
13391394 for (const auto & trackId : trackIds) {
1340- // TODO(rryan) slowly fixing the issues with BaseSqlTableModel. This
1341- // code is broken for playlists because it assumes each trackid is in
1342- // the table once. This will erroneously select all instances of the
1343- // track for playlists, but it works fine for every other view. The way
1344- // to fix this that we should do is to delegate the selection saving to
1345- // the TrackModel. This will allow the playlist table model to use the
1346- // table index as the unique id instead of this code stupidly using
1347- // trackid.
13481395 const auto rows = pTrackModel->getTrackRows (trackId);
13491396 for (int row : rows) {
13501397 // Restore sort order by rows, so the following commands will act as expected
0 commit comments