| 
									
										
										
										
											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>
 | 
					
						
							| 
									
										
										
										
											2014-06-02 18:28:02 -03:00
										 |  |  |  | #include <exif.h>
 | 
					
						
							|  |  |  |  | #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) { | 
					
						
							|  |  |  |  | 		int gr = weight_in_grams % 1000; | 
					
						
							|  |  |  |  | 		int kg = weight_in_grams / 1000; | 
					
						
							| 
									
										
										
										
											2016-02-24 08:20:24 +01:00
										 |  |  |  | 		if (kg >= 20.0) | 
					
						
							|  |  |  |  | 			str = QString("%1").arg(kg + (gr >= 500 ? 1 : 0)); | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			str = QString("%1.%2").arg(kg).arg((unsigned)(gr + 50) / 100); | 
					
						
							| 
									
										
										
										
											2013-10-04 21:39:33 +03:00
										 |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		double lbs = grams_to_lbs(weight_in_grams); | 
					
						
							| 
									
										
										
										
											2016-02-24 08:20:24 +01:00
										 |  |  |  | 		if (lbs >= 40.0) | 
					
						
							|  |  |  |  | 			lbs = rint(lbs + 0.5); | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			lbs = rint(lbs + 0.05); | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							|  |  |  |  | 			while (txt[++pos].isSpace()) | 
					
						
							|  |  |  |  | 				/* 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; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	latudeg = rint(1000000 * latitude); | 
					
						
							|  |  |  |  | 	longudeg = rint(1000000 * longitude); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	/* 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) { | 
					
						
							|  |  |  |  | 			qDebug() << "cannot open stylesheet" << QLatin1String(":/xslt/") + (const char *)uri; | 
					
						
							|  |  |  |  | 			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
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-24 14:19:41 +02:00
										 |  |  |  | extern "C" timestamp_t picture_get_timestamp(char *filename) | 
					
						
							| 
									
										
										
										
											2015-03-14 15:35:47 +01:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	EXIFInfo exif; | 
					
						
							|  |  |  |  | 	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)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (!s.value("UseSystemLanguage", true).toBool()) { | 
					
						
							|  |  |  |  | 		loc = QLocale(s.value("UiLanguage", QLocale().uiLanguages().first()).toString()); | 
					
						
							|  |  |  |  | 	} 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]; | 
					
						
							| 
									
										
										
										
											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, "")) { | 
					
						
							|  |  |  |  | 			free((void*)prefs.date_format); | 
					
						
							|  |  |  |  | 			prefs.date_format = strdup(qPrintable(dateFormat)); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if (!prefs.date_format_override || same_string(prefs.date_format_short, "")) { | 
					
						
							|  |  |  |  | 			free((void*)prefs.date_format_short); | 
					
						
							|  |  |  |  | 			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", ""); | 
					
						
							|  |  |  |  | 		free((void*)prefs.time_format); | 
					
						
							|  |  |  |  | 		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")); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* these methods retrieve used gas per cylinder */ | 
					
						
							|  |  |  |  | static unsigned start_pressure(cylinder_t *cyl) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return cyl->start.mbar ?: cyl->sample_start.mbar; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static unsigned end_pressure(cylinder_t *cyl) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return cyl->end.mbar ?: cyl->sample_end.mbar; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_cylinder_used_gas_string(cylinder_t *cyl, bool showunit) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int decimals; | 
					
						
							|  |  |  |  | 	const char *unit; | 
					
						
							|  |  |  |  | 	double gas_usage; | 
					
						
							|  |  |  |  | 	/* Get the cylinder gas use in mbar */ | 
					
						
							|  |  |  |  | 	gas_usage = start_pressure(cyl) - end_pressure(cyl); | 
					
						
							|  |  |  |  | 	/* Can we turn it into a volume? */ | 
					
						
							|  |  |  |  | 	if (cyl->type.size.mliter) { | 
					
						
							|  |  |  |  | 		gas_usage = bar_to_atm(gas_usage / 1000); | 
					
						
							|  |  |  |  | 		gas_usage *= cyl->type.size.mliter; | 
					
						
							|  |  |  |  | 		gas_usage = get_volume_units(gas_usage, &decimals, &unit); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		gas_usage = get_pressure_units(gas_usage, &unit); | 
					
						
							|  |  |  |  | 		decimals = 0; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	// translate("gettextFromC","%.*f %s"
 | 
					
						
							|  |  |  |  | 	return QString("%1 %2").arg(gas_usage, 0, 'f', decimals).arg(showunit ? unit : ""); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 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); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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)) { | 
					
						
							| 
									
										
										
										
											2016-01-01 00:32:30 -08:00
										 |  |  |  | 		mm = 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: | 
					
						
							|  |  |  |  | 			mm = number * 1000; | 
					
						
							|  |  |  |  | 			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)) { | 
					
						
							| 
									
										
										
										
											2016-02-05 22:51:46 -08:00
										 |  |  |  | 		grams = rint(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: | 
					
						
							|  |  |  |  | 			grams = rint(number * 1000); | 
					
						
							|  |  |  |  | 			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)) { | 
					
						
							| 
									
										
										
										
											2016-02-09 19:52:02 +01:00
										 |  |  |  | 		mbar = rint(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: | 
					
						
							|  |  |  |  | 			mbar = rint(number * 1000); | 
					
						
							|  |  |  |  | 			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; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 09:09:48 -08:00
										 |  |  |  | QString get_dive_duration_string(timestamp_t when, QString hourText, QString minutesText) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	int hrs, mins; | 
					
						
							|  |  |  |  | 	mins = (when + 59) / 60; | 
					
						
							|  |  |  |  | 	hrs = mins / 60; | 
					
						
							|  |  |  |  | 	mins -= hrs * 60; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	QString displayTime; | 
					
						
							|  |  |  |  | 	if (hrs) | 
					
						
							|  |  |  |  | 		displayTime = QString("%1%2%3%4").arg(hrs).arg(hourText).arg(mins, 2, 10, QChar('0')).arg(minutesText); | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 		displayTime = QString("%1%2").arg(mins).arg(minutesText); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return displayTime; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 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()); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2015-10-06 21:08:27 +02:00
										 |  |  |  | 	QDateTime localTime = QDateTime::fromTime_t(when); | 
					
						
							|  |  |  |  | 	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 { | 
					
						
							| 
									
										
										
										
											2015-10-29 11:24:47 +03:00
										 |  |  |  | 		ret = localTime.date().toString("MMM yy") + 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
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | extern "C" char * hashstring(char * filename) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	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()); | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void write_hashes() | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-23 11:13:07 +02:00
										 |  |  |  | 	QSaveFile hashfile(hashfile_name()); | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											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
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | QString localFilePath(const QString originalFilename) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											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
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString fileFromHash(char *hash) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	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) { | 
					
						
							|  |  |  |  | 	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) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-13 10:33:30 -07:00
										 |  |  |  | 	char *oldHash = copy_string(picture->hash); | 
					
						
							| 
									
										
										
										
											2015-09-17 16:56:58 +02:00
										 |  |  |  | 	learnHash(picture, hashFile(QString(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; | 
					
						
							|  |  |  |  | 	if (!hashOf.contains(filename)) | 
					
						
							| 
									
										
										
										
											2016-03-15 21:31:59 +01:00
										 |  |  |  | 		QtConcurrent::run(hashPicture, clone_picture(picture)); | 
					
						
							| 
									
										
										
										
											2015-09-17 16:56:58 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 21:32:12 -03:00
										 |  |  |  | void learnImages(const QDir dir, int max_recursions) | 
					
						
							| 
									
										
										
										
											2015-02-26 14:44:27 +01:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	QStringList filters, files; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	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 format, QImageReader::supportedImageFormats()) { | 
					
						
							|  |  |  |  | 		filters.append(QString("*.").append(format)); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	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) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	EXIFInfo exif; | 
					
						
							|  |  |  |  | 	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; | 
					
						
							|  |  |  |  | 	p->longitude.udeg= lrint(1000000.0 * exif.GeoLocation.Longitude); | 
					
						
							|  |  |  |  | 	p->latitude.udeg  = lrint(1000000.0 * exif.GeoLocation.Latitude); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 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; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | QString get_divepoint_gas_string(const divedatapoint &p) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return get_gas_string(p.gasmix); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							|  |  |  |  | 	weight.grams = rint(value * 1000); | 
					
						
							|  |  |  |  | 	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; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	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: | 
					
						
							|  |  |  |  | 	depth.mm = rint(value * 1000); | 
					
						
							|  |  |  |  | 	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: | 
					
						
							|  |  |  |  | 	pressure.mbar = rint(value * 1000); | 
					
						
							|  |  |  |  | 	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: | 
					
						
							|  |  |  |  | 	volume.mliter = rint(value * 1000); | 
					
						
							|  |  |  |  | 	return volume; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | fraction_t string_to_fraction(const char *str) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	const char *end; | 
					
						
							|  |  |  |  | 	double value = strtod_flags(str, &end, 0); | 
					
						
							|  |  |  |  | 	fraction_t fraction; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	fraction.permille = rint(value * 10); | 
					
						
							|  |  |  |  | 	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) { | 
					
						
							|  |  |  |  | 		free(prefs.cloud_storage_email_encoded); | 
					
						
							|  |  |  |  | 		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-07-25 22:08:25 -07:00
										 |  |  |  | void loadPreferences() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	QSettings s; | 
					
						
							|  |  |  |  | 	QVariant v; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-22 16:55:03 -02:00
										 |  |  |  | 	uiLanguage(NULL); | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | 	s.beginGroup("Units"); | 
					
						
							|  |  |  |  | 	if (s.value("unit_system").toString() == "metric") { | 
					
						
							|  |  |  |  | 		prefs.unit_system = METRIC; | 
					
						
							|  |  |  |  | 		prefs.units = SI_units; | 
					
						
							|  |  |  |  | 	} else if (s.value("unit_system").toString() == "imperial") { | 
					
						
							|  |  |  |  | 		prefs.unit_system = IMPERIAL; | 
					
						
							|  |  |  |  | 		prefs.units = IMPERIAL_units; | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		prefs.unit_system = PERSONALIZE; | 
					
						
							|  |  |  |  | 		GET_UNIT("length", length, units::FEET, units::METERS); | 
					
						
							|  |  |  |  | 		GET_UNIT("pressure", pressure, units::PSI, units::BAR); | 
					
						
							|  |  |  |  | 		GET_UNIT("volume", volume, units::CUFT, units::LITER); | 
					
						
							|  |  |  |  | 		GET_UNIT("temperature", temperature, units::FAHRENHEIT, units::CELSIUS); | 
					
						
							|  |  |  |  | 		GET_UNIT("weight", weight, units::LBS, units::KG); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	GET_UNIT("vertical_speed_time", vertical_speed_time, units::MINUTES, units::SECONDS); | 
					
						
							|  |  |  |  | 	GET_BOOL("coordinates", coordinates_traditional); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 	s.beginGroup("TecDetails"); | 
					
						
							|  |  |  |  | 	GET_BOOL("po2graph", pp_graphs.po2); | 
					
						
							|  |  |  |  | 	GET_BOOL("pn2graph", pp_graphs.pn2); | 
					
						
							|  |  |  |  | 	GET_BOOL("phegraph", pp_graphs.phe); | 
					
						
							|  |  |  |  | 	GET_DOUBLE("po2threshold", pp_graphs.po2_threshold); | 
					
						
							|  |  |  |  | 	GET_DOUBLE("pn2threshold", pp_graphs.pn2_threshold); | 
					
						
							|  |  |  |  | 	GET_DOUBLE("phethreshold", pp_graphs.phe_threshold); | 
					
						
							|  |  |  |  | 	GET_BOOL("mod", mod); | 
					
						
							|  |  |  |  | 	GET_DOUBLE("modpO2", modpO2); | 
					
						
							|  |  |  |  | 	GET_BOOL("ead", ead); | 
					
						
							|  |  |  |  | 	GET_BOOL("redceiling", redceiling); | 
					
						
							|  |  |  |  | 	GET_BOOL("dcceiling", dcceiling); | 
					
						
							|  |  |  |  | 	GET_BOOL("calcceiling", calcceiling); | 
					
						
							|  |  |  |  | 	GET_BOOL("calcceiling3m", calcceiling3m); | 
					
						
							|  |  |  |  | 	GET_BOOL("calcndltts", calcndltts); | 
					
						
							|  |  |  |  | 	GET_BOOL("calcalltissues", calcalltissues); | 
					
						
							|  |  |  |  | 	GET_BOOL("hrgraph", hrgraph); | 
					
						
							|  |  |  |  | 	GET_BOOL("tankbar", tankbar); | 
					
						
							| 
									
										
										
										
											2016-01-25 18:15:06 -02:00
										 |  |  |  | 	GET_BOOL("RulerBar", rulergraph); | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | 	GET_BOOL("percentagegraph", percentagegraph); | 
					
						
							|  |  |  |  | 	GET_INT("gflow", gflow); | 
					
						
							|  |  |  |  | 	GET_INT("gfhigh", gfhigh); | 
					
						
							|  |  |  |  | 	GET_BOOL("gf_low_at_maxdepth", gf_low_at_maxdepth); | 
					
						
							|  |  |  |  | 	GET_BOOL("show_ccr_setpoint",show_ccr_setpoint); | 
					
						
							|  |  |  |  | 	GET_BOOL("show_ccr_sensors",show_ccr_sensors); | 
					
						
							|  |  |  |  | 	GET_BOOL("zoomed_plot", zoomed_plot); | 
					
						
							|  |  |  |  | 	set_gf(prefs.gflow, prefs.gfhigh, prefs.gf_low_at_maxdepth); | 
					
						
							|  |  |  |  | 	GET_BOOL("show_sac", show_sac); | 
					
						
							|  |  |  |  | 	GET_BOOL("display_unused_tanks", display_unused_tanks); | 
					
						
							|  |  |  |  | 	GET_BOOL("show_average_depth", show_average_depth); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.beginGroup("GeneralSettings"); | 
					
						
							|  |  |  |  | 	GET_TXT("default_filename", default_filename); | 
					
						
							|  |  |  |  | 	GET_INT("default_file_behavior", default_file_behavior); | 
					
						
							|  |  |  |  | 	if (prefs.default_file_behavior == UNDEFINED_DEFAULT_FILE) { | 
					
						
							|  |  |  |  | 		// undefined, so check if there's a filename set and
 | 
					
						
							|  |  |  |  | 		// use that, otherwise go with no default file
 | 
					
						
							|  |  |  |  | 		if (QString(prefs.default_filename).isEmpty()) | 
					
						
							|  |  |  |  | 			prefs.default_file_behavior = NO_DEFAULT_FILE; | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 			prefs.default_file_behavior = LOCAL_DEFAULT_FILE; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	GET_TXT("default_cylinder", default_cylinder); | 
					
						
							|  |  |  |  | 	GET_BOOL("use_default_file", use_default_file); | 
					
						
							|  |  |  |  | 	GET_INT("defaultsetpoint", defaultsetpoint); | 
					
						
							|  |  |  |  | 	GET_INT("o2consumption", o2consumption); | 
					
						
							|  |  |  |  | 	GET_INT("pscr_ratio", pscr_ratio); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.beginGroup("Display"); | 
					
						
							|  |  |  |  | 	// get the font from the settings or our defaults
 | 
					
						
							|  |  |  |  | 	// respect the system default font size if none is explicitly set
 | 
					
						
							|  |  |  |  | 	QFont defaultFont = s.value("divelist_font", prefs.divelist_font).value<QFont>(); | 
					
						
							|  |  |  |  | 	if (IS_FP_SAME(system_divelist_default_font_size, -1.0)) { | 
					
						
							|  |  |  |  | 		prefs.font_size = qApp->font().pointSizeF(); | 
					
						
							|  |  |  |  | 		system_divelist_default_font_size = prefs.font_size; // this way we don't save it on exit
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	prefs.font_size = s.value("font_size", prefs.font_size).toFloat(); | 
					
						
							|  |  |  |  | 	// painful effort to ignore previous default fonts on Windows - ridiculous
 | 
					
						
							|  |  |  |  | 	QString fontName = defaultFont.toString(); | 
					
						
							|  |  |  |  | 	if (fontName.contains(",")) | 
					
						
							|  |  |  |  | 		fontName = fontName.left(fontName.indexOf(",")); | 
					
						
							|  |  |  |  | 	if (subsurface_ignore_font(fontName.toUtf8().constData())) { | 
					
						
							|  |  |  |  | 		defaultFont = QFont(prefs.divelist_font); | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		free((void *)prefs.divelist_font); | 
					
						
							|  |  |  |  | 		prefs.divelist_font = strdup(fontName.toUtf8().constData()); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	defaultFont.setPointSizeF(prefs.font_size); | 
					
						
							|  |  |  |  | 	qApp->setFont(defaultFont); | 
					
						
							|  |  |  |  | 	GET_INT("displayinvalid", display_invalid_dives); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.beginGroup("Animations"); | 
					
						
							|  |  |  |  | 	GET_INT("animation_speed", animation_speed); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.beginGroup("Network"); | 
					
						
							|  |  |  |  | 	GET_INT_DEF("proxy_type", proxy_type, QNetworkProxy::DefaultProxy); | 
					
						
							|  |  |  |  | 	GET_TXT("proxy_host", proxy_host); | 
					
						
							|  |  |  |  | 	GET_INT("proxy_port", proxy_port); | 
					
						
							|  |  |  |  | 	GET_BOOL("proxy_auth", proxy_auth); | 
					
						
							|  |  |  |  | 	GET_TXT("proxy_user", proxy_user); | 
					
						
							|  |  |  |  | 	GET_TXT("proxy_pass", proxy_pass); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s.beginGroup("CloudStorage"); | 
					
						
							|  |  |  |  | 	GET_TXT("email", cloud_storage_email); | 
					
						
							|  |  |  |  | 	GET_BOOL("save_password_local", save_password_local); | 
					
						
							|  |  |  |  | 	if (prefs.save_password_local) { // GET_TEXT macro is not a single statement
 | 
					
						
							|  |  |  |  | 		GET_TXT("password", cloud_storage_password); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	GET_INT("cloud_verification_status", cloud_verification_status); | 
					
						
							|  |  |  |  | 	GET_BOOL("cloud_background_sync", cloud_background_sync); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// creating the git url here is simply a convenience when C code wants
 | 
					
						
							|  |  |  |  | 	// to compare against that git URL - it's always derived from the base URL
 | 
					
						
							|  |  |  |  | 	GET_TXT("cloud_base_url", cloud_base_url); | 
					
						
							|  |  |  |  | 	prefs.cloud_git_url = strdup(qPrintable(QString(prefs.cloud_base_url) + "/git")); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-06 08:53:54 +01:00
										 |  |  |  | 	// Subsurface webservice id is stored outside of the groups
 | 
					
						
							|  |  |  |  | 	GET_TXT("subsurface_webservice_uid", userid); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-14 09:10:06 -08:00
										 |  |  |  | 	// but the related time / distance threshold (only used in the mobile app)
 | 
					
						
							|  |  |  |  | 	// are in their own group
 | 
					
						
							|  |  |  |  | 	s.beginGroup("locationService"); | 
					
						
							|  |  |  |  | 	GET_INT("distance_threshold", distance_threshold); | 
					
						
							|  |  |  |  | 	GET_INT("time_threshold", time_threshold); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | 	// GeoManagement
 | 
					
						
							|  |  |  |  | 	s.beginGroup("geocoding"); | 
					
						
							| 
									
										
										
										
											2015-10-05 23:02:55 +01:00
										 |  |  |  | #ifdef DISABLED
 | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | 	GET_BOOL("enable_geocoding", geocoding.enable_geocoding); | 
					
						
							| 
									
										
										
										
											2015-10-05 23:02:55 +01:00
										 |  |  |  | 	GET_BOOL("parse_dive_without_gps", geocoding.parse_dive_without_gps); | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | 	GET_BOOL("tag_existing_dives", geocoding.tag_existing_dives); | 
					
						
							| 
									
										
										
										
											2015-10-05 23:02:55 +01:00
										 |  |  |  | #else
 | 
					
						
							|  |  |  |  | 	prefs.geocoding.enable_geocoding = true; | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | 	GET_ENUM("cat0", taxonomy_category, geocoding.category[0]); | 
					
						
							|  |  |  |  | 	GET_ENUM("cat1", taxonomy_category, geocoding.category[1]); | 
					
						
							|  |  |  |  | 	GET_ENUM("cat2", taxonomy_category, geocoding.category[2]); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 11:18:20 -07:00
										 |  |  |  | 	// GPS service time and distance thresholds
 | 
					
						
							|  |  |  |  | 	s.beginGroup("LocationService"); | 
					
						
							|  |  |  |  | 	GET_INT("time_threshold", time_threshold); | 
					
						
							|  |  |  |  | 	GET_INT("distance_threshold", distance_threshold); | 
					
						
							|  |  |  |  | 	s.endGroup(); | 
					
						
							| 
									
										
										
										
											2015-07-25 22:08:25 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 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() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	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; | 
					
						
							|  |  |  |  | } |