Commit df156a56c0 replaced "virtual"
by "override" where appropriate. Unfortunately, this had the
unintended consequence of producing numerous clang warnings. If
clang finds a override-modified function in a class definition,
it warns for *all* overriden virtual functions without the override
modifier.
To solve this, go the easy route and remove all overrides. At least
it is consistent.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The keyword "virtual" signalizes that the function is virtual,
i.e. the function of the derived class is called, even if the
call is on the parent class.
It is not necessary to repeat the "virtual" keyword in derived
classes. To highlight derived virtual functions, the keyword
"override" should be used instead. It results in a hard compile-
error, if no function is overridden, thus avoiding subtle bugs.
Replace "virtual" by "override" where appropriate. Moreover,
replace Q_DECL_OVERRIDE by override, since we require reasonably
recent compilers anyway. Likewise, replace /* reimp */ by
"override" for consistency and compiler support.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function DiveListView::fixMessyQtModelBehaviour() was used to
expand the first columns of dive-trips in the dive-list view.
This function was called everytime that the dive-list was modified.
It is kind of ludicrous that external callers would have to
tell the DiveListView, when it has to update its column headers.
Instead, place this functionality in the overriden reset() and
rowsInserted() functions, as these are the only ways that
rows can be added. Change the DiveTripModel to use the proper
beginResetModel()/endResetModel() pair instead of the previous
full deletion and full repopulation using the beginRemoveRows()/
endRemoveRows() and beginInsertRows()/endInsertRows().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On the profile, the run-length of the videos is visualized by a bar.
Add the same information to video-thumbnails in the dive-photo-tab.
Though in this case, render it as text on top of the thumbnails.
Fixes#359
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Conceptually, the width of the columns should probably reside in
the view not the model. But much more severly, the old code didn't
work: Columns were set in a DiveTripModel, which was deleted
right away.
Therefore, move the logic back to the DiveListView. Introduce
a QVector<int> of the initial column widths, so that they can be
erased from the setting if unchanged.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Paint a rectangle on top of thumbnails indicating the run-time
of the video.
Use the z=100.0-101.0 range for painting the thumbnails, whereby
the z-value increases uniformly from first to last thumbnail
(sorted by timestamp). The duration-bars are placed at z-values
midway between those of the thumbnails.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Each DiveItem (which is a wrapper around diveId with some virtual
functions), had a member icon_names, which is an array of
four QStrings. These were not used anywhere and must be an obscure
oversight and was probably planned as a static cons array?.
In any case, remove it.
There *was* a function-local analogous icon_names array in
DiveItem::data() though. This array would initialize four
QStrings from C-string literals on every invocation. Make
this array static, local to the translation unit and use
the QStringLiteral macro to construct the QString object at
compile-time.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
9efb56e2d4 introduced rather complex
logic for picture drag'n'drop events onto the profile. Among other
things, the code had to check whether the picture actually belongs
to the displayed dive.
This can be simplified by transporting the dive-id in the drag'n'drop
event structure. The flow goes like this:
DivePictureModel--(1)-->DivePictureWidget--(2)-->ProfileWidget
For (1), we can use the Qt::UserRole role. This was used to transport
the picture-offset, but this is not needed anymore since ProfileWidget
was decoupled from DivePictureModel.
For (2), we simply replace the "position" value, which was never used.
Why would the receiver care which pixel was pressed in the media-tab?
This commit also contains a minor cleanup in DivePictureWidget:
QListView::mousePressEvent(event) was called in both branches of an
if and can therefore be removed from the if. This is so trivial,
that it doesn't warrant its own commit.
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>
Gracefully handle drag & drop to the profile, which changes the
offset of the pictures. To do this, keep the pictures in the
DivePictureModel and the ProfileWidget2 sorted by offset and
re-arrange if needed to keep the list sorted. This needs some
code reshuffling.
Introduce a helper-function that moves ranges in arrays.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
As long as ProfileWidget2 and DivePictureModel showed the same set of
pictures and any change would lead to a full recalculation of the set,
it made sense to let ProfileWidget2 use DivePictureModel's data.
Recently, keeping the two lists in sync become more and more of a
burden. Therefore, disconnect ProfileWidget2 and DivePictureModel. This
will lead to some code-duplication and perhaps a temporary drop in
UI-performance, but in the end the code is distinctly simpler and also
more flexible.
Thus, for example the DivePhotoTab could be changed to support headings
without having to touch ProfileWidget2 at all.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
This fixes a bug introduced in fbe1144eaf:
For an empty log, in DivePictureModel::updateDivePictures()
beginResetModel() would be called without a corresponding endResetModel().
It is unclear whether this can ever be hit, because in the no-dives
case, at least in the desktop version no profile is shown.
Note, that this makes the check double-unnecessary.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In DivePictureModel, rowDDEnd and rowDDStart specify the range of
pictures in the profile plot. Obviously, these have to be adjusted
when pictures are deleted.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In order to trigger the redraw of an edited dive we need to make sure
the model realizes that it has been updated. So far the only way to make
sure this happens reliably appears to be to remove the item and
re-insert it. Seems weird, but with this the bug of not redrawing the
profile after an edit appears fixed.
Fixes#1419
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
There were a handfull instances of the kind
1) gettextFromC::instance()->tr(...)
2) gettextFromC::instance()->trGettext(...)
1) is pointless, as tr is a static function.
All instances of 2) were likewise pointless, because trGettext()
returns a C-string, which was then immediately converted to a
QString.
Thus, replace both constructs by gettextFromC::tr(...).
After this change there was only one user of gettextFromC::instance()
left, viz. the C-interface funtion trGettext(). Therefore, remove
gettextFromC::instance() and do all the caching / translating
directly in the global trGettext().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
... by taking into acount that dive planner points refer
to the sement before the waypoint (while change mode
events are concerned with the future of a waypoint).
Signed-off-by: Robert C. Helling <helling@atdotde.de>
When making a segment non-CCR, its setpoint should be 0.
OTOH, when it becomes CCR, use the default setpoint
(or should we try to find the last previous setpoint?)
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Instead of a constant or a macro for the maximum
number of 'ws_info' elements the 100 literal was used.
Define MAX_WS_INFO in dive.h and use it everywhere.
Also clamp loops that iterate `ws_info' to MAX_WS_INFO.
Prevents potential out-of-bounds reading, similarly to
the previous commit about 'tank_info'.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
In a number of places the global 'tank_info' array
is being iterated based on a 'tank_info[idx].name != NULL'
condition.
This is dangerous because if the user has added a lot of tanks,
such loops can reach 'tank_info[MAX_TANK_INFO]'. This is an
out of bounds read and if the 'name' pointer there happens to be
non-NULL, passing that address to a peace of code that tries
to read it (like strlen()) would either SIGSEGV or have undefined
behavior.
Clamp all loops that iterate 'tank_info' to MAX_TANK_INFO.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
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>
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>
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>
On deletion of a single or multiple pictures, the whole DivePictureModel
was repopulated, which was clearly visible in the UI, owing to the
reconstructing of all images in the profile plot.
To avoid this vexing behavior, implement proper deletion routines in
DivePictureModel and ProfileWidget2. Since this needs sensible erase()
semantics the QList<PictureEntry> member of DivePictureModel was
replaced by a QVector. A QVector should be the default anyway, unless
there are very specific reasons to use a QList (which actually is
a deque, not a classical linked list).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function removePicture() had a flag "last", which would indicate
that the called had finished removing pictures. Only then would
the model be recalculated.
This is a strange interface and, matter of fact, the caller was buggy:
if the last picture to be removed didn't have a proper url, removePicture()
was never called with "last" being set.
Change the interface to take a list of pictures to be deleted. This
will allow us to make picture deletion smarter in follow-up commits.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the old code a combination of removeRows()/insertRows() was used
to signal a model reset.
Replace this by a single, modelReset signal. This saves a call to
plotPictures() and will allow us to be smarter in the future,
when removing pictures.
Reset-model and remove-items are semantically different.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
on iOS it is practically impossible to copy the App log
to e.g. a mail! in iOS 11 the log file is stored within
the subsurface container and you first need to copy (actually
using the clipboard) out from there to the "normal" document
shared space, before it can be used.
At least iOS users (and I believe Android users) are not really
used to work with files, so the process is not easy to document
in an understandable way.
The alternative is to provide a button, which simply puts the
log on the general clipboard, allowing it to be pasted in a
multitud of applications.
Signed-off-by: Jan Iversen <jani@apache.org>
...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>
Add a divemode column to the planner model and a
corresponding field to struct divepoint and fill it
in the corresponding functions.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
In the old code, we used to reload the whole picture list on drag & drop
to the profile. Instead, only update the drag&dropped picture and repaint
the profile-pictures.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The size of the to-be-created thumbnails was passed from DivePictureModel
to Thumbnailer. This became more and more bothersome, because the size
had to be stored with the request. Calling from Thumbnailer into
DivePictureModel was not an option, since this is not linked to all tests.
Therefore, move these functions to the Thumbnailer class.
Since the maximum thumbnail size is now known to the thumbnailer, the
dummy and failure images can be precalculated, which makes switching
between dives faster.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Connect the thumbnailer signal to the dive picture model slot.
This needs some code-reshuffling in the dive picture model.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Create a new class, which performs all thumbnailing code.
This is mostly code reshuffling. Thumbnails are extracted
either from a cache or thumbnail calculation is started in
a worker thread.
Since getHashedImage() is called from a worker thread it
makes no sense to call subfunctions in yet another worker
thread. Remove these calls.
In contrast to the previous code, on error the background
thread produces a failure image, but it is not yet shown.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In imagedownloader.cpp the only thing we need from the picture struct
is the filename. Therefore, use QStrings instead of the picture struct.
This simplifies memory management.
Remove the clone_picture() function, which is not needed anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
SHashedImage was a subclass of QImage, which fetched the image according
to the filename hashes. Turn this into a function, as this is much more
idiomatic and flexible.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old code loaded all thumbnails into memory at once. This does
not scale to logs with thousands of pictures. Therefore, save
the pictures to individual files and only load the currently
needed pictures.
Currently, this will make changing switching between dives slower,
because the thumbnails are loaded from disk. In the future, it
is planned to do this in a background thread without blocking
the user interface.
A notable difference to the old code: Thumbnails are now indexed
by the image-hash (i.e. the content of the raw image) and not
by the filename of the image. Thus, different paths to the same
image should only be saved once.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To potentially conserve memory, don't keep copies of scaled thumbnails.
Scale the thumbnails on demand.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
fake_dc() used to return a statically allocated dc with statically
allocated samples. This is of course a questionable practice in
the light of multi-threading / resource ownership. Once these
problems were recognized, the parameter "alloc" was added. If set
to true, the function would still return a statically allocated
dc, but heap-allocated samples, which could then be copied in
a different dc.
All in all an ownership nightmare and a recipie for disaster.
The returned static dc was only used as a pointer to the samples
anyway. There are four callers of fake_dc() and they all have access
to a dc-structure without samples. Therefore, change the semantics
of fake_dc() to fill out the passed in dc. If the caller does
not care about the samples, it can simply reset the sample number
to zero after work.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit allows plotting the OC-equivalent pO2 graph for PSCR
dives. This happens in both the cases where there is no external
O2-monitoring AND when there is external pO2 monitoring. The
calculations are only done for PSCR dives and is achieved as
follows:
1) Within plot-info create a pressure-t called OC_pO2 in
profile.h and populate this variable with the open-circuit
pO2 values in profile.c.
2) Create a new partialPressureGasItem ocpo2GasItem in
profilewidget2.h and, in profilewidget2.cpp, initialise it
to read the plot-info OC_pO2 values and enable its
display by using the setVisible method. The
diveplotdatamodel was also touched in order to achieve
this.
3) Create a pref button that controls the display of OC-pO2 for SCR dives
4) Change the colour of the OC-pO2 grpah to orange
5) Change the connection of the crr_OC_pO2 signal to be appropriate
6) rename the OC_pO2 attribute to scr_OC-pO2
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
So far we only wrote messages to subsurface.log on Android (since we couldn't
figure out how to make that file user accessible on iOS). Now that that's
fixed, we also need to actually write to the file in the first place.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>