mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Add hashes to images
Upon successfull reading an image file, this computes a SHA1 hash of the image and saves it with the picture tag in the log file. When a file is not successfully loaded (for example because the log was created on a different computer) we look up the hash in a dictionary that maps hashes to local file names. That dictionary (actually two for both directions), is loaded on startup and saved upon destruction of the main window. Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
ea00fdb36a
commit
b02bf002a6
11 changed files with 139 additions and 15 deletions
|
@ -3,7 +3,25 @@
|
|||
#include "dive.h"
|
||||
#include "divelist.h"
|
||||
#include <QtConcurrentMap>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QDir>
|
||||
#include <QCryptographicHash>
|
||||
#include <mainwindow.h>
|
||||
#include <qthelper.h>
|
||||
|
||||
SHashedImage::SHashedImage(struct picture *picture) : QImage(picture->filename)
|
||||
{
|
||||
if (isNull()) {
|
||||
// Hash lookup.
|
||||
load(fileFromHash(picture->hash));
|
||||
if (!isNull())
|
||||
QtConcurrent::run(updateHash, picture);
|
||||
} else {
|
||||
QByteArray hash = hashFile(QString(picture->filename));
|
||||
free(picture->hash);
|
||||
picture->hash = strdup(hash.toHex().data());
|
||||
}
|
||||
}
|
||||
|
||||
DivePictureModel *DivePictureModel::instance()
|
||||
{
|
||||
|
@ -15,20 +33,21 @@ DivePictureModel::DivePictureModel() : numberOfPictures(0)
|
|||
{
|
||||
}
|
||||
|
||||
typedef QPair<QString, QImage> SPixmap;
|
||||
typedef QList<SPixmap> SPixmapList;
|
||||
typedef struct picture *picturepointer;
|
||||
typedef QPair<picturepointer, QImage> SPixmap;
|
||||
typedef QList<struct picture *> SPictureList;
|
||||
|
||||
SPixmap scaleImages(const QString &s)
|
||||
SPixmap scaleImages(picturepointer picture)
|
||||
{
|
||||
static QHash <QString, QImage > cache;
|
||||
SPixmap ret;
|
||||
ret.first = s;
|
||||
if (cache.contains(s)) {
|
||||
ret.second = cache.value(s);
|
||||
ret.first = picture;
|
||||
if (cache.contains(picture->filename) && !cache.value(picture->filename).isNull()) {
|
||||
ret.second = cache.value(picture->filename);
|
||||
} else {
|
||||
int dim = defaultIconMetrics().sz_pic;
|
||||
QImage p = QImage(s).scaled(dim, dim, Qt::KeepAspectRatio);
|
||||
cache.insert(s, p);
|
||||
QImage p = SHashedImage(picture).scaled(dim, dim, Qt::KeepAspectRatio);
|
||||
cache.insert(picture->filename, p);
|
||||
ret.second = p;
|
||||
}
|
||||
return ret;
|
||||
|
@ -49,14 +68,15 @@ void DivePictureModel::updateDivePictures()
|
|||
}
|
||||
|
||||
stringPixmapCache.clear();
|
||||
QStringList pictures;
|
||||
SPictureList pictures;
|
||||
FOR_EACH_PICTURE_NON_PTR(displayed_dive) {
|
||||
stringPixmapCache[QString(picture->filename)].offsetSeconds = picture->offset.seconds;
|
||||
pictures.push_back(QString(picture->filename));
|
||||
pictures.push_back(picture);
|
||||
}
|
||||
|
||||
Q_FOREACH (const SPixmap &pixmap, QtConcurrent::blockingMapped<SPixmapList>(pictures, scaleImages))
|
||||
stringPixmapCache[pixmap.first].image = pixmap.second;
|
||||
QList<SPixmap> list = QtConcurrent::blockingMapped(pictures, scaleImages);
|
||||
Q_FOREACH (const SPixmap &pixmap, list)
|
||||
stringPixmapCache[pixmap.first->filename].image = pixmap.second;
|
||||
|
||||
beginInsertRows(QModelIndex(), 0, numberOfPictures - 1);
|
||||
endInsertRows();
|
||||
|
@ -121,5 +141,5 @@ DivePictureWidget::DivePictureWidget(QWidget *parent) : QListView(parent)
|
|||
void DivePictureWidget::doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
QString filePath = model()->data(index, Qt::DisplayPropertyRole).toString();
|
||||
emit photoDoubleClicked(filePath);
|
||||
emit photoDoubleClicked(localFilePath(filePath));
|
||||
}
|
||||
|
|
|
@ -5,11 +5,18 @@
|
|||
#include <QListView>
|
||||
#include <QThread>
|
||||
|
||||
typedef QPair<QString, QByteArray> SHashedFilename;
|
||||
|
||||
struct PhotoHelper {
|
||||
QImage image;
|
||||
int offsetSeconds;
|
||||
};
|
||||
|
||||
class SHashedImage : public QImage {
|
||||
public:
|
||||
SHashedImage(struct picture *picture);
|
||||
};
|
||||
|
||||
class DivePictureModel : public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#endif
|
||||
#include <QNetworkProxy>
|
||||
#include <QUndoStack>
|
||||
#include <qthelper.h>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
MainWindow *MainWindow::m_Instance = NULL;
|
||||
|
||||
|
@ -50,6 +52,7 @@ MainWindow::MainWindow() : QMainWindow(),
|
|||
Q_ASSERT_X(m_Instance == NULL, "MainWindow", "MainWindow recreated!");
|
||||
m_Instance = this;
|
||||
ui.setupUi(this);
|
||||
read_hashes();
|
||||
// Define the States of the Application Here, Currently the states are situations where the different
|
||||
// widgets will change on the mainwindow.
|
||||
|
||||
|
@ -201,6 +204,7 @@ MainWindow::MainWindow() : QMainWindow(),
|
|||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
write_hashes();
|
||||
m_Instance = NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue