diff options
-rw-r--r-- | dives/test43.xml | 29 | ||||
-rw-r--r-- | qt-ui/divepicturewidget.cpp | 60 | ||||
-rw-r--r-- | qt-ui/divepicturewidget.h | 13 | ||||
-rw-r--r-- | qthelper.cpp | 7 | ||||
-rw-r--r-- | qthelper.h | 1 |
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 |