diff --git a/core/selection.cpp b/core/selection.cpp index c63ceed95..ca38359df 100644 --- a/core/selection.cpp +++ b/core/selection.cpp @@ -10,20 +10,9 @@ #include struct dive *current_dive = NULL; -unsigned int dc_number = 0; int amount_selected; static int amount_trips_selected; -static void fixup_current_dc() -{ - // Every dive is guaranteed to have a dc - if (!current_dive || dc_number == 0) - return; - - // Note that number_of_computers returns at least 1, so subtraction is valid. - dc_number = std::min(dc_number, number_of_computers(current_dive) - 1); -} - extern "C" struct dive *first_selected_dive() { int idx; @@ -139,7 +128,7 @@ static void setClosestCurrentDive(timestamp_t when, const std::vector &s // Set the current dive to "currentDive". "currentDive" must be an element of "selection" (or // null if "selection" is empty). // Does not send signals or clear the trip selection. -QVector setSelectionCore(const std::vector &selection, dive *currentDive, int currentDc) +QVector setSelectionCore(const std::vector &selection, dive *currentDive) { // To do so, generate vectors of dives to be selected and deselected. // We send signals batched by trip, so keep track of trip/dive pairs. @@ -177,9 +166,6 @@ QVector setSelectionCore(const std::vector &selection, dive *cur setClosestCurrentDive(currentDive->when, selection, divesToSelect); } - if (currentDc >= 0) - dc_number = currentDc; - fixup_current_dc(); return divesToSelect; } @@ -199,7 +185,7 @@ void setSelection(const std::vector &selection, dive *currentDive, int c // Since we select only dives, there are no selected trips! clear_trip_selection(); - auto selectedDives = setSelectionCore(selection, currentDive, currentDc); + auto selectedDives = setSelectionCore(selection, currentDive); // Send the new selection to the UI. emit diveListNotifier.divesSelected(selectedDives, current_dive, currentDc); @@ -219,7 +205,7 @@ bool setSelectionKeepCurrent(const std::vector &selection) dive *newCurrent = current_dive; if (current_dive && std::find(selection.begin(), selection.end(), current_dive) == selection.end()) newCurrent = closestInSelection(current_dive->when, selection); - setSelectionCore(selection, newCurrent, -1); + setSelectionCore(selection, newCurrent); return current_dive != oldCurrent; } diff --git a/core/selection.h b/core/selection.h index 7c579cf0d..6c330f3bd 100644 --- a/core/selection.h +++ b/core/selection.h @@ -7,7 +7,6 @@ struct dive; extern int amount_selected; -extern unsigned int dc_number; extern struct dive *current_dive; /*** C and C++ functions ***/ @@ -45,7 +44,7 @@ extern void dump_selection(void); // "currentDive" must be an element of "selection" (or null if "seletion" is empty). // If "currentDc" is negative, an attempt will be made to keep the current computer number. // Returns the list of selected dives -QVector setSelectionCore(const std::vector &selection, dive *currentDive, int currentDc); +QVector setSelectionCore(const std::vector &selection, dive *currentDive); // As above, but sends a signal to inform the frontend of the changed selection. // Returns true if the current dive changed. diff --git a/desktop-widgets/divelistview.cpp b/desktop-widgets/divelistview.cpp index ff8abb1df..7a7e09fed 100644 --- a/desktop-widgets/divelistview.cpp +++ b/desktop-widgets/divelistview.cpp @@ -527,7 +527,7 @@ void DiveListView::selectionChanged(const QItemSelection &selected, const QItemS std::vector selection = getDiveSelection(); updateSelection(selection, addToSelection, removeFromSelection); dive *newCurrent = selection.empty() ? nullptr : selection.front(); - setSelectionCore(selection, newCurrent, -1); + setSelectionCore(selection, newCurrent); // Display the new, processed, selection QTreeView::selectionChanged(selectionModel()->selection(), newDeselected); diff --git a/desktop-widgets/diveplanner.cpp b/desktop-widgets/diveplanner.cpp index 93f6f2bde..246d0ab18 100644 --- a/desktop-widgets/diveplanner.cpp +++ b/desktop-widgets/diveplanner.cpp @@ -548,7 +548,6 @@ PlannerWidgets::PlannerWidgets() void PlannerWidgets::planDive(dive *currentDive) { DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN); - dc_number = 0; // create a simple starting dive, using the first gas from the just copied cylinders DivePlannerPointsModel::instance()->createSimpleDive(&displayed_dive); diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index 5af0b8c5b..25c46a7b4 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -300,14 +300,6 @@ void MainWindow::enableDisableCloudActions() ui.actionCloudstoragesave->setEnabled(prefs.cloud_verification_status == qPrefCloudStorage::CS_VERIFIED); } -void MainWindow::enableDisableOtherDCsActions() -{ - bool nr = number_of_computers(current_dive) > 1; - enableShortcuts(); - ui.actionNextDC->setEnabled(nr); - ui.actionPreviousDC->setEnabled(nr); -} - void MainWindow::setDefaultState() { setApplicationState(ApplicationState::Default); @@ -333,10 +325,19 @@ void MainWindow::updateAutogroup() void MainWindow::divesSelected(const std::vector &selection, dive *currentDive, int currentDC) { - mainTab->updateDiveInfo(selection, currentDive, currentDC); - if (currentDive) - enableDisableOtherDCsActions(); - profile->plotCurrentDive(); + // We call plotDive first, so that the profile can decide which + // dive computer to plot. The plotted dive computer is then + // used for displaying data in the tab-widgets. + profile->plotDive(currentDive, currentDC); + mainTab->updateDiveInfo(selection, profile->d, profile->dc); + + // Activate cursor keys to switch through DCs if there are more than one DC. + if (currentDive) { + bool nr = number_of_computers(current_dive) > 1; + enableShortcuts(); + ui.actionNextDC->setEnabled(nr); + ui.actionPreviousDC->setEnabled(nr); + } } void MainWindow::on_actionNew_triggered() @@ -665,8 +666,8 @@ void MainWindow::on_actionReplanDive_triggered() disableShortcuts(true); copy_dive(current_dive, &displayed_dive); // Planning works on a copy of the dive (for now). - profile->setPlanState(&displayed_dive, dc_number); - plannerWidgets->replanDive(dc_number); + profile->setPlanState(&displayed_dive, profile->dc); + plannerWidgets->replanDive(profile->dc); } void MainWindow::on_actionDivePlanner_triggered() @@ -825,20 +826,16 @@ void MainWindow::restoreSplitterSizes() void MainWindow::on_actionPreviousDC_triggered() { - unsigned nrdc = number_of_computers(current_dive); - dc_number = (dc_number + nrdc - 1) % nrdc; - profile->plotCurrentDive(); + profile->prevDC(); // TODO: remove - mainTab->updateDiveInfo(getDiveSelection(), current_dive, dc_number); + mainTab->updateDiveInfo(getDiveSelection(), profile->d, profile->dc); } void MainWindow::on_actionNextDC_triggered() { - unsigned nrdc = number_of_computers(current_dive); - dc_number = (dc_number + 1) % nrdc; - profile->plotCurrentDive(); + profile->nextDC(); // TODO: remove - mainTab->updateDiveInfo(getDiveSelection(), current_dive, dc_number); + mainTab->updateDiveInfo(getDiveSelection(), profile->d, profile->dc); } void MainWindow::on_actionFullScreen_triggered(bool checked) diff --git a/desktop-widgets/mainwindow.h b/desktop-widgets/mainwindow.h index 9d3d1035c..316fdd6e4 100644 --- a/desktop-widgets/mainwindow.h +++ b/desktop-widgets/mainwindow.h @@ -75,7 +75,6 @@ public: void enterPreviousState(); NotificationWidget *getNotificationWidget(); void enableDisableCloudActions(); - void enableDisableOtherDCsActions(); void editDiveSite(dive_site *ds); void setEnabledToolbar(bool arg1); diff --git a/desktop-widgets/profilewidget.cpp b/desktop-widgets/profilewidget.cpp index 9b1d66142..cab19db40 100644 --- a/desktop-widgets/profilewidget.cpp +++ b/desktop-widgets/profilewidget.cpp @@ -52,7 +52,7 @@ void EmptyView::resizeEvent(QResizeEvent *) update(); } -ProfileWidget::ProfileWidget() : originalDive(nullptr), placingCommand(false) +ProfileWidget::ProfileWidget() : d(nullptr), dc(0), originalDive(nullptr), placingCommand(false) { ui.setupUi(this); @@ -183,34 +183,72 @@ void ProfileWidget::setDive(const struct dive *d) void ProfileWidget::plotCurrentDive() { + plotDive(d, dc); +} + +void ProfileWidget::plotDive(dive *dIn, int dcIn) +{ + d = dIn; + + if (dcIn >= 0) + dc = dcIn; + + // The following is valid because number_of_computers is always at least 1. + if (d) + dc = std::min(dc, (int)number_of_computers(current_dive) - 1); + // Exit edit mode if the dive changed - if (editedDive && (originalDive != current_dive || editedDc != dc_number)) + if (editedDive && (originalDive != d || editedDc != dc)) exitEditMode(); // If this is a manually added dive and we are not in the planner // or already editing the dive, switch to edit mode. - if (current_dive && !editedDive && + if (d && !editedDive && DivePlannerPointsModel::instance()->currentMode() == DivePlannerPointsModel::NOTHING) { - struct divecomputer *dc = get_dive_dc(current_dive, dc_number); - if (dc && is_manually_added_dc(dc) && dc->samples) + struct divecomputer *comp = get_dive_dc(d, dc); + if (comp && is_manually_added_dc(comp) && comp->samples) editDive(); } - setEnabledToolbar(current_dive != nullptr); + setEnabledToolbar(d != nullptr); if (editedDive) { view->plotDive(editedDive.get(), editedDc); setDive(editedDive.get()); - } else if (current_dive) { - view->setProfileState(current_dive, dc_number); + } else if (d) { + view->setProfileState(d, dc); view->resetZoom(); // when switching dive, reset the zoomLevel - view->plotDive(current_dive, dc_number); - setDive(current_dive); + view->plotDive(d, dc); + setDive(d); } else { view->clear(); stack->setCurrentIndex(0); } } +void ProfileWidget::nextDC() +{ + rotateDC(1); +} + +void ProfileWidget::prevDC() +{ + rotateDC(-1); +} + +void ProfileWidget::rotateDC(int dir) +{ + if (!d) + return; + int numDC = number_of_computers(d); + int newDC = (dc + dir) % numDC; + if (newDC < 0) + newDC += numDC; + if (newDC == dc) + return; + + plotDive(d, newDC); +} + void ProfileWidget::divesChanged(const QVector &dives, DiveField field) { // If the current dive is not in list of changed dives, do nothing. @@ -218,13 +256,13 @@ void ProfileWidget::divesChanged(const QVector &dives, DiveField field) // Also, if we are currently placing a command, don't do anything. // Note that we cannot use Command::placingCommand(), because placing // a depth or time change on the maintab requires an update. - if (!current_dive || !dives.contains(current_dive) || !(field.duration || field.depth) || placingCommand) + if (!d || !dives.contains(d) || !(field.duration || field.depth) || placingCommand) return; // If were editing the current dive and not currently // placing command, we have to update the edited dive. if (editedDive) { - copy_dive(current_dive, editedDive.get()); + copy_dive(d, editedDive.get()); // TODO: Holy moly that function sends too many signals. Fix it! DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), editedDc); } @@ -254,9 +292,9 @@ void ProfileWidget::unsetProfTissues() void ProfileWidget::editDive() { editedDive.reset(alloc_dive()); - editedDc = dc_number; - copy_dive(current_dive, editedDive.get()); // Work on a copy of the dive - originalDive = current_dive; + editedDc = dc; + copy_dive(d, editedDive.get()); // Work on a copy of the dive + originalDive = d; DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::ADD); DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), editedDc); view->setEditState(editedDive.get(), editedDc); @@ -267,7 +305,7 @@ void ProfileWidget::exitEditMode() if (!editedDive) return; DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING); - view->setProfileState(current_dive, dc_number); // switch back to original dive before erasing the copy. + view->setProfileState(d, dc); // switch back to original dive before erasing the copy. editedDive.reset(); originalDive = nullptr; } diff --git a/desktop-widgets/profilewidget.h b/desktop-widgets/profilewidget.h index 0af81d13b..a217168bb 100644 --- a/desktop-widgets/profilewidget.h +++ b/desktop-widgets/profilewidget.h @@ -23,9 +23,14 @@ public: ProfileWidget(); ~ProfileWidget(); std::unique_ptr view; + void plotDive(struct dive *d, int dc); // Attempt to keep DC number id dc < 0 void plotCurrentDive(); void setPlanState(const struct dive *d, int dc); void setEnabledToolbar(bool enabled); + void nextDC(); + void prevDC(); + dive *d; + int dc; private slots: void divesChanged(const QVector &dives, DiveField field); @@ -47,8 +52,9 @@ private: void setDive(const struct dive *d); void editDive(); void exitEditMode(); + void rotateDC(int dir); std::unique_ptr editedDive; - unsigned int editedDc; + int editedDc; dive *originalDive; bool placingCommand; }; diff --git a/qt-models/divetripmodel.h b/qt-models/divetripmodel.h index 2fc55a510..2ff449bef 100644 --- a/qt-models/divetripmodel.h +++ b/qt-models/divetripmodel.h @@ -79,12 +79,14 @@ protected slots: signals: // The propagation of selection changes is complex. // The control flow of programmatical dive-selection goes: - // Commands/DiveListNotifier ---(dive */dive_trip *)---> DiveTripModel ---(QModelIndex)---> DiveListView + // Commands/DiveListNotifier ---(dive */dive_trip *)---> DiveTripModel + // ---(QModelIndex)---> MultiFilterSortModel + // ---(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 + // into QModelIndexes according to the current view (tree/list). These are modified according to current + // filtering/sorting. Finally, the DiveListView instructs the QSelectionModel to // perform the appropriate actions. - void divesSelected(const QVector &indices, QModelIndex currentDive, int currentDC); + void divesSelected(const QVector &indices, QModelIndex currentDive, int currentDC); // currentDC < 0 -> keep DC. void tripSelected(QModelIndex trip, QModelIndex currentDive); protected: dive *oldCurrent; diff --git a/qt-models/filtermodels.h b/qt-models/filtermodels.h index bae29932b..4617fc3a6 100644 --- a/qt-models/filtermodels.h +++ b/qt-models/filtermodels.h @@ -18,7 +18,7 @@ public: void resetModel(DiveTripModelBase::Layout layout); signals: - void divesSelected(const QVector &indices, QModelIndex currentDive, int currentDC); + void divesSelected(const QVector &indices, QModelIndex currentDive, int currentDC); // currentDC < 0 -> keep DC. void tripSelected(QModelIndex trip, QModelIndex currentDive); private slots: void divesSelectedSlot(const QVector &indices, QModelIndex currentDive, int currentDC);