summaryrefslogtreecommitdiffstats
path: root/qt-ui/divepicturewidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt-ui/divepicturewidget.cpp')
-rw-r--r--qt-ui/divepicturewidget.cpp120
1 files changed, 107 insertions, 13 deletions
diff --git a/qt-ui/divepicturewidget.cpp b/qt-ui/divepicturewidget.cpp
index 92695b6a6..8c1cb3571 100644
--- a/qt-ui/divepicturewidget.cpp
+++ b/qt-ui/divepicturewidget.cpp
@@ -2,8 +2,90 @@
#include "metrics.h"
#include "dive.h"
#include "divelist.h"
+#include <unistd.h>
#include <QtConcurrentMap>
+#include <QtConcurrentRun>
+#include <QFuture>
#include <QDir>
+#include <QCryptographicHash>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <mainwindow.h>
+#include <qthelper.h>
+#include <QStandardPaths>
+
+void loadPicuture(struct picture *picture)
+{
+ ImageDownloader download(picture);
+ download.load();
+}
+
+SHashedImage::SHashedImage(struct picture *picture) : QImage()
+{
+ QUrl url = QUrl::fromUserInput(QString(picture->filename));
+ if(url.isLocalFile())
+ load(url.toLocalFile());
+ if (isNull()) {
+ // Hash lookup.
+ load(fileFromHash(picture->hash));
+ if (!isNull()) {
+ QtConcurrent::run(updateHash, picture);
+ } else {
+ QtConcurrent::run(loadPicuture, picture);
+ }
+ } else {
+ QByteArray hash = hashFile(url.toLocalFile());
+ free(picture->hash);
+ picture->hash = strdup(hash.toHex().data());
+ }
+}
+
+ImageDownloader::ImageDownloader(struct picture *pic)
+{
+ picture = pic;
+}
+
+void ImageDownloader::load(){
+ QUrl url = QUrl::fromUserInput(QString(picture->filename));
+ if (url.isValid()) {
+ QEventLoop loop;
+ QNetworkRequest request(url);
+ connect(&manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(saveImage(QNetworkReply *)));
+ QNetworkReply *reply = manager.get(request);
+ while (reply->isRunning()) {
+ loop.processEvents();
+ sleep(1);
+ }
+ }
+
+}
+
+void ImageDownloader::saveImage(QNetworkReply *reply)
+{
+ QByteArray imageData = reply->readAll();
+ QImage image = QImage();
+ image.loadFromData(imageData);
+ if (image.isNull())
+ return;
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(imageData);
+ QString path = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first();
+ QDir dir(path);
+ if (!dir.exists())
+ dir.mkpath(path);
+ QFile imageFile(path.append("/").append(hash.result().toHex()));
+ if (imageFile.open(QIODevice::WriteOnly)) {
+ QDataStream stream(&imageFile);
+ stream.writeRawData(imageData.data(), imageData.length());
+ imageFile.waitForBytesWritten(-1);
+ imageFile.close();
+ add_hash(imageFile.fileName(), hash.result());
+ learnHash(picture, hash.result());
+ DivePictureModel::instance()->updateDivePictures();
+ }
+ reply->manager()->deleteLater();
+ reply->deleteLater();
+}
DivePictureModel *DivePictureModel::instance()
{
@@ -15,25 +97,36 @@ 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);
+ if(!p.isNull())
+ p = p.scaled(dim, dim, Qt::KeepAspectRatio);
+ cache.insert(picture->filename, p);
ret.second = p;
}
return ret;
}
+void DivePictureModel::updateDivePicturesWhenDone(QList<QFuture<void> > futures)
+{
+ Q_FOREACH (QFuture<void> f, futures) {
+ f.waitForFinished();
+ }
+ updateDivePictures();
+}
+
void DivePictureModel::updateDivePictures()
{
if (numberOfPictures != 0) {
@@ -49,14 +142,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 +215,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));
}