From 72a15c46d9e567b44f073ba8748a99cd06abdf3e Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sat, 3 Sep 2022 22:45:08 +0200 Subject: [PATCH] selection: move dive selection, current dive and dc through signals To reduce access of global variables. Signed-off-by: Berthold Stoeger --- core/selection.cpp | 2 +- core/subsurface-qt/divelistnotifier.h | 3 ++- desktop-widgets/divelistview.cpp | 37 +++++++++++++++++---------- desktop-widgets/divelistview.h | 7 ++--- desktop-widgets/mainwindow.cpp | 6 ++--- desktop-widgets/mainwindow.h | 2 +- qt-models/divetripmodel.cpp | 10 ++++---- qt-models/divetripmodel.h | 8 +++--- qt-models/filtermodels.cpp | 4 +-- qt-models/filtermodels.h | 4 +-- 10 files changed, 47 insertions(+), 36 deletions(-) diff --git a/core/selection.cpp b/core/selection.cpp index fc48fdf59..c63ceed95 100644 --- a/core/selection.cpp +++ b/core/selection.cpp @@ -202,7 +202,7 @@ void setSelection(const std::vector &selection, dive *currentDive, int c auto selectedDives = setSelectionCore(selection, currentDive, currentDc); // Send the new selection to the UI. - emit diveListNotifier.divesSelected(selectedDives, current_dive); + emit diveListNotifier.divesSelected(selectedDives, current_dive, currentDc); } // Set selection, but try to keep the current dive. If current dive is not in selection, diff --git a/core/subsurface-qt/divelistnotifier.h b/core/subsurface-qt/divelistnotifier.h index 0612d229f..98339e339 100644 --- a/core/subsurface-qt/divelistnotifier.h +++ b/core/subsurface-qt/divelistnotifier.h @@ -111,7 +111,8 @@ signals: void tripChanged(dive_trip *trip, TripField field); // Selection changes - void divesSelected(const QVector &dives, dive *currentDive); + // currentDC == -1 -> keep current dive computer + void divesSelected(const QVector &dives, dive *currentDive, int currentDC); void tripSelected(dive_trip *trip, dive *currentDive); // Dive site signals. Add and delete events are sent per dive site and diff --git a/desktop-widgets/divelistview.cpp b/desktop-widgets/divelistview.cpp index 8beff012d..29ffc2b0c 100644 --- a/desktop-widgets/divelistview.cpp +++ b/desktop-widgets/divelistview.cpp @@ -225,7 +225,7 @@ void DiveListView::reset() } // If items were selected, inform the selection model -void DiveListView::diveSelectionChanged(const QVector &indices, QModelIndex currentDive) +void DiveListView::diveSelectionChanged(const QVector &indices, QModelIndex currentDive, int currentDC) { // This is the entry point for programmatical selection changes. // Set a flag so that selection changes are not further processed, @@ -258,7 +258,14 @@ void DiveListView::diveSelectionChanged(const QVector &indices, QMo } setAnimated(oldAnimated); - selectionChangeDone(); + // This is truly sad, but taking the list of selected indices and turning them + // into dives turned out to be unreasonably slow. Therefore, let's access + // the core list directly. + std::vector selected = getDiveSelection(); + selectDiveSitesOnMap(selected); + struct dive *current = currentDive.data(DiveTripModelBase::DIVE_ROLE).value(); + emit divesSelected(selected, current, currentDC); + programmaticalSelectionChange = false; // Set the currently activated row. @@ -305,7 +312,14 @@ void DiveListView::tripSelected(QModelIndex trip, QModelIndex currentDive) // funny side-effects). selectionModel()->setCurrentIndex(currentDive, QItemSelectionModel::Current); - selectionChangeDone(); + // This is truly sad, but taking the list of selected indices and turning them + // into dives turned out to be unreasonably slow. Therefore, let's access + // the core list directly. + std::vector selection = getDiveSelection(); + selectDiveSitesOnMap(selection); + struct dive *current = currentDive.data(DiveTripModelBase::DIVE_ROLE).value(); + emit divesSelected(selection, current, -1); + programmaticalSelectionChange = false; } @@ -415,7 +429,7 @@ void DiveListView::currentChanged(const QModelIndex ¤t, const QModelIndex& scrollTo(current); } -void DiveListView::selectionChangeDone() +void DiveListView::selectDiveSitesOnMap(const std::vector &dives) { #ifdef MAP_SUPPORT // When receiving the divesSelected signal the main window will @@ -425,21 +439,15 @@ void DiveListView::selectionChangeDone() // the dive-site selection is controlled by the filter not // by the selected dives. if (!DiveFilter::instance()->diveSiteMode()) { - // This is truly sad, but taking the list of selected indices and turning them - // into dive sites turned out to be unreasonably slow. Therefore, let's access - // the core list directly. In my tests, this went down from 700 to 0 ms! QVector selectedSites; - selectedSites.reserve(amount_selected); - int i; - dive *d; - for_each_dive(i, d) { - if (d->selected && !d->hidden_by_filter && d->dive_site && !selectedSites.contains(d->dive_site)) + selectedSites.reserve(dives.size()); + for (dive *d: dives) { + if (!d->hidden_by_filter && d->dive_site && !selectedSites.contains(d->dive_site)) selectedSites.push_back(d->dive_site); } MapWidget::instance()->setSelected(selectedSites); } #endif - emit divesSelected(); } void DiveListView::selectTripItems(QModelIndex index) @@ -524,7 +532,8 @@ void DiveListView::selectionChanged(const QItemSelection &selected, const QItemS // Display the new, processed, selection QTreeView::selectionChanged(selectionModel()->selection(), newDeselected); - selectionChangeDone(); + selectDiveSitesOnMap(selection); + emit divesSelected(selection, newCurrent, -1); programmaticalSelectionChange = false; } diff --git a/desktop-widgets/divelistview.h b/desktop-widgets/divelistview.h index 5e3dec4b7..0590e2574 100644 --- a/desktop-widgets/divelistview.h +++ b/desktop-widgets/divelistview.h @@ -29,7 +29,8 @@ public: void loadImages(); void loadWebImages(); signals: - void divesSelected(); + // currentDC = -1: don't change dc number. + void divesSelected(const std::vector &dives, dive *currentDive, int currentDC); public slots: void settingsChanged(); @@ -51,13 +52,13 @@ slots: void renumberDives(); void addDivesToTrip(); void shiftTimes(); - void diveSelectionChanged(const QVector &indices, QModelIndex currentDive); + void diveSelectionChanged(const QVector &indices, QModelIndex currentDive, int currentDC); void tripSelected(QModelIndex trip, QModelIndex currentDive); private: void rowsInserted(const QModelIndex &parent, int start, int end) override; void reset() override; void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override; - void selectionChangeDone(); + void selectDiveSitesOnMap(const std::vector &dives); void selectTripItems(QModelIndex index); DiveTripModelBase::Layout currentLayout; QModelIndex contextMenuIndex; diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index 4e25fe595..d94739653 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -176,7 +176,7 @@ MainWindow::MainWindow() : if (!QIcon::hasThemeIcon("window-close")) { QIcon::setThemeName("subsurface"); } - connect(diveList.get(), &DiveListView::divesSelected, this, &MainWindow::selectionChanged); + connect(diveList.get(), &DiveListView::divesSelected, this, &MainWindow::divesSelected); connect(&diveListNotifier, &DiveListNotifier::settingsChanged, this, &MainWindow::readSettings); for (int i = 0; i < NUM_RECENT_FILES; i++) { actionsRecent[i] = new QAction(this); @@ -331,10 +331,10 @@ void MainWindow::updateAutogroup() ui.actionAutoGroup->setChecked(divelog.autogroup); } -void MainWindow::selectionChanged() +void MainWindow::divesSelected(const std::vector &selection, dive *currentDive, int currentDC) { mainTab->updateDiveInfo(); - if (current_dive) + if (currentDive) enableDisableOtherDCsActions(); profile->plotCurrentDive(); #ifdef MAP_SUPPORT diff --git a/desktop-widgets/mainwindow.h b/desktop-widgets/mainwindow.h index a88ae9f34..9d3d1035c 100644 --- a/desktop-widgets/mainwindow.h +++ b/desktop-widgets/mainwindow.h @@ -129,7 +129,7 @@ slots: void on_actionReplanDive_triggered(); void on_action_Check_for_Updates_triggered(); - void selectionChanged(); + void divesSelected(const std::vector &selection, dive *currentDive, int currentDC); void initialUiSetup(); void on_actionImportDiveLog_triggered(); diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp index 8870ec5b4..913193798 100644 --- a/qt-models/divetripmodel.cpp +++ b/qt-models/divetripmodel.cpp @@ -1370,7 +1370,7 @@ QModelIndex DiveTripModelTree::diveToIdx(const dive *d) const } } -void DiveTripModelTree::divesSelected(const QVector &divesIn, dive *currentDive) +void DiveTripModelTree::divesSelected(const QVector &divesIn, dive *currentDive, int currentDC) { QVector dives = visibleDives(divesIn); @@ -1382,7 +1382,7 @@ void DiveTripModelTree::divesSelected(const QVector &divesIn, dive *curr processByTrip(dives, [this, &indices] (dive_trip *trip, const QVector &divesInTrip) { divesSelectedTrip(trip, divesInTrip, indices); }); - emit selectionChanged(indices, diveToIdx(currentDive)); + emit selectionChanged(indices, diveToIdx(currentDive), currentDC); // The current dive has changed. Transform the current dive into an index and pass it on to the view. currentChanged(currentDive); @@ -1659,7 +1659,7 @@ QModelIndex DiveTripModelList::diveToIdx(const dive *d) const return createIndex(it - items.begin(), 0); } -void DiveTripModelList::divesSelected(const QVector &divesIn, dive *currentDive) +void DiveTripModelList::divesSelected(const QVector &divesIn, dive *currentDive, int currentDC) { QVector dives = visibleDives(divesIn); @@ -1679,7 +1679,7 @@ void DiveTripModelList::divesSelected(const QVector &divesIn, dive *curr indices.append(createIndex(j, 0, noParent)); } - emit selectionChanged(indices, diveToIdx(currentDive)); + emit selectionChanged(indices, diveToIdx(currentDive), currentDC); // The current dive has changed. Transform the current dive into an index and pass it on to the view. currentChanged(currentDive); @@ -1697,7 +1697,7 @@ void DiveTripModelList::tripSelected(dive_trip *trip, dive *currentDive) for (int i = 0; i < trip->dives.nr; ++i) dives.push_back(trip->dives.dives[i]); - divesSelected(dives, currentDive); + divesSelected(dives, currentDive, -1); } // Simple sorting helper for sorting against a criterium and if diff --git a/qt-models/divetripmodel.h b/qt-models/divetripmodel.h index 3b3e6c711..d9899c2db 100644 --- a/qt-models/divetripmodel.h +++ b/qt-models/divetripmodel.h @@ -78,13 +78,13 @@ protected slots: void reset(); signals: // The propagation of selection changes is complex. - // The control flow of dive-selection goes: + // The control flow of programmatical dive-selection goes: // Commands/DiveListNotifier ---(dive */dive_trip *)---> DiveTripModel ---(QModelIndex)---> DiveListView // i.e. The command objects send changes in terms of pointer-to-dives, which the DiveTripModel transforms // into QModelIndexes according to the current view (tree/list). Finally, the DiveListView transforms these // indices into local indices according to current sorting/filtering and instructs the QSelectionModel to // perform the appropriate actions. - void selectionChanged(const QVector &indices, QModelIndex currentDive); + void selectionChanged(const QVector &indices, QModelIndex currentDive, int currentDC); void tripSelected(QModelIndex trip, QModelIndex currentDive); protected: dive *oldCurrent; @@ -116,7 +116,7 @@ public slots: void divesChanged(const QVector &dives); void diveChanged(dive *d); void divesTimeChanged(timestamp_t delta, const QVector &dives); - void divesSelected(const QVector &dives, dive *currentDive); + void divesSelected(const QVector &dives, dive *currentDive, int currentDC); void tripSelected(dive_trip *trip, dive *currentDive); void tripChanged(dive_trip *trip, TripField); void filterReset(); @@ -195,7 +195,7 @@ public slots: void divesTimeChanged(timestamp_t delta, const QVector &dives); // Does nothing in list view. //void divesMovedBetweenTrips(dive_trip *from, dive_trip *to, bool deleteFrom, bool createTo, const QVector &dives); - void divesSelected(const QVector &dives, dive *currentDive); + void divesSelected(const QVector &dives, dive *currentDive, int currentDC); void tripSelected(dive_trip *trip, dive *currentDive); void filterReset(); diff --git a/qt-models/filtermodels.cpp b/qt-models/filtermodels.cpp index ba23588fd..74340939c 100644 --- a/qt-models/filtermodels.cpp +++ b/qt-models/filtermodels.cpp @@ -33,7 +33,7 @@ void MultiFilterSortModel::resetModel(DiveTripModelBase::Layout layout) } // Translate selection into local indices and re-emit signal -void MultiFilterSortModel::selectionChangedSlot(const QVector &indices, QModelIndex currentDive) +void MultiFilterSortModel::selectionChangedSlot(const QVector &indices, QModelIndex currentDive, int currentDC) { QVector indicesLocal; indicesLocal.reserve(indices.size()); @@ -43,7 +43,7 @@ void MultiFilterSortModel::selectionChangedSlot(const QVector &indi indicesLocal.push_back(local); } - emit selectionChanged(indicesLocal, mapFromSource(currentDive)); + emit selectionChanged(indicesLocal, mapFromSource(currentDive), currentDC); } // Translate selection into local indices and re-emit signal diff --git a/qt-models/filtermodels.h b/qt-models/filtermodels.h index a9fbd167e..5c87fad3e 100644 --- a/qt-models/filtermodels.h +++ b/qt-models/filtermodels.h @@ -18,10 +18,10 @@ public: void resetModel(DiveTripModelBase::Layout layout); signals: - void selectionChanged(const QVector &indices, QModelIndex currentDive); + void selectionChanged(const QVector &indices, QModelIndex currentDive, int currentDC); void tripSelected(QModelIndex trip, QModelIndex currentDive); private slots: - void selectionChangedSlot(const QVector &indices, QModelIndex currentDive); + void selectionChangedSlot(const QVector &indices, QModelIndex currentDive, int currentDC); void tripSelectedSlot(QModelIndex trip, QModelIndex currentDive); private: MultiFilterSortModel(QObject *parent = 0);