Commit 2cea115ddb "fixed" the selection
by hooking into mouseRelease events. An unintended consequence was
that scrolling with the cursor keys didn't update the current dive.
Therefore, also hook into the corresponding key-press events.
This is just horrible, but I'm not aware of any possibility to fix
it properly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There are now three filter modes:
1) Dive site
2) Fulltext
3) Normal
When doing a fulltext search, get the dives that match the
fulltext filter and then apply the other filters on that list.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The FilterData struct has the enum StringMode, which describes how
strings are searched (substring, startswith, exact). To make it
more generally accessible, remove it from the class. Since it is
an "enum class", the values don't pollute the global namespace anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These were used to remove warning-icons to mark tabs with user
changes. However these icons haven't been set since commit
a86aca0378.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The tank-info-delegate cast its model to CylindersModelFiltered,
since this is what the equipment-tab uses since implementing the
filtering of unused cylinders. However, the planner users the same
delegate and still uses the unfiltered CylindersModel. This means
that the (dynamic) cast returns a null pointer and crashes.
One possibility would be to derive CylindersModelFiltered and
CylindersModel from the same class that defines virtual functions
and cast to that class.
This is a different attempt: don't cast (i.e. stay with a
QAbstractItemModel and play it via Qt's model-view system. Firstly,
replace the passInData function by a role to setData(). Secondly,
read the working-pressure and size via new columns using data().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was used to test whether the "really discard changes?"
message should be shown. However, we now edit weightsystems
directly with undo commands. Therefore, the check is unnecessary
and the whole function can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the planner we used to filter out "unused" cylinders as in the
equipment tab. It is unclear whether that makes sense or can even
easily be reproduced, since such cylinders have to come from an
imported dive.
To be on the save side, let's not do this. Replace the
CylindersFilteredModel introduced recently by a plain
CylindersModel.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
Currently, we do substring search. Implement starts-with and
exact mode (for example when search for "Cave vs. Cavern" tags).
For each textual search criterion add a combo-box.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These just make no sense. Since the value is copied, it
has no meaning to the caller whether the function can
change the value (and vice versa for return types).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
exportFunc was a collections of functions for exporting dive data.
It had no state, therefore there is no reason for it to ever be
instantiated.
Simply remove the class. Rename the saveProfile function to
exportProfile so that all export functions start with "export".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When exporting dives we show a message. The message is closed when
the export is finished. This is coordinated by a QFuture. Instead
of keeping a global QFuture in the export-code, pass it around
as a local variable.
This is supported according to Qt's documentation:
"QFuture is a lightweight reference counted class that can be
passed by value." and the source code indicates the same.
Not only does this remove a global, it also makes the code
more flexible: Now we could show one notification per export,
for example.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Fix two issues:
1) When narrowing the selection, we didn't get setSelection()
calls. Only, when the user released the mouse button was
the selection updated. Therefore, hook into the mouse-release-
event and update the UI if the selection changed.
2) We updated the ui in setSelection(). However, this was called
on mouse-move even if the actual selection didn't change.
Therefore, compare selection before and after processing of
the event and only refresh the UI if there are changes.
Clearly, this can only be a quick stopgap solution and we
should find out how to properly hook into the selection change
machinery. Though see commit 4928c4ae04
for the reason why we do things as we do them.
Fixes#2595
Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The whole point of having X::instance() functions is to solve
the infamous "Static Initialization Order Fiasco": When having
global objects in different translation units, their order
of initialization is undefined. Thus, when these objects access
each other one cannot guarantee the correct order of
initialization. The X::instance() functions generate the objects
on first use.
DivePlannerPointsModel has such an instance() function. However,
for convenience(?) in diveplanner.cpp we find the global variable
static DivePlannerPointsModel* plannerModel =
DivePlannerPointsModel::instance();
Thus, the DivePlannerPointsModel constructor is run before main(),
negating the whole purpose of the instance() function.
Let's remove this line to avoid hard-to-debug startup issues.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On the dive site screen, when entering invalid GPS coordinates,
we cleared the location of the dive site. Don't do this. To
clear the location, the user now has to enter the empty string.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On the dive site edit screen, when the user enters invalid
coordinates and saves, we treat this as "no location". This
is rather unfriendly, therefore warn the user with a visual
clue. This is performed by setting the background color of
the widget to red.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
After selecting dives, the selected dive sites are collected.
This was done using the selectionModel()->selection().indexes(),
which is wrong, because it gives one index per row *and* column.
Accordingly, every dive site was added numerous times to the
array of dive sites to be selected. Change this to
selectionModel()->selectedRows(), which gives one entry per row.
Moreover, if multiple dives with the same site were selected,
this site was also added to the array multiple times. Therefore,
check the array before adding sites.
Note that all this should not change the user experience in
any way, it is only a code-hygiene thing.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Usually, we use PascalCase (i.e. camelCase with a capital
letter at the start) for class names. For consistency, let's
do it here as well.
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>
This class contains only static functions (i.e. it does not contain
any state). There does not seem to be a reason to have an instance
of that class. Therefore, remove the instance() function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add surface_segment to plannerShared and then
update desktop-widgets.
Signed-off-by: jan Iversen <jan@casacondor.com>
desktop-widgets: use plannerShared for surface_segment
Change getter/setter for surface_segment to plannerShared, in
order to share the conversion with mobile diveplanner
Signed-off-by: jan Iversen <jan@casacondor.com>
Move conversion cuft <-> liter from desktop-widget/diveplanner.cpp
to plannerShared, to facilitate the same results in mobile
diveplanner
Use Backend for bottomsac/decosac and update to check
for switch LITER <-> CUFT
Add bottomsac/decosac to QMLinterface.
Signed-off-by: jan Iversen <jan@casacondor.com>
Variables without conversion, do not need to pass plannerShared
(due to the QML interface).
Simple variables do not pass plannerShared, but diveplanner
in desktop-widgets and qmlinterface in mobile-widgets call the
implementation directly.
Signed-off-by: jan Iversen <jan@casacondor.com>
Make notes rates available to QML through the Backend interface.
Remove the corresponding variables from plannerShared.
Getters are from prefs. while setters are linked to diveplan model.
Remark: signals from qPrefDivePlanner is used, because the diveplanner model
sets qPrefDivePlanner but do not issue special signals.
Signed-off-by: jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This shouldn't be part of the desktop UI code; there's still the issue that we
really shouldn't hand code XML parsing, but I'll leave that for later.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This allows Subsurface to obtain the coordinates of a dive directly
from a GPS track. It parses a GPX file (GPX V1.0 or V1.1) from
a GPS to locate the trackpoint immediatedly after the start of a
dive. There is an additional "Use GPS file" button in the Edit Dive
Site panel that is selected from the Notes tab. Image:
This allows one to select a GPX file, bringing up the Import GPS
dialog.
There is extensive provision for cross-checking that the dive track
synchronises with the dive start and end. If the Save button in the
dialog is pressed the dive coordinates are copied into the Dive
Coordinates text box in the Edit Dive Site panel. The map moves
to indicate the location of the dive site.
The bulk of the work is done in importgps.cpp. The code is
pretty intergrated: I tried to break it up in smaller commits but that
was not feasible.
The code includes responses to the comments by @neolit123 and
@bstoeger. The C-based file input was replaced with Qt-based
code using QChar, QString and QFile.
[Dirk Hohndel: fixed several small issues in the .ui file, removed
various headers includes that weren't needed and
fixed printing of minutes as zero padded]
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Change ascent/descent setter function names to set_<name>Display
to show the value is prepared for displaying (common for desktop and QML).
Signed-off-by: jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The spinboxes are already connected to diveplannermodel set_ functions, remove
second connect to plannerShared.
Change get functions to use diveplannermodel.
Signed-off-by: jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Remove string version of unit_system, duration_units, length, pressure,
temperature, vertical_speed_time, and volume, including tests and make signals
strongly typed in C++
Signed-off-by: jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
It's not even clear if we need the setCaseSensitivity() call as it appears
that a case insensitive completer is the default.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
While technically the initial value of this variable makes no difference as
it is set when the first dive is displayed, technically Coverity is correct.
Fixes CID 353273
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The last SIGNAL/SLOT cannot be converted due to a limitation in the
new connect() syntax, it does not "understand" default parameters.
Signed-off-by: jan Iversen <jan@casacondor.com>
Change connect for QAbstractButton::clickedto new syntax.
Change connect for QDialogButtonBox::accepted/rejected to new syntax.
Signed-off-by: Jan Iversen <jan@casacondor.com>
correct SLOT was sec_bottomsac(double), which
is not reported as an error.
correct to set_bottomsac(double)
Signed-off-by: Jan Iversen <jan@casacondor.com>
QSignalMapper gives a warning that it is depreciated, and the
doc. states that using a lambda function is more efficient.
Replace use of QSignalMapper.
Signed-off-by: Jan Iversen <jan@casacondor.com>
QSignalMapper had a parameter convert problem, when mapping to
set_deco_mode in plannerShared.
Use lambda function in connect to avoid parameter convert problem.
Signed-off-by: Jan Iversen <jan@casacondor.com>
There were two cases that were handled incorrectly:
- if the user hasn't entered a salinity, obviously there shouldn't be a warning
- if this is a manually entered dive, there is no salinity downloaded from a
dive computer, so equally, no warning
Suggested-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We need to show this whenever the value in the dive (which could have been
entered by the user some other time) doesn't correspond to the value in the DC.
This, btw, will point out to the user if different DCs have different values.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We were royally confused when we didn't know the salinity value (e.g., if the
dive computer didn't provide that information). We somehow treated this as the
same as wanting to use the salinity information in the dive computer. Which
makes no sense.
While cleaning this up, this also adds the textual representations of the water
types as a string list that corresponds to the enum values that we use - this
way it's easier to stay consistent.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Added code for string translation.
Added code to improve UI on Windows.
Added some comments to make the code more understandable.
Enable salinity combobox for manually entered dives
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The user may modify the salinity by selecting a water type from the combobox.
The new datum does not replace the existing salinity value but is stored in a
separate variable within the dive structure. If the dc-based salinity is
overwritten, there is an exclamation mark next to the modified salinity value
to indicate that the salinity has been overwritten. The dc-derived salinity can
always be recovered by selecting the "use dc" option in the combobox.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Create a checkbox in the Preferences: General screen that enables or disables
editing of the salinity data. This preference is saved with all the other
preferences.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is a cosmetic update to remove some warning messages
while building a fresh subsurface. These warnings were due to
duplicate label names in the .UI files.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Use plannerShared setter to update the variables in qPref.
This will also signal the cylindermodel to calculate a new bestmix.
variables:
bottompo2
decopo2
bestmixend
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Use plannerShared setter to update o2narcotic. This will also signal
the cylindermodel to calculate a new bestmix.
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
variables
bottomsac
decosac
problemsolvingtime
sacfactor
are not set in diveplanner.cpp, but instead
signals a slot in plannerModel.
change signals to slots in plannerShared
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
variables
min_switch_duration
are not set in diveplanner.cpp, but instead
signals a slot in plannerModel.
and are read from plannerShared which includes a conversion
change signals to slots in plannerShared
change read from prefs. to plannerShared
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
change local doo2breaks to plannerShared and update connect.
change signals to slots in plannerShared
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
variables
drop_stone_mode,
last_stop,
switch_at_req_stop
are not set in diveplanner.cpp, but instead
signals a slot in plannerModel.
change signals to slots in plannerShared
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
change local setBailout to plannerShared and update connect.
change signals to slots in plannerShared
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
planner_deco_mode is not set in diveplanner.cpp, but instead
signals a slot in plannerModel.
reserve_gas is not set in diveplanner.cpp, but instead
signals a slot in plannerModel.
change signals to slots in plannerShared
Signed-off-by: Jan Iversen <jan@casacondor.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit does some final cleaning up to the code, mostly deleting
white space and comments.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Add a separate preferences tab for resetting all preferences to their default values.
One or two very small alterations to other sections of the preferences UI code.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This adds a tab for dive log - related preferences.
A suitable test programs is still required.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Add a preferences tab for dive download, allowing resetting the
buttons representing download connections in the Download panel.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Remove the preference settings dealing with thumbnails (currently under
General preferences and Profile preferences) and put them in a newly-created
Media preference tab.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Remove the "Show unused cylinders" checkbox (Profile tab) and the
"Set default cylinder" qTextEdit box (General tab) and put them in a
separate and new Equipment tab. This sounds like a simple task but,
as can be seen from the files changed, was actually a complex matter.
Adapt the existing test programs (General and TechDetails) for creating
a test program that tests parts of the Equipment tab.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
WARNING: multi directory commit, needed to secure it builds.
move the core/plannerShared.* to backend-shared.
update CMakeLists.txt to include backend-shared lib in link process.
update ios project to reflect new directory
Signed-off-by: Jan Iversen <jan@casacondor.com>
WARNING: multi directory commit, needed to secure it builds.
move the core/exportfuncs.* to backend-shared.
update backend-shared/CMakeLists.txt to generate backend-shared lib
update CMakeLists.txt to include backend-shared lib in link process.
update ios project to reflect new directory
Signed-off-by: Jan Iversen <jan@casacondor.com>
change the settings variables using UNIT_FACTOR to use
plannerShared instead.
There are no changed functionality, it is simply removing calculations
from the UI.
Signed-off-by: Jan Iversen <jan@casacondor.com>
The CMakeLists.txt referenced mapwidget which is in another root
directory (and also a seperate library)
Remove mapwidget reference from CMakeLists.txt
Signed-off-by: Jan Iversen <jan@casacondor.com>
Use doUpload() from uploadDiveLogsDE
Connect signals from uploadDiveLogsDE to do UI part.
Clean slots to only contain UI.
Signed-off-by: Jan Iversen <jan@casacondor.com>
Do not prepare zip file, just because user selected the divelogs.de
radiobutton
Move prepareDives to startUpload (slot handling user clicking on
upload button).
Signed-off-by: Jan Iversen <jan@casacondor.com>
Clean prepareDivesForUpload() and uploadDives() so that
uploadDives() only contain network handling no UI.
Signed-off-by: Jan Iversen <jan@casacondor.com>
Use qPrefCloudStorage for divelogde_user/password to secure same
handling as other settings, as well as same handling as used in
shared uploadDiveLogsDE class
Signed-off-by: Jan Iversen <jan@casacondor.com>
Remove local implementation (prepare_dives_for_divelog) and call
uploadDiveLogsDE::prepareDives, which are shared between
mobile and desktop
Signed-off-by: Jan Iversen <jan@casacondor.com>
Remove shared code from DiveShareExportDialog::doUpload()
and add call to uploadDiveShare::doUpload()
Remark signal handling is not implemented.
Signed-off-by: Jan Iversen <jan@casacondor.com>
Diveshare upload in mobile is using qPrefCloudStorage, so change
diveshareexportdialog as well, to keep consistency.
Signed-off-by: Jan Iversen <jan@casacondor.com>
The dive list accesses the filter model, therefore it makes sense
to also get the header data from there, even if they are only
forwarded from the source model.
This makes control flow more logical and will allow us to remove
the global DiveTripModel instance.
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 selection changes upon completing the filter are handled by
the core. Don't do this explicitly in the DiveListView.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since changes to the weight model are not modal anymore, nobody
queries the changed-flag. Remove it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Implement the EditWeight undo command. Since there is common code
(storage of the old weight), this creates a common base class for
RemoveWeight and EditWeight. The model calls directly into the undo
command, which is somewhat unfortunate as it feels like a layering
violation. It's the easy thing to do for now.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The WSInfoDelegate (weight-system-info delegate) is used to display
a combo box of known weightsystem-types and auto-fills the weight if
the weightsystem-type is changed.
This would overwrite the weight data of the displayed dive when the
user hovers over the different entries. Moreover, it saves the original
weight in case the user cancels the editing action.
This is not viable when implementing undo of weightsystem changes,
because hovering over entries should not produce individual undo
commands. Instead, implement a special "temporary" row in the
weightsystem model. On canceling of the edit actions, simply reload
the weightsystem from the unmodified dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is only one caller of WeightModel::weightSystemAt() and that
certainly does not need a pointer into the weightsystem-table of
the current dive. Return a value type instead of a pointer.
This allows us to mark WeightModel::weightSystemAt() as const and
use it from WeightModel::data(). Slightly cleaner code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This one is a bit more complicated than weight adding, because the
multiple-dive case is not well defined. If multiple dives are selected,
this implementation will search for weights that are identical to the
weight deleted in the currently shown dive. The position of the weight
in the list is ignored.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When connecting a model to the TableModel class, it would connect
clicking on an item to the remove() slot of the model.
This breaks the program flow implied by the undo code:
Ui --> Undo-Command --> Model --> UI
Moreover, the naming of the remove() slot is illogical, because
clicks can also have different effects, as for example in the
cylinder-table.
Therefore, move the connect() call from TableModel to the
callers. In the case of TabDiveSite, move the remove() function
from the model to the TabWidget, where it makes more sense.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Introduce an AddWeight undo command. This is modelled after the
numerous dive-edit undo commands. The redo and undo actions are
connected to the WeightModel via two new signals, weightAdded
and weightRemoved.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The WeightModel always acted on the displayed dive. To support undo
of weightsystem changes, operate on an arbitrary dive. This is
in line with other models, where the updateDive() function resets
the model to represent a certain dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The QList served as backing store for backupExpandedRows()
and restoreExpandedRows(). However, these always came in
pairs in the same scope. There is no reason to store the
expanded rows over a longer time.
Therefore, return the expanded rows from backupExpandedRows()
and take them as argument in restoreExpandedRows(). Morover
replace the QList<int> by the much lighter std::vector<int>.
We certainly don't need copy-on-write, reference-counting and
immutability of iterators in this case.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Calls of these functions were removed in the previous commits.
Now, remove the functions themselves.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old code saved, cleared and restored the selection. This
is not necessary anymore, because on model reset the selection,
which is stored in the core, is reset. Remove the unnecessary
selection handling.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When accepting changes, the main tab refreshes the display in
a remember/restoreSelection() pair. Since the display refresh
doesn't lose selection, these calls can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old renumbering-dives code had to remember and restore the
selection. This became unnecessary with the undo-code. The
restore-call was removed, the remember-call left in. Remove it
as well.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveListView caught signals from the DiveTripModel
with the corresponding indexes. However, the DiveListView
is actually connected to the MultiFilterSortModel and
thus has to translate the indexes.
Instead, catch the signals in the MultiFilterSortModel,
transform them and resend. Let the DiveListView get
its signal from the MultiFilterSortModel.
Yes, this makes things less efficient because there is
an extra signal. On the upside, the makes data-flow much
more logical. Selection will have to be fixed anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The goal here is to unify desktop and mobile by moving
selection code from the desktop-only view.
Currently, initialization of the selection still has to be
called from the view after connecting the appropriate signals.
This is due to the weird way in which create completely new
models when resetting them.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveListView has a function to select the first dive. Move
this to the core to be able to call it from all parts (not only
desktop) of the code.
Currently, this has a (small?) UI regression: when filtering dives
and no selected dive is visible anymore, the old code would select
the first dive in the list. The new code selects the newest dive,
which might not be the first if some sort-criterion is active.
To revert to the old behavior, it will be necessary to move the
sorting function likewise to the core.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since we now have a selection.c translation unit, put the selection-
related functions there.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For deterministic construction/destruction (i.e. objects are
destructed in reverse order of construction) it is crucial that
constructor initializer lists follow the order of the class
definition.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Recently, undo of dive-replanning was introduced. Therefore,
it appears logical to do the same thing for editing of the
profile of manually added dives.
For now, use the same undo-command, just change the displayed
text from "replan dive" to "edit profile". Move the fixup dive
call into the undo-command.
Eventually, every action on the profile should be made undoable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Connect the UI to the underlying dive structure. Enable proper initialisation
and management of star widgets while Information tab is active. Enable undo for
the addtional star widgets.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Implement the UI features related to the additonal star widgets.
Create the additonal star widgets and connect them to the preferences settings.
By default only the current and visibility widgets are shown. In this case the
current widget is on the left hand side of the tab. If the additional widgets
are enabled the horizontal order of the widegts are changed to reflect
attributes roughly from the start of the dive on the left to those towards the
end of the dive on the right.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Create a preference setting on the General Settings page. The setting is saved
with the other preferences.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When selecting all dives via CTRL-A or manually and the trips
were not expanded, the QSelectionModel sends a single
selectionChanged signal per trip. We are reloading the map
in every call, making this very slow.
I couldn't figure out how to make QSelectionModel behave more
nicely, therefore I chose the nuclear option: Remove the map
reloading from selectionChanged() and hook into all functions
that do selection changes. In these functions, first call the
original code and then do the selection-changed operations.
This will certainly need some tuning.
Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
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>
Split out the actual filtering from the MultiFilterSortModel.
Create a DiveFilter class that does the actual filtering.
Currently, mobile and desktop have their own version of this
class, though ultimately we may want to merge them.
The idea here is that the trip-model and undo-commands have
direct access to the filter-function and thus can take care
of keeping track of the number of shown dives, etc.
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>
We mark hidden/shown dives in the core but store the number
of shown dives in the MultiFilterSortModel. Move this datum
to the core for improved locality.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Remove modification of style sheet for "Dive mode" box in info tab.
This fixes a broken UI layout under Windows.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Three minor changes in tab widget UI layout and txt:
- Remove leading space in string "Gas name"
- Remove duplicate <item> entry
- Correct "leftMargin" and "rightMargin" to 0 everywhere
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
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>
We used to only keep sites with dives around. This changed when
implementing the dive site tab. The paste-dive code was written
using the old semantics and thus, when overwriting dive sites,
it deleted unused dive sites.
To make things consistent, remove that code. It would be very
weird when dive sites are deleted by pasting, but not by setting
a different dive site manually.
Bonus: no more dependencies on desktop-includes in the undo code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This file included "desktop-widgets/divelistview.h" without needing
it. If we want to use the undo commands on mobile we shouldn't
include desktop headers. Therefore, remove the include.
This has the unintended side-effect that the Qt debug headers are
not included indirectly anymore. Thus, change a few
"qWarning() << ..." instances to "qWarning(...)".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Removing / moving a dive computer needs a profile replot. This
was done explicitly in DiveComputerBase::redoit(). This is
unnecessary, as a profile replot is performed implicitly by the
setSelection() call.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Dives used to be added from a special dive-edit screen. Thus, the
undo command had to close that screen. This is no longer the case.
Remove the calls.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
clang correctly warns about std::move()ing objects returned from
functions. This is a pessimization, because the compiler can't
copy elide the object. Remove.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the information tab, presenting atmospheric pressure is a bit
unintuitive because the diver cannot easily relate that to altitude.
For the Atm. Pressure widget in the Information tab this code does:
If the atmospheric pressure for a dive exists and the user selects
the 'm' or 'ft' option from the combobox, then the estimated altitude
is shown in the text box.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
To test whether an entry is a trip, we passed a pointer to the
trip through a QVariant and tested that for null-ity.
Passing pointers through QVariants has given us myriads of
problems in QML, therefore introduce a bool IS_TRIP_ROLE
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently the top righthand part of the notes tab is used for
showing and editing air teperature and water temperature. But
these fields were moved over to the Information tab and are not
required in the Notes tab any more. Rather use this space for the
depth and duration data for manually-entered dives. Currently
extra vertical space is created in the Notes tab for showing this
field, resulting in inefficient use of screen space and
inelegant layout. This code moves the Duration and Depth fields
into the top righthand of the Notes tab.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
The undo stack is preserved.
This is in preparation of removing temperatures from the Notes tab.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
1) Reorganise the existing widgets in the Information tab
2) Move divemode widget and visibility widget from Notes tab to
Information tab
3) Translate water density to a word indicating water type
4) Reorganise the Notes tab to compensate for the moving the
divemode and visibility widgets to the Information tab
5) Remove the problems in showing a QGroupBox in Qt Windows. I do
this by removing the CSS specifying border characteristics
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Instead of accessing the cylinder table directly, use the get_cylinder()
function. This gives less unwieldy expressions. But more importantly,
the function does bound checking. This is crucial for now as the code
hasn't be properly audited since the change to arbitrarily sized
cylinder tables. Accesses of invalid cylinder indexes may lead to
silent data-corruption that is sometimes not even noticed by
valgrind. Returning NULL instead of an invalid pointer will make
debugging much easier.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The tab was crashing if there were no cylinders because
1) per_cylinder_mean_depth() would access non-existing cylinders.
2) TabDiveInformation::updateProfile() would access a non-existing
mean.
Fix both of these crash conditions by checking whether the dive
actually has cylinders.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of using fixed size arrays, use a new cylinder_table structure.
The code copies the weightsystem code, but is significantly more complex
because cylinders are such an integral part of the core.
Two functions to access the cylinders were added:
get_cylinder() and get_or_create_cylinder()
The former does a simple array access and supposes that the cylinder
exists. The latter is used by the parser(s) and if a cylinder with
the given id does not exist, cylinders up to that id are generated.
One point will make C programmers cringe: the cylinder structure is
passed by value. This is due to the way the table-macros work. A
refactoring of the table macros is planned. It has to be noted that
the size of a cylinder_t is 64 bytes, i.e. 8 long words on a 64-bit
architecture, so passing on the stack is probably not even significantly
slower than passing as reference.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of using a sub-array, use a std::vector<>. This is
a necessary step in removing the MAX_CYLINDERS restriction.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When keeping track of cylinder related data, the code was using
static arrays of MAX_CYLINDERS length. If we want to use dynamically
sized cylinder arrays, these have to be dynamically allocated.
In C++ code, this is trivial: simply replace the C-style arrays
by std::vector<>. Don't use QVector, as no reference counting or
COW semantics are needed here. These are purely local and unshared
arrays.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
get_gas_used() returns the volume of used gases. Currently,
an array with MAX_CYLINDERS is passed in. If we want to make the
number of cylinders dynamic, the function must use an arbitrarilly
sized array.
Therefore, return a dynamically allocated array and free it
in the caller.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The ProfileWidget2::recalcCeiling() function is used in one place,
namely when an undo-command changes the mode. It recalculates
decompression data and repaints the ceilings and thus avoids a
full profile-redraw.
This is smart, but it becomes problematic when the dive is changed
and the ceiling is recalculated before the profile is redrawn.
The DivePlotDataModel then still has data from the previous dive
but cylinders of the new dive are accessed.
This kind of situation may arise if multiple dive fields are
updated, as for example when replanning a dive.
Currently, this only causes a temporary mis-calculation. When
removing MAX_CYLINDERS this will lead to crashes.
One might attempt to fix the whole data-dependency mess. This
commit goes the cheap route and simply redraws the profile when
the mode is changed. Yes, it is in a way ineffective, but we
do worse things. The ProfileWidget2::recalcCeiling() thus becomes
unused and is removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When computing the best mix for a target depth, for helium, one
can either require that the partial pressure of N2 is the same
as at the target depth or the partial pressure of N2 plus O2.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
We test for d being NULL so that's clearly an option we worried about, yet
we already called get_dive_site_for_dive(d) which dereferences d.
Found by Coverity. Fixes CID 350118
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When clicking "done" on the dive site edit screen, the diveSite
member variable was reset to nullptr in acceptChanges() at the
beginning of the function. This prevented posting an undo-command
as a consequence of the active widget losing focus.
Reset the diveSite variable after exiting dive-site mode, which
causes the active widget to lose focus.
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The native buffer of a membuffer is not NUL-terminated, so when you want
to detach it and use it as a C string, you had to first do
'mb_cstring()' that adds the proper termination/
This was all documented in the header files, and all but two users did
it correctly.
But there were those two users, and the exported interface was
unnecessarily hard to use. We do want the "just detach the raw buffer"
internally in the membuffer code, but let's not make the exported
interface be that hard to use.
So this switches the exported interface to be 'detach_cstring()', which
does that 'mb_cstring()' for you, and avoids the possibility that you'd
use a non-terminated memory buffer as a C string.
The old 'detach_buffer()' is now purely the internal membuffer
implementation, and not used by others.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This should never matter as we should never call undoit before redoit.
Extra ensurance that we don't access random data.
Found by Coverity. Fixes CID 350076
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This one is a bit complicated as it depends on a specific flow, but it
seems like setup_cvs_parms might indeed write NULL to the element at
index 49 of parm. I'm not 100% sure that the sequence of events required
for this can happen, but adding one more pointer to the array seems like
cheap insurance.
Found by Coverity. Fixes CID 350120
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The profile repainting code that was called when a dive changed was
located in a separate function. Not only did it take a redundant
parameter, it also performed very weird stuff like entering and
exiting plan state. That did not work at all. Replace by a simple
call to plotDive() and things work much better.
There was a comment about DivePlannerPointsModel and profile
getting out of sync. So let's keep an eye out for that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The divesEdited signal sends the changed field as a parameter.
Since some undo-commands change multiple fields, this led to
numerous signals for a single command. This in turn would lead
to multiple profile-reloads and statistic recalculations.
Therefore, turn the enum into a bitfield. For simplicity,
provide a constructor that takes classical flags and turns
them into the bitfield. This is necessary because C-style
named initialization is only supported on C++20 onward!
Is this somewhat overengineered? Yes, maybe.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On undo/redo, the dive statistics tab was not updated even
if a selected dive was changed. Fix that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Implement an undo command that overwrites the dive-computers and
cylinders of the current dive with a given dive. This will be used
when replanning a dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The undo system sets updates individual dive fields on
redo respectively undo. Make salinity such a field, since
it is changed on replanning a dive.
To do this, break out the "update salinity" functionality
into its own function, add an entry to the DiveField enum
and add the corresponding switch-case.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since requiring Qt >= 5.9.1, we can use the pointer-to-member-function
overloads of addAction (introduced in Qt 5.6). This has the advantage
of compile-time checking of the signal/slot parameters.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The plan is to make the model the authoritative source of
the imported dives. Therefore, access the number of
downloaded dives from there.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Clearing the table in the thread leaves the model in an inconsistent
state. Don't do that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When importing dives, consume the tables from DiveImportedModel
and not the DownloadThread. This appears more logical and avoids
an inconsistent state of the DiveImportedModel: On import the
tables would be reset, but the DiveImportedModel wasn't
informed of that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In DownloadFromDCWidget::on_ok_clicked() deselected dives were
directly deleted from the dive table, leaving DiveImportedModel
in an inconsistent state. Use the function in DiveImportedModel
instead. This also removes code duplication.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, desktop and mobile are accessing the DownloadThread
and the DiveImportedModel concurrently. This makes a big data
flow mess. To achieve a more hierarchical data flow, start
by making the DownloadThread a subobject of DiveImportedModel.
Start the download by calling a function in DiveImportedModel.
Route the finished signal through DiveImportedModel. Thus,
the model can reload itself with the new data.
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>
In stats tab, when only one dive is selected, on one stat, only average is
shown, except temperature which 3 same temps for max, min and avg are shown.
[Dirk Hohndel: fixed whitespace]
Signed-off-by: Fabio Rueda <avances123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In dive site mode, export selected dive sites, not dive sites
of selected dives.
Fixes#2275.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In TabDiveSite::selectedDiveSites(), the QItemSelectionModel::
selectedIndexes() function was used. Thus for every selected
dive site 8 entries were added to the return-vector!
Instead, use the QItemSelectionModel::selectedRows() function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>