| 
									
										
										
										
											2017-04-27 20:24:53 +02:00
										 |  |  | // SPDX-License-Identifier: GPL-2.0
 | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | #include "dive.h"
 | 
					
						
							|  |  |  | #include "metrics.h"
 | 
					
						
							|  |  |  | #include "divelist.h"
 | 
					
						
							|  |  |  | #include "qthelper.h"
 | 
					
						
							|  |  |  | #include "imagedownloader.h"
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2016-05-01 00:00:29 +02:00
										 |  |  | #include <QString>
 | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QtConcurrent>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | QUrl cloudImageURL(const char *hash) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return QUrl::fromUserInput(QString("https://cloud.subsurface-divelog.org/images/").append(hash)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | ImageDownloader::ImageDownloader(struct picture *pic) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	picture = pic; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  | ImageDownloader::~ImageDownloader() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	picture_free(picture); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | void ImageDownloader::load(bool fromHash){ | 
					
						
							|  |  |  | 	QUrl url; | 
					
						
							| 
									
										
										
										
											2016-03-15 22:45:17 +01:00
										 |  |  | 	loadFromHash = fromHash; | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 	if(fromHash) | 
					
						
							|  |  |  | 		url = cloudImageURL(picture->hash); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		url = QUrl::fromUserInput(QString(picture->filename)); | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2016-03-15 22:45:17 +01:00
										 |  |  | 	if (image.isNull()) { | 
					
						
							|  |  |  | 		if (loadFromHash) | 
					
						
							|  |  |  | 			load(false); | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2016-03-15 22:45:17 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 	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()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	reply->manager()->deleteLater(); | 
					
						
							|  |  |  | 	reply->deleteLater(); | 
					
						
							| 
									
										
										
										
											2016-03-15 22:45:17 +01:00
										 |  |  | 	// This should be called to make the picture actually show.
 | 
					
						
							| 
									
										
										
										
											2016-04-04 22:02:03 -07:00
										 |  |  | 	// Problem is DivePictureModel is not in core.
 | 
					
						
							| 
									
										
										
										
											2016-03-15 22:45:17 +01:00
										 |  |  | 	// Nevertheless, the image shows when the dive is selected the next time.
 | 
					
						
							|  |  |  | 	// DivePictureModel::instance()->updateDivePictures();
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 00:00:29 +02:00
										 |  |  | QSet<QString> queuedPictures; | 
					
						
							|  |  |  | QMutex pictureQueueMutex; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | void loadPicture(struct picture *picture, bool fromHash) | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  | 	if (!picture) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2016-05-01 00:00:29 +02:00
										 |  |  | 	QMutexLocker locker(&pictureQueueMutex); | 
					
						
							|  |  |  | 	if (queuedPictures.contains(QString(picture->filename))) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	queuedPictures.insert(QString(picture->filename)); | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 	ImageDownloader download(picture); | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 	download.load(fromHash); | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHashedImage::SHashedImage(struct picture *picture) : QImage() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-03-15 22:45:17 +01:00
										 |  |  | 	QUrl url = QUrl::fromUserInput(localFilePath(QString(picture->filename))); | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 	if(url.isLocalFile()) | 
					
						
							|  |  |  | 		load(url.toLocalFile()); | 
					
						
							|  |  |  | 	if (isNull()) { | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 		// This did not load anything. Let's try to get the image from other sources
 | 
					
						
							|  |  |  | 		// Let's try to load it locally via its hash
 | 
					
						
							|  |  |  | 		QString filename = fileFromHash(picture->hash); | 
					
						
							| 
									
										
										
										
											2016-12-15 14:31:20 +01:00
										 |  |  | 		if (filename.isNull()) | 
					
						
							|  |  |  | 			filename = QString(picture->filename); | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 		if (filename.isNull()) { | 
					
						
							|  |  |  | 			// That didn't produce a local filename.
 | 
					
						
							|  |  |  | 			// Try the cloud server
 | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  | 			QtConcurrent::run(loadPicture, clone_picture(picture), true); | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 			// Load locally from translated file name
 | 
					
						
							|  |  |  | 			load(filename); | 
					
						
							|  |  |  | 			if (!isNull()) { | 
					
						
							|  |  |  | 				// Make sure the hash still matches the image file
 | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  | 				QtConcurrent::run(updateHash, clone_picture(picture)); | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				// Interpret filename as URL
 | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  | 				QtConcurrent::run(loadPicture, clone_picture(picture), false); | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 		// We loaded successfully. Now, make sure hash is up to date.
 | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  | 		QtConcurrent::run(hashPicture, clone_picture(picture)); | 
					
						
							| 
									
										
										
										
											2015-11-06 10:39:59 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-01-09 16:29:49 +01:00
										 |  |  | 
 |