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>