The info box can get longish. Offer the user to turn
off display of deco information (surface GF and
individual ceilings).
Signed-off-by: Robert C. Helling <helling@atdotde.de>
In commit b0556abdd35f96b816ba11e40bf5707abe0c3ebf, the filter-widget
and the filter were connected by a direct function call. This led
to a rather obscure crash on application-close with Qt 5.12. The
crash is due to the Ui::MainWindow class being a sub-object of MainWindow,
but the FilterWidget2 being *not* a subobject.
What happens is that after calling the MainWindow destructor, the
subobjects are destructed, notably the Ui class. Then the base-class
destructor is called (which makes sense, as destructors are called
in reverse order of constructors).
But: the QObject destructor calls hide() on all still existing child-objects
according to Qt's object hierarchy, notably the visible FilterWidget2.
Now the FilterWidget2, on hiding, updates the MainWindow, which has already
destructed all its subobjects. Crash.
Prevent this crash by making FilterWidget2 a subobject of MainWindow
and thus have it destructed before running the QObject destructor.
Alternative ways would be:
1) Use signal/slot() instead of function calls, as these are automatically
removed if an object is destroyed.
2) Make the FilterWidget2 subobject a smart-pointer. Thus, we probably
wouldn't have to include the corresponding header.
3) Make the FilterWidget2 subobject a plain pointer and delete it
explicitly in the constructor.
Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
process_imported_dives() takes four boolean parameters. Replace these
by flags. This makes the function calls much more descriptive. Morover,
it becomes easier to add or remove flags.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If this flag is set, dives that are not assigned to a trip will
be assigned to a new trip. This flag is set if the user checked
"add to new trip" in the download dialog of the desktop version.
Currently this is a no-op as the dives will already have been
added to a new trip by the downloading code. This will be removed
in a subsequent commit.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This adds a checkbox for rebreather modes of the planner
that force the ascent to be in OC mode. Before, one had
to add a one minute last segment with the mode change but
this is not practical when manually searching for the
maximal bottom time given gas reserves.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
On desktop, replace all add_imported_dives() calls by a new undo-command.
This was rather straight forward, as all the preparation work was done
in previous commits.
By using an undo-command, a full UI-reset can be avoided, making the UI
react smoother.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Split the process_imported_dives() function in two:
1) process_imported_dives() processes the dives and generates
a list of dives and trips to be added and removed.
2) add_imported_dives() calls process_imported_dives() and
does the actual removal / addition of dives and trips.
The goal is to split preparation and actual work, to
make dive import undo-able.
The code adds extra checks to never merge into the same
dive twice, as this would lead to a double-free() bug.
This should in principle never happen, as dives that
compare equal according to is_same_dive() are merged
in the imported-dives list, but perhaps in some pathologival
corner-cases is_same_dive() turns out to be non-transitive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When importing log-files we generally want to merge trips. But
when downloading and the user chose "generate new trip", that
new trip should not be merged into existing trips.
Therefore, add a "merge_all_trips" parameter to process_imported_dives().
If false only autogenerated trips [via autogroup] will be merged.
In the future we might want to let the user choose if trips
should be merged when importing log-files.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old way of merging log-files was not well defined: Trips
were recognized as the same if and only if the first dives
started at the same instant. Later dives did not matter.
Change this to merge dives if they are overlapping.
Moreover, on parsing and download generate trips in a separate
trip-table.
This will be fundamental for undo of dive-import: Firstly, we
don't want to mix trips of imported and not-yet imported dives.
Secondly, by merging trip-wise, we can autogroup the dives
in the import-data to trips and merge these at once. This will
simplify the code to decide to which trip dives should be
autogrouped.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To allow parsing into arbitrary trip_tables, add the corresponding
parameter to the parsing functions and the parser state. Currently,
all callers pass the global trip_table so there should be no change
in functionality. These arguments will be replaced in subsequent commits.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
After loading or importing, the caller usually called autogroup()
to autogroup dives if so wished by the user. This has already led
to bugs, when autogroup() was forgotten.
Instead, call autogroup() directly in the process_loaded_dives()
and process_imported_dives() functions. Not only does this prevent
forgetting the call - it also means that autogrouping can be
changed without changing every caller.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveTripModel was used to represent both, trip and list views.
Thus many functions had conditionals checking for the current mode
and both modes had to be represented by the same data structure.
Instead, split the model in two and derive them from a base class,
which implements common functions and defines an interface.
The model can be switched by a call to resetModel(), which invalidates
any pointer obtained by instance(). This is quite surprising
behavior. To handle it, straighten out the control flow:
DiveListView --> MultiFilterSortModel --> DiveTripModelBase
Before, DiveListView accessed DiveTripModelBase directly.
A goal of this commit is to enable usage of the same model by mobile
and desktop.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Register the new FilterDive widget on the mainwindow
so we can trigger a shortcut to display it.
The shortcut currently doesn't exists.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
The whole point of the undo-command system is that the divelist
doesn't have to be refreshed. Therefore, don't do it for autogrouping
/ deautogrouping.
Moreover, the divelist-changed flag is also set by the command and
doesn't have to be set explicitly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old code always sorted by "ascending" by default. But
because users typically want their new dives top, "ascending"
was defined for NR and DATE, such that it is actually descending.
Turn these around and intitialize these two fields as
default-descending.
This is possible using the Qt::InitialSortOrderRole role
in DiveTripModel::headerData().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveListView code had a very fundamental problem with its
header: Each had its own idea of who is responsible for sorting.
Since we can't easily change QHeaderView, accept QHeaderView
as the authority on sort-column and order.
To make this possible, split the reload() function in two
distinct functions:
- reload() reloads the model and sorts according to the
current sort criterion.
- setSortOrder() tells the header to display a certain
sort criterion. If this is a new criterion, it will then
emit a signal. In this signal, resort according to that
criterion.
Thus, the actual sorting code has to be moved from the
headerClicked() to a new sortIndicatorChanged() slot.
Morover, the sorting of the QHeaderView has to be used.
Reported-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Does not solve any problem, but might help users that are confused
about the next/prev DC menu items, to select a different profile
for the currently selected dive. So, enable these menu items only
for dives where more than one DC is used.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Comits f427226b3b and 43c3885249 of the undo series introduced 2 calls
of autogroup_dives() without checking the autogroup global boolean.
This is a bug. An import from DC (for example) then triggers an
autogrouping, the divelist is autogrouped, and the UI button
is off.
This commit solves this. I've chosen for a guard in the autogroup_dives()
that now is a no-op when called when the user did not select autogrouping.
In additon, simplified the other calls to this function, as we do
not need to check before calling any more.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Instead of the weirdly named "information" and the inconsistent
"dive_list" use the logical "mainTab" and the camel-cased
"diveList", respectively.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The keeps track of different sub widgets needed by other parts
of the code, notably:
MainTab
PlannerDetails
PlannerSettingsWidget
ProfileWidget2
DivePlannerWidget
DiveListView
Access to these widgets was provided with accessor functions.
Now these functions were very weird: instead of simply returning
pointers that were stored in the class, they accessed a data
structure which describes the different application states.
But this data structure was "duck-typed", so there was an
implicit agreement at which position the pointers to the
widgets were put inside. The widgets were then down-cast by
the accessor functions. This might make sense if the individual
widgets could for some reason be replaced by other widgets
[dynamic plugins?], but even then it would be strange, as one
would expect to get a pointer to some base class.
Therefore, directly store the properly typed pointers to the
widgets and simply remove the accessor functions. Why bother?
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The global object "displayed_dive_site" is used to store the
old dive site data for the edit-dive-site widget. The fields
of the widget were initialized from this object in the show
event. Therefore the object was updated in numerous parts of
the code to make sure that it was up-to-date. Instead, move
the initialization of the object to the function that also
initiatlizes the fields. Call this function explicitly before
showing the widget.
This makes the data-fow distinctly easier to understand.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Fetching the taxonomy from GPS coordinates was implemented in
a QThread. But the only access to the main function was a
direct call to run(). Thus, the thread was *never* started.
The function call was always asynchronous [it was using an
event loop though, so the UI doesn't hang]. Notably this
means that the signals connected to the thread would never
fire. And the spinner would never be activated.
Thus:
1) Turn the thread into a simple function.
2) Remove the spinner.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Planned dives were still added by directly calling core code.
This could confuse the undo-machinery, leading to crashes.
Instead, use the proper undo-command. The problem is that as
opposed to the other AddDive-commands, planned dives may
belong to a trip. Thus, the interface to the AddDive command
was changed to respect the divetrip field. Make sure that
the other callers reset that field (actually, it should never
be set). Add a comment describing the perhaps surprising
interface (the passed-in dive, usually displayed dive, is
reset).
Moreover, a dive cloned in the planner is not assigned a
new number. Thus, add an argument to the AddDive-command,
which expresses whether a new number should be generated
for the to-be-added dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The command-objects select a current item, but this selection
was not propagated to the front-end. The current item is the
base for keyboard-navigation through the dive-list and therefore
should be set correctly.
It took some experimentation to get the flags right:
QItemSelectionModel::Current
Hopefully, these are the correct flags across all supported
Qt versions!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Select the proper dives after the add, remove, split and merge
dives commands on undo *and* redo. Generally, select the added
dives. For undo of add, remember the pre-addition selection.
For redo of remove, select the closest dive to the first removed
dive.
The biggest part of the commit is the signal-interface between
the dive commands and the dive-list model and dive-list view.
This is done in two steps:
1) To the DiveTripModel in batches of trips. The dive trip model
transforms the dives into indices.
2) To the DiveListView. The DiveListView has to translate the
DiveTripModel indexes to actual indexes via its QSortFilterProxy-
model.
For code-reuse, derive all divelist-changing commands from a new base-class,
which has a flag that describes whether the divelist changed. The helper
functions which add and remove dives are made members of the base class and
set the flag is a selected dive is added or removed.
To properly detect when the current dive was deleted it
became necessary to turn the current dive from an index
to a pointer, because indices are not stable.
Unfortunately, in some cases an index was expected and these
places now have to transform the dive into an index. These
should be converted in due course.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In DiveListView, we have a very fundamental problem: When
On the one hand, we get informed of user-selection in the
DiveListView::selectionChanged() slot. This has to set the
correct flags in the C-backend.
On the other hand, sometimes we have to set the selection
programatically, e.g. when selecting a trip. This is done
by calling QItemSelectionModel::select().
But: this will *also* call into the above slot, in which
we can't tell whether it was a user interaction or an
internal call. This can lead to either infinite loops or
very inefficient behavior, because the current dive
is set numerous times.
The current code is aware of that and disconnects the
corresponding signal. This is scary, as these signals are
set internally by the model and view. Replace this
by a global "command executing" flag in DiveListNotifier.
The flag is set using a "marker" class, which resets the flag
once it goes out of scope (cf. RAII pattern).
In DiveListView, only process a selection if the flag is not
set. Otherwise simply call the QTreeView base class, to reflect
the new selection in the UI.
To have a common point for notifications of selection changes,
add such a signal to DiveListNotifier. This signal will be
used by the DiveListView as well as the Command-objects.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We have to avoid that undo/redo removes the currently edited
dive from under our feet. This code can be removed once proper
undo/redo (including editing) is implemented.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Previously, each dive-list modifying function would lead to a
full model reset. Instead, implement proper Qt-model semantics
using beginInsertRows()/endInsertRows(), beginRemoveRows()/
endRemoveRows(), dataChange().
To do so, a DiveListNotifer singleton is generatated, which
broadcasts all changes to the dive-list. Signals are sent by
the commands and received by the DiveTripModel. Signals are
batched by dive-trip. This seems to be an adequate compromise
for the two kinds of list-views (tree and list). In the common
usecase mostly dives of a single trip are affected.
Thus, batching of dives is performed in two positions:
- At command-level to batch by trip
- In DiveTripModel to feed batches of contiguous elements
to Qt's begin*/end*-functions.
This is conceptually simple, but rather complex code. To avoid
repetition of complex loops, the batching is implemented in
templated-functions, which are passed lambda-functions, which
are called for each batch.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This refactors the undo-commands (which are now only "commands").
- Move everything in namespace Command. This allows shortening of
names without polluting the global namespace. Moreover, the prefix
Command:: will immediately signal that the undo-machinery is
invoked. This is more terse than UndoCommands::instance()->...
- Remove the Undo in front of the class-names. Creating an "UndoX"
object to do "X" is paradoxical.
- Create a base class for all commands that defines the Qt-translation
functions. Thus all translations end up in the "Command" context.
- Add a workToBeDone() function, which signals whether this should be
added to the UndoStack. Thus the caller doesn't have to check itself
whether this any work will be done. Note: Qt5.9 introduces "setObsolete"
which does the same.
- Split into public and internal header files. In the public header
file only export the function calls, thus hiding all implementation
details from the caller.
- Split in different translation units: One for the stubs, one for
the base classes and one for groups of commands. Currently, there
is only one class of commands: divelist-commands.
- Move the undoStack from the MainWindow class into commands_base.cpp.
If we want to implement MDI, this can easily be moved into an
appropriate Document class.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
AddDivesToTrip, CreateTrip, AutogroupDives, RemoveAutogenTrips
and MergeTrips basically all did the same thing as RemoveDivesFromTrip,
which was already implemented. Thus, factor our the common functionality
and hook it up to make all these functions undo-able.
Don't do the autogroup-call everytime the dive-list is rebuilt
(that would create innumberable undo-actions), but only on dive-load /
import or if expressly asked by the user [by switching the autogroup
flag].
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Keeping undo-history across load makes little sense. The user was
expressly reminded that they have unsaved work.
For import (from other logs or the dive-computer) an undo-functionality
would be desirable. Nevertheless, this is rather complex since
new and old dives are merged. Implementation would require a finer
backend<->undocommand interface. Thus, leave this for now until more
experience with the undo system is acquired.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The dive site list was connected to centerOnDiveSite(). Apparently,
the currently selected dive site should have been shown in the map.
Yet, this never worked, because the actual dive site of the selected
dive had precedence in centerOnDiveSite().
It seems that centerOnDiveSite() had actually to purposes:
1) center on the passed in dive site
2) center on the dive sites of the selected dives
Therefore, split this function in two separate functions for
each of these use-cases. This allows us to remove some pre-processor
magic (mobile vs. desktop) and to remove a parameter from the
MainTab::diveSiteChanged() signal.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
process_imported_dives() is more efficient for downloaded than for
imported (from a file) dives, because it checks only the divecomputer
of the first dive.
This condition is checked via the "downloaded" flag of the first
dive. Instead, pass an argument to process_imported_dives().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Dives were directly imported into the global dive table and then
merged in process_imported_dives(). Make this interface more flexible,
by passing an independent dive table.
The dive table of the to-be-imported dives will be sorted and merged.
Then each dive is inserted in a one-by-one manner to into the global
dive table.
This actually introduces (at least) two functional changes:
1) If a new dive spans two old dives, it will only be merged to the
first dive. But this seems like a pathological case, which is of
dubious value anyway.
2) Dives unrelated to the import will not be merged. The old code
would happily merge dives that were not even close to the
newly imported dives. A surprising behavior.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
By making this modal, we can use a local variable and remove the
nasty "deleteLater()" hack to reclaim the resources after the
dialog closes.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Poseidon MkVI logs (.txt) were special cased in MainWindow.cpp,
which led to a user-interface inconsistency. In some cases
[user chooses ".txt" (non-Poseidon) and ".csv"], *two*
import-dialogs were shown.
Move handling of Poseidon MkVI logs into DiveLogImportDialog.
There are already other "special" cases handled in this dialog.
At the moment, this shows the first 10 depth-values, which is
kind of useless, as this will all be at surface level. We
might think about something more useful.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
QByteArray::data() provides access to the underlying data
for direct manipulation. Thus, the construct
csv = fileNamePtr.data();
found in MainWindow::importTxtFiles() suggests that modifications
to csv also affect fileNamePtr. This is *not* the case, because
csv itself is a QByteArray. It is therefore constructed from
the data.
Replace this treacherous construct by a simple assignment.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On CSV import, the dive list was recalculated after the import
dialog was shown. This is pointless, as no dives are yet imported.
Remove.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In d815e0c947 a dive_table pointer
was added to the parsing functions to allow parsing into tables
other than the global dive table. This will be necessary for undo of
import and implementation a cleaner interface. A few cases, notably
CSV and proprietary formats were forgotten.
Implement parsing into arbitrary tables also for these cases.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
A few of these prototypes were already in import-csv.h.
Put them in an 'extern "C" { ... }' block.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
process_dives() is used to post-process the dive table after loading
or importing. The first parameter states whether this was after
load or import.
Especially in the light of undo, load and import are fundamentally
different things. Notably, that latter should be undo-able, whereas
the former is not. Therefore, as a first step to make import undo-able,
split the function in two versions and remove the first parameter.
It turns out the the load-version is very light. It only sets the
DC nicknames and sorts the dive-table. There seems to be no reason
to merge dives.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The << alternative can reallocate the vector, but we know it's size, so
preallocate.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Unamed namespace behaves the same way as static variables in C source.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Nowadays, we edit dives just by starting to enter data for the dive.
There is no need to explicitly ask to start editing the dive, using the
now removed menu option. This was a left-over of a long past history.
This is fallout from PR #1673.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
As described in the referenced issue, we where able to navigate to
nonlogical static pages (like information, statistics. extra data) when
adding a dive. These are output style pages that make no sense on
edit or add. Further, disable access to some pages when entering edit mode.
Notice that the small change in file mainwindow.cpp is simply
because this this not work at all, and became superfluous any
way.
Fixes: #1445
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Actually remove the Subsurface webservice UI from the source, and
deal with all the fallout.
Notice that a part of the change in subsurfacewebservices.cpp is
a block of code that becomes unused, but might contain some valid
logic to be used later. Very similar code is in core/gpslocation.cpp.
And as I earlier broke something here, the unused code is ifdef-ed for
now.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This reverts commit 321a920a98.
It appears that the load_xxx functions aren't called, so while the correct
values are stored to the settings, they aren't retrieved. Let's revert while
this gets fixed.
Fixes#1609
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The variables referenced are moved into qPref in earlier commits
so in general all QSettings calls are replaced by qPref*:: calls
Signed-off-by: Jan Iversen <jani@apache.org>
To enable undo of divelog-importing it is crucial that parse_file()
can parse into arbitrary dive tables.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
remove use of SettingsObjectWrapper::
remove include of SettingsObjectWrapper.h
use qPrefFoo:: for setters and getters
replace prefs.foo with qPrefXYZ::foo() where feasible
(this expands to the same code, but gives us more control
over the variable).
Signed-off-by: Jan Iversen <jani@apache.org>
remove PartialPressureGas from SettingsObjectWrapper and reference qPrefPartialPressureGas
update files using SettingsObjectWrapper/PartialPressureGas to use qPrefPartialPressureGas
this activated qPrefPartialPressureGas and removed the similar class from
SettingsObjectWrapper.
Signed-off-by: Jan Iversen <jani@apache.org>
remove TechnicalDetails from SettingsObjectWrapper and reference qPrefTechnicalDetails
update files using SettingsObjectWrapper/TechnicalDetails to use qPrefTechnicalDetails
this activated qPrefTechnicalDetails and removed the similar class from
SettingsObjectWrapper.
Signed-off-by: Jan Iversen <jani@apache.org>
WindowsTitleUpdate is such a trivial object (a QObject with a single
signal and no own state), that it's not really understandable why
it would need all that "singleton" boiler-plate. Just make it
a default constructed/destructed global object.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The currentDiveChanged signal was emitted by the DiveListView
to inform the MainWindow of a change of current dive. The
new current dive was passed as a parameter. The slot in MainWindow
then called select_dive() on the dive.
This seems pointless because:
1) In both emits, selected_dive dive was passed as argument. But
MainWindow can read this global variable itself.
2) Calling select_dive() again is a no-op, because obviously,
this already *was* the selected dive.
Moreover it seems conceptually wrong to set the current dive in the
slot that is informed of the change of the current dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
dive_getUniqID() is used to create unique dive ids, which are
stable during application lifetime. It was passed a dive, checked
that the id was not set (if it was that it is know to the application)
and set a new id (in contradiction to its name!) if it hadn't any.
There were three callers:
alloc_dive(): called the function on a zeroed dive struct.
fixup_dive(): called the function only if the dive had a 0 id.
MainWindow::setupForAddAndPlan(): called the function on a zeroed dive
struct.
Thus, in all three callers the id is guaranteed to be zero and
the whole keeping-track-of-ids logic is moot. Remove the logic,
don't pass a dive struct to dive_getUniqID() and move the function
to the C-backend.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
add enum to qPref and remove elsewhere
update source core to reference qPref.
the enum cannot be in pref.h because it is to be used in qml and Q_ENUM
need the enum to be defined as part of the class
Signed-off-by: Jan Iversen <jani@apache.org>
There were two catch-all classes for translations outside of class
context. gettextFromC was used exclusively from C, but C++ used
both, gettextFromC and QObject. Some of the string were even present
in both. Therefore, unify to gettextFromC throughout the code base.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Remove cloud_storage_status from qmlprefs.h.
usage to qPref::
enum cloud_storage_status is not used from C, but only from C++, and
having the same structure defined multiple times is a maintenance
challenge.
Signed-off-by: Jan Iversen <jani@apache.org>
Move the find-moved-images functions into a new translation unit
and present the user with the identified matches before applying
them.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the last commits, the canonical-to-local filename map was made
independent from the image hashes and the location of moved images
was based on filename not hashes. The hashes are now in principle
unused (except for conversion of old-style local filename lookups).
Therefore, remove the hashes in this commit. This makes addition
of images distinctly faster.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Users might have edited their pictures. Therefore, instead of identifying
pictures by the hash of the file-content, use the file path. The match
between original and new filename is graded by a score. Currently, this
is the number of path components that match, starting from the filename.
Camparison is case-insensitive.
After having identified the matching images, write the caches so that they
are saved even if the user doesn't cleanly quit the application.
Since the new code uses significantly less resources, it can be run in a
single background thread. Thus, the multi-threading can be simplified.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old trGettext() was not thread-safe and the returned C-strings
could be freed in the case of empty translations strings. Therefore:
1) Introduce a mutex protecting access to the cache.
2) Never change existing entries, even if the translation string is empty.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The list of known dive computers was stored in a multi-map indexed
by the device name. Turn this into a sorted QVector. Thus, no
map-to-list conversion is needed in the device editing dialog,
which distinctly simplifies the code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
update() was only called in conjunction with init(). No point in
having two functions. The separation between both functions seemed
arbitrary anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We shouldn't need to manually set it, but it appears we do. To avoid
constant resizing, let's only grow it - and let's set the size before we
update the text.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The lastUsedDir() functions of MainWindow and Smrtk2ssrfcWindow don't
use any member-objects and are only used in their respective translation
units. Therefore, remove them from the class and made of static linkage.
The lastUsedImageDir() function was declared as a slog, which makes
no sense. Make it a normal static function (though one might argue
why it is assiociated with the DiveListView class in the first place).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In commit d21d42b691 helpView was made
a child-object of MainWindow, which is Qt's idiomatic way of having
helpView deleted with MainWindow.
As an unintended consequence, the helpView didn't show. The reason
is that UserManual derives directly from QObject. In contrast, UserSurvey
derives from QDialog and is correctly shown. Therefore also derive
UserManual from QDialog.
Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
deleteLater() can be dangerous. Remove where not necessary.
Analysis:
1) `helpView` was a pointer which was initialized on demand. close() and
deleteLater() were called on closure of the main window. Firstly, there's
no point in calling deleteLater(), because no references to helpView
are used later on. Secondly, the deletion (and closing) can be done
automatically in the destructor, by passing `this` as parent object.
2) `survey`: pretty much the same situation. But here, `this` was already
passed as parent object.
3) `progressDialog` is a global (not thread safe!) pointer. The object
is deleted after use. There is no point in using deleteLater(), because
the callers are not active after hideProgressBar(), which is the
place were the deleteLater() call was found.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In MainWindow::current_dive_changed() first plotDive() is called,
which replots all the pictures by calling plotPictures(). This
is pointess, because it plots the pictures of the previous dive.
Then, updateDiveInfo() is called, which resets the dive pictures
and automatically replots them. Thus, switching between dives
both with hundreds of pictures is way slower than necessary.
Switching the plotDive() and updateDiveInfo() calls doesn't work.
The reason is not 100% clear, but it doesn't make sense to plot
pictures of the new dive as long as the profile still shows the
old dive anyway.
As a quick-fix, add a flag to plotDive(), which tells the function
to clear the pictures list instead of redrawing it.
Ultimately, plotDive() should probably be split in two functions.
One for the callers who update the pictures themselves and one
for the others.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Make the behavior consistent: Don't save an empty file to the cloud,
neither on selection of "Save to cloud" nor on "Save". The latter
was not the case. It was a bit hard to trigger: Open cloud, delete
all dives, save.
Fixes#1228
Reported-by: Jan Iversen <jani@apache.org>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If "Edit dive" is selected from the dive list or the map view, switch
to a new mode, which shows the dive infos and the profile.
After the edit, switch back to the previous state.
Fixes#1213
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Confusingly, "Edit dive" did only work for planned / manually
entered dives. Change this, but only start profile-editing for
planned / manually entered dives.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This reverts commit 70e0e80de5.
This caused the GPS workflow to break for Linus. Let's revert
for 4.7.8 and figure out how to do this cleanup correctly, later.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Only allow to enable maximum one of both items tissue heatmap or
heartrate in profile.
This is done by always switching off the other one at the moment you
turn on one of the two items (heatmap or heartrate).
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
strdup(qPrintable(s)) and copy_string(qPrintable(s)) were such common
occurrences that they seem worthy of a short helper-function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace constructs of the kind
s.toUtf8().data(),
s.toUtf8().constData(),
s.toLocal8Bit().data(),
s.toLocal8Bit.constData() or
qUtf8Printable(s)
by
qPrintable(s).
This is concise, consistent and - in principle - more performant than
the .data() versions.
Sadly, owing to a suboptimal implementation, qPrintable(s) currently
is a pessimization compared to s.toUtf8().data(). A fix is scheduled for
new Qt versions: https://codereview.qt-project.org/#/c/221331/
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Remove the global error buffer and pass the error string directly
to the frontend. The frontend is then responsible for accumulating
errors.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>