On first startup, use the splitter values suggested by Dirk:
Top/Bottom: 60/40
Info/Profile: 50/50
List/Map: 60/40
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On state change, the splitters were completely emptied and
refilled. Instead try to reuse already existing splitter
slots. This reduces annoying flickering.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The memory management of the quadrant widgets is a total mess:
When setting the widget, the QSplitters take ownership, which
means that they will delete the widget in their destructor.
This is inherently incompatible with singletons, which must
not be deleted.
To avoid all these troubles, remove the widgets from the
QSplitters in the desctructor of the MainWindow. This of
course means that we now have to take care about deletion
of the widgets.
For local widgets use std::unique_ptr, for singletons use
a static variable that is deleted on application exit.
Sadly, for the map widget we can't use a normal singleton,
because the QML MapWidget's memory management is buggy.
Add a comment in the source code explaining this.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When in planner mode, don't allow the user to change the application
state. This brought us nothing but troubles and inconsistencies.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was the "application state", which decided what to show
in the "quadrants" and the "view state" which decided which
quadrant to show. These interacted in a hard-to-grasp way.
The "view state" is used to show the map or dive list in
full screen.
I simply couldn't get these two orthogonal states to interact
properly. Moreover the thing was buggy: If a quadrant was hidden,
the user could still show it, by dragging from the side of the
window, at least under KDE.
To solve these woes, merge the two states into a single
application state. If the widget of a quadrant is set to null,
don't show it. So the four "view states" are now "application
states" where three of the four quadrants are not shown.
This also changes the memory management of the widgets:
widgets that are not shown are now removed from the QSplitter
objects. This makes it possible that the same widget is
shown in *different* quadrants.
While writing this, I stumbled upon a Qt bug, which is known
since 2014:
https://forum.qt.io/topic/43176/qsplitter-sizes-return-0
When restoring the quadrant sizes there was a test whether
the quadrant size is 0. If that was the case, a default size
was set. This seems not to work if the widgets were recently
added. Since this test now always fails, make the quadrants
non-collapsible and thus guarantee that 0 is never saved as
a size.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
The cylinder-model had an instance() function, but actually
there were two cylinder models: one used by the equipment tab,
one used by the planner.
This is misleading. Therefore, remove the instance() function
and make the cylinder-model a subobject of the planner-model.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When the show_unused_cylinders flag is not set, the cylinder tables
in the equipment tab and the planner should not show unused cylinders.
However, the code in CylindersModel is fundamentally broken if the
unused cylinders are not at the end of the list: The correct number
of cylinders is shown, but not the correct cylinders.
Therefore, add a higher-level CylindersModelFiltered model on top
of CylindersModel that does the actual filtering. Some calls are
routed through to the base model (notably those that take indexes,
as these have to be mapped), for some calls the caller has to get
access to the source model first. We might want to adjust this.
For filtering, reuse the already existing show_cylinder function
and export it via CylindersModel.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We tend to use lower-case filenames. Let's do it for these files
as well. Simple search & replace.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The UI talks to the filter model. Therefore route clearing of
data through that model instead of accessing the source model
directly.
This will allow us to remove the DiveTripModel::instance()
function and makes control flow less "jumpy".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function had only one line and had only one caller.
We might just as well fold that line into the caller.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
By clearing the model, its contents are removed. There is no
point in reloading the model.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The hidden_by_filter items are set on reload of the dive list.
No point in reloading the filter again.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The way this was accessed via Qt's model semantics was horrible.
This gives arguably more readable code, since we don't have to
shoehorn things through QVariants.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The filter-model was catching dives-added / dives-deleted signals
from the models to keep track of the number of shown dives.
To simplify the data flow, do this directly in the undo-command.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Introduce a DiveTripModelBase::clear() function that cleanly
clears all dive data inside a beginResetModel()/endResetModel()
pair. Thus, the UI will be cleanly reset and we can remove
explicit calls to
- graphics->setEmptyState()
- mainTab->clearTabs()
- mainTab->clearTabs()
- diveList->reload()
from MainWindow::closeCurrentFile().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
It makes no sense to have a non-NULL current_dive once all dives
have been deleted. Therefore, clear current_dive implicitly in
clear_dive_file_data() and don't depend on the caller performing
this.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The latter was the only caller of the former and there seems
to be no clear separation between the two. By making a single
function out of this the code is easier to follow and duplicate
code can be more easily detected. Matter of fact, the profile
was cleared twice.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the future we might want to use undo-commands for mobile as
well (even if not implementing undo).
Therefore, move the undo-command source from desktop-widgets
to their own commands top-level folder.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The way we handle singletons in QML, QML insists on allocating the
objects. This leads to a very idiosyncratic way of handling
singletons: The global instance pointer is set in the constructor.
Unify all these by implementing a "SillySingleton" template. All
of the weird singleton-classes can derive from this template and
don't have to bother with reimplementing the instance() function
with all the safety-checks, etc.
This serves firstly as documentation but also improves debugging
as we will now see wanted and unwanted creation and destruction
of these weird singletons.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The setting of the disclaimer variable was removed inadvertently
some time ago, which removed the disclaimer from the printed plan.
Instead, introduce a function that returns the disclaimer with
the current deco mode. Use that function to generate the dive
notes and for printing.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When changing the selection the MapLocationModel was reset.
This lead to crashes on Qt-5.9 which are due to QML accessing
data that was freed during model reset. This putative Qt bug
doesn't happen on newer Qt versions. At least Qt-5.12 is known
to work.
Instead of fighting the bug, let's simply not reset the model
but send a dataChanged() for every element of the MapLocationModel.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In MainWindow::refreshDisplay() with doRecreateDiveList=true
the map was reset before the dive list was recreated. This
makes no sense and only worked because the map was reloaded
again when a dive in the list was selected.
Reload the map after recreating the dive list.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
But don't show our cloud storage entry (as that is already in the File menu,
anyway).
This is extremely useful because while you can manually enter a file name to
save to (and therefore can use the 'magic' git repo syntax), on most OSs there
is no way to enter that non-existing 'file name' (which is the git branch in
square brackets) in the file open dialog.
Fixes: #2236
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Move the declarations of the "report_error()" and "set_error_cb()"
functions and the "verbose" variable to errorhelper.h.
Thus, error-reporting translation units don't have to import the
big dive.h header file.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In 2e230da361 the dive-selection signals
were unified. Sadly, this was done in a suboptimal way resulting in
numerous calls to updateDiveInfo(), which refreshes the main-tab.
Firstly, the MainWindow connected to selection changes from both,
the undo-command and the divelist. Secondly, every selected dive
in the divelist caused a single signal.
Thus, connect only to the divelist (this is necessary for user-initiated
selection changes) and only send a single signal in the divelist
per selection-reset.
This is still less than perfect as updateDiveInfo() is called even
if the current dive doesn't change.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For historic reasons, there where three distinct signals concerning
dive-selection from the undo-machinery:
1) divesSelected: sent newly selected dives
2) currentDiveChanged: sent if the current dive changed
3) selectionChanged: sent at the end of a command if either the selection
or the current dive changed
Since now the undo-commands do a full reset of the selection, merge these
three signals into a single signal.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of calling into the planner, simply create the dive computer
information right there, using the existing helper function we have to
create simple profiles.
Fixes#2128
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
These functions were spread out over dive.c and divelist.c.
Move them into their own file to make all this a bit less monolithic.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The way the application state would enable/disable widgets was very
"dynamic". A property-list would be generated and put in a set
of arrays. Very hard to figure out what is going on.
Replace these property-list by flags and explicit old-fashioned boolean
expressions.
Join the two arrays (widget- and property-lists) into an array of
a unified data structure.
Replace the macro that sets the widgets by a simple static function.
Factor out the four loops that added widgets to the quadrants into
a simple static function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The application state was encoded in a QByteArray. Thus, there was
no compile-time checking. Typos would lead to silent failures.
Turn the application state into an enum. Use the enum-class construct,
so that the values don't polute the global namespace. Moreover,
this makes them strongly typed, i.e. they don't auto-convert to
integers.
A disadvantage is that the enums now have to be cast to int
explicitly when used to index an array.
Replace two hash-maps in MainWindow to arrays of fixed sizes.
Move the application-state details into their own files.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of looping over the dive table and extract dive sites,
loop over the dive site table.
This makes it possible to show dive sites that have no dive
associated with them.
But we have to create to functions that check whether a dive
site has any shown dives or has any selected dives.
Moreover, change the code to add near dive sites of the same
name if in edit mode. Other wise (erroneously added?) dive
sites with the same name cannot be moved on the map.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When changing the dive selection, we have to reload the map to show
the correctly highlighted flags. Do this directly by hooking into
the DiveListNotifier::divesChanged signal instead of indirectly
via the MainTab.
Moreover, on reload center on the highlighted dive sites.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Adds "Import->Import dive sites" menu to mainwindow.cpp and adds the
on_actionImportDiveSites_triggered() method to prompt for the filename
to import from. The files are parsed and then any dive and trip data is
cleared before opening a dialog box to select which sites are to be
imported.
Signed-off-by: Doug Junkins <junkins@foghead.com>
- Use a beginResetModel()/endResetModel() pair instead of distinct
addRows / removeRows pairs.
- Reuse the update function in the constructor().
- Let "rows" be the number of rows, not the number of rows minus one.
- Remove updateInfo() function as it does the same as update().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The only caller of said function used to check whether MainTab is
in edit mode. For this case there is already a function - use that
instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Apparently, in some Qt-versions the destructor of the base class
calls hide on child-objects (according to Qt's object hierarchy).
This is obviously called after the derived class has been destructed.
In a concrete case, the base class of the destructed MainWindow
would hide the TabDiveSite object. That would reset the filtering
if a dive site was selected, which would indirectly access the
MainWindow, which is already partially destroyed.
Therefore, destroy the MainTab before destroying the MainWindow.
Do this by keeping it as a std::unique_ptr subobject. Thus, it
will be destroyed before the MainWindow and remove itself from
Qt's object hierarchy.
Reported-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The model was not reset on file close, leading to weird effects.
New dive sites would be added at the end of a table full of empty
entries.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The editing of a dive field is only performed when focus
is removed from the field. On pressing CTRL-s, the changes
in the currently active field were therefore not saved.
Remove the focus from all fields to trigger an edit command
yand thus ensure that all changes are saved.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Properly implement the unsaved-changes flag(s). Since we currently have
two kinds of changes, there are two flags:
1) dive_list_changed in divelist.c marks non-undoable changes. This flag
is only cleared on save or load.
2) QUndoStack::isClean() is used to determine the state of undoable
changes. Every time the user returns to the state where they saved,
this flag is cleared.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The whole edit logic moved from displayed_dive to current_dive
and it became more and more tedious to keep these in sync.
Therefore, simply always display current_dive. The only exceptions
are the equipment tab and the planner, as these are not yet
integrated in the undo system. Once this is done, displayed_dive
can be removed.
Moreover, remove the clear parameter from updateDiveInfo().
Instead simply clear of there is no current_dive set.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of letting the user edit the fields before adding a dive,
simply add an empty dive. Thus, the ADD mode of the main tab can
be removed.
Constructing a new dive with default-depth and making sure that
the dive is displayed correctly is very subtle. This all needs
to be detangled in due course.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Remove a few cases of
void fun() {
...
}
While touching these functions, fix a few other whitespace
coding style violations.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These functions are now performed by the edit commands and the
macros have no users. Remove them.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>