Commit graph

249 commits

Author SHA1 Message Date
Berthold Stoeger
b19adecb9f Undo: make adding of planned dive undo-able
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
3c6cdfd8c0 Dive list: propagate current-item to frontend
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
7067e33596 Undo: select dives after add, remove, merge, split dive commands
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
23db0ba68d Dive list view: replace signal-magic by flag
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
26901a8dbd Undo: disable undo- and redo-actions in edit mode
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
ec7d85835f Dive list: implement proper Qt-model semantics for DiveTripModel
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
43c3885249 Undo: isolate undo-commands
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
f427226b3b Undo: make diverse trip-related operations undo-able
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
c30efc95d4 Undo: clear undo history on load / import
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>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
0aef04352a Map: zoom on dive sites when flipping through dive site list
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>
2018-10-08 13:29:51 -07:00
Berthold Stoeger
6dc1dcaea5 Import: pass "downloaded" parameter to process_imported_dives()
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>
2018-10-06 19:47:06 -07:00
Berthold Stoeger
810903bdb9 Import: pass a dive table to process_imported_dives()
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>
2018-10-06 19:47:06 -07:00
Berthold Stoeger
5a78730561 Import: Make DiveLogImportDialog modal
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>
2018-10-04 10:22:11 +02:00
Berthold Stoeger
a4051749fd Import: import Poseidon MkVI logs via DiveLogImportDialog
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>
2018-10-04 10:22:11 +02:00
Berthold Stoeger
41089b74a9 Cleanup: don't use QByteArray::data() to create copy
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>
2018-09-29 14:01:22 -07:00
Berthold Stoeger
3923f54e10 Cleanup: don't needlessly recalculate dive list on CSV import
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>
2018-09-29 14:01:22 -07:00
Berthold Stoeger
32a4ce6169 Parser: parse text-based files into arbitrary table
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>
2018-09-28 15:06:00 -07:00
Berthold Stoeger
3137fbe973 Cleanup: remove redundant prototypes from dive.h
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>
2018-09-28 07:47:39 -07:00
Berthold Stoeger
35b8a4f404 Core: split process_dives() in post-import and post-load versions
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>
2018-09-23 11:50:53 -07:00
Tomaz Canabrava
7319b50a5d code cleanup: replace lring with file local function
And simplify the code.

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
77d7e550fe code cleanup: no need for default if we test every case
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
7ab35f7858 code cleanup: use ByteArray.size() instead of strlen
Removes a size_t vs int warning

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
00ef514da3 code cleanup: pre-calculate the test and pass it directly
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
6d552d61b9 code cleanup: allocate the vector in one go
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>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
858740e8a1 code cleanup: simplify if / else chains
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
9e6a3bee0d code cleanup: remove allocations
Simply create the string in one go.

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
2d6633eee0 code cleanup: use nullptr in C++ files
Using 0 or NULL are C idioms.

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
17a6f28827 code cleanup: unamed namespace instead of global or static variables
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>
2018-09-15 15:51:26 -07:00
Tomaz Canabrava
3b4877a073 code cleanup: sort headers alphabetically
This was driving me nuts.

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 15:51:26 -07:00
Jan Mulder
d16bcd8978 Desktop: remove "edit dive" from log menu
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>
2018-09-14 13:18:42 -07:00
Jan Mulder
5133a38d25 Desktop: disable UI elements that make no sense during editing
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>
2018-09-14 10:00:54 +02:00
jan Iversen
2385f48c6a core/settings ... : remove qPref* includes in qPref.h
reduce number of includes by removing qPref* includes in qPref.h

Signed-off-by: Jan Iversen <jani@apache.org>
2018-09-11 17:25:00 -07:00
jan Iversen
684e334fb6 core: declare cloud_status in qPrefCloudStorage
qml declaration of cloud_status (defined in pref.h) does not
belong in qPref.h but in qPrefCloudStorage

Signed-off-by: Jan Iversen <jani@apache.org>
2018-09-11 17:25:00 -07:00
jan Iversen
1a130ec461 desktop/profile-widget: update signal from _changed to Changed
Update connect calls to use Changed from qPref, due to QML demands

Signed-off-by: Jan Iversen <jani@apache.org>
2018-09-11 17:22:58 -07:00
Dirk Hohndel
ae653703a5 prefs: git_local_only is not a preference
It's the current state of the app, so it should be a global variable, not a
preference.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-10 16:26:49 -07:00
Jan Mulder
876e6adf74 Desktop: Remove webservice, remove UI components (2)
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>
2018-09-09 18:28:08 -07:00
Dirk Hohndel
2d87a657d2 Revert "desktop-widgets: remove QSettings from desktop-widgets"
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>
2018-08-29 03:09:10 -07:00
jan Iversen
321a920a98 desktop-widgets: remove QSettings from desktop-widgets
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>
2018-08-25 11:49:47 -07:00
jan Iversen
c85f5c560c desktop-widget: remove QSettings
Update desktop-widget to use qPrefDisplay (amended variable)

Signed-off-by: Jan Iversen <jani@apache.org>
2018-08-25 11:49:47 -07:00
Berthold Stoeger
d815e0c947 Parse: pass dive_table argument to parse_file()
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>
2018-08-23 10:17:12 -07:00
jan Iversen
0f68e0cc2e desktop-widget: remove SettingsObjectWrapper and update qPref calls
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>
2018-08-15 16:11:39 -07:00
jan Iversen
9d005888fb core: activate qPrefPartialPressureGas
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>
2018-08-14 07:12:41 -07:00
jan Iversen
cb2dc7515b core: activate qPrefTechnicalDetails
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>
2018-08-12 07:36:10 -07:00
Berthold Stoeger
7fe76a5dbd Cleanup: Make WindowsTitleUpdate a global object
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>
2018-07-30 13:55:23 -07:00
Berthold Stoeger
5e1e6110ce Cleanup: remove parameter from currentDiveChanged signal
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>
2018-07-30 12:20:26 -07:00
Berthold Stoeger
2c6b1a99af Cleanup: simplify dive_getUniqID()
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>
2018-07-17 15:20:52 -07:00
jan Iversen
8d66633fe7 core: make qPref::cloud_status the only version of the enum
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>
2018-07-10 10:30:50 -07:00
Berthold Stoeger
57c01f7a66 Translations: unify gettextFromC::tr() and QObject::tr()
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>
2018-07-04 05:33:31 +08:00
jan Iversen
2f95141330 core: remove double definition of enum cloud_storage_status
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>
2018-07-04 05:32:30 +08:00
Berthold Stoeger
09fd5c40d1 Dive pictures: implement FindMovedImagesDialog
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>
2018-07-04 02:27:36 +08:00
Berthold Stoeger
f3ef38ca0d Dive pictures: remove hashes
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>
2018-07-04 02:27:36 +08:00
Berthold Stoeger
0646b41275 Dive pictures: find moved pictures based on filename
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>
2018-07-04 02:27:36 +08:00
Berthold Stoeger
db0dd54c37 Localization: make cache thread safe and robust against use-after-free
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>
2018-06-24 20:31:14 +02:00
Berthold Stoeger
1f654050fa Dive computers: turn QMultiMap into sorted vector
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>
2018-06-17 06:53:13 +09:00
Berthold Stoeger
b0cc416954 Cleanup: fold DiveComputerManagementDialog::update() into init()
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>
2018-06-17 06:53:13 +09:00
Dirk Hohndel
b9318a9ab1 desktop: better handling of progress dialog width
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>
2018-06-17 06:17:08 +09:00
Berthold Stoeger
4e8079f527 Cleanup: make lastUsedDir() functions static and non-slot, respectively
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>
2018-06-09 17:11:29 +02:00
Berthold Stoeger
9611e92cf0 Desktop: Derive UserManual from QDialog
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>
2018-05-31 21:29:29 +03:00
Berthold Stoeger
d21d42b691 Cleanup: remove three instances of deleteLater() in mainwindow.cpp
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>
2018-05-26 09:21:46 -07:00
jan Iversen
e536682b84 desktop-widgets: Change Q_UNUSED to no parameter name
C++ permits use of parameters without name, which signals unused

Signed-off-by: Jan Iversen <jani@apache.org>
2018-05-21 12:48:04 -07:00
Berthold Stoeger
45395fd466 Dive pictures: Don't plot pictures twice when changing current dive
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>
2018-05-17 07:24:54 -07:00
Berthold Stoeger
9b4728c7a9 Cloud-storage: consistently don't save empty file on desktop version
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>
2018-05-14 12:52:54 -07:00
Dirk Hohndel
d577467f97 Core: introduce new subsurface-string header
First small step to shrinking dive.h.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-05-14 10:13:39 -07:00
Berthold Stoeger
57bf174c4f Desktop: On dive edit from the dive list or map, switch to new state
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>
2018-05-13 07:08:34 -07:00
Berthold Stoeger
9d342d0e1a Desktop: Make "Edit dive" menu entry work for downloaded dives
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>
2018-05-13 07:08:34 -07:00
Oliver Schwaneberg
55ac07f6f6 Corrected file name "weigthsysteminfomodel" to "weightsysteminfomodel"
Signed-off-by: Oliver Schwaneberg <oliver.schwaneberg@gmail.com>
2018-05-11 02:23:51 +03:00
Dirk Hohndel
7e73b30e97 Revert "GPS: use applyGpsLocation::applyLocations from core"
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>
2018-04-03 11:52:46 -07:00
Stefan Fuchs
cfd4c42829 Profile heatmap/heartrate: Only enable max one of these at same time
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>
2018-03-19 15:44:02 -07:00
Berthold Stoeger
d1572a8d95 Cleanup: introduce copy_qstring() function
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>
2018-03-14 13:55:36 +02:00
Berthold Stoeger
b72cc1f317 Cleanup: consistently use qPrintable()
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>
2018-03-14 13:55:36 +02:00
Berthold Stoeger
8f81a22e7f Make report_error() reentrant
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>
2018-01-31 14:47:26 +01:00
Berthold Stoeger
df81a39aa5 Remove unnecessary check for MainWindow instance
The error-callback is installed in the MainWindow constructor.
Therefore, in the error-callback the existence of the MainWindow
instance is guaranteed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-31 14:47:26 +01:00
Berthold Stoeger
a25f54e3c2 Use queued connection to thread-safe MainWindow error handling
Up to now, errors produced by threads were not directly shown in
the MainWindow. Code running in the GUI thread had to manually
show the errors.

This can be simplified by using Qt's queued connection as message
passing facility.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-31 14:47:26 +01:00
Robert C. Helling
de49f2484f Resize progress bar width to fit all text
At least on Mac with larger font sizes part of the label
text of the git access progress bar is cut off (even though
it should automatically resize). This patch adds explicit
resize.

Fixes #1041

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2018-01-13 19:13:14 +01:00
Berthold Stoeger
6a07ccbad2 Use helper function empty_string() instead of manual checks
For code consistency, substitute boolean expressions:
 s && *s     -> !empty_string(s)
 s && s[0]   -> !empty_string(s)
 !s || !*s   ->  empty_string(s)
 !s || !s[0] ->  empty_string(s)

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-11 06:07:13 +01:00
Berthold Stoeger
e85ecdd925 Introduce helper function empty_string()
There are ca. 50 constructs of the kind
  same_string(s, "")
to test for empty or null strings. Replace them by the new helper
function empty_string().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-11 06:07:13 +01:00
Berthold Stoeger
339f214384 Remove redundant setting of prefs.git_local_only
In MainWindow::on_actionCloudOnline_triggered(), prefs.git_local_only
was set twice in the case of going online. Remove the second,
unnecessary, assignment.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-08 12:01:04 +01:00
Berthold Stoeger
099662023c Move resetting of current file out of clear_dive_file_data()
This is the only case where C-code sets the current file.
Remove this call for a better separation of C-backend and
C++-frontend parts.

There were four callers of clear_dive_file_data(). Two of them
would call set_filename() anyway. For the remaining two add an
explicit call to set_filename().

This commit fixes a bug introduced in commit b3901aa8f9:
The cloud-online menu entry was still enabled after "closing" the
cloud storage.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-08 12:01:04 +01:00
Berthold Stoeger
b3901aa8f9 Enable cloud-online menu entry only if connected to cloud
Enable the menu item cloud-online only if the current file is the
cloud storage. Since this has to be checked every time the current
file is set, factor this out into the new MainWindow::setCurrentFile()
function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-06 10:46:07 -08:00
Berthold Stoeger
bb64c6bda8 Turn take-cloud-online menu action into checkbox
Replace the "Take cloud storage online" menu entry by a "Cloud online"
checkbox. After this change, the user can also force going offline.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-06 10:46:07 -08:00
Berthold Stoeger
dbef391786 Sync cloud storage on take-cloud-online
When taking the cloud online, actually sync with the online cloud storage.
If there are no unsaved changes, do the same as "Open cloud storage".
If there are unsaved changes, ask the user if they want to commit them
(do the same as "Save to cloud storage") or if they want to sync manually.

If syncing failed, inform the user.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-06 10:46:07 -08:00
Jan Mulder
70e0e80de5 GPS: use applyGpsLocation::applyLocations from core
Fixes a big duplication of code. The code to apply GPS locations
from the location service was already in core, and used from mobile,
but there was an almost literal copy in the desktop code.

See also commits 6f42ab46da and ee9531f76e, where only
one side of the duplicated code was fixed.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2018-01-06 09:21:16 +01:00
Berthold Stoeger
40fa148548 Replace BEHAVIOR macro by initializer lists
The macro BEHAVIOR expanded to "QList<int>()". This was used to
generate temporary QList<int>s with constructs such as
  BEHAVIOR << COLLAPSED << EXPANDED
Instead, simply use initializer lists such as
  {COLLAPSED, EXPANDED}

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-04 08:21:43 -08:00
Berthold Stoeger
f8517c583b Replace macro TOGGLE_COLLAPSABLE by function toggleCollapsible()
There was no reason to do this in a macro. Let the compiler decide
if it wants to inline or not. Note that for consistency with the
Qt functions, collapsAble was replaced by collabsIble.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-04 08:21:43 -08:00
Berthold Stoeger
b4e36c5912 Use set_autogroup() function
Since this function exists, use it instead of setting the global
variable directly.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-01-04 08:21:43 -08:00
Jan Mulder
e16b58ee08 Desktop: follow autogroup setting in UI
When importing a dive (using import from logfile) and it is a
ssrf/xml file that contains the autogroup setting, the autogroup
is effectuated in the dive list. Not sure that I like this
behavior, but thats the way it currently is. Simply wrong
is that in this case the menu item toggle is not adapted
so we end up with a dive list that is autogrouped, but
the menu toggle is off.

This can be solved by setting the UI toggle in a more central
location.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2018-01-02 06:47:53 +02:00
Berthold Stoeger
f74308bed4 Desktop: Don't hide errors on opening cloud storage
In MainWindow::on_actionCloudstorageopen_triggered(),
getNotificationWidget()->hideNotification() was called, thus hiding
any error message produced by the cloud code. Notably, the information
"Cannot sync with cloud server, working with offline copy" was
not shown.

Therefore, remove this call. Note that on cloud save messages were
not hidden.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-29 09:19:17 -08:00
Berthold Stoeger
4ac5b9c965 Simplify mainwindow title logic: remove MainWindowTitleFormat enum
The MainWindow::setTitle() function was passed an enum, which depended
on whether existing_file is set or not. The check can be (and was!) done
directly in setTitle(). Therefore, remove the whole enum.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-11 23:10:09 -06:00
Berthold Stoeger
931bcc1966 Remove unused variable in on_actionCloudstorageopen_triggered()
This was an artifact of commit 136110784e

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-12 04:08:58 +01:00
Berthold Stoeger
ea0cbba804 Remove second parameter (bool force) in set_filename()
The last force=false case was removed in commit 96d1cc570e.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-11 00:17:39 +01:00
Berthold Stoeger
0a2e53caf2 Use QDir::exists() instead of QDir::setCurrent() to check for existence
Don't change into a directory just to see if it exists.
Remove unnecessary braces of one of the changed if statements.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-04 18:35:44 +01:00
Berthold Stoeger
136110784e On failed cloud save hide progress bar
The progressbar was not hidden on failed save to cloud. In return
remove an unnecessary variable on loading from cloud.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-01 16:39:58 -08:00
Robert C. Helling
a9703628c4 Actually compute variations in background
This reenables the computation of plan variations but now in a separate
thread. Once finieshed, a signal is sent to update the notes.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2017-12-01 15:47:51 -08:00
Martin Měřinský
0855f6f315 Use icons relative path.
Icon paths are defined in one place only - application's embedded resources.

Signed-off-by: Martin Měřinský <mermar@centrum.cz>
2017-11-30 23:14:46 -08:00
Stefan Fuchs
4ee9791cb8 Fix views in mainwindow
Divelist only view was broken.

Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
2017-12-01 04:03:30 +01:00
Berthold Stoeger
f8a200dbce Don't use action tooltip to access recently used file
Currently, the path to the recently used file is stored in the tooltip
of the corresponding recent file action. Instead, store the number
of the recent file in the action. This allows for more flexibility
concerning formating of the tooltips (think git repositories, etc.).

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-01 03:39:10 +01:00
Berthold Stoeger
4296ca11a6 Dynamically generate recent files actions
Instead of using four recent files actions defined in mainwindow.ui,
generate these actions dynamically depending on the macro NUM_RECENT_FILES.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-01 03:39:10 +01:00
Berthold Stoeger
1208bc8428 Remove "#if !defined(SUBSURFACE_MOBILE)" in mainwindow.cpp
The file mainwindow.cpp is only compiled for desktop versions, so the
condition is redundant.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-30 16:52:22 +01:00
Berthold Stoeger
8b9c63b2d8 Move creation of QSession object into MainWindow::checkSurvey()
Instead of handing the QSession object down, simply create it in
MainWindow::checkSurvey()

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-30 16:52:22 +01:00
Berthold Stoeger
135ea00d88 implify recent file handling in mainwindow.cpp
The old code used to be unnecessarily complex: the recent files list
was extended for each file and shrunk if a load failed.

By adding a file to the recent file list only if the load succeeded, a
whole method could be removed.

Other changes: keep track of the recent files using a QStringList and
clearly separate the actions:
 - Read recent files from settings [loadRecentFiles()]
 - Write recent files to settings [updateRecentFiles()]
 - Update the recent files actions in the menu [updateRecentFilesMenu()]
 - Add a file to the list of recent files [addRecentFile()]
With this reorganization the code hopefully became more clear.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-30 16:52:22 +01:00