| 
									
										
										
										
											2017-04-27 20:24:53 +02:00
										 |  |  |  | // SPDX-License-Identifier: GPL-2.0
 | 
					
						
							| 
									
										
										
										
											2013-06-17 15:58:26 -07:00
										 |  |  |  | #include "qthelper.h"
 | 
					
						
							| 
									
										
										
										
											2015-02-14 20:01:33 -08:00
										 |  |  |  | #include "helpers.h"
 | 
					
						
							| 
									
										
										
										
											2014-07-16 09:54:39 -07:00
										 |  |  |  | #include "gettextfromc.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-09 22:45:44 -07:00
										 |  |  |  | #include "statistics.h"
 | 
					
						
							| 
									
										
										
										
											2015-02-14 20:01:33 -08:00
										 |  |  |  | #include "membuffer.h"
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | #include "subsurfacesysinfo.h"
 | 
					
						
							|  |  |  |  | #include "version.h"
 | 
					
						
							|  |  |  |  | #include "divecomputer.h"
 | 
					
						
							|  |  |  |  | #include "time.h"
 | 
					
						
							|  |  |  |  | #include "gettextfromc.h"
 | 
					
						
							|  |  |  |  | #include <sys/time.h>
 | 
					
						
							| 
									
										
										
										
											2016-04-04 22:02:03 -07:00
										 |  |  |  | #include "exif.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-02 18:28:02 -03:00
										 |  |  |  | #include "file.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | #include "prefs-macros.h"
 | 
					
						
							| 
									
										
										
										
											2014-07-13 23:36:35 +02:00
										 |  |  |  | #include <QFile>
 | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | #include <QRegExp>
 | 
					
						
							| 
									
										
										
										
											2013-12-24 16:26:00 -08:00
										 |  |  |  | #include <QDir>
 | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | #include <QDebug>
 | 
					
						
							| 
									
										
										
										
											2014-04-17 12:21:39 -03:00
										 |  |  |  | #include <QSettings>
 | 
					
						
							| 
									
										
										
										
											2015-02-08 11:35:50 -08:00
										 |  |  |  | #include <QStandardPaths>
 | 
					
						
							| 
									
										
										
										
											2015-02-14 20:01:33 -08:00
										 |  |  |  | #include <QJsonDocument>
 | 
					
						
							|  |  |  |  | #include <QNetworkReply>
 | 
					
						
							|  |  |  |  | #include <QNetworkRequest>
 | 
					
						
							|  |  |  |  | #include <QNetworkAccessManager>
 | 
					
						
							| 
									
										
										
										
											2015-06-12 06:24:48 -07:00
										 |  |  |  | #include <QNetworkProxy>
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | #include <QDateTime>
 | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | #include <QImageReader>
 | 
					
						
							|  |  |  |  | #include <QtConcurrent>
 | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | #include <QFont>
 | 
					
						
							|  |  |  |  | #include <QApplication>
 | 
					
						
							| 
									
										
										
										
											2015-10-27 12:08:57 +01:00
										 |  |  |  | #include <QTextDocument>
 | 
					
						
							| 
									
										
										
										
											2015-02-14 20:01:33 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-17 12:21:39 -03:00
										 |  |  |  | #include <libxslt/documents.h>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | const char *existing_filename; | 
					
						
							|  |  |  |  | static QLocale loc; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-16 09:54:39 -07:00
										 |  |  |  | #define translate(_context, arg) trGettext(arg)
 | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | static const QString DEGREE_SIGNS("dD" UTF8_DEGREE); | 
					
						
							| 
									
										
										
										
											2013-06-17 15:58:26 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-04 21:39:33 +03:00
										 |  |  |  | QString weight_string(int weight_in_grams) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString str; | 
					
						
							|  |  |  |  | 	if (get_units()->weight == units::KG) { | 
					
						
							| 
									
										
										
										
											2017-08-07 13:07:36 +02:00
										 |  |  |  | 		double kg = (double) weight_in_grams / 1000.0; | 
					
						
							|  |  |  |  | 		str = QString("%1").arg(kg, 0, 'f', kg >= 20.0 ? 0 : 1); | 
					
						
							| 
									
										
										
										
											2013-10-04 21:39:33 +03:00
										 |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		double lbs = grams_to_lbs(weight_in_grams); | 
					
						
							| 
									
										
										
										
											2014-02-27 20:09:57 -08:00
										 |  |  |  | 		str = QString("%1").arg(lbs, 0, 'f', lbs >= 40.0 ? 0 : 1); | 
					
						
							| 
									
										
										
										
											2013-10-04 21:39:33 +03:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return (str); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 11:35:04 -07:00
										 |  |  |  | QString distance_string(int distanceInMeters) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString str; | 
					
						
							|  |  |  |  | 	if(get_units()->length == units::METERS) { | 
					
						
							|  |  |  |  | 		if (distanceInMeters >= 1000) | 
					
						
							|  |  |  |  | 			str = QString(translate("gettextFromC", "%1km")).arg(distanceInMeters / 1000); | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			str = QString(translate("gettextFromC", "%1m")).arg(distanceInMeters); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		double miles = m_to_mile(distanceInMeters); | 
					
						
							|  |  |  |  | 		if (miles >= 1.0) | 
					
						
							|  |  |  |  | 			str = QString(translate("gettextFromC", "%1mi")).arg((int)miles); | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			str = QString(translate("gettextFromC", "%1yd")).arg((int)(miles * 1760)); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return str; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-14 17:50:48 -08:00
										 |  |  |  | extern "C" const char *printGPSCoords(int lat, int lon) | 
					
						
							| 
									
										
										
										
											2014-05-12 13:19:57 -03:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	unsigned int latdeg, londeg; | 
					
						
							|  |  |  |  | 	unsigned int latmin, lonmin; | 
					
						
							|  |  |  |  | 	double latsec, lonsec; | 
					
						
							|  |  |  |  | 	QString lath, lonh, result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (!lat && !lon) | 
					
						
							| 
									
										
										
										
											2015-02-14 17:50:48 -08:00
										 |  |  |  | 		return strdup(""); | 
					
						
							| 
									
										
										
										
											2014-05-12 13:19:57 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-20 12:25:46 +02:00
										 |  |  |  | 	if (prefs.coordinates_traditional) { | 
					
						
							|  |  |  |  | 		lath = lat >= 0 ? translate("gettextFromC", "N") : translate("gettextFromC", "S"); | 
					
						
							|  |  |  |  | 		lonh = lon >= 0 ? translate("gettextFromC", "E") : translate("gettextFromC", "W"); | 
					
						
							|  |  |  |  | 		lat = abs(lat); | 
					
						
							|  |  |  |  | 		lon = abs(lon); | 
					
						
							|  |  |  |  | 		latdeg = lat / 1000000U; | 
					
						
							|  |  |  |  | 		londeg = lon / 1000000U; | 
					
						
							|  |  |  |  | 		latmin = (lat % 1000000U) * 60U; | 
					
						
							|  |  |  |  | 		lonmin = (lon % 1000000U) * 60U; | 
					
						
							|  |  |  |  | 		latsec = (latmin % 1000000) * 60; | 
					
						
							|  |  |  |  | 		lonsec = (lonmin % 1000000) * 60; | 
					
						
							|  |  |  |  | 		result.sprintf("%u%s%02d\'%06.3f\"%s %u%s%02d\'%06.3f\"%s", | 
					
						
							|  |  |  |  | 			       latdeg, UTF8_DEGREE, latmin / 1000000, latsec / 1000000, lath.toUtf8().data(), | 
					
						
							|  |  |  |  | 			       londeg, UTF8_DEGREE, lonmin / 1000000, lonsec / 1000000, lonh.toUtf8().data()); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		result.sprintf("%f %f", (double) lat / 1000000.0, (double) lon / 1000000.0); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-14 17:50:48 -08:00
										 |  |  |  | 	return strdup(result.toUtf8().data()); | 
					
						
							| 
									
										
										
										
											2014-05-12 13:19:57 -03:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | /**
 | 
					
						
							|  |  |  |  | * Try to parse in a generic manner a coordinate. | 
					
						
							|  |  |  |  | */ | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | static bool parseCoord(const QString& txt, int& pos, const QString& positives, | 
					
						
							|  |  |  |  | 		       const QString& negatives, const QString& others, | 
					
						
							|  |  |  |  | 		       double& value) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	bool numberDefined = false, degreesDefined = false, | 
					
						
							|  |  |  |  | 		minutesDefined = false, secondsDefined = false; | 
					
						
							|  |  |  |  | 	double number = 0.0; | 
					
						
							|  |  |  |  | 	int posBeforeNumber = pos; | 
					
						
							|  |  |  |  | 	int sign = 0; | 
					
						
							|  |  |  |  | 	value = 0.0; | 
					
						
							|  |  |  |  | 	while (pos < txt.size()) { | 
					
						
							|  |  |  |  | 		if (txt[pos].isDigit()) { | 
					
						
							|  |  |  |  | 			if (numberDefined) | 
					
						
							|  |  |  |  | 				return false; | 
					
						
							|  |  |  |  | 			QRegExp numberRe("(\\d+(?:[\\.,]\\d+)?).*"); | 
					
						
							|  |  |  |  | 			if (!numberRe.exactMatch(txt.mid(pos))) | 
					
						
							|  |  |  |  | 				return false; | 
					
						
							|  |  |  |  | 			number = numberRe.cap(1).toDouble(); | 
					
						
							|  |  |  |  | 			numberDefined = true; | 
					
						
							|  |  |  |  | 			posBeforeNumber = pos; | 
					
						
							|  |  |  |  | 			pos += numberRe.cap(1).size() - 1; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 		} else if (positives.indexOf(txt[pos]) >= 0) { | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 			if (sign != 0) | 
					
						
							|  |  |  |  | 				return false; | 
					
						
							|  |  |  |  | 			sign = 1; | 
					
						
							|  |  |  |  | 			if (degreesDefined || numberDefined) { | 
					
						
							|  |  |  |  | 				//sign after the degrees =>
 | 
					
						
							|  |  |  |  | 				//at the end of the coordinate
 | 
					
						
							|  |  |  |  | 				++pos; | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 		} else if (negatives.indexOf(txt[pos]) >= 0) { | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 			if (sign != 0) { | 
					
						
							|  |  |  |  | 				if (others.indexOf(txt[pos]) >= 0) | 
					
						
							|  |  |  |  | 					//special case for the '-' sign => next coordinate
 | 
					
						
							|  |  |  |  | 					break; | 
					
						
							|  |  |  |  | 				return false; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			sign = -1; | 
					
						
							|  |  |  |  | 			if (degreesDefined || numberDefined) { | 
					
						
							|  |  |  |  | 				//sign after the degrees =>
 | 
					
						
							|  |  |  |  | 				//at the end of the coordinate
 | 
					
						
							|  |  |  |  | 				++pos; | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 		} else if (others.indexOf(txt[pos]) >= 0) { | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 			//we are at the next coordinate.
 | 
					
						
							|  |  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 		} else if (DEGREE_SIGNS.indexOf(txt[pos]) >= 0 || | 
					
						
							|  |  |  |  | 			   (txt[pos].isSpace() && !degreesDefined && numberDefined)) { | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 			if (!numberDefined) | 
					
						
							|  |  |  |  | 				return false; | 
					
						
							|  |  |  |  | 			if (degreesDefined) { | 
					
						
							|  |  |  |  | 				//next coordinate => need to put back the number
 | 
					
						
							|  |  |  |  | 				pos = posBeforeNumber; | 
					
						
							|  |  |  |  | 				numberDefined = false; | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			value += number; | 
					
						
							|  |  |  |  | 			numberDefined = false; | 
					
						
							|  |  |  |  | 			degreesDefined = true; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 		} else if (txt[pos] == '\'' || (txt[pos].isSpace() && !minutesDefined && numberDefined)) { | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 			if (!numberDefined || minutesDefined) | 
					
						
							|  |  |  |  | 				return false; | 
					
						
							|  |  |  |  | 			value += number / 60.0; | 
					
						
							|  |  |  |  | 			numberDefined = false; | 
					
						
							|  |  |  |  | 			minutesDefined = true; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 		} else if (txt[pos] == '"' || (txt[pos].isSpace() && !secondsDefined && numberDefined)) { | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 			if (!numberDefined || secondsDefined) | 
					
						
							|  |  |  |  | 				return false; | 
					
						
							|  |  |  |  | 			value += number / 3600.0; | 
					
						
							|  |  |  |  | 			numberDefined = false; | 
					
						
							|  |  |  |  | 			secondsDefined = true; | 
					
						
							| 
									
										
										
										
											2015-10-07 17:19:58 +01:00
										 |  |  |  | 		} else if ((numberDefined || minutesDefined || secondsDefined) && | 
					
						
							|  |  |  |  | 			   (txt[pos] == ',' || txt[pos] == ';')) { | 
					
						
							|  |  |  |  | 			// next coordinate coming up
 | 
					
						
							|  |  |  |  | 			// eat the ',' and any subsequent white space
 | 
					
						
							| 
									
										
										
										
											2017-01-14 09:09:58 -08:00
										 |  |  |  | 			while (++pos < txt.size() && txt[pos].isSpace()) | 
					
						
							| 
									
										
										
										
											2015-10-07 17:19:58 +01:00
										 |  |  |  | 				/* nothing */ ; | 
					
						
							|  |  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			return false; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		++pos; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if (!degreesDefined && numberDefined) { | 
					
						
							|  |  |  |  | 		value = number; //just a single number => degrees
 | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 	} else if (!minutesDefined && numberDefined) { | 
					
						
							|  |  |  |  | 		value += number / 60.0; | 
					
						
							|  |  |  |  | 	} else if (!secondsDefined && numberDefined) { | 
					
						
							|  |  |  |  | 		value += number / 3600.0; | 
					
						
							|  |  |  |  | 	} else if (numberDefined) { | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 	if (sign == -1) value *= -1.0; | 
					
						
							|  |  |  |  | 	return true; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | /**
 | 
					
						
							|  |  |  |  | * Parse special coordinate formats that cannot be handled by parseCoord. | 
					
						
							|  |  |  |  | */ | 
					
						
							|  |  |  |  | static bool parseSpecialCoords(const QString& txt, double& latitude, double& longitude) { | 
					
						
							| 
									
										
										
										
											2015-05-24 22:59:00 +02:00
										 |  |  |  | 	QRegExp xmlFormat("(-?\\d+(?:\\.\\d+)?),?\\s+(-?\\d+(?:\\.\\d+)?)"); | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 	if (xmlFormat.exactMatch(txt)) { | 
					
						
							|  |  |  |  | 		latitude = xmlFormat.cap(1).toDouble(); | 
					
						
							|  |  |  |  | 		longitude = xmlFormat.cap(2).toDouble(); | 
					
						
							|  |  |  |  | 		return true; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-27 20:09:57 -08:00
										 |  |  |  | bool parseGpsText(const QString &gps_text, double *latitude, double *longitude) | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 	static const QString POS_LAT = QString("+N") + translate("gettextFromC", "N"); | 
					
						
							|  |  |  |  | 	static const QString NEG_LAT = QString("-S") + translate("gettextFromC", "S"); | 
					
						
							|  |  |  |  | 	static const QString POS_LON = QString("+E") + translate("gettextFromC", "E"); | 
					
						
							|  |  |  |  | 	static const QString NEG_LON = QString("-W") + translate("gettextFromC", "W"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	//remove the useless spaces (but keep the ones separating numbers)
 | 
					
						
							|  |  |  |  | 	static const QRegExp SPACE_CLEANER("\\s*([" + POS_LAT + NEG_LAT + POS_LON + | 
					
						
							|  |  |  |  | 		NEG_LON + DEGREE_SIGNS + "'\"\\s])\\s*"); | 
					
						
							|  |  |  |  | 	const QString normalized = gps_text.trimmed().toUpper().replace(SPACE_CLEANER, "\\1"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (normalized.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | 		*latitude = 0.0; | 
					
						
							|  |  |  |  | 		*longitude = 0.0; | 
					
						
							|  |  |  |  | 		return true; | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 	if (parseSpecialCoords(normalized, *latitude, *longitude)) | 
					
						
							|  |  |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2015-02-04 09:30:24 +01:00
										 |  |  |  | 	int pos = 0; | 
					
						
							| 
									
										
										
										
											2015-02-23 13:38:41 +01:00
										 |  |  |  | 	return parseCoord(normalized, pos, POS_LAT, NEG_LAT, POS_LON + NEG_LON, *latitude) && | 
					
						
							|  |  |  |  | 		parseCoord(normalized, pos, POS_LON, NEG_LON, "", *longitude) && | 
					
						
							|  |  |  |  | 		pos == normalized.size(); | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-12 22:24:12 -08:00
										 |  |  |  | #if 0 // we'll need something like this for the dive site management, eventually
 | 
					
						
							| 
									
										
										
										
											2014-06-02 18:13:50 -07:00
										 |  |  |  | bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out) | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	double latitude, longitude; | 
					
						
							|  |  |  |  | 	int latudeg, longudeg; | 
					
						
							| 
									
										
										
										
											2014-06-02 18:13:50 -07:00
										 |  |  |  | 	bool ignore; | 
					
						
							|  |  |  |  | 	bool *parsed = parsed_out ?: &ignore; | 
					
						
							| 
									
										
										
										
											2014-07-30 09:46:21 -07:00
										 |  |  |  | 	*parsed = true; | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* if we have a master and the dive's gps address is different from it,
 | 
					
						
							|  |  |  |  | 	 * don't change the dive */ | 
					
						
							|  |  |  |  | 	if (master && (master->latitude.udeg != dive->latitude.udeg || | 
					
						
							|  |  |  |  | 		       master->longitude.udeg != dive->longitude.udeg)) | 
					
						
							|  |  |  |  | 		return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-23 14:56:40 -08:00
										 |  |  |  | 	if (!(*parsed = parseGpsText(gps_text, &latitude, &longitude))) | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | 		return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 	latudeg = lrint(1000000 * latitude); | 
					
						
							|  |  |  |  | 	longudeg = lrint(1000000 * longitude); | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* if dive gps didn't change, nothing changed */ | 
					
						
							|  |  |  |  | 	if (dive->latitude.udeg == latudeg && dive->longitude.udeg == longudeg) | 
					
						
							|  |  |  |  | 		return false; | 
					
						
							|  |  |  |  | 	/* ok, update the dive and mark things changed */ | 
					
						
							|  |  |  |  | 	dive->latitude.udeg = latudeg; | 
					
						
							|  |  |  |  | 	dive->longitude.udeg = longudeg; | 
					
						
							|  |  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2013-11-26 15:44:18 -02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-12 22:24:12 -08:00
										 |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-27 20:09:57 -08:00
										 |  |  |  | QList<int> getDivesInTrip(dive_trip_t *trip) | 
					
						
							| 
									
										
										
										
											2013-11-26 15:44:18 -02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	QList<int> ret; | 
					
						
							| 
									
										
										
										
											2014-05-10 22:12:40 -03:00
										 |  |  |  | 	int i; | 
					
						
							|  |  |  |  | 	struct dive *d; | 
					
						
							|  |  |  |  | 	for_each_dive (i, d) { | 
					
						
							| 
									
										
										
										
											2014-02-27 20:09:57 -08:00
										 |  |  |  | 		if (d->divetrip == trip) { | 
					
						
							| 
									
										
										
										
											2013-11-26 15:44:18 -02:00
										 |  |  |  | 			ret.push_back(get_divenr(d)); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2013-10-05 09:48:26 -07:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-01-07 09:30:01 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // we need this to be uniq, but also make sure
 | 
					
						
							|  |  |  |  | // it doesn't change during the life time of a Subsurface session
 | 
					
						
							|  |  |  |  | // oh, and it has no meaning whatsoever - that's why we have the
 | 
					
						
							|  |  |  |  | // silly initial number and increment by 3 :-)
 | 
					
						
							| 
									
										
										
										
											2014-05-10 22:18:37 -03:00
										 |  |  |  | int dive_getUniqID(struct dive *d) | 
					
						
							| 
									
										
										
										
											2014-01-07 09:30:01 +08:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	static QSet<int> ids; | 
					
						
							|  |  |  |  | 	static int maxId = 83529; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	int id = d->id; | 
					
						
							|  |  |  |  | 	if (id) { | 
					
						
							|  |  |  |  | 		if (!ids.contains(id)) { | 
					
						
							|  |  |  |  | 			qDebug() << "WTF - only I am allowed to create IDs"; | 
					
						
							|  |  |  |  | 			ids.insert(id); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return id; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	maxId += 3; | 
					
						
							|  |  |  |  | 	id = maxId; | 
					
						
							|  |  |  |  | 	Q_ASSERT(!ids.contains(id)); | 
					
						
							|  |  |  |  | 	ids.insert(id); | 
					
						
							|  |  |  |  | 	return id; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-04-17 12:21:39 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static xmlDocPtr get_stylesheet_doc(const xmlChar *uri, xmlDictPtr, int, void *, xsltLoadType) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QFile f(QLatin1String(":/xslt/") + (const char *)uri); | 
					
						
							| 
									
										
										
										
											2015-03-14 18:07:20 -07:00
										 |  |  |  | 	if (!f.open(QIODevice::ReadOnly)) { | 
					
						
							|  |  |  |  | 		if (verbose > 0) { | 
					
						
							| 
									
										
										
										
											2016-12-27 13:31:30 +01:00
										 |  |  |  | 			qDebug() << "cannot open stylesheet" << QLatin1String(":/xslt/") + (const char *)uri << f.errorString(); | 
					
						
							| 
									
										
										
										
											2015-03-14 18:07:20 -07:00
										 |  |  |  | 			return NULL; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-04-17 12:21:39 -03:00
										 |  |  |  | 	/* Load and parse the data */ | 
					
						
							|  |  |  |  | 	QByteArray source = f.readAll(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xmlDocPtr doc = xmlParseMemory(source, source.size()); | 
					
						
							|  |  |  |  | 	return doc; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" xsltStylesheetPtr get_stylesheet(const char *name) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	// this needs to be done only once, but doesn't hurt to run every time
 | 
					
						
							|  |  |  |  | 	xsltSetLoaderFunc(get_stylesheet_doc); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// get main document:
 | 
					
						
							|  |  |  |  | 	xmlDocPtr doc = get_stylesheet_doc((const xmlChar *)name, NULL, 0, NULL, XSLT_LOAD_START); | 
					
						
							|  |  |  |  | 	if (!doc) | 
					
						
							|  |  |  |  | 		return NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	//	xsltSetGenericErrorFunc(stderr, NULL);
 | 
					
						
							|  |  |  |  | 	xsltStylesheetPtr xslt = xsltParseStylesheetDoc(doc); | 
					
						
							|  |  |  |  | 	if (!xslt) { | 
					
						
							|  |  |  |  | 		xmlFreeDoc(doc); | 
					
						
							|  |  |  |  | 		return NULL; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return xslt; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-06-02 18:28:02 -03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-09 22:45:44 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 10:00:16 +01:00
										 |  |  |  | extern "C" timestamp_t picture_get_timestamp(const char *filename) | 
					
						
							| 
									
										
										
										
											2015-03-14 15:35:47 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-02-19 10:27:27 +01:00
										 |  |  |  | 	easyexif::EXIFInfo exif; | 
					
						
							| 
									
										
										
										
											2015-03-14 15:35:47 +01:00
										 |  |  |  | 	memblock mem; | 
					
						
							|  |  |  |  | 	int retval; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-24 17:10:55 +02:00
										 |  |  |  | 	// filename might not be the actual filename, so let's go via the hash.
 | 
					
						
							|  |  |  |  | 	if (readfile(localFilePath(QString(filename)).toUtf8().data(), &mem) <= 0) | 
					
						
							| 
									
										
										
										
											2015-04-24 14:19:41 +02:00
										 |  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2015-03-14 15:35:47 +01:00
										 |  |  |  | 	retval = exif.parseFrom((const unsigned char *)mem.buffer, (unsigned)mem.size); | 
					
						
							|  |  |  |  | 	free(mem.buffer); | 
					
						
							|  |  |  |  | 	if (retval != PARSE_EXIF_SUCCESS) | 
					
						
							| 
									
										
										
										
											2015-04-24 14:19:41 +02:00
										 |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 	return exif.epoch(); | 
					
						
							| 
									
										
										
										
											2015-03-14 15:35:47 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-23 05:08:35 -07:00
										 |  |  |  | extern "C" char *move_away(const char *old_path) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (verbose > 1) | 
					
						
							|  |  |  |  | 		qDebug() << "move away" << old_path; | 
					
						
							| 
									
										
										
										
											2015-09-26 12:34:38 -04:00
										 |  |  |  | 	QDir oldDir(old_path); | 
					
						
							|  |  |  |  | 	QDir newDir; | 
					
						
							| 
									
										
										
										
											2015-09-23 05:08:35 -07:00
										 |  |  |  | 	QString newPath; | 
					
						
							|  |  |  |  | 	int i = 0; | 
					
						
							|  |  |  |  | 	do { | 
					
						
							|  |  |  |  | 		newPath = QString(old_path) + QString(".%1").arg(++i); | 
					
						
							| 
									
										
										
										
											2015-09-26 12:34:38 -04:00
										 |  |  |  | 		newDir.setPath(newPath); | 
					
						
							|  |  |  |  | 	} while(newDir.exists()); | 
					
						
							| 
									
										
										
										
											2015-09-23 05:08:35 -07:00
										 |  |  |  | 	if (verbose > 1) | 
					
						
							|  |  |  |  | 		qDebug() << "renaming to" << newPath; | 
					
						
							| 
									
										
										
										
											2015-09-26 12:34:38 -04:00
										 |  |  |  | 	if (!oldDir.rename(old_path, newPath)) { | 
					
						
							|  |  |  |  | 		if (verbose) | 
					
						
							|  |  |  |  | 			qDebug() << "rename of" << old_path << "to" << newPath << "failed"; | 
					
						
							| 
									
										
										
										
											2015-09-26 12:35:21 -04:00
										 |  |  |  | 		// this next one we only try on Windows... if we are on a different platform
 | 
					
						
							|  |  |  |  | 		// we simply give up and return an empty string
 | 
					
						
							|  |  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |  | 		if (subsurface_dir_rename(old_path, qPrintable(newPath)) == 0) | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 			return strdup(""); | 
					
						
							| 
									
										
										
										
											2015-09-23 05:08:35 -07:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return strdup(qPrintable(newPath)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-17 10:42:47 -07:00
										 |  |  |  | extern "C" char *get_file_name(const char *fileName) | 
					
						
							| 
									
										
										
										
											2014-07-13 23:36:35 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-17 10:42:47 -07:00
										 |  |  |  | 	QFileInfo fileInfo(fileName); | 
					
						
							|  |  |  |  | 	return strdup(fileInfo.fileName().toUtf8()); | 
					
						
							| 
									
										
										
										
											2014-07-13 23:36:35 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-21 11:55:40 -07:00
										 |  |  |  | extern "C" void copy_image_and_overwrite(const char *cfileName, const char *path, const char *cnewName) | 
					
						
							| 
									
										
										
										
											2014-07-13 23:36:35 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-21 11:55:40 -07:00
										 |  |  |  | 	QString fileName(cfileName); | 
					
						
							|  |  |  |  | 	QString newName(path); | 
					
						
							|  |  |  |  | 	newName += cnewName; | 
					
						
							| 
									
										
										
										
											2014-07-13 23:36:35 +02:00
										 |  |  |  | 	QFile file(newName); | 
					
						
							|  |  |  |  | 	if (file.exists()) | 
					
						
							|  |  |  |  | 		file.remove(); | 
					
						
							| 
									
										
										
										
											2015-06-21 07:43:35 -07:00
										 |  |  |  | 	if (!QFile::copy(fileName, newName)) | 
					
						
							|  |  |  |  | 		qDebug() << "copy of" << fileName << "to" << newName << "failed"; | 
					
						
							| 
									
										
										
										
											2014-07-13 23:36:35 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-12 16:01:58 -08:00
										 |  |  |  | extern "C" bool string_sequence_contains(const char *string_sequence, const char *text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (same_string(text, "") || same_string(string_sequence, "")) | 
					
						
							|  |  |  |  | 		return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	QString stringSequence(string_sequence); | 
					
						
							|  |  |  |  | 	QStringList strings = stringSequence.split(",", QString::SkipEmptyParts); | 
					
						
							| 
									
										
										
										
											2014-11-13 17:36:49 -02:00
										 |  |  |  | 	Q_FOREACH (const QString& string, strings) { | 
					
						
							| 
									
										
										
										
											2014-11-12 16:01:58 -08:00
										 |  |  |  | 		if (string.trimmed().compare(QString(text).trimmed(), Qt::CaseInsensitive) == 0) | 
					
						
							|  |  |  |  | 			return true; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-09 22:45:44 -07:00
										 |  |  |  | static bool lessThan(const QPair<QString, int> &a, const QPair<QString, int> &b) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return a.second < b.second; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void selectedDivesGasUsed(QVector<QPair<QString, int> > &gasUsedOrdered) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int i, j; | 
					
						
							|  |  |  |  | 	struct dive *d; | 
					
						
							|  |  |  |  | 	QMap<QString, int> gasUsed; | 
					
						
							|  |  |  |  | 	for_each_dive (i, d) { | 
					
						
							|  |  |  |  | 		if (!d->selected) | 
					
						
							|  |  |  |  | 			continue; | 
					
						
							|  |  |  |  | 		volume_t diveGases[MAX_CYLINDERS] = {}; | 
					
						
							|  |  |  |  | 		get_gas_used(d, diveGases); | 
					
						
							|  |  |  |  | 		for (j = 0; j < MAX_CYLINDERS; j++) | 
					
						
							|  |  |  |  | 			if (diveGases[j].mliter) { | 
					
						
							|  |  |  |  | 				QString gasName = gasname(&d->cylinder[j].gasmix); | 
					
						
							|  |  |  |  | 				gasUsed[gasName] += diveGases[j].mliter; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-11-13 17:37:54 -02:00
										 |  |  |  | 	Q_FOREACH(const QString& gas, gasUsed.keys()) { | 
					
						
							| 
									
										
										
										
											2014-06-10 13:38:51 -07:00
										 |  |  |  | 		gasUsedOrdered.append(qMakePair(gas, gasUsed[gas])); | 
					
						
							| 
									
										
										
										
											2014-06-09 22:45:44 -07:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	qSort(gasUsedOrdered.begin(), gasUsedOrdered.end(), lessThan); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-14 20:01:33 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | QString getUserAgent() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString arch; | 
					
						
							|  |  |  |  | 	// fill in the system data - use ':' as separator
 | 
					
						
							|  |  |  |  | 	// replace all other ':' with ' ' so that this is easy to parse
 | 
					
						
							| 
									
										
										
										
											2015-11-18 14:44:07 -08:00
										 |  |  |  | #ifdef SUBSURFACE_MOBILE
 | 
					
						
							| 
									
										
										
										
											2016-03-05 12:53:38 -08:00
										 |  |  |  | 	QString userAgent = QString("Subsurface-mobile:%1(%2):").arg(subsurface_mobile_version()).arg(subsurface_canonical_version()); | 
					
						
							| 
									
										
										
										
											2015-11-18 14:44:07 -08:00
										 |  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-12-20 07:59:50 -08:00
										 |  |  |  | 	QString userAgent = QString("Subsurface:%1:").arg(subsurface_canonical_version()); | 
					
						
							| 
									
										
										
										
											2015-11-18 14:44:07 -08:00
										 |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	userAgent.append(SubsurfaceSysInfo::prettyOsName().replace(':', ' ') + ":"); | 
					
						
							|  |  |  |  | 	arch = SubsurfaceSysInfo::buildCpuArchitecture().replace(':', ' '); | 
					
						
							|  |  |  |  | 	userAgent.append(arch); | 
					
						
							|  |  |  |  | 	if (arch == "i386") | 
					
						
							|  |  |  |  | 		userAgent.append("/" + SubsurfaceSysInfo::currentCpuArchitecture()); | 
					
						
							|  |  |  |  | 	userAgent.append(":" + uiLanguage(NULL)); | 
					
						
							|  |  |  |  | 	return userAgent; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-20 07:59:50 -08:00
										 |  |  |  | extern "C" const char *subsurface_user_agent() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	static QString uA = getUserAgent(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return strdup(qPrintable(uA)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-27 22:13:33 -03:00
										 |  |  |  | /* TOOD: Move this to SettingsObjectWrapper, and also fix this complexity.
 | 
					
						
							|  |  |  |  |  * gezus. | 
					
						
							|  |  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | QString uiLanguage(QLocale *callerLoc) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-29 16:57:43 -07:00
										 |  |  |  | 	QString shortDateFormat; | 
					
						
							|  |  |  |  | 	QString dateFormat; | 
					
						
							|  |  |  |  | 	QString timeFormat; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	QSettings s; | 
					
						
							| 
									
										
										
										
											2015-11-02 11:32:46 -08:00
										 |  |  |  | 	QVariant v; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	s.beginGroup("Language"); | 
					
						
							| 
									
										
										
										
											2016-08-27 22:13:33 -03:00
										 |  |  |  | 	GET_BOOL("UseSystemLanguage", locale.use_system_language); | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 12:38:23 -07:00
										 |  |  |  | 	if (!prefs.locale.use_system_language) { | 
					
						
							| 
									
										
										
										
											2016-09-22 22:07:42 -07:00
										 |  |  |  | 		loc = QLocale(s.value("UiLangLocale", QLocale().uiLanguages().first()).toString()); | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		loc = QLocale(QLocale().uiLanguages().first()); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-01-05 23:41:30 -08:00
										 |  |  |  | 	QStringList languages = loc.uiLanguages(); | 
					
						
							|  |  |  |  | 	QString uiLang; | 
					
						
							|  |  |  |  | 	if (languages[0].contains('-')) | 
					
						
							|  |  |  |  | 		uiLang = languages[0]; | 
					
						
							|  |  |  |  | 	else if (languages.count() > 1 && languages[1].contains('-')) | 
					
						
							|  |  |  |  | 		uiLang = languages[1]; | 
					
						
							|  |  |  |  | 	else if (languages.count() > 2 && languages[2].contains('-')) | 
					
						
							|  |  |  |  | 		uiLang = languages[2]; | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		uiLang = languages[0]; | 
					
						
							| 
									
										
										
										
											2016-09-20 12:40:30 -07:00
										 |  |  |  | 	prefs.locale.lang_locale = copy_string(qPrintable(uiLang)); | 
					
						
							| 
									
										
										
										
											2015-11-02 11:32:46 -08:00
										 |  |  |  | 	GET_BOOL("time_format_override", time_format_override); | 
					
						
							|  |  |  |  | 	GET_BOOL("date_format_override", date_format_override); | 
					
						
							|  |  |  |  | 	GET_TXT("time_format", time_format); | 
					
						
							|  |  |  |  | 	GET_TXT("date_format", date_format); | 
					
						
							|  |  |  |  | 	GET_TXT("date_format_short", date_format_short); | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// there's a stupid Qt bug on MacOS where uiLanguages doesn't give us the country info
 | 
					
						
							|  |  |  |  | 	if (!uiLang.contains('-') && uiLang != loc.bcp47Name()) { | 
					
						
							|  |  |  |  | 		QLocale loc2(loc.bcp47Name()); | 
					
						
							|  |  |  |  | 		loc = loc2; | 
					
						
							| 
									
										
										
										
											2016-01-05 23:41:30 -08:00
										 |  |  |  | 		QStringList languages = loc2.uiLanguages(); | 
					
						
							|  |  |  |  | 		if (languages[0].contains('-')) | 
					
						
							|  |  |  |  | 			uiLang = languages[0]; | 
					
						
							|  |  |  |  | 		else if (languages.count() > 1 && languages[1].contains('-')) | 
					
						
							|  |  |  |  | 			uiLang = languages[1]; | 
					
						
							|  |  |  |  | 		else if (languages.count() > 2 && languages[2].contains('-')) | 
					
						
							|  |  |  |  | 			uiLang = languages[2]; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if (callerLoc) | 
					
						
							|  |  |  |  | 		*callerLoc = loc; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-02 11:32:46 -08:00
										 |  |  |  | 	if (!prefs.date_format_override || same_string(prefs.date_format_short, "") || same_string(prefs.date_format, "")) { | 
					
						
							|  |  |  |  | 		// derive our standard date format from what the locale gives us
 | 
					
						
							|  |  |  |  | 		// the short format is fine
 | 
					
						
							|  |  |  |  | 		// the long format uses long weekday and month names, so replace those with the short ones
 | 
					
						
							|  |  |  |  | 		// for time we don't want the time zone designator and don't want leading zeroes on the hours
 | 
					
						
							|  |  |  |  | 		shortDateFormat = loc.dateFormat(QLocale::ShortFormat); | 
					
						
							|  |  |  |  | 		dateFormat = loc.dateFormat(QLocale::LongFormat); | 
					
						
							|  |  |  |  | 		dateFormat.replace("dddd,", "ddd").replace("dddd", "ddd").replace("MMMM", "MMM"); | 
					
						
							|  |  |  |  | 		// special hack for Swedish as our switching from long weekday names to short weekday names
 | 
					
						
							|  |  |  |  | 		// messes things up there
 | 
					
						
							|  |  |  |  | 		dateFormat.replace("'en' 'den' d:'e'", " d"); | 
					
						
							|  |  |  |  | 		if (!prefs.date_format_override || same_string(prefs.date_format, "")) { | 
					
						
							| 
									
										
										
										
											2017-11-18 19:57:50 +01:00
										 |  |  |  | 			free((void *)prefs.date_format); | 
					
						
							| 
									
										
										
										
											2015-11-02 11:32:46 -08:00
										 |  |  |  | 			prefs.date_format = strdup(qPrintable(dateFormat)); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if (!prefs.date_format_override || same_string(prefs.date_format_short, "")) { | 
					
						
							| 
									
										
										
										
											2017-11-18 19:57:50 +01:00
										 |  |  |  | 			free((void *)prefs.date_format_short); | 
					
						
							| 
									
										
										
										
											2015-11-02 11:32:46 -08:00
										 |  |  |  | 			prefs.date_format_short = strdup(qPrintable(shortDateFormat)); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if (!prefs.time_format_override || same_string(prefs.time_format, "")) { | 
					
						
							|  |  |  |  | 		timeFormat = loc.timeFormat(); | 
					
						
							|  |  |  |  | 		timeFormat.replace("(t)", "").replace(" t", "").replace("t", "").replace("hh", "h").replace("HH", "H").replace("'kl'.", ""); | 
					
						
							|  |  |  |  | 		timeFormat.replace(".ss", "").replace(":ss", "").replace("ss", ""); | 
					
						
							| 
									
										
										
										
											2017-11-18 19:57:50 +01:00
										 |  |  |  | 		free((void *)prefs.time_format); | 
					
						
							| 
									
										
										
										
											2015-11-02 11:32:46 -08:00
										 |  |  |  | 		prefs.time_format = strdup(qPrintable(timeFormat)); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	return uiLang; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QLocale getLocale() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return loc; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void set_filename(const char *filename, bool force) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (!force && existing_filename) | 
					
						
							|  |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	free((void *)existing_filename); | 
					
						
							|  |  |  |  | 	if (filename) | 
					
						
							|  |  |  |  | 		existing_filename = strdup(filename); | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		existing_filename = NULL; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const QString get_dc_nickname(const char *model, uint32_t deviceid) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const DiveComputerNode *existNode = dcList.getExact(model, deviceid); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (existNode && !existNode->nickName.isEmpty()) | 
					
						
							|  |  |  |  | 		return existNode->nickName; | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		return model; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_depth_string(int mm, bool showunit, bool showdecimal) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (prefs.units.length == units::METERS) { | 
					
						
							|  |  |  |  | 		double meters = mm / 1000.0; | 
					
						
							|  |  |  |  | 		return QString("%1%2").arg(meters, 0, 'f', (showdecimal && meters < 20.0) ? 1 : 0).arg(showunit ? translate("gettextFromC", "m") : ""); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		double feet = mm_to_feet(mm); | 
					
						
							|  |  |  |  | 		return QString("%1%2").arg(feet, 0, 'f', 0).arg(showunit ? translate("gettextFromC", "ft") : ""); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_depth_string(depth_t depth, bool showunit, bool showdecimal) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return get_depth_string(depth.mm, showunit, showdecimal); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_depth_unit() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (prefs.units.length == units::METERS) | 
					
						
							|  |  |  |  | 		return QString("%1").arg(translate("gettextFromC", "m")); | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		return QString("%1").arg(translate("gettextFromC", "ft")); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_weight_string(weight_t weight, bool showunit) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString str = weight_string(weight.grams); | 
					
						
							|  |  |  |  | 	if (get_units()->weight == units::KG) { | 
					
						
							|  |  |  |  | 		str = QString("%1%2").arg(str).arg(showunit ? translate("gettextFromC", "kg") : ""); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		str = QString("%1%2").arg(str).arg(showunit ? translate("gettextFromC", "lbs") : ""); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return (str); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_weight_unit() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (prefs.units.weight == units::KG) | 
					
						
							|  |  |  |  | 		return QString("%1").arg(translate("gettextFromC", "kg")); | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		return QString("%1").arg(translate("gettextFromC", "lbs")); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_temperature_string(temperature_t temp, bool showunit) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (temp.mkelvin == 0) { | 
					
						
							|  |  |  |  | 		return ""; //temperature not defined
 | 
					
						
							|  |  |  |  | 	} else if (prefs.units.temperature == units::CELSIUS) { | 
					
						
							|  |  |  |  | 		double celsius = mkelvin_to_C(temp.mkelvin); | 
					
						
							|  |  |  |  | 		return QString("%1%2%3").arg(celsius, 0, 'f', 1).arg(showunit ? (UTF8_DEGREE) : "").arg(showunit ? translate("gettextFromC", "C") : ""); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		double fahrenheit = mkelvin_to_F(temp.mkelvin); | 
					
						
							|  |  |  |  | 		return QString("%1%2%3").arg(fahrenheit, 0, 'f', 1).arg(showunit ? (UTF8_DEGREE) : "").arg(showunit ? translate("gettextFromC", "F") : ""); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_temp_unit() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (prefs.units.temperature == units::CELSIUS) | 
					
						
							|  |  |  |  | 		return QString(UTF8_DEGREE "C"); | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		return QString(UTF8_DEGREE "F"); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Don't use "get_volume_string()" for cylinder size string
We had two totally different usage cases for "get_volume_string()": one
that did the obvious "show this volume as a string", and one that tried
to show a cylinder size.
The function used a magic third argument (the working pressure of the
cylinder) to distinguish between the two cases, but it still got it
wrong.
A metric cylinder doesn't necessarily have a working pressure at all,
and the size is a wet size in liters.  We'd pass in zero as the working
pressure, and if the volume units were set to cubic feet, the logic in
"get_volume_string()" would happily convert the metric wet size into the
wet size in cubic feet.
But that's completely wrong.  An imperial cylinder size simply isn't a
wet size.  If you don't have a working pressure, you cannot convert the
cylinder size to cubic feet.  End of story.
So instead of having "get_volume_string()" have magical behavior
depending on working pressure, and getting it wrong anyway, just make
get_volume_string do a pure volume conversion, and create a whole new
function for showing the size of a cylinder.
Now, if the cylinder doesn't have a working pressure, we just show the
metric size, even if the user had asked for cubic feet.
[Dirk Hohndel: added call to translation functions for the units]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
											
										 
											2016-02-24 14:42:56 -08:00
										 |  |  |  | QString get_volume_string(volume_t volume, bool showunit) | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *unit; | 
					
						
							|  |  |  |  | 	int decimals; | 
					
						
							|  |  |  |  | 	double value = get_volume_units(volume.mliter, &decimals, &unit); | 
					
						
							|  |  |  |  | 	return QString("%1%2").arg(value, 0, 'f', decimals).arg(showunit ? unit : ""); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_volume_unit() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *unit; | 
					
						
							|  |  |  |  | 	(void) get_volume_units(0, NULL, &unit); | 
					
						
							|  |  |  |  | 	return QString(unit); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_pressure_string(pressure_t pressure, bool showunit) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (prefs.units.pressure == units::BAR) { | 
					
						
							|  |  |  |  | 		double bar = pressure.mbar / 1000.0; | 
					
						
							|  |  |  |  | 		return QString("%1%2").arg(bar, 0, 'f', 1).arg(showunit ? translate("gettextFromC", "bar") : ""); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		double psi = mbar_to_PSI(pressure.mbar); | 
					
						
							|  |  |  |  | 		return QString("%1%2").arg(psi, 0, 'f', 0).arg(showunit ? translate("gettextFromC", "psi") : ""); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString getSubsurfaceDataPath(QString folderToFind) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString execdir; | 
					
						
							|  |  |  |  | 	QDir folder; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// first check if we are running in the build dir, so the path that we
 | 
					
						
							|  |  |  |  | 	// are looking for is just a  subdirectory of the execution path;
 | 
					
						
							|  |  |  |  | 	// this also works on Windows as there we install the dirs
 | 
					
						
							|  |  |  |  | 	// under the application path
 | 
					
						
							|  |  |  |  | 	execdir = QCoreApplication::applicationDirPath(); | 
					
						
							|  |  |  |  | 	folder = QDir(execdir.append(QDir::separator()).append(folderToFind)); | 
					
						
							|  |  |  |  | 	if (folder.exists()) | 
					
						
							|  |  |  |  | 		return folder.absolutePath(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// next check for the Linux typical $(prefix)/share/subsurface
 | 
					
						
							|  |  |  |  | 	execdir = QCoreApplication::applicationDirPath(); | 
					
						
							|  |  |  |  | 	if (execdir.contains("bin")) { | 
					
						
							|  |  |  |  | 		folder = QDir(execdir.replace("bin", "share/subsurface/").append(folderToFind)); | 
					
						
							|  |  |  |  | 		if (folder.exists()) | 
					
						
							|  |  |  |  | 			return folder.absolutePath(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	// then look for the usual locations on a Mac
 | 
					
						
							|  |  |  |  | 	execdir = QCoreApplication::applicationDirPath(); | 
					
						
							|  |  |  |  | 	folder = QDir(execdir.append("/../Resources/share/").append(folderToFind)); | 
					
						
							|  |  |  |  | 	if (folder.exists()) | 
					
						
							|  |  |  |  | 		return folder.absolutePath(); | 
					
						
							|  |  |  |  | 	execdir = QCoreApplication::applicationDirPath(); | 
					
						
							|  |  |  |  | 	folder = QDir(execdir.append("/../Resources/").append(folderToFind)); | 
					
						
							|  |  |  |  | 	if (folder.exists()) | 
					
						
							|  |  |  |  | 		return folder.absolutePath(); | 
					
						
							|  |  |  |  | 	return QString(""); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-19 00:25:14 +03:00
										 |  |  |  | static const char *printing_templates = "printing_templates"; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString getPrintingTemplatePathUser() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	static QString path = QString(); | 
					
						
							|  |  |  |  | 	if (path.isEmpty()) | 
					
						
							|  |  |  |  | 		path = QString(system_default_directory()) + QDir::separator() + QString(printing_templates); | 
					
						
							|  |  |  |  | 	return path; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString getPrintingTemplatePathBundle() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	static QString path = QString(); | 
					
						
							|  |  |  |  | 	if (path.isEmpty()) | 
					
						
							|  |  |  |  | 		path = getSubsurfaceDataPath(printing_templates); | 
					
						
							|  |  |  |  | 	return path; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void copyPath(QString src, QString dst) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QDir dir(src); | 
					
						
							|  |  |  |  | 	if (!dir.exists()) | 
					
						
							|  |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { | 
					
						
							|  |  |  |  | 		QString dst_path = dst + QDir::separator() + d; | 
					
						
							|  |  |  |  | 		dir.mkpath(dst_path); | 
					
						
							|  |  |  |  | 		copyPath(src + QDir::separator() + d, dst_path); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	foreach (QString f, dir.entryList(QDir::Files)) | 
					
						
							|  |  |  |  | 		QFile::copy(src + QDir::separator() + f, dst + QDir::separator() + f); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | int gettimezoneoffset(timestamp_t when) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QDateTime dt1, dt2; | 
					
						
							|  |  |  |  | 	if (when == 0) | 
					
						
							|  |  |  |  | 		dt1 = QDateTime::currentDateTime(); | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		dt1 = QDateTime::fromMSecsSinceEpoch(when * 1000); | 
					
						
							|  |  |  |  | 	dt2 = dt1.toUTC(); | 
					
						
							|  |  |  |  | 	dt1.setTimeSpec(Qt::UTC); | 
					
						
							|  |  |  |  | 	return dt2.secsTo(dt1); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-25 20:23:03 -08:00
										 |  |  |  | int parseDurationToSeconds(const QString &text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int secs; | 
					
						
							|  |  |  |  | 	QString numOnly = text; | 
					
						
							|  |  |  |  | 	QString hours, minutes, seconds; | 
					
						
							|  |  |  |  | 	numOnly.replace(",", ".").remove(QRegExp("[^-0-9.:]")); | 
					
						
							|  |  |  |  | 	if (numOnly.isEmpty()) | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 	if (numOnly.contains(':')) { | 
					
						
							|  |  |  |  | 		hours = numOnly.left(numOnly.indexOf(':')); | 
					
						
							|  |  |  |  | 		minutes = numOnly.right(numOnly.length() - hours.length() - 1); | 
					
						
							|  |  |  |  | 		if (minutes.contains(':')) { | 
					
						
							|  |  |  |  | 			numOnly = minutes; | 
					
						
							|  |  |  |  | 			minutes = numOnly.left(numOnly.indexOf(':')); | 
					
						
							|  |  |  |  | 			seconds = numOnly.right(numOnly.length() - minutes.length() - 1); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		hours = "0"; | 
					
						
							|  |  |  |  | 		minutes = numOnly; | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-23 08:13:49 +07:00
										 |  |  |  | 	secs = lrint(hours.toDouble() * 3600 + minutes.toDouble() * 60 + seconds.toDouble()); | 
					
						
							| 
									
										
										
										
											2017-02-25 20:23:03 -08:00
										 |  |  |  | 	return secs; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-01 00:32:30 -08:00
										 |  |  |  | int parseLengthToMm(const QString &text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int mm; | 
					
						
							|  |  |  |  | 	QString numOnly = text; | 
					
						
							|  |  |  |  | 	numOnly.replace(",", ".").remove(QRegExp("[^-0-9.]")); | 
					
						
							|  |  |  |  | 	if (numOnly.isEmpty()) | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 	double number = numOnly.toDouble(); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	if (text.contains(QObject::tr("m"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2017-03-23 08:13:49 +07:00
										 |  |  |  | 		mm = lrint(number * 1000); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	} else if (text.contains(QObject::tr("ft"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 		mm = feet_to_mm(number); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		switch (prefs.units.length) { | 
					
						
							|  |  |  |  | 		case units::FEET: | 
					
						
							|  |  |  |  | 			mm = feet_to_mm(number); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case units::METERS: | 
					
						
							| 
									
										
										
										
											2017-03-23 08:13:49 +07:00
										 |  |  |  | 			mm = lrint(number * 1000); | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			mm = 0; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-01-01 00:32:30 -08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return mm; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | int parseTemperatureToMkelvin(const QString &text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int mkelvin; | 
					
						
							|  |  |  |  | 	QString numOnly = text; | 
					
						
							|  |  |  |  | 	numOnly.replace(",", ".").remove(QRegExp("[^-0-9.]")); | 
					
						
							|  |  |  |  | 	if (numOnly.isEmpty()) | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 	double number = numOnly.toDouble(); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	if (text.contains(QObject::tr("C"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 		mkelvin = C_to_mkelvin(number); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	} else if (text.contains(QObject::tr("F"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 		mkelvin = F_to_mkelvin(number); | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		switch (prefs.units.temperature) { | 
					
						
							|  |  |  |  | 		case units::CELSIUS: | 
					
						
							|  |  |  |  | 			mkelvin = C_to_mkelvin(number); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case units::FAHRENHEIT: | 
					
						
							|  |  |  |  | 			mkelvin = F_to_mkelvin(number); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			mkelvin = 0; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return mkelvin; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-05 22:51:46 -08:00
										 |  |  |  | int parseWeightToGrams(const QString &text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int grams; | 
					
						
							|  |  |  |  | 	QString numOnly = text; | 
					
						
							|  |  |  |  | 	numOnly.replace(",", ".").remove(QRegExp("[^0-9.]")); | 
					
						
							|  |  |  |  | 	if (numOnly.isEmpty()) | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 	double number = numOnly.toDouble(); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	if (text.contains(QObject::tr("kg"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 		grams = lrint(number * 1000); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	} else if (text.contains(QObject::tr("lbs"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2016-02-05 22:51:46 -08:00
										 |  |  |  | 		grams = lbs_to_grams(number); | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2016-02-12 21:12:23 +01:00
										 |  |  |  | 		switch (prefs.units.weight) { | 
					
						
							|  |  |  |  | 		case units::KG: | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 			grams = lrint(number * 1000); | 
					
						
							| 
									
										
										
										
											2016-02-12 21:12:23 +01:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case units::LBS: | 
					
						
							|  |  |  |  | 			grams = lbs_to_grams(number); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			grams = 0; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-05 22:51:46 -08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return grams; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 19:52:02 +01:00
										 |  |  |  | int parsePressureToMbar(const QString &text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int mbar; | 
					
						
							|  |  |  |  | 	QString numOnly = text; | 
					
						
							|  |  |  |  | 	numOnly.replace(",", ".").remove(QRegExp("[^0-9.]")); | 
					
						
							|  |  |  |  | 	if (numOnly.isEmpty()) | 
					
						
							|  |  |  |  | 		return 0; | 
					
						
							|  |  |  |  | 	double number = numOnly.toDouble(); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	if (text.contains(QObject::tr("bar"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 		mbar = lrint(number * 1000); | 
					
						
							| 
									
										
										
										
											2016-02-20 22:00:07 -08:00
										 |  |  |  | 	} else if (text.contains(QObject::tr("psi"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2016-02-09 19:52:02 +01:00
										 |  |  |  | 		mbar = psi_to_mbar(number); | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2016-02-12 21:12:23 +01:00
										 |  |  |  | 		switch (prefs.units.pressure) { | 
					
						
							|  |  |  |  | 		case units::BAR: | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 			mbar = lrint(number * 1000); | 
					
						
							| 
									
										
										
										
											2016-02-12 21:12:23 +01:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case units::PSI: | 
					
						
							|  |  |  |  | 			mbar = psi_to_mbar(number); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			mbar = 0; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-09 19:52:02 +01:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return mbar; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-13 18:34:30 +01:00
										 |  |  |  | int parseGasMixO2(const QString &text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString gasString = text; | 
					
						
							|  |  |  |  | 	int o2, number; | 
					
						
							|  |  |  |  | 	if (gasString.contains(QObject::tr("AIR"), Qt::CaseInsensitive)) { | 
					
						
							|  |  |  |  | 		o2 = O2_IN_AIR; | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 	} else if (gasString.contains(QObject::tr("EAN"), Qt::CaseInsensitive)) { | 
					
						
							| 
									
										
										
										
											2016-02-13 18:34:30 +01:00
										 |  |  |  | 		gasString.remove(QRegExp("[^0-9]")); | 
					
						
							|  |  |  |  | 		number = gasString.toInt(); | 
					
						
							|  |  |  |  | 		o2 = number * 10; | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 	} else if (gasString.contains("/")) { | 
					
						
							| 
									
										
										
										
											2016-02-13 18:34:30 +01:00
										 |  |  |  | 		QStringList gasSplit = gasString.split("/"); | 
					
						
							|  |  |  |  | 		number = gasSplit[0].toInt(); | 
					
						
							|  |  |  |  | 		o2 = number * 10; | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2016-02-13 18:34:30 +01:00
										 |  |  |  | 		number = gasString.toInt(); | 
					
						
							|  |  |  |  | 		o2 = number * 10; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return o2; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | int parseGasMixHE(const QString &text) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString gasString = text; | 
					
						
							|  |  |  |  | 	int he, number; | 
					
						
							|  |  |  |  | 	if (gasString.contains("/")) { | 
					
						
							|  |  |  |  | 		QStringList gasSplit = gasString.split("/"); | 
					
						
							|  |  |  |  | 		number = gasSplit[1].toInt(); | 
					
						
							|  |  |  |  | 		he = number * 10; | 
					
						
							| 
									
										
										
										
											2016-02-15 07:48:57 -08:00
										 |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2016-02-13 18:34:30 +01:00
										 |  |  |  | 		he = 0; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return he; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | QString get_dive_duration_string(timestamp_t when, QString hoursText, QString minutesText, QString secondsText, QString separator, bool isFreeDive) | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-05-06 17:43:32 -07:00
										 |  |  |  | 	int hrs, mins, fullmins, secs; | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | 	mins = (when + 30) / 60; | 
					
						
							| 
									
										
										
										
											2017-05-06 17:43:32 -07:00
										 |  |  |  | 	fullmins = when / 60; | 
					
						
							|  |  |  |  | 	secs = when - 60 * fullmins; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	hrs = mins / 60; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	QString displayTime; | 
					
						
							| 
									
										
										
										
											2017-05-06 17:43:32 -07:00
										 |  |  |  | 	if (prefs.units.duration_units == units::ALWAYS_HOURS || (prefs.units.duration_units == units::MIXED && hrs)) { | 
					
						
							|  |  |  |  | 		mins -= hrs * 60; | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | 		displayTime = QString("%1%2%3%4%5").arg(hrs).arg(separator == ":" ? "" : hoursText).arg(separator) | 
					
						
							|  |  |  |  | 			.arg(mins, 2, 10, QChar('0')).arg(separator == ":" ? hoursText : minutesText); | 
					
						
							|  |  |  |  | 	} else if (isFreeDive && ( prefs.units.duration_units == units::MINUTES_ONLY || minutesText != "" )) { | 
					
						
							|  |  |  |  | 		// Freedive <1h and we display no hours but only minutes for other dives
 | 
					
						
							|  |  |  |  | 		// --> display a short (5min 35sec) freedives e.g. as "5:35"
 | 
					
						
							|  |  |  |  | 		// Freedive <1h and we display a unit for minutes
 | 
					
						
							|  |  |  |  | 		// --> display a short (5min 35sec) freedives e.g. as "5:35min"
 | 
					
						
							|  |  |  |  | 		if (separator == ":") displayTime = QString("%1%2%3%4").arg(fullmins).arg(separator) | 
					
						
							|  |  |  |  | 			.arg(secs, 2, 10, QChar('0')).arg(minutesText); | 
					
						
							|  |  |  |  | 		else displayTime = QString("%1%2%3%4%5").arg(fullmins).arg(minutesText).arg(separator) | 
					
						
							|  |  |  |  | 			.arg(secs).arg(secondsText); | 
					
						
							| 
									
										
										
										
											2017-05-06 17:43:32 -07:00
										 |  |  |  | 	} else if (isFreeDive) { | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | 		// Mixed display (hh:mm / mm only) and freedive < 1h and we have no unit for minutes
 | 
					
						
							| 
									
										
										
										
											2017-11-09 06:43:38 -08:00
										 |  |  |  | 		// --> Prefix duration with "0:" --> "0:05:35"
 | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | 		if (separator == ":") displayTime = QString("%1%2%3%4%5%6").arg(hrs).arg(separator) | 
					
						
							|  |  |  |  | 			.arg(fullmins, 2, 10, QChar('0')).arg(separator) | 
					
						
							|  |  |  |  | 			.arg(secs, 2, 10, QChar('0')).arg(hoursText); | 
					
						
							|  |  |  |  | 		// Separator != ":" and no units for minutes --> unlikely case - remove?
 | 
					
						
							|  |  |  |  | 		else displayTime = QString("%1%2%3%4%5%6%7%8").arg(hrs).arg(hoursText).arg(separator) | 
					
						
							|  |  |  |  | 			.arg(fullmins).arg(minutesText).arg(separator) | 
					
						
							|  |  |  |  | 			.arg(secs).arg(secondsText); | 
					
						
							| 
									
										
										
										
											2017-05-06 17:43:32 -07:00
										 |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | 		displayTime = QString("%1%2").arg(mins).arg(minutesText); | 
					
						
							| 
									
										
										
										
											2017-05-06 17:43:32 -07:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	return displayTime; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | QString get_dive_surfint_string(timestamp_t when, QString daysText, QString hoursText, QString minutesText, QString separator, int maxdays) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int days, hrs, mins; | 
					
						
							|  |  |  |  | 	days = when / 3600 / 24; | 
					
						
							|  |  |  |  | 	hrs = (when - days * 3600 * 24) / 3600; | 
					
						
							|  |  |  |  | 	mins = (when + 30 - days * 3600 * 24 - hrs * 3600) / 60; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	QString displayInt; | 
					
						
							| 
									
										
										
										
											2017-06-23 08:33:34 +02:00
										 |  |  |  | 	if (maxdays && days > maxdays) displayInt = QString(translate("gettextFromC", "more than %1 days")).arg(maxdays); | 
					
						
							| 
									
										
										
										
											2017-05-11 22:43:36 +02:00
										 |  |  |  | 	else if (days) displayInt = QString("%1%2%3%4%5%6%7%8").arg(days).arg(daysText).arg(separator) | 
					
						
							|  |  |  |  | 		.arg(hrs).arg(hoursText).arg(separator) | 
					
						
							|  |  |  |  | 		.arg(mins).arg(minutesText); | 
					
						
							|  |  |  |  | 	else displayInt = QString("%1%2%3%4%5").arg(hrs).arg(hoursText).arg(separator) | 
					
						
							|  |  |  |  | 		.arg(mins).arg(minutesText); | 
					
						
							|  |  |  |  | 	return displayInt; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | QString get_dive_date_string(timestamp_t when) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QDateTime ts; | 
					
						
							|  |  |  |  | 	ts.setMSecsSinceEpoch(when * 1000L); | 
					
						
							| 
									
										
										
										
											2015-10-29 16:57:43 -07:00
										 |  |  |  | 	return loc.toString(ts.toUTC(), QString(prefs.date_format) + " " + prefs.time_format); | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_short_dive_date_string(timestamp_t when) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QDateTime ts; | 
					
						
							|  |  |  |  | 	ts.setMSecsSinceEpoch(when * 1000L); | 
					
						
							| 
									
										
										
										
											2015-10-29 16:57:43 -07:00
										 |  |  |  | 	return loc.toString(ts.toUTC(), QString(prefs.date_format_short) + " " + prefs.time_format); | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const char *get_dive_date_c_string(timestamp_t when) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString text = get_dive_date_string(when); | 
					
						
							|  |  |  |  | 	return strdup(text.toUtf8().data()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-31 08:14:36 +02:00
										 |  |  |  | extern "C" const char *get_current_date() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QDateTime ts(QDateTime::currentDateTime());; | 
					
						
							|  |  |  |  | 	QString current_date; | 
					
						
							| 
									
										
										
										
											2017-05-06 17:43:32 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-31 08:14:36 +02:00
										 |  |  |  | 	current_date = loc.toString(ts, QString(prefs.date_format_short)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return strdup(current_date.toUtf8().data()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-06 21:08:27 +02:00
										 |  |  |  | bool is_same_day(timestamp_t trip_when, timestamp_t dive_when) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	static timestamp_t twhen = (timestamp_t) 0; | 
					
						
							|  |  |  |  | 	static struct tm tmt; | 
					
						
							|  |  |  |  | 	struct tm tmd; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	utc_mkdate(dive_when, &tmd); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (twhen != trip_when) { | 
					
						
							|  |  |  |  | 		twhen = trip_when; | 
					
						
							|  |  |  |  | 		utc_mkdate(twhen, &tmt); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return ((tmd.tm_mday == tmt.tm_mday) && (tmd.tm_mon == tmt.tm_mon) && (tmd.tm_year == tmt.tm_year)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_trip_date_string(timestamp_t when, int nr, bool getday) | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	struct tm tm; | 
					
						
							|  |  |  |  | 	utc_mkdate(when, &tm); | 
					
						
							| 
									
										
										
										
											2016-04-28 16:31:37 -07:00
										 |  |  |  | 	QDateTime localTime = QDateTime::fromMSecsSinceEpoch(1000*when,Qt::UTC); | 
					
						
							| 
									
										
										
										
											2015-10-06 21:08:27 +02:00
										 |  |  |  | 	localTime.setTimeSpec(Qt::UTC); | 
					
						
							|  |  |  |  | 	QString ret ; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 11:24:47 +03:00
										 |  |  |  | 	QString suffix = " " + QObject::tr("(%n dive(s))", "", nr); | 
					
						
							|  |  |  |  | 	if (getday) { | 
					
						
							| 
									
										
										
										
											2015-11-02 11:32:46 -08:00
										 |  |  |  | 		ret = localTime.date().toString(prefs.date_format) + suffix; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2016-08-08 03:11:06 +03:00
										 |  |  |  | 		ret = localTime.date().toString("MMM yyyy") + suffix; | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-10-06 21:08:27 +02:00
										 |  |  |  | 	return ret; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-14 20:01:33 -08:00
										 |  |  |  | extern "C" void reverseGeoLookup(degrees_t latitude, degrees_t longitude, uint32_t uuid) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QNetworkRequest request; | 
					
						
							|  |  |  |  | 	QNetworkAccessManager *rgl = new QNetworkAccessManager(); | 
					
						
							|  |  |  |  | 	request.setUrl(QString("http://open.mapquestapi.com/nominatim/v1/reverse.php?format=json&accept-language=%1&lat=%2&lon=%3") | 
					
						
							|  |  |  |  | 		       .arg(uiLanguage(NULL)).arg(latitude.udeg / 1000000.0).arg(longitude.udeg / 1000000.0)); | 
					
						
							|  |  |  |  | 	request.setRawHeader("Accept", "text/json"); | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | 	request.setRawHeader("User-Agent", getUserAgent().toUtf8()); | 
					
						
							| 
									
										
										
										
											2015-02-14 20:01:33 -08:00
										 |  |  |  | 	QNetworkReply *reply = rgl->get(request); | 
					
						
							|  |  |  |  | 	QEventLoop loop; | 
					
						
							|  |  |  |  | 	QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); | 
					
						
							|  |  |  |  | 	loop.exec(); | 
					
						
							|  |  |  |  | 	QJsonParseError errorObject; | 
					
						
							|  |  |  |  | 	QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &errorObject); | 
					
						
							|  |  |  |  | 	if (errorObject.error != QJsonParseError::NoError) { | 
					
						
							|  |  |  |  | 		qDebug() << errorObject.errorString(); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		QJsonObject obj = jsonDoc.object(); | 
					
						
							|  |  |  |  | 		QJsonObject address = obj.value("address").toObject(); | 
					
						
							|  |  |  |  | 		qDebug() << "found country:" << address.value("country").toString(); | 
					
						
							|  |  |  |  | 		struct dive_site *ds = get_dive_site_by_uuid(uuid); | 
					
						
							|  |  |  |  | 		ds->notes = add_to_string(ds->notes, "countrytag: %s", address.value("country").toString().toUtf8().data()); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | QHash<QString, QByteArray> hashOf; | 
					
						
							| 
									
										
										
										
											2015-03-25 14:28:36 +01:00
										 |  |  |  | QMutex hashOfMutex; | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | QHash<QByteArray, QString> localFilenameOf; | 
					
						
							| 
									
										
										
										
											2015-11-09 16:48:12 +01:00
										 |  |  |  | QHash <QString, QImage > thumbnailCache; | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 10:00:16 +01:00
										 |  |  |  | extern "C" char * hashstring(const char *filename) | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 	return hashOf[QString(filename)].toHex().data(); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-23 11:13:07 +02:00
										 |  |  |  | const QString hashfile_name() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return QString(system_default_directory()).append("/hashes"); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" char *hashfile_name_string() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return strdup(hashfile_name().toUtf8().data()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | void read_hashes() | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-23 11:13:07 +02:00
										 |  |  |  | 	QFile hashfile(hashfile_name()); | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 	if (hashfile.open(QIODevice::ReadOnly)) { | 
					
						
							|  |  |  |  | 		QDataStream stream(&hashfile); | 
					
						
							|  |  |  |  | 		stream >> localFilenameOf; | 
					
						
							| 
									
										
										
										
											2015-09-17 16:56:58 +02:00
										 |  |  |  | 		stream >> hashOf; | 
					
						
							| 
									
										
										
										
											2015-11-09 16:48:12 +01:00
										 |  |  |  | 		stream >> thumbnailCache; | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 		hashfile.close(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-02 23:43:30 +01:00
										 |  |  |  | 	localFilenameOf.remove(""); | 
					
						
							|  |  |  |  | 	QMutableHashIterator<QString, QByteArray> iter(hashOf); | 
					
						
							|  |  |  |  | 	while (iter.hasNext()) { | 
					
						
							|  |  |  |  | 		iter.next(); | 
					
						
							|  |  |  |  | 		if (iter.value().isEmpty()) | 
					
						
							|  |  |  |  | 			iter.remove(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void write_hashes() | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-23 11:13:07 +02:00
										 |  |  |  | 	QSaveFile hashfile(hashfile_name()); | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 	if (hashfile.open(QIODevice::WriteOnly)) { | 
					
						
							|  |  |  |  | 		QDataStream stream(&hashfile); | 
					
						
							|  |  |  |  | 		stream << localFilenameOf; | 
					
						
							| 
									
										
										
										
											2015-09-17 16:56:58 +02:00
										 |  |  |  | 		stream << hashOf; | 
					
						
							| 
									
										
										
										
											2015-11-09 16:48:12 +01:00
										 |  |  |  | 		stream << thumbnailCache; | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 		hashfile.commit(); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		qDebug() << "cannot open" << hashfile.fileName(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void add_hash(const QString filename, QByteArray hash) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-12-02 23:43:30 +01:00
										 |  |  |  | 	if (hash.isEmpty()) | 
					
						
							|  |  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2015-03-25 14:28:36 +01:00
										 |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 	hashOf[filename] =  hash; | 
					
						
							|  |  |  |  | 	localFilenameOf[hash] = filename; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QByteArray hashFile(const QString filename) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QCryptographicHash hash(QCryptographicHash::Sha1); | 
					
						
							|  |  |  |  | 	QFile imagefile(filename); | 
					
						
							| 
									
										
										
										
											2015-07-31 22:25:43 +02:00
										 |  |  |  | 	if (imagefile.exists() && imagefile.open(QIODevice::ReadOnly)) { | 
					
						
							| 
									
										
										
										
											2015-06-21 10:25:53 -07:00
										 |  |  |  | 		hash.addData(&imagefile); | 
					
						
							|  |  |  |  | 		add_hash(filename, hash.result()); | 
					
						
							|  |  |  |  | 		return hash.result(); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		return QByteArray(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-02 16:18:16 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | void learnHash(struct picture *picture, QByteArray hash) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-12-15 14:31:20 +01:00
										 |  |  |  | 	if (hash.isNull()) | 
					
						
							|  |  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2015-04-24 17:10:55 +02:00
										 |  |  |  | 	if (picture->hash) | 
					
						
							|  |  |  |  | 		free(picture->hash); | 
					
						
							| 
									
										
										
										
											2015-03-25 14:28:36 +01:00
										 |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							| 
									
										
										
										
											2015-03-02 16:18:16 +01:00
										 |  |  |  | 	hashOf[QString(picture->filename)] = hash; | 
					
						
							|  |  |  |  | 	picture->hash = strdup(hash.toHex()); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 10:00:16 +01:00
										 |  |  |  | bool haveHash(const QString &filename) | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							|  |  |  |  | 	return hashOf.contains(filename); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | QString localFilePath(const QString originalFilename) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-24 17:10:55 +02:00
										 |  |  |  | 	if (hashOf.contains(originalFilename) && localFilenameOf.contains(hashOf[originalFilename])) | 
					
						
							|  |  |  |  | 		return localFilenameOf[hashOf[originalFilename]]; | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		return originalFilename; | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 10:00:16 +01:00
										 |  |  |  | QString fileFromHash(const char *hash) | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-12-15 14:31:20 +01:00
										 |  |  |  | 	if (!hash || !*hash) | 
					
						
							|  |  |  |  | 		return ""; | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	QMutexLocker locker(&hashOfMutex); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 	return localFilenameOf[QByteArray::fromHex(hash)]; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  |  | // This needs to operate on a copy of picture as it frees it after finishing!
 | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | void updateHash(struct picture *picture) { | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	if (!picture) | 
					
						
							|  |  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | 	QByteArray hash = hashFile(fileFromHash(picture->hash)); | 
					
						
							| 
									
										
										
										
											2016-01-09 16:27:23 +01:00
										 |  |  |  | 	learnHash(picture, hash); | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  |  | 	picture_free(picture); | 
					
						
							| 
									
										
										
										
											2015-02-26 14:39:42 +01:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-26 14:44:27 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  |  | // This needs to operate on a copy of picture as it frees it after finishing!
 | 
					
						
							| 
									
										
										
										
											2015-09-17 16:56:58 +02:00
										 |  |  |  | void hashPicture(struct picture *picture) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	if (!picture) | 
					
						
							|  |  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2015-10-13 10:33:30 -07:00
										 |  |  |  | 	char *oldHash = copy_string(picture->hash); | 
					
						
							| 
									
										
										
										
											2016-12-15 14:31:20 +01:00
										 |  |  |  | 	learnHash(picture, hashFile(localFilePath(picture->filename))); | 
					
						
							| 
									
										
										
										
											2015-10-13 10:33:30 -07:00
										 |  |  |  | 	if (!same_string(picture->hash, "") && !same_string(picture->hash, oldHash)) | 
					
						
							|  |  |  |  | 		mark_divelist_changed((true)); | 
					
						
							|  |  |  |  | 	free(oldHash); | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  |  | 	picture_free(picture); | 
					
						
							| 
									
										
										
										
											2015-09-17 16:56:58 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" void cache_picture(struct picture *picture) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString filename = picture->filename; | 
					
						
							| 
									
										
										
										
											2016-04-29 16:18:06 +02:00
										 |  |  |  | 	if (!haveHash(filename)) | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  |  | 		QtConcurrent::run(hashPicture, clone_picture(picture)); | 
					
						
							| 
									
										
										
										
											2015-09-17 16:56:58 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-05 21:13:46 +02:00
										 |  |  |  | QStringList imageExtensionFilters() { | 
					
						
							|  |  |  |  | 	QStringList filters; | 
					
						
							|  |  |  |  | 	foreach (QString format, QImageReader::supportedImageFormats()) { | 
					
						
							|  |  |  |  | 		filters.append(QString("*.").append(format)); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return filters; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 21:32:12 -03:00
										 |  |  |  | void learnImages(const QDir dir, int max_recursions) | 
					
						
							| 
									
										
										
										
											2015-02-26 14:44:27 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-05-05 21:13:46 +02:00
										 |  |  |  | 	QStringList files; | 
					
						
							|  |  |  |  | 	QStringList filters = imageExtensionFilters(); | 
					
						
							| 
									
										
										
										
											2015-02-26 14:44:27 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (max_recursions) { | 
					
						
							|  |  |  |  | 		foreach (QString dirname, dir.entryList(QStringList(), QDir::NoDotAndDotDot | QDir::Dirs)) { | 
					
						
							| 
									
										
										
										
											2016-03-06 21:32:12 -03:00
										 |  |  |  | 			learnImages(QDir(dir.filePath(dirname)), max_recursions - 1); | 
					
						
							| 
									
										
										
										
											2015-02-26 14:44:27 +01:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	foreach (QString file, dir.entryList(filters, QDir::Files)) { | 
					
						
							|  |  |  |  | 		files.append(dir.absoluteFilePath(file)); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	QtConcurrent::blockingMap(files, hashFile); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-24 17:10:55 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-21 10:29:02 -07:00
										 |  |  |  | extern "C" const char *local_file_path(struct picture *picture) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-22 06:45:48 -07:00
										 |  |  |  | 	QString hashString = picture->hash; | 
					
						
							|  |  |  |  | 	if (hashString.isEmpty()) { | 
					
						
							|  |  |  |  | 		QByteArray hash = hashFile(picture->filename); | 
					
						
							|  |  |  |  | 		free(picture->hash); | 
					
						
							|  |  |  |  | 		picture->hash = strdup(hash.toHex().data()); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-21 10:29:02 -07:00
										 |  |  |  | 	QString localFileName = fileFromHash(picture->hash); | 
					
						
							| 
									
										
										
										
											2015-06-22 06:45:48 -07:00
										 |  |  |  | 	if (localFileName.isEmpty()) | 
					
						
							|  |  |  |  | 		localFileName = picture->filename; | 
					
						
							| 
									
										
										
										
											2015-06-21 10:29:02 -07:00
										 |  |  |  | 	return strdup(qPrintable(localFileName)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-21 07:43:35 -07:00
										 |  |  |  | extern "C" bool picture_exists(struct picture *picture) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString localFilename = fileFromHash(picture->hash); | 
					
						
							|  |  |  |  | 	QByteArray hash = hashFile(localFilename); | 
					
						
							|  |  |  |  | 	return same_string(hash.toHex().data(), picture->hash); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-23 11:13:07 +02:00
										 |  |  |  | const QString picturedir() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return QString(system_default_directory()).append("/picturedata/"); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" char *picturedir_string() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return strdup(picturedir().toUtf8().data()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-21 07:43:35 -07:00
										 |  |  |  | /* when we get a picture from git storage (local or remote) and can't find the picture
 | 
					
						
							|  |  |  |  |  * based on its hash, we create a local copy with the hash as filename and the appropriate | 
					
						
							|  |  |  |  |  * suffix */ | 
					
						
							|  |  |  |  | extern "C" void savePictureLocal(struct picture *picture, const char *data, int len) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-23 11:13:07 +02:00
										 |  |  |  | 	QString dirname = picturedir(); | 
					
						
							| 
									
										
										
										
											2015-06-21 07:43:35 -07:00
										 |  |  |  | 	QDir localPictureDir(dirname); | 
					
						
							|  |  |  |  | 	localPictureDir.mkpath(dirname); | 
					
						
							|  |  |  |  | 	QString suffix(picture->filename); | 
					
						
							|  |  |  |  | 	suffix.replace(QRegularExpression(".*\\."), ""); | 
					
						
							|  |  |  |  | 	QString filename(dirname + picture->hash + "." + suffix); | 
					
						
							|  |  |  |  | 	QSaveFile out(filename); | 
					
						
							|  |  |  |  | 	if (out.open(QIODevice::WriteOnly)) { | 
					
						
							|  |  |  |  | 		out.write(data, len); | 
					
						
							|  |  |  |  | 		out.commit(); | 
					
						
							|  |  |  |  | 		add_hash(filename, QByteArray::fromHex(picture->hash)); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-24 17:10:55 +02:00
										 |  |  |  | extern "C" void picture_load_exif_data(struct picture *p) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-02-19 10:27:27 +01:00
										 |  |  |  | 	easyexif::EXIFInfo exif; | 
					
						
							| 
									
										
										
										
											2015-04-24 17:10:55 +02:00
										 |  |  |  | 	memblock mem; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (readfile(localFilePath(QString(p->filename)).toUtf8().data(), &mem) <= 0) | 
					
						
							|  |  |  |  | 		goto picture_load_exit; | 
					
						
							|  |  |  |  | 	if (exif.parseFrom((const unsigned char *)mem.buffer, (unsigned)mem.size) != PARSE_EXIF_SUCCESS) | 
					
						
							|  |  |  |  | 		goto picture_load_exit; | 
					
						
							| 
									
										
										
										
											2017-10-07 21:39:20 +03:00
										 |  |  |  | 	p->longitude.udeg = lrint(1000000.0 * exif.GeoLocation.Longitude); | 
					
						
							|  |  |  |  | 	p->latitude.udeg = lrint(1000000.0 * exif.GeoLocation.Latitude); | 
					
						
							| 
									
										
										
										
											2015-04-24 17:10:55 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | picture_load_exit: | 
					
						
							|  |  |  |  | 	free(mem.buffer); | 
					
						
							|  |  |  |  | 	return; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-28 16:23:49 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_gas_string(struct gasmix gas) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	uint o2 = (get_o2(&gas) + 5) / 10, he = (get_he(&gas) + 5) / 10; | 
					
						
							|  |  |  |  | 	QString result = gasmix_is_air(&gas) ? QObject::tr("AIR") : he == 0 ? (o2 == 100 ? QObject::tr("OXYGEN") : QString("EAN%1").arg(o2, 2, 10, QChar('0'))) : QString("%1/%2").arg(o2).arg(he); | 
					
						
							|  |  |  |  | 	return result; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 22:40:28 +10:00
										 |  |  |  | QString get_divepoint_gas_string(struct dive *d, const divedatapoint &p) | 
					
						
							| 
									
										
										
										
											2015-05-28 16:23:49 -03:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-06 22:40:28 +10:00
										 |  |  |  | 	int idx = p.cylinderid; | 
					
						
							|  |  |  |  | 	return get_gas_string(d->cylinder[idx].gasmix); | 
					
						
							| 
									
										
										
										
											2015-05-28 16:23:49 -03:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-28 17:17:09 -03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | weight_t string_to_weight(const char *str) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *end; | 
					
						
							|  |  |  |  | 	double value = strtod_flags(str, &end, 0); | 
					
						
							|  |  |  |  | 	QString rest = QString(end).trimmed(); | 
					
						
							|  |  |  |  | 	QString local_kg = QObject::tr("kg"); | 
					
						
							|  |  |  |  | 	QString local_lbs = QObject::tr("lbs"); | 
					
						
							|  |  |  |  | 	weight_t weight; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (rest.startsWith("kg") || rest.startsWith(local_kg)) | 
					
						
							|  |  |  |  | 		goto kg; | 
					
						
							|  |  |  |  | 	// using just "lb" instead of "lbs" is intentional - some people might enter the singular
 | 
					
						
							|  |  |  |  | 	if (rest.startsWith("lb") || rest.startsWith(local_lbs)) | 
					
						
							|  |  |  |  | 		goto lbs; | 
					
						
							|  |  |  |  | 	if (prefs.units.weight == prefs.units.LBS) | 
					
						
							|  |  |  |  | 		goto lbs; | 
					
						
							|  |  |  |  | kg: | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 	weight.grams = lrint(value * 1000); | 
					
						
							| 
									
										
										
										
											2015-05-28 17:17:09 -03:00
										 |  |  |  | 	return weight; | 
					
						
							|  |  |  |  | lbs: | 
					
						
							|  |  |  |  | 	weight.grams = lbs_to_grams(value); | 
					
						
							|  |  |  |  | 	return weight; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | depth_t string_to_depth(const char *str) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *end; | 
					
						
							|  |  |  |  | 	double value = strtod_flags(str, &end, 0); | 
					
						
							|  |  |  |  | 	QString rest = QString(end).trimmed(); | 
					
						
							|  |  |  |  | 	QString local_ft = QObject::tr("ft"); | 
					
						
							|  |  |  |  | 	QString local_m = QObject::tr("m"); | 
					
						
							|  |  |  |  | 	depth_t depth; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 11:00:22 +10:00
										 |  |  |  | 	if (value < 0) | 
					
						
							|  |  |  |  | 		value = 0; | 
					
						
							| 
									
										
										
										
											2015-05-28 17:17:09 -03:00
										 |  |  |  | 	if (rest.startsWith("m") || rest.startsWith(local_m)) | 
					
						
							|  |  |  |  | 		goto m; | 
					
						
							|  |  |  |  | 	if (rest.startsWith("ft") || rest.startsWith(local_ft)) | 
					
						
							|  |  |  |  | 		goto ft; | 
					
						
							|  |  |  |  | 	if (prefs.units.length == prefs.units.FEET) | 
					
						
							|  |  |  |  | 		goto ft; | 
					
						
							|  |  |  |  | m: | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 	depth.mm = lrint(value * 1000); | 
					
						
							| 
									
										
										
										
											2015-05-28 17:17:09 -03:00
										 |  |  |  | 	return depth; | 
					
						
							|  |  |  |  | ft: | 
					
						
							|  |  |  |  | 	depth.mm = feet_to_mm(value); | 
					
						
							|  |  |  |  | 	return depth; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | pressure_t string_to_pressure(const char *str) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *end; | 
					
						
							|  |  |  |  | 	double value = strtod_flags(str, &end, 0); | 
					
						
							|  |  |  |  | 	QString rest = QString(end).trimmed(); | 
					
						
							|  |  |  |  | 	QString local_psi = QObject::tr("psi"); | 
					
						
							|  |  |  |  | 	QString local_bar = QObject::tr("bar"); | 
					
						
							|  |  |  |  | 	pressure_t pressure; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (rest.startsWith("bar") || rest.startsWith(local_bar)) | 
					
						
							|  |  |  |  | 		goto bar; | 
					
						
							|  |  |  |  | 	if (rest.startsWith("psi") || rest.startsWith(local_psi)) | 
					
						
							|  |  |  |  | 		goto psi; | 
					
						
							|  |  |  |  | 	if (prefs.units.pressure == prefs.units.PSI) | 
					
						
							|  |  |  |  | 		goto psi; | 
					
						
							|  |  |  |  | bar: | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 	pressure.mbar = lrint(value * 1000); | 
					
						
							| 
									
										
										
										
											2015-05-28 17:17:09 -03:00
										 |  |  |  | 	return pressure; | 
					
						
							|  |  |  |  | psi: | 
					
						
							|  |  |  |  | 	pressure.mbar = psi_to_mbar(value); | 
					
						
							|  |  |  |  | 	return pressure; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | volume_t string_to_volume(const char *str, pressure_t workp) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *end; | 
					
						
							|  |  |  |  | 	double value = strtod_flags(str, &end, 0); | 
					
						
							|  |  |  |  | 	QString rest = QString(end).trimmed(); | 
					
						
							|  |  |  |  | 	QString local_l = QObject::tr("l"); | 
					
						
							|  |  |  |  | 	QString local_cuft = QObject::tr("cuft"); | 
					
						
							|  |  |  |  | 	volume_t volume; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (rest.startsWith("l") || rest.startsWith("ℓ") || rest.startsWith(local_l)) | 
					
						
							|  |  |  |  | 		goto l; | 
					
						
							|  |  |  |  | 	if (rest.startsWith("cuft") || rest.startsWith(local_cuft)) | 
					
						
							|  |  |  |  | 		goto cuft; | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * If we don't have explicit units, and there is no working | 
					
						
							|  |  |  |  | 	 * pressure, we're going to assume "liter" even in imperial | 
					
						
							|  |  |  |  | 	 * measurements. | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	if (!workp.mbar) | 
					
						
							|  |  |  |  | 		goto l; | 
					
						
							|  |  |  |  | 	if (prefs.units.volume == prefs.units.LITER) | 
					
						
							|  |  |  |  | 		goto l; | 
					
						
							|  |  |  |  | cuft: | 
					
						
							|  |  |  |  | 	if (workp.mbar) | 
					
						
							|  |  |  |  | 		value /= bar_to_atm(workp.mbar / 1000.0); | 
					
						
							|  |  |  |  | 	value = cuft_to_l(value); | 
					
						
							|  |  |  |  | l: | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 	volume.mliter = lrint(value * 1000); | 
					
						
							| 
									
										
										
										
											2015-05-28 17:17:09 -03:00
										 |  |  |  | 	return volume; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | fraction_t string_to_fraction(const char *str) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *end; | 
					
						
							|  |  |  |  | 	double value = strtod_flags(str, &end, 0); | 
					
						
							|  |  |  |  | 	fraction_t fraction; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 13:41:41 +07:00
										 |  |  |  | 	fraction.permille = lrint(value * 10); | 
					
						
							| 
									
										
										
										
											2016-05-22 11:00:22 +10:00
										 |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * Don't permit values less than zero or greater than 100% | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 	if (fraction.permille < 0) | 
					
						
							|  |  |  |  | 		fraction.permille = 0; | 
					
						
							|  |  |  |  | 	else if (fraction.permille > 1000) | 
					
						
							|  |  |  |  | 		fraction.permille = 1000; | 
					
						
							| 
									
										
										
										
											2015-05-28 17:17:09 -03:00
										 |  |  |  | 	return fraction; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-01 13:09:45 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | int getCloudURL(QString &filename) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString email = QString(prefs.cloud_storage_email); | 
					
						
							| 
									
										
										
										
											2015-06-09 11:21:46 -07:00
										 |  |  |  | 	email.replace(QRegularExpression("[^a-zA-Z0-9@._+-]"), ""); | 
					
						
							| 
									
										
										
										
											2015-06-01 13:09:45 -07:00
										 |  |  |  | 	if (email.isEmpty() || same_string(prefs.cloud_storage_password, "")) | 
					
						
							|  |  |  |  | 		return report_error("Please configure Cloud storage email and password in the preferences"); | 
					
						
							|  |  |  |  | 	if (email != prefs.cloud_storage_email_encoded) { | 
					
						
							| 
									
										
										
										
											2017-11-18 19:57:50 +01:00
										 |  |  |  | 		free((void *)prefs.cloud_storage_email_encoded); | 
					
						
							| 
									
										
										
										
											2015-06-01 13:09:45 -07:00
										 |  |  |  | 		prefs.cloud_storage_email_encoded = strdup(qPrintable(email)); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-15 06:05:00 -07:00
										 |  |  |  | 	filename = QString(QString(prefs.cloud_git_url) + "/%1[%1]").arg(email); | 
					
						
							| 
									
										
										
										
											2015-09-23 12:20:21 -07:00
										 |  |  |  | 	if (verbose) | 
					
						
							|  |  |  |  | 		qDebug() << "cloud URL set as" << filename; | 
					
						
							| 
									
										
										
										
											2015-06-01 13:09:45 -07:00
										 |  |  |  | 	return 0; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-12 06:24:48 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-23 11:13:07 +02:00
										 |  |  |  | extern "C" char *cloud_url() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString filename; | 
					
						
							|  |  |  |  | 	getCloudURL(filename); | 
					
						
							|  |  |  |  | 	return strdup(filename.toUtf8().data()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-13 09:08:39 -07:00
										 |  |  |  | extern "C" bool isCloudUrl(const char *filename) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QString email = QString(prefs.cloud_storage_email); | 
					
						
							|  |  |  |  | 	email.replace(QRegularExpression("[^a-zA-Z0-9@._+-]"), ""); | 
					
						
							|  |  |  |  | 	if (!email.isEmpty() && | 
					
						
							| 
									
										
										
										
											2015-06-15 06:05:00 -07:00
										 |  |  |  | 	    QString(QString(prefs.cloud_git_url) + "/%1[%1]").arg(email) == filename) | 
					
						
							| 
									
										
										
										
											2015-06-13 09:08:39 -07:00
										 |  |  |  | 		return true; | 
					
						
							|  |  |  |  | 	return false; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-12 06:24:48 -07:00
										 |  |  |  | extern "C" bool getProxyString(char **buffer) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (prefs.proxy_type == QNetworkProxy::HttpProxy) { | 
					
						
							|  |  |  |  | 		QString proxy; | 
					
						
							|  |  |  |  | 		if (prefs.proxy_auth) | 
					
						
							|  |  |  |  | 			proxy = QString("http://%1:%2@%3:%4").arg(prefs.proxy_user).arg(prefs.proxy_pass) | 
					
						
							|  |  |  |  | 					.arg(prefs.proxy_host).arg(prefs.proxy_port); | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			proxy = QString("http://%1:%2").arg(prefs.proxy_host).arg(prefs.proxy_port); | 
					
						
							|  |  |  |  | 		if (buffer) | 
					
						
							|  |  |  |  | 			*buffer = strdup(qPrintable(proxy)); | 
					
						
							|  |  |  |  | 		return true; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-12 06:31:16 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-13 18:25:36 -07:00
										 |  |  |  | extern "C" void subsurface_mkdir(const char *dir) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QDir directory; | 
					
						
							|  |  |  |  | 	if (!directory.mkpath(QString(dir))) | 
					
						
							|  |  |  |  | 		qDebug() << "failed to create path" << dir; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-16 20:30:06 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" void parse_display_units(char *line) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	qDebug() << line; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-08-18 10:03:51 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-22 07:05:13 -07:00
										 |  |  |  | static QByteArray currentApplicationState; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QByteArray getCurrentAppState() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return currentApplicationState; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void setCurrentAppState(QByteArray state) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	currentApplicationState = state; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 10:03:51 +02:00
										 |  |  |  | extern "C" bool in_planner() | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-22 07:05:13 -07:00
										 |  |  |  | 	return (currentApplicationState == "PlanDive" || currentApplicationState == "EditPlannedDive"); | 
					
						
							| 
									
										
										
										
											2015-08-18 10:03:51 +02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-14 10:43:37 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-07 03:01:14 +01:00
										 |  |  |  | extern "C" enum deco_mode decoMode() | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-01-07 03:11:19 +01:00
										 |  |  |  | 	return in_planner() ? prefs.planner_deco_mode : prefs.display_deco_mode; | 
					
						
							| 
									
										
										
										
											2017-01-07 03:01:14 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-14 10:43:37 -08:00
										 |  |  |  | void init_proxy() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QNetworkProxy proxy; | 
					
						
							|  |  |  |  | 	proxy.setType(QNetworkProxy::ProxyType(prefs.proxy_type)); | 
					
						
							|  |  |  |  | 	proxy.setHostName(prefs.proxy_host); | 
					
						
							|  |  |  |  | 	proxy.setPort(prefs.proxy_port); | 
					
						
							|  |  |  |  | 	if (prefs.proxy_auth) { | 
					
						
							|  |  |  |  | 		proxy.setUser(prefs.proxy_user); | 
					
						
							|  |  |  |  | 		proxy.setPassword(prefs.proxy_pass); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	QNetworkProxy::setApplicationProxy(proxy); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-18 17:57:13 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | QString getUUID() | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-11 11:26:37 -03:00
										 |  |  |  | 	// This is a correct usage of QSettings,
 | 
					
						
							|  |  |  |  | 	// it's not a setting per se - the user cannot change it
 | 
					
						
							|  |  |  |  | 	// and thus, don't need to be on the prefs structure
 | 
					
						
							|  |  |  |  | 	// and this is the *only* point of access from it,
 | 
					
						
							| 
									
										
										
										
											2015-11-18 17:57:13 -08:00
										 |  |  |  | 	QString uuidString; | 
					
						
							|  |  |  |  | 	QSettings settings; | 
					
						
							|  |  |  |  | 	settings.beginGroup("UpdateManager"); | 
					
						
							|  |  |  |  | 	if (settings.contains("UUID")) { | 
					
						
							|  |  |  |  | 		uuidString = settings.value("UUID").toString(); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		QUuid uuid = QUuid::createUuid(); | 
					
						
							|  |  |  |  | 		uuidString = uuid.toString(); | 
					
						
							|  |  |  |  | 		settings.setValue("UUID", uuidString); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	uuidString.replace("{", "").replace("}", ""); | 
					
						
							|  |  |  |  | 	return uuidString; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-05-07 09:41:27 +03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-07 13:41:09 +03:00
										 |  |  |  | int parse_seabear_header(const char *filename, char **params, int pnr) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QFile f(filename); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	f.open(QFile::ReadOnly); | 
					
						
							|  |  |  |  | 	QString parseLine = f.readLine(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-07 14:19:58 +03:00
										 |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * Parse dive number from Seabear CSV header | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 		if (parseLine.contains("//DIVE NR: ")) { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("diveNro"); | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup(parseLine.replace(QString::fromLatin1("//DIVE NR: "), QString::fromLatin1("")).toUtf8().data()); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-07 15:53:35 +03:00
										 |  |  |  | 	f.seek(0); | 
					
						
							| 
									
										
										
										
											2017-05-07 14:19:58 +03:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-07 13:41:09 +03:00
										 |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * Parse header - currently only interested in sample | 
					
						
							|  |  |  |  | 	 * interval and hardware version. If we have old format | 
					
						
							|  |  |  |  | 	 * the interval value is missing from the header. | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 		if (parseLine.contains("//Hardware Version: ")) { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("hw"); | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup(parseLine.replace(QString::fromLatin1("//Hardware Version: "), QString::fromLatin1("\"Seabear ")).trimmed().append("\"").toUtf8().data()); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-07 15:53:35 +03:00
										 |  |  |  | 	f.seek(0); | 
					
						
							| 
									
										
										
										
											2017-05-07 13:41:09 +03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2017-05-07 15:34:27 +03:00
										 |  |  |  | 	 * Grab the sample interval | 
					
						
							| 
									
										
										
										
											2017-05-07 13:41:09 +03:00
										 |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 		if (parseLine.contains("//Log interval: ")) { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("delta"); | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup(parseLine.remove(QString::fromLatin1("//Log interval: ")).trimmed().remove(QString::fromLatin1(" s")).toUtf8().data()); | 
					
						
							| 
									
										
										
										
											2017-05-07 15:34:27 +03:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-07 15:53:35 +03:00
										 |  |  |  | 	f.seek(0); | 
					
						
							| 
									
										
										
										
											2017-05-07 15:34:27 +03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * Dive mode, can be: OC, APNEA, BOTTOM TIMER, CCR, CCR SENSORBOARD | 
					
						
							|  |  |  |  | 	 * Note that we scan over the "Log interval" on purpose | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 		QString needle = "//Mode: "; | 
					
						
							|  |  |  |  | 		if (parseLine.contains(needle)) { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("diveMode"); | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup(parseLine.replace(needle, QString::fromLatin1("")).prepend("\"").append("\"").toUtf8().data()); | 
					
						
							| 
									
										
										
										
											2017-05-07 13:41:09 +03:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-07 15:53:35 +03:00
										 |  |  |  | 	f.seek(0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-07 21:22:00 +03:00
										 |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * Grabbing some fields for the extradata | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 		QString needle = "//Firmware Version: "; | 
					
						
							|  |  |  |  | 		if (parseLine.contains(needle)) { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("Firmware"); | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup(parseLine.replace(needle, QString::fromLatin1("")).prepend("\"").append("\"").toUtf8().data()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	f.seek(0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 		QString needle = "//Serial number: "; | 
					
						
							|  |  |  |  | 		if (parseLine.contains(needle)) { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("Serial"); | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup(parseLine.replace(needle, QString::fromLatin1("")).prepend("\"").append("\"").toUtf8().data()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	f.seek(0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 		QString needle = "//GF: "; | 
					
						
							|  |  |  |  | 		if (parseLine.contains(needle)) { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("GF"); | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup(parseLine.replace(needle, QString::fromLatin1("")).prepend("\"").append("\"").toUtf8().data()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	f.seek(0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-07 15:53:35 +03:00
										 |  |  |  | 	while ((parseLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) { | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-07 13:41:09 +03:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/*
 | 
					
						
							|  |  |  |  | 	 * Parse CSV fields | 
					
						
							|  |  |  |  | 	 */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	parseLine = f.readLine().trimmed(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	QStringList currColumns = parseLine.split(';'); | 
					
						
							|  |  |  |  | 	unsigned short index = 0; | 
					
						
							|  |  |  |  | 	Q_FOREACH (QString columnText, currColumns) { | 
					
						
							|  |  |  |  | 		if (columnText == "Time") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("timeField"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "Depth") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("depthField"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "Temperature") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("tempField"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "NDT") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("ndlField"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "TTS") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("ttsField"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "pO2_1") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("o2sensor1Field"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "pO2_2") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("o2sensor2Field"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "pO2_3") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("o2sensor3Field"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "Ceiling") { | 
					
						
							|  |  |  |  | 			/* TODO: Add support for dive computer reported ceiling*/ | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("ceilingField"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else if (columnText == "Tank pressure") { | 
					
						
							|  |  |  |  | 			params[pnr++] = strdup("pressureField"); | 
					
						
							|  |  |  |  | 			params[pnr++] = intdup(index++); | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			// We do not know about this value
 | 
					
						
							|  |  |  |  | 			qDebug() << "Seabear import found an un-handled field: " << columnText; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* Separator is ';' and the index for that in DiveLogImportDialog constructor is 2 */ | 
					
						
							|  |  |  |  | 	params[pnr++] = strdup("separatorIndex"); | 
					
						
							|  |  |  |  | 	params[pnr++] = intdup(2); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* And metric units */ | 
					
						
							|  |  |  |  | 	params[pnr++] = strdup("units"); | 
					
						
							|  |  |  |  | 	params[pnr++] = intdup(0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	params[pnr] = NULL; | 
					
						
							|  |  |  |  | 	f.close(); | 
					
						
							|  |  |  |  | 	return pnr; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-07 09:41:27 +03:00
										 |  |  |  | char *intdup(int index) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	char tmpbuf[21]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	snprintf(tmpbuf, sizeof(tmpbuf) - 2, "%d", index); | 
					
						
							|  |  |  |  | 	tmpbuf[20] = 0; | 
					
						
							|  |  |  |  | 	return strdup(tmpbuf); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-25 23:21:27 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | QHash<int, double> factor_cache; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 11:41:30 +02:00
										 |  |  |  | QMutex factorCacheLock; | 
					
						
							| 
									
										
										
										
											2017-08-25 23:21:27 +02:00
										 |  |  |  | extern "C" double cache_value(int tissue, int timestep, enum inertgas inertgas) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int key = (timestep << 5) + (tissue << 1); | 
					
						
							|  |  |  |  | 	if (inertgas == HE) | 
					
						
							|  |  |  |  | 		++key; | 
					
						
							| 
									
										
										
										
											2017-08-29 11:41:30 +02:00
										 |  |  |  | 	QMutexLocker locker(&factorCacheLock); | 
					
						
							| 
									
										
										
										
											2017-08-25 23:21:27 +02:00
										 |  |  |  | 	return factor_cache.value(key); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" void cache_insert(int tissue, int timestep, enum inertgas inertgas, double value) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int key = (timestep << 5) + (tissue << 1); | 
					
						
							|  |  |  |  | 	if (inertgas == HE) | 
					
						
							|  |  |  |  | 		++key; | 
					
						
							| 
									
										
										
										
											2017-08-29 11:41:30 +02:00
										 |  |  |  | 	QMutexLocker locker(&factorCacheLock); | 
					
						
							| 
									
										
										
										
											2017-08-25 23:21:27 +02:00
										 |  |  |  | 	factor_cache.insert(key, value); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-09 06:43:38 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" void print_qt_versions() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	printf("%s\n", QStringLiteral("built with Qt Version %1, runtime from Qt Version %2").arg(QT_VERSION_STR).arg(qVersion()).toUtf8().data()); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-29 11:41:30 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | QMutex planLock; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" void lock_planner() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	planLock.lock(); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" void unlock_planner() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	planLock.unlock(); | 
					
						
							|  |  |  |  | } |