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>
The whole undo system assumes that the indexes in the dive table
do not change under its feet. On desktop, there seems only one
exception left: editing of the dive time. To circumvent this,
hook editing of the dive-time to the already existing UndoShiftTime
command.
This introduces a temporary UI-inconsistency: this is the only
edit that is reflected in the undo-list. This will be fixed in
due course, when other edit actions are also made undoable.
UndoShiftTime is changed to take pointers to dives (which should
be stable by now) instead of uniq-ids.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On dive editing, for every changed field the code looped through
the whole dive-list and modified the selected dives. Instead,
get the list of selected dives once and use that.
Whereas this may look like a gratuitous optimization, it will
make things easier for subsequent commits. Notably, we can
pass the list of selected dives to an "UndoObject".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For this, an output-parameter was added to the backend merge_dives()
function. When non-zero, instead of adding the merged dive to
the preferred trip, the preferred trip is returned to the caller.
Since the new UndoObject, just like the delete-dives UndoObject,
needs to remove/readd a set of dives, the corresponding functionality
was split-off in a helper function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Play manual addition of dives via an UndoCommand. Since this does in
large parts the same thing as undo/redo of dive deletion (just the
other way round and only a single instead of multiple dive), factor
out the functions that add/delete dives and take care of trips.
The UI-interaction is just mindless copy&paste and will have to
be adapted.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Both callers have a dive * and transform that into an id,
the callee transforms it right back to the dive *. Simply pass
the dive directly. This will allow us to use the function for
dives that have not yet been added.
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>
The statistics of the selected dives were calculated
a) into a global objects and
b) at a completely different place than where they're used.
There's no plausible reason for either. There fore render
into a caller-provided structure at the place of use.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Statistics were calculated into global variables every time the
current dive was changed.
Calculate statistics only when needed and into a structure
provided by the caller.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old surface interval calculation had fundamental issues:
1) process_all_dives(), which calculates the statistics over *all*
dives was used to get the pointer to the previous dive.
2) If two dives in the table had the same time, one of those would
have been considered the "previous" dive.
3) If the dive, for which the surface interval is calculated is
not yet in the table, no previous dive would be determined.
Fix all this by creating a get_surface_interval() function and
removing the "get previous dive" functionality of process_all_dives().
Remove the process_all_dives() call from TabDiveInformation::updateData().
Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
1) Add a missing <div>
2) More importantly: recognize html content via <div>-tags instead of
<table>-tags.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signals can be useful. In this case, a simple function call does
it. Thus, remove the signal. It can be readded later at an more
appropriate place.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This changes the above mentioned terms everywhere in the UI to
reflect the fact that Subsurface now also supports video files on top
of image files.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Correctly use gettextFromC::instance()->tr(); instead of a simple
tr(); to translate the dive mode names.
This goes on top of 0bc9edf855
and finally makes the whole thing work.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
helpers.h included qthelper.h and all functions declared in helpers.h
were defined in qthelper.h. Therefore fold the former into the latter,
since the split seems completely arbitrary.
While doing so, change the return-type of get_dc_nichname from
"const QString" to "QString".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The former should be translated but not those that
go to xml/git.
... and fix capitalization of pSCR.
Suggested-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
...as the usuage is not anymore about a computer but
a momentary dive mode. Rename the end indicator as well.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
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>
Previous taglist_get_tagstring signature/implementation did not allow
handling of cases where inputted buffer could not contain all tags.
New implementation allocates buffer based on pre-computed size allowing to
insert all tags in the returned string.
Added get_taglist_string in qthelper to handle conversion to QString
Added TestTagList with tests for taglist_get_tagstring
Signed-off-by: Jeremie Guichard <djebrest@gmail.com>
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>
This change deals with issue #554.
If you enter a dive duration manually, the cell renderer cuts the seconds
away when the changes are saved. I added the helper "render_seconds_to_string"
as a counterpart to "parseDurationToSeconds". The helper keeps the seconds,
if not null. The rendering of the cell is done at two places in the code,
so I think it is cleaner to add a dedicated method for it.
Signed-off-by: Oliver Schwaneberg <oliver.schwaneberg@gmail.com>
A very simple commit to start 2018. When hitting new logbook from
a currently open logbook, and the current dive has tags filled in,
they stayed around in the UI. Just clear them. Further, delete
an unused variable.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Besides being the right thing to do (code reflects reality), it
silences a compiler warning.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Disable tabs for equipment, info, pictures and extra info if a
dive trip is selected.
Remember specific tab selection for dives and dive trip to recover
selection when browsing dive list.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
After one selected a dive and then selects NO dive don't touch
the visibility of UI fields for depth and duration.
So if previously selected dive was a manually added dive, keep them
visible. If it was no manually added dive keep them invisible.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Remove duplicate and incorrect setPlainText call via macro for dive notes.
Deal correctly with ASCII line breaks "\n" in dive notes with html
markup (replace them with <br>).
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
After editing the cylinder table (e.g. deleting a cylinder) and
accepting the changes copy the whole dc samples for the dive edited.
This is important because the sensor idx in the samples may have changed.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
If the user implicitly adds a dive site by editing a dive, and
a location filter is active, check the new dive site in the
location filter.
This is done by informing the LocationFilterModel of the new
dive site name prior to repopulation. The LocationFilterModel
then adds a corresponding entry and marks it as checked.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since commit 01d961086c, MainWindow::refreshDisplay()
is called in the refreshDiveInfo() signal of maintab after editing a
dive site. Since this was the only use of the refreshDiveInfo signal,
remove this signal and instead connect to MainWindow::refreshDisplay directly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Until now when selecting a dive w/o dive site after having a previous
dive with dive site and location tags displayed, the location tags of the
previously selected dive where still displayed.
This fixes this behavior.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Calls MainWindow::refreshDisplay() if a dive site was edited so that
the filter lists are updated. The old call to updateDiveInfo() was
removed because it is call implicitly in MainWindow::refreshDisplay()
anyway.
Fixes#675.
Requested-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Until now accidentally the dateLabel was disabled and the timeLabel
was enabled. Changed this the other (correct) way round.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
current_dc is a macro that determines the dive computer
based on the current dive number. When the planner is started
from an emtpy dive list, the dive number ends up being -1 and
that doesn't produce a valid dive computer. Use the divecomputer
of the displayed_dive instead. This is done via a macro that
can also be used in two other places. Without this patch, the
planner crashed when called on an empty dive list.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
For the geo references tags update the following:
- Nicer look w/o "Tags:" text and brackets when inside location UI
- Translation for "Tags:"
- Warning message when no dive site layout categories are set
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Entering a name first creates and hooks up a dive site which we can then
use in the edit dive site dialog to store modifications.
This doesn't really fix these two bugs, but it might impact whether they
can still be recreated
See #633
See #636
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In desktop-widgets, remove globe.cpp, globe.h and also remove
the NO_MARBLE macro usage.
At this point the MapWidget will always be created and there will
always be a map in the application.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Based on NO_MARBLE, call the same methods in the two different classes.
Later the dummy Marble GlobeGPS (for NO_MARBLE) should be removed.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Tags are handled differently from other fields, we need to call
the special handling after the new dive was added and marked as
the current dive.
Fixes: #369
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We need to make sure the model is avaliable for the table
until it hits the destructor.
Fixes#347
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Simplify logic of handling the Message that this
dive is being modified.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Maintab is one of our most complex classes, and it's
something I'm not actually proud of. But it currently
works and the idea of splitting it was in my head for
quite a while.
This is the third or fourth tentative of splitting it,
and this time I let the most complex part of it untouched,
the Notes and Equipment tab are way too complex to untangle
right now on my limited time.
A new class 'TabBase' should be used for any new tab that
we may create, and added on the MainTab (see the new lines
on the MainTab constructor).
Also, Extra Info, Information, Photos and Statistics where
ported to this new way helping reduce the number of
lines and functions on the MainTab quite a bit.
Overall this is a step in the right direction for the future.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>