mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Dive pictures: Move thumbnail-size to Thumbnailer class
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>
This commit is contained in:
parent
afe20ce029
commit
b450c155fd
4 changed files with 43 additions and 23 deletions
|
@ -140,7 +140,8 @@ QImage getHashedImage(const QString &file)
|
|||
return res;
|
||||
}
|
||||
|
||||
Thumbnailer::Thumbnailer()
|
||||
Thumbnailer::Thumbnailer() : failImage(QImage(":filter-close").scaled(maxThumbnailSize(), maxThumbnailSize(), Qt::KeepAspectRatio)), // TODO: Don't misuse filter close icon
|
||||
dummyImage(QImage(":photo-icon").scaled(maxThumbnailSize(), maxThumbnailSize(), Qt::KeepAspectRatio)) // TODO: Don't misuse photo-icon
|
||||
{
|
||||
// Currently, we only process one image at a time. Stefan Fuchs reported problems when
|
||||
// calculating multiple thumbnails at once and this hopefully helps.
|
||||
|
@ -200,16 +201,16 @@ static void addThumbnailToCache(const QImage &thumbnail, const QString &picture_
|
|||
file.commit();
|
||||
}
|
||||
|
||||
void Thumbnailer::processItem(QString filename, int size)
|
||||
void Thumbnailer::processItem(QString filename)
|
||||
{
|
||||
QImage thumbnail = getThumbnailFromCache(filename);
|
||||
|
||||
if (thumbnail.isNull()) {
|
||||
thumbnail = getHashedImage(filename);
|
||||
if (thumbnail.isNull()) {
|
||||
// TODO: Don't misuse filter close icon
|
||||
thumbnail = QImage(":filter-close").scaled(size, size, Qt::KeepAspectRatio);
|
||||
thumbnail = failImage;
|
||||
} else {
|
||||
int size = maxThumbnailSize();
|
||||
thumbnail = thumbnail.scaled(size, size, Qt::KeepAspectRatio);
|
||||
addThumbnailToCache(thumbnail, filename);
|
||||
}
|
||||
|
@ -220,7 +221,7 @@ void Thumbnailer::processItem(QString filename, int size)
|
|||
workingOn.remove(filename);
|
||||
}
|
||||
|
||||
QImage Thumbnailer::fetchThumbnail(PictureEntry &entry, int size)
|
||||
QImage Thumbnailer::fetchThumbnail(PictureEntry &entry)
|
||||
{
|
||||
QMutexLocker l(&lock);
|
||||
|
||||
|
@ -228,9 +229,9 @@ QImage Thumbnailer::fetchThumbnail(PictureEntry &entry, int size)
|
|||
const QString &filename = entry.filename;
|
||||
if (!workingOn.contains(filename)) {
|
||||
workingOn.insert(filename,
|
||||
QtConcurrent::run(&pool, [this, filename, size]() { processItem(filename, size); }));
|
||||
QtConcurrent::run(&pool, [this, filename]() { processItem(filename); }));
|
||||
}
|
||||
return QImage(":photo-icon").scaled(size, size, Qt::KeepAspectRatio);
|
||||
return dummyImage;
|
||||
}
|
||||
|
||||
void Thumbnailer::clearWorkQueue()
|
||||
|
@ -240,3 +241,27 @@ void Thumbnailer::clearWorkQueue()
|
|||
it->cancel();
|
||||
workingOn.clear();
|
||||
}
|
||||
|
||||
static const int maxZoom = 3; // Maximum zoom: thrice of standard size
|
||||
|
||||
int Thumbnailer::defaultThumbnailSize()
|
||||
{
|
||||
return defaultIconMetrics().sz_pic;
|
||||
}
|
||||
|
||||
int Thumbnailer::maxThumbnailSize()
|
||||
{
|
||||
return defaultThumbnailSize() * maxZoom;
|
||||
}
|
||||
|
||||
int Thumbnailer::thumbnailSize(double zoomLevel)
|
||||
{
|
||||
// Calculate size of thumbnails. The standard size is defaultIconMetrics().sz_pic.
|
||||
// We use exponential scaling so that the central point is the standard
|
||||
// size and the minimum and maximum extreme points are a third respectively
|
||||
// three times the standard size.
|
||||
// Naturally, these three zoom levels are then represented by
|
||||
// -1.0 (minimum), 0 (standard) and 1.0 (maximum). The actual size is
|
||||
// calculated as standard_size*3.0^zoomLevel.
|
||||
return static_cast<int>(round(defaultThumbnailSize() * pow(maxZoom, zoomLevel)));
|
||||
}
|
||||
|
|
|
@ -28,18 +28,23 @@ public:
|
|||
// Schedule a thumbnail for fetching or calculation.
|
||||
// Returns a placehlder thumbnail. The actual thumbnail will be sent
|
||||
// via a signal later.
|
||||
QImage fetchThumbnail(PictureEntry &entry, int size);
|
||||
QImage fetchThumbnail(PictureEntry &entry);
|
||||
|
||||
// If we change dive, clear all unfinished thumbnail creations
|
||||
void clearWorkQueue();
|
||||
static int maxThumbnailSize();
|
||||
static int defaultThumbnailSize();
|
||||
static int thumbnailSize(double zoomLevel);
|
||||
signals:
|
||||
void thumbnailChanged(QString filename, QImage thumbnail);
|
||||
private:
|
||||
Thumbnailer();
|
||||
void processItem(QString filename, int size);
|
||||
void processItem(QString filename);
|
||||
|
||||
mutable QMutex lock;
|
||||
QThreadPool pool;
|
||||
QImage failImage; // Shown when image-fetching fails
|
||||
QImage dummyImage; // Shown before thumbnail is fetched
|
||||
|
||||
QMap<QString,QFuture<void>> workingOn;
|
||||
};
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
#include <QFileInfo>
|
||||
|
||||
static const int maxZoom = 3; // Maximum zoom: thrice of standard size
|
||||
|
||||
DivePictureModel *DivePictureModel::instance()
|
||||
{
|
||||
static DivePictureModel *self = new DivePictureModel();
|
||||
|
@ -19,7 +17,7 @@ DivePictureModel *DivePictureModel::instance()
|
|||
DivePictureModel::DivePictureModel() : rowDDStart(0),
|
||||
rowDDEnd(0),
|
||||
zoomLevel(0.0),
|
||||
defaultSize(defaultIconMetrics().sz_pic)
|
||||
defaultSize(Thumbnailer::defaultThumbnailSize())
|
||||
{
|
||||
connect(Thumbnailer::instance(), &Thumbnailer::thumbnailChanged,
|
||||
this, &DivePictureModel::updateThumbnail, Qt::QueuedConnection);
|
||||
|
@ -47,22 +45,14 @@ void DivePictureModel::setZoomLevel(int level)
|
|||
|
||||
void DivePictureModel::updateZoom()
|
||||
{
|
||||
// Calculate size of thumbnails. The standard size is defaultIconMetrics().sz_pic.
|
||||
// We use exponential scaling so that the central point is the standard
|
||||
// size and the minimum and maximum extreme points are a third respectively
|
||||
// three times the standard size.
|
||||
// Naturally, these three zoom levels are then represented by
|
||||
// -1.0 (minimum), 0 (standard) and 1.0 (maximum). The actual size is
|
||||
// calculated as standard_size*3.0^zoomLevel.
|
||||
size = static_cast<int>(round(defaultSize * pow(maxZoom, zoomLevel)));
|
||||
size = Thumbnailer::thumbnailSize(zoomLevel);
|
||||
}
|
||||
|
||||
void DivePictureModel::updateThumbnails()
|
||||
{
|
||||
int maxSize = defaultSize * maxZoom;
|
||||
updateZoom();
|
||||
for (PictureEntry &entry: pictures)
|
||||
entry.image = Thumbnailer::instance()->fetchThumbnail(entry, maxSize);
|
||||
entry.image = Thumbnailer::instance()->fetchThumbnail(entry);
|
||||
}
|
||||
|
||||
void DivePictureModel::updateDivePictures()
|
||||
|
|
|
@ -31,8 +31,8 @@ private:
|
|||
DivePictureModel();
|
||||
QList<PictureEntry> pictures;
|
||||
double zoomLevel; // -1.0: minimum, 0.0: standard, 1.0: maximum
|
||||
int defaultSize;
|
||||
int size;
|
||||
int defaultSize;
|
||||
void updateThumbnails();
|
||||
void updateZoom();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue