Add a new "statistics" application state. In the statistics state
show the statistics widget and the filter in the top quadrants.
The idea is to allow filtering and doing statistics at the same
time.
Sadly, we can't use the filter-widget in different quadrants,
because Qt's ownership model is completely broken / inflexible.
It does not support a widget having different parents and
thus a widget can only belong to one QStackedWidget.
Hiding the map in the statistics view is quite hacky:
Since the view of the quadrants is not determined by the
"ApplicationState", we have to restore the original quadrant
visibility when exiting the stats mode. Therefore, set the
original visibility-state when changing application state.
The MainWindow-quadrant code really needs to be rewritten!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The mainwindow was connecting preferences changes to the profile.
Do this directly in the profile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Around 2015 there was a push to move planner UI code from
mainwindow.cpp to diveplanner.cpp. That never was completed,
presumably because the planner is actually three widgets.
Collect these widgets in one PlannerWidgets class and move
the code there.
This is not a full dis-entanglement, as the plannerwidgets
have to access the profile via the mainwindow. But at least
it collects the planner UI code at a single place.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The main window called a function to init the header actions
(i.e. the context menu) of the dive-list. There is no reason why
this shouldn't be done in the constructor of the dive list, since
it only accesses the QSettings, which are available at application
startup. This improves modularity of the code (by a tiny, tiny bit).
Moreover, the initialization function was at the same time the
header-reloading function. That function can now be folded
into the settings-changed function, since that is the only
remaining user.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
So far, the PreferencesDialog emitted a settingsChanged signal.
This meant that models that listened to that signal had to
conditionally compile out the code for mobile or the connection
had to be made in MainWindow.
Instead, introduce a global signal that does this and move
the connects to the listeners to remove inter-dependencies.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This used to reload the completion models. Moreover, remove two
obsolete member-function declarations.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function was used to unify both methods of tracking unsaved
changes. Since desktop now only uses the undo system, it can
be replaced by a single call to "Command::setClean()".
Arguably, the UI is the wrong place to do this and the appropriate
calls should be done by the core. However, let's play it safe
for now and avoid any breaking change.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function was used to unify both methods of checking for
unsaved changes: the global unsaved_changes() flag and the
Command::clean() function of the undo-system.
However, all desktop functions are now undoable and therefore
the function is not needed and can be replaced by calls
to !Command::clean().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a device_table parameters to Command::importTable() and
add_imported_dives(). The content of this table will be added
to the global device list (respectively removed on undo).
This is currently a no-op, as the parser doesn't yet fill
out the device table, but adds devices directly to the global
device table.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If we want to avoid the parsers to directly modify global data,
we have to provide a device_table to parse into. This adds such
a state and the corresponding function parameters. However,
for now this is unused.
Adding new parameters is very painful and this commit shows that
we urgently need a "struct divelog" collecting all those tables!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When importing dive-sites we would add to the global filter-preset
table. This data should be thrown away, just like the other tables
that might be imported.
This shows that we really should introduce a "struct divelog",
which collects all those tables into a single structure.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We used a typedef "filter_preset_table_t" for the filter preset table,
because it is a "std::vector<filter_preset>". However, that is in
contrast to all the other global tables (dives, trips, sites) that we
have.
Therefore, turn this into a standard struct, which simply inherits
from "std::vector<filter_preset>". Note that while inheriting from
std::vector<> is generally not recommended, it is not a problem
here, because we don't modify it in any shape or form.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The name "FilterWidget2" is historical and has no meaning anymore,
since the current version has little to nothing to do with the
"second" version of the widget.
Rename the class and source files accordingly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When importing a divelog, import filter presets. If there are
equal names, import only if the presets differ. In that case,
disambiguate the name. This made things a bit more complicated,
as comparison of filter presets had to be implemented.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The filter widget was caching whether the filter was active and
used that flag to calculate the "# dives shown" string. Move this
directly to the DiveFilter class to remove interdependencies and
to unify with mobile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is a bit painful: since we don't want to modify the filter
presets when the user imports (as opposed to opens) a log,
we have to provide a table where the parser stores the presets.
Calling the parser is getting quite unwieldy, since many tables
are passed. We probably should introduce a structure representing
a full log-book at one point, which collects all the things that
are saved to the log.
Apart from that, this is simply the counterpart to saving to XML.
The interpretation of the string data is performed by core
functions, not the parser itself to avoid code duplication with
the git parser.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When planning a dive, dc_number was set to 1, which actually is
the second dc! The code seems to handle this gracefully, however
it appears weird. Let's set dc_number to 0 instead.
Originally, the assignment was introduced in a422957cd6
and moved later in 4f5621c4c6.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When the dive has no explicity salinity, our conversion
between pressure and depth assumed salt water. Make this
explicity by using the corresponding macro.
When the planner starts and no salinity is set explicity,
set the water type chooser to salt water to reflect
our default assumption.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
There is no reason that this dialog is a singleton. Since it is modal,
it can be created on demand. This simplifies code, because the mode
(selected-only or all-dives) can be set in the constructor.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Move this function from maintab.cpp to qthelper.cpp. Since the
functionality was used in numerous places, use the helper function
there as well. This removes a number of inconsistencies. For example,
sometime setTimeSpec(Qt::UTC) was called, even though the
QDateTime object was already created with that time spec.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was an old "optimization" to avoid double plotting of the
pictures, first by the profile itself, then by the picture tab.
Since the profile now updates the pictures itself, this must
be removed: The picture tab doesn't do it anymore.
Fixes#2833
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To reset the core data structures, the mobile and desktop UIs
were calling into the dive-list models, which then reset the
core data structures, themselves and the unrelated
locationinformation model. The UI code then reset various other
things, such as the TankInformation model or the map. . This was
unsatisfying from a control-flow perspective, as the models should
display the core data, not act on it. Moreover, this meant lots
of intricate intermodule-dependencies.
Thus, straighten up the control flow: give the C core the
possibility to send a "all data reset" event. And do that
in those functions that reset the core data structures.
Let each module react to this event by itself. This removes
inter-module dependencies. For example, the MainWindow now
doesn't have to reset the TankInfoModel or the MapWidget.
Then, to reset the core data structures, let the UI code
simply directly call the respective core functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When printing, the dive plan was prepended with a logo, a disclaimer
and the profile. Then it was restored by setting the plan of
displayed_dive.
Instead, simply save the original plan in a QString and restore that.
This removes a further dependency on displayed_dive, which I'd like
to make local to the planner.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
MainWindow::editCurrentDive() used to be a general function to enter
edit mode. Nowadays, this is only called for one very specific case,
namely editing the profile of a manually added dive. Therefore, we
can remove the if-branch that dealt with planned dives.
Moreover, we can do the test right at the beginning and remove
a warning message for duplicate "edition", as this is not
possible anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was only one caller of MainWindow::setupForAddAndPlan() left
and that caller immediately called DivePlannerPointsModel::createSimpleDive().
Thus, we might just as fold the former in the latter and thus
concentrate all the prepare-dive-for-plan business in one place.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Thus, the MainWindow doesn't have to extract the plan from
displayed_dive. This is a tiny step in an attempt to detangle
the interfaces. The bigger goal will be to make displayed_dive
local to the planner.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When calculating variations, they were sent to the mainwindow,
which updated displayed_dive accordingly. Do this directly
in the planner-model.
The idea is to detangle interdependencies and to make the
code reusable (planner on mobile?).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When there is no current dive, mainTab->updateDiveInfo() implicitly
clears the tabs. There is no need to call this explicitly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
ProfileWidget2::plotDive() had this weird interface, where passing
in NULL as dive would mean "show current_dive". However, most callers
would already pass in current_dive. Therefore, unify and always pass
in current_dive if the caller wants to draw the current dive.
This allows us to interpret NULL as "show empty profile". Thus,
passing in current_dive when there is no current_dive simply shows
an empty profile. This makes the calling code in
MainWindow::selectionChanged() simpler.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Firstly, the parameter appears conceptually wrong, as replot suggests
that the currently shown dive is replot. Secondly, the only caller that
passed a parameter was passing in current_dive, which is just what happens
if one doesn't pass a parameter. Therefore, change that caller (call
plotDive directly) and remove the parameter.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We used to cancel a plan (or profile edit) when the user quit
the application while planning. This is inconsistent with
respect to closing or opening a different log, where the user
was asked for confirmation.
Thus, for consistency and to avoid loss of a planned dive,
use the okToClose() function in on_actionClose_triggered() of
MainWindow. As an added bonus, this saves a few SLOC.
Fixes#1078
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Move this to the core so that desktop and mobile don't have
to call this explicitly. Matter of fact, mobile didn't call
this. It is unclear, whether that was even used on mobile,
though.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
It makes no sense to keep the device nodes if all the other data
is cleared. Let's do this automatically and not explicitly.
This ensures that the function is also called on mobile.
Currently it was only called on desktop.
Weirdly, the parser-tests were expecting that the device nodes
were not reset by clear_dive_file_data() and therefore divecomputers
were accumulating in the test results. Thus, the additional
computers had to be removed from the expected test results.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
MainWindow::on_actionAddDive_triggered() updated the profile after
calling Command::addDive(). However, that is redundant because the
undo-machinery does the profile reload. Remove the call.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
All remaining callers were passing MANUALLY_ADDED_DIVE as a new
mode, so we may just as well remove the parameter and thus
simplify the logic.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The only way to enter edit mode is to edit the profile. However,
that means that the profile is already visible, so there is no
need to change the mode. Simply remove the EDIT mode.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When entering the edit state, we don't want the user to be able
to undo/redo lest things become inconsistent. Since the only way
to enter edit state is to edit the profile, we can simply use
the disableShortcuts() function that is used by the profile
when it goes into edit state.
This has one desirable side-effect: Undo is now also disabled in
the planner. Undo during planning likewise can lead to inconsistent
state.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The profile can only be edited for manually added or planned
dives. No point in keeping code for other kinds of dives.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The CylinderModel always accessed the global "displayed_dive" and in
some special cases also "current_dive". To implement cylinder undo,
the model should work on an arbitrary dive. Therefore, in analogy
to the weight model, make the dive dynamic.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When the dive list is cleared or updated, the entries in the
divesite-model become stale and therefore the divesite-model
(with the actual name LocationInformationModel) also must be
updated. This was done manually in some parts of the code and
forgotten in others. Therefore, do it directly in the clear()
and reset() function of the dive list-model.
This might be a bit of a layering violation: why should one
model call into another if they are not in parent/child
relationship? However, this seems easier than introducing
a global "reset dives" function that coordinates the models.
Moreover, it does not appear 100% safe: if the clearing of
the divesite model causes accesses to the divelist-model,
they happen in the midst of a model reset and we had horrible
bugs with that kind of things. However, I don't think that
should happen.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When the dive data is cleared, all pointers in the undo-stack become stale.
Desktop explicitly called Command::clear() in that case, but mobile doesn't.
Thus, move the clear() call into DiveTripModelBase::clear()
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
At least in those cases where we are sending a divesChanged signal we can
easily check if the cache was properly invalidated. Of course this won't help
in cases where we don't notify the dive list about changes, either.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>