@@ -1429,7 +1429,19 @@ void WTrackTableView::doSortByColumn(int headerSection, Qt::SortOrder sortOrder)
14291429 }
14301430
14311431 // Save the selection
1432- const QList<TrackId> selectedTrackIds = getSelectedTrackIds ();
1432+ // If this is a track model that may contain a track multiple times (playlist),
1433+ // we store the positions so we can reselect only the current selection after sorting,
1434+ // not all occurrences of selected tracks.
1435+ QList<TrackId> selectedTrackIds;
1436+ QList<int > selectedTrackPositions;
1437+ bool usePositions = pTrackModel->hasCapabilities (TrackModel::Capability::Reorder);
1438+ if (usePositions) {
1439+ const QModelIndexList indices = getSelectedRows ();
1440+ selectedTrackPositions = pTrackModel->getSelectedPositions (indices);
1441+ } else {
1442+ selectedTrackIds = getSelectedTrackIds ();
1443+ }
1444+
14331445 int savedHScrollBarPos = horizontalScrollBar ()->value ();
14341446 // Save the column of focused table cell.
14351447 // The cell is not necessarily part of the selection, but even if it's
@@ -1442,13 +1454,56 @@ void WTrackTableView::doSortByColumn(int headerSection, Qt::SortOrder sortOrder)
14421454
14431455 sortByColumn (headerSection, sortOrder);
14441456
1445- selectTracksById (selectedTrackIds, prevColumn);
1457+ if (usePositions) {
1458+ selectTracksByPosition (selectedTrackPositions, prevColumn);
1459+ } else {
1460+ selectTracksById (selectedTrackIds, prevColumn);
1461+ }
14461462
14471463 // This seems to be broken since at least Qt 5.12: no scrolling is issued
14481464 // scrollTo(first, QAbstractItemView::EnsureVisible);
14491465 horizontalScrollBar ()->setValue (savedHScrollBarPos);
14501466}
14511467
1468+ void WTrackTableView::selectTracksByPosition (const QList<int >& positions, int prevColumn) {
1469+ if (positions.isEmpty ()) {
1470+ return ;
1471+ }
1472+ TrackModel* pTrackModel = getTrackModel ();
1473+ QItemSelectionModel* pSelectionModel = selectionModel ();
1474+ pSelectionModel->reset (); // remove current selection
1475+
1476+ // Find previously selected tracks and store respective rows for reselection.
1477+ QList<int > rows;
1478+ for (int pos : positions) {
1479+ rows.append (pTrackModel->getTrackRowByPosition (pos));
1480+ }
1481+
1482+ // Select the first row of the previous selection.
1483+ // This scrolls to that row and with the leftmost cell being focused we have
1484+ // a starting point (currentIndex) for navigation with Up/Down keys.
1485+ // Replaces broken scrollTo() (see comment below)
1486+ if (!rows.isEmpty ()) {
1487+ selectRow (rows.first ());
1488+ }
1489+
1490+ // Refocus the cell in the column that was focused before sorting.
1491+ // With this, any Up/Down key press moves the selection and keeps the
1492+ // horizontal scrollbar position we will restore below.
1493+ QModelIndex restoreIndex = model ()->index (currentIndex ().row (), prevColumn);
1494+ if (restoreIndex.isValid ()) {
1495+ setCurrentIndex (restoreIndex);
1496+ }
1497+
1498+ // Restore previous selection (doesn't affect focused cell).
1499+ for (int row : rows) {
1500+ pSelectionModel->select (model ()->index (row, prevColumn),
1501+ QItemSelectionModel::Select | QItemSelectionModel::Rows);
1502+ }
1503+ }
1504+
1505+ // Don't use this on playlists since they may contain a TrackId multiple times.
1506+ // See doSortByColumn.
14521507void WTrackTableView::selectTracksById (const QList<TrackId>& trackIds, int prevColum) {
14531508 TrackModel* pTrackModel = getTrackModel ();
14541509 QAbstractItemModel* pItemModel = model ();
@@ -1459,14 +1514,6 @@ void WTrackTableView::selectTracksById(const QList<TrackId>& trackIds, int prevC
14591514 // Find previously selected tracks and store respective rows for reselection.
14601515 QMap<int , int > selectedRows;
14611516 for (const auto & trackId : trackIds) {
1462- // TODO(rryan) slowly fixing the issues with BaseSqlTableModel. This
1463- // code is broken for playlists because it assumes each trackid is in
1464- // the table once. This will erroneously select all instances of the
1465- // track for playlists, but it works fine for every other view. The way
1466- // to fix this that we should do is to delegate the selection saving to
1467- // the TrackModel. This will allow the playlist table model to use the
1468- // table index as the unique id instead of this code stupidly using
1469- // trackid.
14701517 const auto rows = pTrackModel->getTrackRows (trackId);
14711518 for (int row : rows) {
14721519 // Restore sort order by rows, so the following commands will act as expected
0 commit comments