mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Dive pictures: differentiate between IO-error and unknown format
Show different images for IO-error and unknow file format. Use file-extensions to recognize video files if we couldn't parse them. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
f8f8735cfe
commit
a741f505ca
2 changed files with 40 additions and 19 deletions
|
@ -69,15 +69,12 @@ void ImageDownloader::saveImage(QNetworkReply *reply)
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isVideoFile(const QString &filename)
|
static bool hasVideoFileExtension(const QString &filename)
|
||||||
{
|
{
|
||||||
// Currently, we're very crude. Simply check if the file exists and if it
|
for (const QString &ext: videoExtensionsList)
|
||||||
// is an MP4-style format.
|
if (filename.endsWith(ext, Qt::CaseInsensitive))
|
||||||
QFileInfo fi(filename);
|
return true;
|
||||||
if (!fi.exists() && !fi.isFile())
|
|
||||||
return false;
|
return false;
|
||||||
metadata md;
|
|
||||||
return get_metadata(qPrintable(filename), &md) == MEDIATYPE_VIDEO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch a picture from the given filename and determine its type (picture of video).
|
// Fetch a picture from the given filename and determine its type (picture of video).
|
||||||
|
@ -90,11 +87,29 @@ Thumbnailer::Thumbnail Thumbnailer::fetchImage(const QString &filename, const QS
|
||||||
{
|
{
|
||||||
QUrl url = QUrl::fromUserInput(filename);
|
QUrl url = QUrl::fromUserInput(filename);
|
||||||
if (url.isLocalFile()) {
|
if (url.isLocalFile()) {
|
||||||
|
// We try to determine the type first by peeking into the file.
|
||||||
QString filename = url.toLocalFile();
|
QString filename = url.toLocalFile();
|
||||||
if (isVideoFile(filename))
|
metadata md;
|
||||||
|
mediatype_t type = get_metadata(qPrintable(filename), &md);
|
||||||
|
|
||||||
|
// For io error or video, return early with the appropriate dummy-icon.
|
||||||
|
if (type == MEDIATYPE_IO_ERROR)
|
||||||
|
return { failImage, MEDIATYPE_IO_ERROR };
|
||||||
|
else if (type == MEDIATYPE_VIDEO)
|
||||||
return { videoImage, MEDIATYPE_VIDEO };
|
return { videoImage, MEDIATYPE_VIDEO };
|
||||||
|
|
||||||
|
// Try if Qt can parse this image. If it does, use this as a thumbnail.
|
||||||
QImage thumb(filename);
|
QImage thumb(filename);
|
||||||
return { thumb, thumb.isNull() ? MEDIATYPE_IO_ERROR : MEDIATYPE_PICTURE };
|
if (!thumb.isNull())
|
||||||
|
return { thumb, MEDIATYPE_PICTURE };
|
||||||
|
|
||||||
|
// Neither our code, nor Qt could determine the type of this object from looking at the data.
|
||||||
|
// Try to check for a video-file extension.
|
||||||
|
if (hasVideoFileExtension(filename))
|
||||||
|
return { videoImage, MEDIATYPE_VIDEO };
|
||||||
|
|
||||||
|
// Give up: we simply couldn't determine what this thing is.
|
||||||
|
return { unknownImage, MEDIATYPE_UNKNOWN };
|
||||||
} else if (tryDownload) {
|
} else if (tryDownload) {
|
||||||
// This has to be done in UI main thread, because QNetworkManager refuses
|
// This has to be done in UI main thread, because QNetworkManager refuses
|
||||||
// to treat requests from other threads. invokeMethod() is Qt's way of calling a
|
// to treat requests from other threads. invokeMethod() is Qt's way of calling a
|
||||||
|
@ -115,18 +130,20 @@ Thumbnailer::Thumbnail Thumbnailer::getHashedImage(const QString &filename, bool
|
||||||
{
|
{
|
||||||
QString localFilename = localFilePath(filename);
|
QString localFilename = localFilePath(filename);
|
||||||
|
|
||||||
// If there is a translated filename, try that first
|
// If there is a translated filename, try that first.
|
||||||
Thumbnail thumbnail { QImage(), MEDIATYPE_UNKNOWN };
|
// Note that we set the default type to io-error, so that if we didn't try
|
||||||
|
// the local filename first, we will load the file from the canonical filename.
|
||||||
|
Thumbnail thumbnail { QImage(), MEDIATYPE_IO_ERROR };
|
||||||
if (localFilename != filename)
|
if (localFilename != filename)
|
||||||
thumbnail = fetchImage(localFilename, filename, tryDownload);
|
thumbnail = fetchImage(localFilename, filename, tryDownload);
|
||||||
|
|
||||||
// Note that the translated filename should never be a remote file and therefore checking for
|
// If fetching from the local filename failed (or we didn't even try),
|
||||||
// still-loading is currently not necessary. But in the future, we might support such a use case
|
// use the canonical filename. This might for example happen if we downloaded
|
||||||
// (e.g. images stored in the cloud).
|
// a file, but for some reason lost the cached file.
|
||||||
if (thumbnail.img.isNull() && thumbnail.type != MEDIATYPE_STILL_LOADING)
|
if (thumbnail.type == MEDIATYPE_IO_ERROR)
|
||||||
thumbnail = fetchImage(filename, filename, tryDownload);
|
thumbnail = fetchImage(filename, filename, tryDownload);
|
||||||
|
|
||||||
if (thumbnail.img.isNull() && thumbnail.type != MEDIATYPE_STILL_LOADING)
|
if (thumbnail.type == MEDIATYPE_IO_ERROR)
|
||||||
qInfo() << "Error loading image" << filename << "[local:" << localFilename << "]";
|
qInfo() << "Error loading image" << filename << "[local:" << localFilename << "]";
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
}
|
}
|
||||||
|
@ -143,7 +160,8 @@ static QImage renderIcon(const char *id, int size)
|
||||||
|
|
||||||
Thumbnailer::Thumbnailer() : failImage(renderIcon(":filter-close", maxThumbnailSize())), // TODO: Don't misuse filter close icon
|
Thumbnailer::Thumbnailer() : failImage(renderIcon(":filter-close", maxThumbnailSize())), // TODO: Don't misuse filter close icon
|
||||||
dummyImage(renderIcon(":camera-icon", maxThumbnailSize())),
|
dummyImage(renderIcon(":camera-icon", maxThumbnailSize())),
|
||||||
videoImage(renderIcon(":video-icon", maxThumbnailSize()))
|
videoImage(renderIcon(":video-icon", maxThumbnailSize())),
|
||||||
|
unknownImage(renderIcon(":unknown-icon", maxThumbnailSize()))
|
||||||
{
|
{
|
||||||
// Currently, we only process one image at a time. Stefan Fuchs reported problems when
|
// Currently, we only process one image at a time. Stefan Fuchs reported problems when
|
||||||
// calculating multiple thumbnails at once and this hopefully helps.
|
// calculating multiple thumbnails at once and this hopefully helps.
|
||||||
|
@ -195,6 +213,8 @@ Thumbnailer::Thumbnail Thumbnailer::getThumbnailFromCache(const QString &picture
|
||||||
// TODO: Perhaps extract thumbnails
|
// TODO: Perhaps extract thumbnails
|
||||||
if (type == MEDIATYPE_VIDEO)
|
if (type == MEDIATYPE_VIDEO)
|
||||||
res = videoImage;
|
res = videoImage;
|
||||||
|
else if (type == MEDIATYPE_UNKNOWN)
|
||||||
|
res = unknownImage;
|
||||||
|
|
||||||
return { res, (mediatype_t)type };
|
return { res, (mediatype_t)type };
|
||||||
}
|
}
|
||||||
|
@ -223,7 +243,7 @@ void Thumbnailer::recalculate(QString filename)
|
||||||
// If we couldn't load the image from disk -> leave old thumbnail.
|
// If we couldn't load the image from disk -> leave old thumbnail.
|
||||||
// The case "load from web" is a bit inconsistent: it will call into processItem() later
|
// The case "load from web" is a bit inconsistent: it will call into processItem() later
|
||||||
// and therefore a "broken" image symbol may be shown.
|
// and therefore a "broken" image symbol may be shown.
|
||||||
if (thumbnail.type == MEDIATYPE_STILL_LOADING || thumbnail.img.isNull())
|
if (thumbnail.type == MEDIATYPE_STILL_LOADING || thumbnail.type == MEDIATYPE_IO_ERROR)
|
||||||
return;
|
return;
|
||||||
addThumbnailToCache(thumbnail, filename);
|
addThumbnailToCache(thumbnail, filename);
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ private:
|
||||||
QImage failImage; // Shown when image-fetching fails
|
QImage failImage; // Shown when image-fetching fails
|
||||||
QImage dummyImage; // Shown before thumbnail is fetched
|
QImage dummyImage; // Shown before thumbnail is fetched
|
||||||
QImage videoImage; // Place holder for videos
|
QImage videoImage; // Place holder for videos
|
||||||
|
QImage unknownImage; // Place holder for files where we couldn't determine the type
|
||||||
|
|
||||||
QMap<QString,QFuture<void>> workingOn;
|
QMap<QString,QFuture<void>> workingOn;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue