summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dives/test43.xml29
-rw-r--r--qt-ui/divepicturewidget.cpp60
-rw-r--r--qt-ui/divepicturewidget.h13
-rw-r--r--qthelper.cpp7
-rw-r--r--qthelper.h1
5 files changed, 107 insertions, 3 deletions
diff --git a/dives/test43.xml b/dives/test43.xml
new file mode 100644
index 000000000..9b75754bc
--- /dev/null
+++ b/dives/test43.xml
@@ -0,0 +1,29 @@
+<divelog program='subsurface' version='3'>
+<settings>
+<divecomputerid model='Suunto Vyper' deviceid='7fffffff' serial='00522075' firmware='0.0.33'/>
+<divecomputerid model='Suunto Vyper' deviceid='e9237b0a' nickname='Suunto Vyper (e9237b0a)'/>
+ <autogroup state='1' />
+</settings>
+<divesites>
+<site uuid='47b3e28c' gps='47.934500 11.334500'/>
+</divesites>
+<dives>
+<trip date='2012-01-08' time='15:30:03'>
+<dive number='1' divesiteid='47b3e28c' date='2012-01-08' time='15:30:03' duration='46:06 min'>
+ <notes>This is a dive with an image on a remote server.</notes>
+ <cylinder size='24.0 l' workpressure='232.0 bar' description='D12 232 bar' />
+ <divecomputer model='manually added dive' date='2014-01-09' time='14:22:03'>
+ <depth max='15.0 m' mean='13.698 m' />
+ <sample time='0:00 min' depth='0.0 m' />
+ <sample time='0:50 min' depth='15.0 m' />
+ <sample time='1:00 min' depth='15.0 m' />
+ <sample time='40:00 min' depth='15.0 m' />
+ <sample time='42:00 min' depth='5.0 m' />
+ <sample time='45:00 min' depth='5.0 m' />
+ <sample time='46:06 min' depth='0.0 m' />
+ </divecomputer>
+ <picture filename='http://euve10195.vserver.de/~robert/wreck.jpg' offset='+21:01 min' />
+</dive>
+</trip>
+</dives>
+</divelog>
diff --git a/qt-ui/divepicturewidget.cpp b/qt-ui/divepicturewidget.cpp
index 1baceeb7e..6de317778 100644
--- a/qt-ui/divepicturewidget.cpp
+++ b/qt-ui/divepicturewidget.cpp
@@ -2,21 +2,34 @@
#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(picture->filename)
{
if (isNull()) {
// Hash lookup.
load(fileFromHash(picture->hash));
- if (!isNull())
+ if (!isNull()) {
QtConcurrent::run(updateHash, picture);
+ } else {
+ QtConcurrent::run(loadPicuture, picture);
+ }
} else {
QByteArray hash = hashFile(QString(picture->filename));
free(picture->hash);
@@ -24,6 +37,45 @@ SHashedImage::SHashedImage(struct picture *picture) : QImage(picture->filename)
}
}
+ImageDownloader::ImageDownloader(struct picture *pic)
+{
+ picture = pic;
+}
+
+void ImageDownloader::load(){
+ QUrl url(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();
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(imageData);
+ QFile imageFile(QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first().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()
{
static DivePictureModel *self = new DivePictureModel();
@@ -47,8 +99,10 @@ SPixmap scaleImages(picturepointer picture)
ret.second = cache.value(picture->filename);
} else {
int dim = defaultIconMetrics().sz_pic;
- QImage p = SHashedImage(picture).scaled(dim, dim, Qt::KeepAspectRatio);
- cache.insert(picture->filename, 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;
diff --git a/qt-ui/divepicturewidget.h b/qt-ui/divepicturewidget.h
index 506f85bf8..2ce228daf 100644
--- a/qt-ui/divepicturewidget.h
+++ b/qt-ui/divepicturewidget.h
@@ -5,6 +5,7 @@
#include <QListView>
#include <QThread>
#include <QFuture>
+#include <QNetworkReply>
typedef QPair<QString, QByteArray> SHashedFilename;
@@ -18,6 +19,18 @@ public:
SHashedImage(struct picture *picture);
};
+class ImageDownloader : public QObject {
+ Q_OBJECT;
+public:
+ ImageDownloader(struct picture *picture);
+ void load();
+private:
+ struct picture *picture;
+ QNetworkAccessManager manager;
+private slots:
+ void saveImage(QNetworkReply *reply);
+};
+
class DivePictureModel : public QAbstractTableModel {
Q_OBJECT
public:
diff --git a/qthelper.cpp b/qthelper.cpp
index 6b2f76eba..8ca15f7aa 100644
--- a/qthelper.cpp
+++ b/qthelper.cpp
@@ -850,6 +850,13 @@ QByteArray hashFile(const QString filename)
return hash.result();
}
+void learnHash(struct picture *picture, QByteArray hash)
+{
+ free(picture->hash);
+ hashOf[QString(picture->filename)] = hash;
+ picture->hash = strdup(hash.toHex());
+}
+
QString localFilePath(const QString originalFilename)
{
return localFilenameOf[hashOf[originalFilename]];
diff --git a/qthelper.h b/qthelper.h
index 113aee370..b0765aeda 100644
--- a/qthelper.h
+++ b/qthelper.h
@@ -25,4 +25,5 @@ void learnImages(const QDir dir, int max_recursions, bool recursed);
void add_hash(const QString filename, QByteArray hash);
QString localFilePath(const QString originalFilename);
QString fileFromHash(char *hash);
+void learnHash(struct picture *picture, QByteArray hash);
#endif // QTHELPER_H