Instead of using fixed size arrays, use a new cylinder_table structure.
The code copies the weightsystem code, but is significantly more complex
because cylinders are such an integral part of the core.
Two functions to access the cylinders were added:
get_cylinder() and get_or_create_cylinder()
The former does a simple array access and supposes that the cylinder
exists. The latter is used by the parser(s) and if a cylinder with
the given id does not exist, cylinders up to that id are generated.
One point will make C programmers cringe: the cylinder structure is
passed by value. This is due to the way the table-macros work. A
refactoring of the table macros is planned. It has to be noted that
the size of a cylinder_t is 64 bytes, i.e. 8 long words on a 64-bit
architecture, so passing on the stack is probably not even significantly
slower than passing as reference.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The divesEdited signal sends the changed field as a parameter.
Since some undo-commands change multiple fields, this led to
numerous signals for a single command. This in turn would lead
to multiple profile-reloads and statistic recalculations.
Therefore, turn the enum into a bitfield. For simplicity,
provide a constructor that takes classical flags and turns
them into the bitfield. This is necessary because C-style
named initialization is only supported on C++20 onward!
Is this somewhat overengineered? Yes, maybe.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The undo system sets updates individual dive fields on
redo respectively undo. Make salinity such a field, since
it is changed on replanning a dive.
To do this, break out the "update salinity" functionality
into its own function, add an entry to the DiveField enum
and add the corresponding switch-case.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We'll use them from the model in order to avoid creating this many
DiveObjectHelpers when showing a dive.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is disabled by default - but when compiled in it makes it a lot
easier to pinpoint why we are creating so many DiveObjectHelpers.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The cylindersObject list was only used by grantlee but not by
the mobile code. Since it is quite heavy, split it out and thus
don't generate it for every dive on mobile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of handing a reference-to-dive to QML, prerender all the needed
properties and store them as values in DiveObjectHelper. Exception:
- date(): generated from timestamp
- time(): generated from timestamp
- cylinderList(): does not depend on dive anyway and should be made
static.
This hopefully avoids the random mobile crashes that we are seeing.
Clearly, this code needs to be optimized, but it is a start.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These were temporary functions as long as DiveObjectHelpers were
used to access dives. All users now access the core directly and
therefore don't have to test DiveObjectHelpers for validity.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Don't provide access to the raw dive in DiveObjectHelper. All users
now access the core directly. This is a step in making DiveObjectHelper
value-based.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of keeping track of a list of DiveObjectHelpers, generate
them on-the-fly in DiveListModel. Thus, there is less danger of
model and core getting out of sync. On the flip-side, now the
DiveListModel and the DiveListSortModel might get out of sync.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
DiveObjectHelper is a tiny wrapper around dive * to allow access
to dive data from QML and grantlee. It doesn't have to be a
full-fledged QObject with support for signals, etc. Therefore,
turn it into a Q_GADGET based object. This allows us passing the
object around as object, not as pointer to DiveObjectHelper.
This makes memory-management distinctly easier.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We don't want to generate a DiveObjectHelper numerous times for
every item in the dive list. Therefore, return this datum directly
from the model.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The canonical way of displaying lists in Qt is via models.
Thus, return the tripId directly from the DiveListModel instead
of going indirectly via a DiveObjectHelper. In the future, this
will allow us to make the DiveObjectHelper value-based, as it
is not generated numerous times for every list item.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These properties are not needed anymore, because the full text search
was decoupled from the DiveObjectHelper.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of generating cylinder data in the form of
CylinderObjectHelper objects for every DiveObjectHelper,
generate it only if needed. DiveObjectHelper is used extensively
in the mobile interface, which doesn't use the cylinder data.
Let's not generate unnecessary CylinderObjectHelpers in this
case!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
CylinderObjectHelper is used for structured formatting of cylinder
values in grantlee types. Instead of keeping a reference to a
cylinder, turn it into a value type containing the formatted strings.
This should be distinctly safer, as we don't risk having stale
references flying around. Moreover, we don't have to use pointers
but can use containers containing plain CylinderObjectHelper. Thus,
no explicit memory management is needed, making the code distinctly
easier to understand.
Sadly, currently grantlee does not support Q_GADGET based Q_PROPERTY.
Therefore a GRANTLEE_*_LOOKUP block has to be added. This can be
removed in due course, as a patch to remedy this issue is in current
grantlee master.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We don't support null-dives in DiveObjectHelper. Defaulting the
dive parameter to NULL seems to send the wrong message.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When removing the max-weightsystem restriction, the semantics of
the DiveObjectHelper::singleWeightSystem() function changed:
it now returned false for "no weightsystem". Change it back,
to 0 or 1 weightsystems, because the mobile frontend uses this
to check whether it can edit dive systems.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace the fixed-size weightsystem table by a dynamically
relocated table. Reuse the table-macros used in other parts
of the code.
The table stores weightsystem entries, not pointers to
weightsystems. Thus, ownership of the description string is
taken when adding a weightsystem. An extra function adds
a cloned weightsystem at the end of the table.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For historic reasons, there where three distinct signals concerning
dive-selection from the undo-machinery:
1) divesSelected: sent newly selected dives
2) currentDiveChanged: sent if the current dive changed
3) selectionChanged: sent at the end of a command if either the selection
or the current dive changed
Since now the undo-commands do a full reset of the selection, merge these
three signals into a single signal.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Some commands tried to retain the current selection on undo/redo,
others set the selection to the modified dives.
The latter was introduced because it was easier in some cases, but
it is probably more user-friendly because the user gets feedback
on the change.
Therefore, unify to always select the affected dives on undo()/redo().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since the default view is batched by trips, signals were sent trip-wise.
This seemed like a good idea at first, but when more and more parts used
these signals, it became a burden. Therefore push the batching to the
part of the code where it is needed: the trip view.
The divesAdded and divesDeleted are not yet converted, because these
are combined with trip addition/deletion. This should also be detangled,
but not now.
Since the dive-lists were sorted in the processByTrip function, the
dive-list model now does its own sorting. This will have to be
audited.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In signals dives were sorted by date. This criterion is not be unique.
Therefore sort by the dive_less_than() function of the core to avoid
any inconsistencies between the Qt-models and the core data.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These functions were spread out over dive.c and divelist.c.
Move them into their own file to make all this a bit less monolithic.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When a different field is edited, hide any old multi-dive-edit
warning message. The reason is that we might want to add an "undo"
button to the message. But this will undo the wrong command if
we don't hide the message.
Sadly, this means that we can't use animated show / hide, because
an animatedHide() followed immediately by an animatedShow() does
not necessarily show the message. In other words, and animatedShow()
does not interupt a started animatedHide()!?
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The Information tab shows the atmospheric pressure. Make this value editable
and also ensure that changes to it are undo-able.
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
This is copying the dive editing code. It uses an OO design with
virtual functions for getting and setting the values. It doesn't
use templates though, as both fields of strig type. This feels
a bit over-engineered, but it is 1) consistent with the dive edit
code and 2) the number / types of dive trip fields might increase.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When pasting (or undoing paste) the cylinders or weights may change.
Send the appropriate signals and update the models accordingly.
Currently, this means copying from current dive to displayed dive,
but hopefully we can get rid of "displayed_dive" in the not so
distant future.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The dive list was not updated automatically when an edit command was
executed. There was already a signal to do that, viz. divesChanged().
But that signal worked by-trip and didn't have a dive-field specifier.
The edit-commands used the divesEdited() signal that isn't by-trip
but has a dive-field specifier.
Unify these two signals to be by-trip and with dive-field specifier.
This needs common code to generate the by-trip list that is moved to
a command_private.h header.
Since there might now be multiple signals (one per trip) actually
check in the main-tab whether the current trip is affected to
avoid multiple update of fields. This has the positive(?) effect
of not doing any update if the current dive isn't changed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was a bit different from the other editing commands:
1) Only the current dive is edited not all selected dives.
Therefore, create a function that turns the current dive
into a one-element list.
2) The profile has to be replot. Here, likewise, create a
function to do that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This one is a bit more tricky. There are two modes: set dive site
and set newly created dive site. This is realized using an OO model
with derived classed. Quite convoluted - but it seems to work.
Moreover, editing a dive site is not simply setting a value,
but the list of dives in a dive site has to be kept up to date.
Finally, we have to inform the dive site list of the changed
number of dives. Therefore add a new signal diveSiteDivesChanged.
To send only one signal per dive site, hook into the undo() and
redo() functions and call the functions of the base class there.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To keep the UI in a consistent state, update the notes field if
it is changed by an undo command. To that purpose, add a new
signal to diveListNotifier with a list of dives and a field-id
as payload.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Implement an undo command that edits the name of a dive site.
Connect it to the dive site table, so that names can be edited
directly in the table.
Send signals on undo / redo so that the dive site table and
the dive site edit widget can be updated.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Introduce two DiveListNotifier signals which are sent by
the undo commands if dives are added to / removed from the
core.
The signal has the dive site and the index in the global
dive site table as payload. Thus, the model has only to
remove the appropriate rows.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a new signal to DiveListNotifier. Send signal if dives are
added or removed and therefore the dive count of a dive site
changes. The dive sites are collected and the signal is sent
at the end of the command.
Add code to update the table view.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a dive site table to each dive site to keep track of dives
that have been added to a dive site. Add two functions to add
dives to / remove dives from dive sites.
Since dive sites now contain a dive table, the order of includes
had to be changed: "divesite.h" now includes "dive.h" and not
vice-versa. This caused some include churn.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
printGPSCoords() returned a newly allocated C-style string. Most
callers simply made a QString out of it and freed the C-style string.
This is paradoxical, as printGPSCoords internally works with QStrings
and converts them to C-style on return.
Therefore, let printGPSCoords() return a QString and create a
printGPSCoordsC() wrapper for the two C-callers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The printGPSCoords() function returns a copied C-style string. Since
the owndership is transferred to the caller, the correct return type
is "char *" instead of "const char *".
Thus a number of casts when calling free can be removed.
Moreover a number of callers didn't free the string and thus were
leaking memory. Fix them. Ultimately we might want two versions
of the function: one for QString, one for C-style strings.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
EMPTY_DIVE_STRING used to be a string-literal representing missing
information ("--"). In 6985c123d4 it
was replaced by the actual empty string. Using a literal to represent
the empty string seems a bit pointless, therefore remove it completely.
Notably:
QString(EMPTY_DIVE_STRING) -> QString()
if (temp.isEmpty()) temp = EMPTY_DIVE_STRING; -> noop
if (s == EMPTY_DIVE_STRING) -> if (s.isEmpty())
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
QML's ListView uses the "section" property to test if items belong to the
same section. Apparently, this must be a string and therefore we can't
pass e.g. a dive-trip object. Therefore a specially formatted string
was passed in, which was guaranteed to be unique (contained the dive-trip
pointer value) and the fully formatted trip-title and short-date.
The disadvantage of that approach is that the formatting is performed for
every dive and not every trip. Perhaps not a problem now, but it makes
it for example necessary to cache the number of filtered dives.
To be more flexible, pass in only the pointer value formatted as
hexadecimal string and provide a function to convert that string
back to a trip-pointer (in the form of a QVariant, so that it can
be passed to QML). Moreover provide two functions for formatting the
title and the short-date.
The three new functions are members of DiveListSortModel. This might not
be the perfect place, but it is easy to reach from the DiveListView.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveObjectHelper::trip() function was
1) Misnamed: it returned the *location* of the trip
2) Not used outside of DiveObjectHelper
Remove it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>