"Roles" is a C-style enum (i.e. not C++-style enum class). Since that
means that the names spill into the outer namespace, the names
themselves are prefixed with "Role". Nevertheless the code qualified
the names with "Roles::". This is redundant and unnecessary.
Remove this redundancy to show that we understand how the language
works.
Note: we could also transform the enum into an enum class and remove
the "Role" prefix from the names. That would arguably be "cleaner",
but then the enum doesn't auto-convert to/from int, but Qt uses int
to pass the roles to functions. So let's go the simple way that
avoids casting.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since this is no longer a Q_METATYPE, nobody will try to
default construct this object. Remove the default constructor
and guarantee that there will be no null divesite.
Of course, the lack of default constructor means that the
default argument to the "selected" member variable should
be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Let's face it: this is a value type. No point in having Java-style
getters and setters. Replace by plain old and boring member variables.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Nobody was listening for that signal. Remove it. This, quite
obviously, makse the setCoordinateNoEmit() function redundant.
Merge with setCoordinateNoEmit().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We never dish out an object of this type to QML. It is unclear how
Q_PROPERTIEs could be of any use.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Recently we changed the MapLocationModel-items to store whether
they are selected. Thus, we can directly export an isSelected
flag instead of calling a function taking a dive-site argument.
1) This makes the QML easier to read.
2) This avoids passing pointers through QML which has caused
us lots of pain.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To connect a model to QML, one is supposed to provide a
QHash<int, QByteArray> MapLocationModel::roleNames()
function that returns a role -> attribute-name hash.
That was realized by filling the hash in the constructor,
storing it as a member variable, using static strings that
were declared in the class-definition and defined in the
translation unit.
Adding a new role was a pain and the whole thing was totally
pointless as the attribute names were used nowhere else and
the roleNames() function is called only once.
Simply do, what we do everywhere else: initialize the hash
in the roleNames() function and use normal string literals.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since not fully reloading the map on selection change,
the selected sites were not moved to the top. Not calculating
the z-value in QML, but making it a simple model property
helps.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When clicking a dive site on the map, the QML code would set
the selected dive site, but then all dives of dive sites in
the vicinity were set. But still only the clicked-on dive site
was shown.
Therefore, don't set the list of selected dive sites in QML,
but later in DiveListView::selectDives(), where we know all
the dives that were selected.
This, again, gives nasty entanglement of diverse widgets and
models.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When changing the selection the MapLocationModel was reset.
This lead to crashes on Qt-5.9 which are due to QML accessing
data that was freed during model reset. This putative Qt bug
doesn't happen on newer Qt versions. At least Qt-5.12 is known
to work.
Instead of fighting the bug, let's simply not reset the model
but send a dataChanged() for every element of the MapLocationModel.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Experimentation has shown that the image of a flag will
only be changed after dataChanged() if it is a simple
property. The old code had a complex QML expression and
then - for some reason - it didn't work.
To give us better control over the flags and avoid full
reloads of the map therefore introduce a model-property
pixmap name. The name depends on whether the site is
selected and if not, whether we are in divesite-edit mode.
This makes the code rather convoluted. Firstly, we have
to save whether the site is selected in the map-item.
Secondly we have to access the global map-widget, which
in turn has to go to the map-widget helper (layering
violation!).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When clicking on a flag
1) The QML would call MapLocationModel::setSelected() with
fromClick = true
2) MapLocationModel::setSelected() would emit a signal
selectedLocationChanged()
3) MapWidgetHelper would catch that signal and do the actual
processing.
Other functions would call MapLocationModel::setSelected() with
fromClick = false, which would not emit the selectedLocationChanged()
signal.
Detangle this a bit by calling the selectedLocationChanged() function
directly from QML and remove the fromClick parameter.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Just to be sure, refuse to add null divesites to the selection.
Moreover, refuse to call the setSelected function on a null-divesite.
I got an unfriendly Qt-Warning there:
"Passing incompatible arguments to C++ functions from JavaScript is
dangerous and deprecated."
"This will throw a JavaScript TypeError in future releases of Qt!"
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Commit 0c38754916 introduced a
bug in MapLocationModel::reload() by setting an entry in the
name-to-location map before the location was initialized.
Move the setting of the map entry back where it was before:
after the assignment of the location variable.
Moreover, define the location variable directly on allocation
of the location to avoid thus bugs in the future.
Why did we not get a "might be used unitialized" warning
anyway?
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, dive site names are only updated on full reload.
Instead hook directly into the corresponding signal in the
MapLocationModel to set the name. Also to the coordinates
directly there instead of going via the MapWidgetHelper.
In the MapWidgetHelper, just center on the changed dive site.
Hook into the signal directly there and remove the slot
from the MapWidget. This makes the whole call-chain at least
one call shorter.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Move the code to add the first selected dive site from
MapWidgetHelper::enterEditMode() to MapLocationModel::reload().
Thus, the list of sites is built only at one place. For this
it is necessary to pass a pointer to the map, so that new
dive sites can be added at the center of the map.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of looping over the dive table and extract dive sites,
loop over the dive site table.
This makes it possible to show dive sites that have no dive
associated with them.
But we have to create to functions that check whether a dive
site has any shown dives or has any selected dives.
Moreover, change the code to add near dive sites of the same
name if in edit mode. Other wise (erroneously added?) dive
sites with the same name cannot be moved on the map.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When dive sites are edited, we shouldn't highlight the sites
of the current dive, but the currently edited site(s).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since the dive-site-filter is active either on the dive-site-edit
page or the dive-site-list page, use that as the flag for dive-site-edit
mode. Moreover, when the filter is reset, the
MapWidgetHelper::reloadMapLocations() function is called, so we
can use that place to enter/exit edit mode.
This makes it easier to keep everything consistent.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If multiple dives are selected, highlight all corresponding sites.
For that, replace the MapLocationModel::m_selectedDs pointer by
a QVector<>. Fill the vector in MapLocationModel::reload() and
add a isSelected() member function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The map model keeps track of the dive site positions on the
map. Therefore, it seems more logical to have the code calculating
the map position in the model, not in the helper-class.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When updating the coordinates of a dive site, the MapLocationModel
is updated. The code created a (col, row) index with col = 0.
[The idea of course being col = x, row = y]. Alas, that's not
how Qt works - its models want (row, col) indices. The code
worked, because the only time when the dive site locations were
updated was in dive site edit mode, when only one site is visible,
i.e. there is only one row leading to the correct (0, 0) index.
Fix this so that we can also change dive site positions if more
than one site is displayed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Now that struct dive_site * is a proper Q_METATYPE it is not
necessary anymore to pass dive-sites as opaque uintptr_t types.
Simply pass a QVariants or directly via dive_site *.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace the UUID reference of struct dive by a pointer to dive_site.
This commit is rather large in lines, but nevertheless quite simple
since most of the UUID->pointer work was done in previous commits.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This patch allows updating the location of map markers
while editing a dive site and updating the text in the
LocationInformationWidget in real-time.
Currently it is only possible to see the marker changes by
clicking 'Apply'.
The modification required the following changes:
- add the MapWidget::updateCurrentDiveSiteCoordinatesToMap() slot
and call it each time the GPS text updates
- separate the updateCurrentDiveSiteCoordinates(FromMap/ToMap) logic
by having the FromMap/ToMap suffix to method names
- make MapWidgetHelper::updateCurrentDiveSiteCoordinatesToMap()
call a new MapLocationModel::updateMapLocationCoordinates()
method, which updates selected location coordinates and the model
- add MapLocation::setCoordinateNoEmit() that does not emit
a signal when updating a coordinate
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
I thought we had this automated, but Lubomirs commits introduced a few
files with dos line endings. This is purely a change of line endings, no
other changes.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
getRole() returns a QVariant and the cast is a small overhead.
Using these helpers will reduce the overhead.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The MapLocation QObject now has a QString property "name", which is
translating the dive_site->name member.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The idea of this flag is to be able to only to emit the
selectedLocationChanged() signal when the user clicked on the map
(fromClick == true).
MapWidgetHelper::selectedLocationChanged() listens for this signal
and only then it will select nearby dives based on a "small-cicle".
If "fromClick" is false, it's the backend or the dive list that
updated the selection and MapWidgetHelper::selectedLocationChanged()
should no be called.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
getMapLocationForUuid() accepts a UUID, searches the MapLocation table
and returns a pointer.
Make use of the new method in setSelectedUuid().
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Inside the QML Map class there is a MapItemView item.
This item uses a delegate that receive a "model" property from
the MapLocationModel, but infact that's a QObject with the MapLocation
defined properties. That's how MapItemView works.
The problem here is that "model" QObject cannot be cast back
to a MapLocation as the meta data in there does not include
a MapLocation sub-class, for some reason.
Even if using propery() on that QObject to fetch data like coordinates
works, instead of storing this strange object pointer, store the
MapLocation UUID (from dive_site) which is a uint32_t.
setSelectedUuid() deals with this oddity and finds the correct
MapLocation pointer in the table and dispatches a selectedLocationChanged()
signal for it.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The "uuid" property will be the one from the dive_site. At first it
will also be used to track the active marker/flag selection.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This method should be used if many markers are added at once.
It's main purpose is to reduces the number of beingInsertRows()
calls.
Make MapWidgetHelper::reloadMapLocations() use it.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Instead of maintaining a seperate latitude/longitude values
in C++ and passing them to QML separatelly, pass them as a QGeoCoordinate.
This reduces the number of model "roles" and also prevents the creations
of extra objects in QML (e.g. via QtPositioning.coordinate(..)).
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
- add() will be used to add a MapLocation to the model with
beginInsertRows()...endInsertRows()
- clear() will be used to clear the model with beginRemoveRows()...
endRemoveRows()
NOTE: emiting dataChanged() does not seem to update the QML view for
this model so calling being<..>Rows() seems to be the "correct Qt
approach" to do this.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The QML Map widget requires a QAbstractListModel based model to operate
with good performance. Technically gpslistmodel.cpp can be used for that
same purpose (e.g. has GPS coordinates), but the way it updates
may complicate the Map widget integration.
Thus, a new model is created - MapLocationModel, with items of type
MapLocation, for an attempt for a clean project structure on the C++ side.
For now it only handles latitude and longitude.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>