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>
On startup, convert an old-style thumbnailHash to individual
thumbnail files. Show a modal progress bar while doing so.
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>
get_dive_date_c_string() and get_current_date() return copied strings.
Make this explicit by returning non-const pointers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
qthelper.cpp is already quite voluminous. Move the recently
introduced localized versions of (v)snprintf() and put_format()
into their own translation unit.
Moreover, adopt C-style semantics for asprintf_loc(). This function
will be used to remove fixed-size buffers in core/plannernotes.c.
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>
This is a preparation for supporting videos. Some video formats may
not possess such meta data, or we may not yet be able to parse them.
In such a case, use the file creation date.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is a preparation for video support. We don't want to read a whole
potentially multi-GB file into memory just to detect that it isn't a
JPEG. Especially since at the moment EXIF metadata are parsed twice,
once for GPS, once for timestamp.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
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>
The hash field in the picture-structure was in principle non-operational.
It was set on loading, but never actually changed. The authoritative
hash comes from the filename->hash map.
Therefore, make this explicit by removing the hash field from the
picture structure.
Instead of filling the picture structure on loading, add the
hash directly to the filename->hash map. This is done in the
register_hash() function, which does not overwrite old entries.
I.e. the local hash has priority over the save-file. This
policy might be refined in the future.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Passing of QStrings and QByteArrays was inconsistent in qthelper.cpp.
Unify to passing const-references. Passing by value is no big deal, since
QString and QByteArray do copy-on-write "optimization". Nevertheless, let's
keep it as consistent and effective as possible.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
learnHash() was always called in conjunction with add_hash(). The
pattern was that a local filename and a hash were connected in
the hash-to-filename and the filename-to-hash maps. Then, the
original picture-filename or url were registered in the filename-to-hash
map.
This commit changes learnHash() to take three parameters (original-filename,
local-filename and hash) and do all of the above. The new code is
simpler because no dummy picture struct has to be generated in
DiveListView::loadImageFromURL().
The tests were extended to check for all hash<->filename associations.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
learnHash() is called either on a local picture structure
[DiveListView::loadImageFromURL()] or on a cloned picture structure
[ImageDownloader::saveImage()]. In neither case the picture structure
is passed to the frontend. Therefore, storing the new hash in the
picture struct is not necessary.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
hashPicture() calls hashFile(), which calls add_hash(). add_hash()
updates the filename-to-hash and hash-to-filename maps. Therefore,
there is no point in calling learnHash() in hashPicture(), which
updates the filename-to-hash map.
Note that learnHash() updates the picture-struct with the new hash,
but since hashPicture() works on a cloned picture-struct, which
is free()d in hashPicture(), these changes are lost anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
updateHash() and hashPicture() did the same thing, with the exception
that hashPicture() marked the dive list as changed if a hash changed.
This seems like a good idea in any case, therefore always use
hashPicture().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This changes the numeric format of many values printed to the UI to
reflect the correct numeric format of the selected locale:
- dot or comma as decimal separator
- comma or dot as thousands separator
In the Qt domain the `L` flag is used case specific mostly
in qthelper.cpp.
Then the helper functions get_xxx_string() are used more consistently.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
This commit introduces functions:
- QString asprintf_loc(const char *cformat, ...);
- int snprintf_loc(char *dst, size_t size, const char *cformat, ...);
- put_format_loc(struct membuffer *, const char *fmt, ...);
and their va_arg equivalents, which use Qt's QString::arg() formatting
options to render the strings.
The snprintf_loc() function takes care not to truncate multi-byte
UTF-8 encodings. Thus, on overflow, the resulting string might be
shorter than size-1.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Mostly replace "return (expression);" by "return expression;" and one
case of "function((parameter))" by "function(parameter)".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The following statement in the hashstring() function:
return hashOf[QString(filename)].toHex().data();
returns data of the temporary QByteArray generated by toHex().
Thus, the caller will access released memory, which could lead to
data corruption.
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>
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>
In a session with the profile I saw that the planner spends
a lot of time waiting to obtain the lock for the factor cache.
Most of the time we are only reading that cache and that
is save to do in parallel (according to the Qt IRC channel).
So we can use a QReadWriteLock instead of a QMutex. This
appears to be quite a performance boost, in particular
for VPM-B
Signed-off-by: Robert C. Helling <helling@atdotde.de>
I never realized that my hashes weren't written, because it only
outputs a debug instead of a warning message.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function isCloudUrl() was only called in one place, parse_file().
But, isCloudUrl() could only return true if the filename was of the
git-repository kind (url[branch]). In such a case, control flow would
never reach the point where isCloudUrl() is called, since
is_git_repository() returns non-NULL and the function returns early.
Therefore, remove this function. Moreover, adapt the affected if-statement
by replacing "str && !strcmp(str, ...)" with the more concise
"same_string(str, ...)".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
copy_string() does the same as the current code, but in one instead
of four lines. Strictly speaking, it does not exactly the same thing
because the empty string ("") case is handled differently. copy_string()
returns NULL instead of a copy of "", which is probably preferred anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Make all char * pointers in pref.h const to make it clear that these
strings are not mutable. This meant adding a number of (void *) casts
in calls to free(). Apart from being the right thing to do, this commit
makes the code more consistent, as many of the strings in pref.h were
already const.
While touching core/qthelper.cpp turn three instances of (void*) into
(void *).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In certain places the '(int)' cast is used, while in other the
llrint() or lrint() functions. Make the conversation from degrees
in the 'double' form to the 'int' degrees_t consistent using lrint().
lrint() is the function which should give the best results,
because it accepts a 'double' and results in a 'long'
even if degrees_t is 'int'. If the truncation from 'long' to 'int'
is discarding some of the precision then the next step
would be to turn degrees_t into a 64bit signed integer type.
Possible fix for #625.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Simplify and fix prestation of weights. Due to the attempt to round
only the grams part (by just adding 50 to it, and truncating
afterwards) a weird effect was introduced. For example, a value
0.98 was presented as 0.10. Just replay the old logic, and see
what happens. Rewrote the logic to a simpler and better one.
fixes: #532
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
The following call in weight_string():
str = QString("%1").arg(lbs, 0, 'f', lbs >= 40.0 ? 0 : 1);
will make values in lbs larger or equal to 40 to have no fractional
part and be rounded to nearest, while values less than 40 will have one
decimal place.
fixes#412
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Update the function to create the dive duration string in a way that
it can be used also in info and stats tab and added some more flexibility.
Changed layout for <1h freedives to "0:05:35" (w/o units) or "5:35min"
(with units and :) or "5min 35sec" (with units with space).
Add a new function to create the surface interval string.
Completely remove old function get_time_string() and get_time_string_s().
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Moving the GUI independent Seabear import functionality to Subsurface
core. This will allow Robert to call it directly from download from DC.
Tested with H3 against released and daily versions of Subsurface. The
result differs somewhat, but it is actually fixing 2 bugs:
- Temperature was mis-interpreted previously
- Sample interval for a dive with 1 second interval was parsed
incorrectly
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>