1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-27 21:24:47 +01:00

Android port

This commit is contained in:
Martin Tůma 2022-05-28 14:05:14 +02:00
parent e701ad0ed0
commit ba0b7c62a4
41 changed files with 913 additions and 112 deletions

View File

@ -1,4 +1,4 @@
version: 10.8.{build} version: 11.0.{build}
configuration: configuration:
- Release - Release

View File

@ -1,9 +1,9 @@
unix:!macx { unix:!macx:!android {
TARGET = gpxsee TARGET = gpxsee
} else { } else {
TARGET = GPXSee TARGET = GPXSee
} }
VERSION = 10.8 VERSION = 11.0
QT += core \ QT += core \
gui \ gui \
@ -13,7 +13,8 @@ QT += core \
concurrent \ concurrent \
widgets \ widgets \
printsupport \ printsupport \
positioning positioning \
svg
greaterThan(QT_MAJOR_VERSION, 5) { greaterThan(QT_MAJOR_VERSION, 5) {
QT += openglwidgets \ QT += openglwidgets \
core5compat core5compat
@ -24,6 +25,7 @@ INCLUDEPATH += ./src
HEADERS += src/common/config.h \ HEADERS += src/common/config.h \
src/GUI/crosshairitem.h \ src/GUI/crosshairitem.h \
src/GUI/motioninfoitem.h \ src/GUI/motioninfoitem.h \
src/GUI/navigationwidget.h \
src/GUI/pluginparameters.h \ src/GUI/pluginparameters.h \
src/common/garmin.h \ src/common/garmin.h \
src/common/coordinates.h \ src/common/coordinates.h \
@ -246,6 +248,7 @@ HEADERS += src/common/config.h \
SOURCES += src/main.cpp \ SOURCES += src/main.cpp \
src/GUI/crosshairitem.cpp \ src/GUI/crosshairitem.cpp \
src/GUI/motioninfoitem.cpp \ src/GUI/motioninfoitem.cpp \
src/GUI/navigationwidget.cpp \
src/GUI/pluginparameters.cpp \ src/GUI/pluginparameters.cpp \
src/common/coordinates.cpp \ src/common/coordinates.cpp \
src/common/rectc.cpp \ src/common/rectc.cpp \
@ -504,7 +507,7 @@ win32 {
NOGDI NOGDI
} }
unix:!macx { unix:!macx:!android {
isEmpty(PREFIX):PREFIX = /usr/local isEmpty(PREFIX):PREFIX = /usr/local
maps.files = $$files(pkg/maps/*) maps.files = $$files(pkg/maps/*)
@ -524,3 +527,39 @@ unix:!macx {
target.path = $$PREFIX/bin target.path = $$PREFIX/bin
INSTALLS += target maps csv symbols locale icon desktop mime INSTALLS += target maps csv symbols locale icon desktop mime
} }
android {
defineReplace(versionCode) {
segments = $$split(1, ".")
for (segment, segments): \
vCode = "$$first(vCode)$$format_number($$segment, width=3 zeropad)"
contains(ANDROID_TARGET_ARCH, armeabi-v7a): \
suffix = 0
contains(ANDROID_TARGET_ARCH, arm64-v8a): \
suffix = 1
contains(ANDROID_TARGET_ARCH, x86): \
suffix = 2
contains(ANDROID_TARGET_ARCH, x86_64): \
suffix = 3
return($$first(vCode)$$first(suffix))
}
include($$OPENSSL_PATH/openssl.pri)
ANDROID_VERSION_NAME = $$VERSION
ANDROID_VERSION_CODE = $$versionCode($$ANDROID_VERSION_NAME)
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/pkg/android
DISTFILES += \
pkg/android/AndroidManifest.xml \
pkg/android/build.gradle \
pkg/android/res/values/libs.xml
maps.files = $$files(pkg/maps/*)
maps.path = /assets/maps
csv.files = $$files(pkg/csv/*)
csv.path = /assets/csv
symbols.files = $$files(icons/symbols/*.png)
symbols.path = /assets/symbols
INSTALLS += maps csv symbols
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.gpxsee.gpxsee" android:installLocation="auto" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:versionName="-- %%INSERT_VERSION_NAME%% --">
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:extractNativeLibs="true" android:hardwareAccelerated="true" android:label="-- %%INSERT_APP_NAME%% --" android:requestLegacyExternalStorage="true" android:allowNativeHeapPointerTagging="false" android:icon="@drawable/icon">
<activity android:name="org.qtproject.qt.android.bindings.QtActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:label="-- %%INSERT_APP_NAME%% --" android:launchMode="singleTop" android:screenOrientation="unspecified">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.arguments" android:value="-- %%INSERT_APP_ARGUMENTS%% --"/>
<meta-data android:name="android.app.extract_android_style" android:value="minimal"/>
</activity>
</application>
</manifest>

78
pkg/android/build.gradle Normal file
View File

@ -0,0 +1,78 @@
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.2'
}
}
repositories {
google()
mavenCentral()
}
apply plugin: 'com.android.application'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qtAndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
ndkVersion androidNdkVersion
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qtAndroidDir + '/res', 'res']
resources.srcDirs = ['resources']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
tasks.withType(JavaCompile) {
options.incremental = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
abortOnError false
}
// Do not compress Qt binary resources file
aaptOptions {
noCompress 'rcc'
}
defaultConfig {
resConfig "en"
minSdkVersion qtMinSdkVersion
targetSdkVersion qtTargetSdkVersion
ndk.abiFilters = qtTargetAbiList.split(",")
}
}

View File

@ -0,0 +1,14 @@
# Project-wide Gradle settings.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2500m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# Enable building projects in parallel
org.gradle.parallel=true
# Gradle caching allows reusing the build artifacts from a previous
# build with the same inputs. However, over time, the cache size will
# grow. Uncomment the following line to enable it.
#org.gradle.caching=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,20 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. -->
<array name="bundled_libs">
<!-- %%INSERT_EXTRA_LIBS%% -->
</array>
<array name="qt_libs">
<!-- %%INSERT_QT_LIBS%% -->
</array>
<array name="load_local_libs">
<!-- %%INSERT_LOCAL_LIBS%% -->
</array>
<string name="static_init_classes"><!-- %%INSERT_INIT_CLASSES%% --></string>
<string name="use_local_qt_libs"><!-- %%USE_LOCAL_QT_LIBS%% --></string>
<string name="bundle_local_qt_libs"><!-- %%BUNDLE_LOCAL_QT_LIBS%% --></string>
</resources>

View File

@ -37,7 +37,7 @@ Unicode true
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "10.8" !define VERSION "11.0"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}_x64.exe" OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -61,6 +61,10 @@ App::App(int &argc, char **argv) : QApplication(argc, argv)
Waypoint::loadSymbolIcons(ProgramPaths::symbolsDir()); Waypoint::loadSymbolIcons(ProgramPaths::symbolsDir());
_gui = new GUI(); _gui = new GUI();
#ifdef Q_OS_ANDROID
connect(this, &App::applicationStateChanged, this, &App::appStateChanged);
#endif // Q_OS_ANDROID
} }
App::~App() App::~App()
@ -93,6 +97,14 @@ int App::run()
return exec(); return exec();
} }
#ifdef Q_OS_ANDROID
void App::appStateChanged(Qt::ApplicationState state)
{
if (state == Qt::ApplicationSuspended)
_gui->writeSettings();
}
#endif // Q_OS_ANDROID
bool App::event(QEvent *event) bool App::event(QEvent *event)
{ {
if (event->type() == QEvent::FileOpen) { if (event->type() == QEvent::FileOpen) {

View File

@ -5,7 +5,7 @@
class GUI; class GUI;
class App : QApplication class App : public QApplication
{ {
Q_OBJECT Q_OBJECT
@ -17,6 +17,11 @@ public:
protected: protected:
bool event(QEvent *event); bool event(QEvent *event);
#ifdef Q_OS_ANDROID
private slots:
void appStateChanged(Qt::ApplicationState state);
#endif // Q_OS_ANDROID
private: private:
void loadDatums(); void loadDatums();
void loadPCSs(); void loadPCSs();

View File

@ -24,10 +24,17 @@ void CadenceGraph::setInfo()
if (_showTracks) { if (_showTracks) {
QLocale l(QLocale::system()); QLocale l(QLocale::system());
#ifdef Q_OS_ANDROID
GraphView::addInfo(tr("Avg"), l.toString(avg() * yScale() + yOffset(),
'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Max"), l.toString(max() * yScale() + yOffset(),
'f', 1) + UNIT_SPACE + yUnits());
#else // Q_OS_ANDROID
GraphView::addInfo(tr("Average"), l.toString(avg() * yScale() GraphView::addInfo(tr("Average"), l.toString(avg() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits()); + yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale() GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits()); + yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else } else
clearInfo(); clearInfo();
} }

View File

@ -52,8 +52,7 @@ void ColorBox::paintEvent(QPaintEvent *event)
void ColorBox::mousePressEvent(QMouseEvent *event) void ColorBox::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() != Qt::LeftButton) if (event->button() == Qt::LeftButton) {
return;
QColorDialog::ColorDialogOptions options = _alpha QColorDialog::ColorDialogOptions options = _alpha
? QColorDialog::ColorDialogOptions(QColorDialog::ShowAlphaChannel) ? QColorDialog::ColorDialogOptions(QColorDialog::ShowAlphaChannel)
: QColorDialog::ColorDialogOptions(); : QColorDialog::ColorDialogOptions();
@ -65,6 +64,9 @@ void ColorBox::mousePressEvent(QMouseEvent *event)
} }
} }
QWidget::mousePressEvent(event);
}
void ColorBox::setColor(const QColor &color) void ColorBox::setColor(const QColor &color)
{ {
_color = color; _color = color;

View File

@ -9,10 +9,12 @@
DirSelectWidget::DirSelectWidget(QWidget *parent) : QWidget(parent) DirSelectWidget::DirSelectWidget(QWidget *parent) : QWidget(parent)
{ {
QFontMetrics fm(QApplication::font());
_edit = new QLineEdit(); _edit = new QLineEdit();
#ifndef Q_OS_ANDROID
QFontMetrics fm(QApplication::font());
_edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length() _edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length()
+ 12)); + 12));
#endif // Q_OS_ANDROID
_edit->setPlaceholderText(tr("System default")); _edit->setPlaceholderText(tr("System default"));
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
_button = new QPushButton("..."); _button = new QPushButton("...");

View File

@ -54,6 +54,16 @@ void ElevationGraph::setInfo()
else { else {
QLocale l(QLocale::system()); QLocale l(QLocale::system());
#ifdef Q_OS_ANDROID
GraphView::addInfo(tr("Up"), l.toString(ascent() * yScale(), 'f', 0)
+ UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Down"), l.toString(descent() * yScale(), 'f', 0)
+ UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Max"), l.toString(max() * yScale(), 'f', 0)
+ UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Min"), l.toString(min() * yScale(), 'f', 0)
+ UNIT_SPACE + yUnits());
#else // Q_OS_ANDROID
GraphView::addInfo(tr("Ascent"), l.toString(ascent() * yScale(), GraphView::addInfo(tr("Ascent"), l.toString(ascent() * yScale(),
'f', 0) + UNIT_SPACE + yUnits()); 'f', 0) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Descent"), l.toString(descent() * yScale(), GraphView::addInfo(tr("Descent"), l.toString(descent() * yScale(),
@ -62,6 +72,7 @@ void ElevationGraph::setInfo()
0) + UNIT_SPACE + yUnits()); 0) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale(), 'f', GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale(), 'f',
0) + UNIT_SPACE + yUnits()); 0) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} }
} }

View File

@ -5,14 +5,25 @@
FileBrowser::FileBrowser(QObject *parent) : QObject(parent) FileBrowser::FileBrowser(QObject *parent) : QObject(parent)
{ {
#ifndef Q_OS_ANDROID
_watcher = new QFileSystemWatcher(this); _watcher = new QFileSystemWatcher(this);
connect(_watcher, &QFileSystemWatcher::directoryChanged, this, connect(_watcher, &QFileSystemWatcher::directoryChanged, this,
&FileBrowser::reloadDirectory); &FileBrowser::reloadDirectory);
#endif // Q_OS_ANDROID
_index = -1; _index = -1;
} }
#ifdef Q_OS_ANDROID
void FileBrowser::setCurrentDir(const QString &path)
{
QDir dir(path);
_files = dir.entryInfoList(_filter, QDir::Files);
_index = _files.empty() ? -1 : 0;
emit listChanged();
}
#else // Q_OS_ANDROID
void FileBrowser::setCurrent(const QString &path) void FileBrowser::setCurrent(const QString &path)
{ {
QFileInfo file(path); QFileInfo file(path);
@ -28,6 +39,7 @@ void FileBrowser::setCurrent(const QString &path)
_index = _files.empty() ? -1 : _files.indexOf(file); _index = _files.empty() ? -1 : _files.indexOf(file);
} }
#endif // Q_OS_ANDROID
void FileBrowser::setFilter(const QStringList &filter) void FileBrowser::setFilter(const QStringList &filter)
{ {
@ -46,6 +58,11 @@ bool FileBrowser::isFirst() const
return (_files.size() > 0 && _index == 0); return (_files.size() > 0 && _index == 0);
} }
QString FileBrowser::current()
{
return (_index >= 0) ? _files.at(_index).absoluteFilePath() : QString();
}
QString FileBrowser::next() QString FileBrowser::next()
{ {
if (_index < 0 || _index == _files.size() - 1) if (_index < 0 || _index == _files.size() - 1)

View File

@ -14,9 +14,14 @@ class FileBrowser : public QObject
public: public:
FileBrowser(QObject *parent = 0); FileBrowser(QObject *parent = 0);
void setFilter(const QStringList &filter); #ifdef Q_OS_ANDROID
void setCurrentDir(const QString &path);
#else // Q_OS_ANDROID
void setCurrent(const QString &path); void setCurrent(const QString &path);
#endif // Q_OS_ANDROID
void setFilter(const QStringList &filter);
QString current();
QString next(); QString next();
QString prev(); QString prev();
QString last(); QString last();
@ -32,7 +37,9 @@ private slots:
void reloadDirectory(const QString &path); void reloadDirectory(const QString &path);
private: private:
#ifndef Q_OS_ANDROID
QFileSystemWatcher *_watcher; QFileSystemWatcher *_watcher;
#endif // Q_OS_ANDROID
QStringList _filter; QStringList _filter;
QFileInfoList _files; QFileInfoList _files;
int _index; int _index;

View File

@ -10,10 +10,12 @@
FileSelectWidget::FileSelectWidget(QWidget *parent) : QWidget(parent) FileSelectWidget::FileSelectWidget(QWidget *parent) : QWidget(parent)
{ {
QFontMetrics fm(QApplication::font());
_edit = new QLineEdit(); _edit = new QLineEdit();
#ifndef Q_OS_ANDROID
QFontMetrics fm(QApplication::font());
_edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length() _edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length()
+ 12)); + 12));
#endif // Q_OS_ANDROID
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
_button = new QPushButton("..."); _button = new QPushButton("...");
_button->setMaximumWidth(_button->sizeHint().width() / 2); _button->setMaximumWidth(_button->sizeHint().width() / 2);

View File

@ -24,12 +24,21 @@ void GearRatioGraph::setInfo()
if (_showTracks) { if (_showTracks) {
QLocale l(QLocale::system()); QLocale l(QLocale::system());
#ifdef Q_OS_ANDROID
GraphView::addInfo(tr("Top"), l.toString(top() * yScale(), 'f', 2)
+ UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Min"), l.toString(min() * yScale(), 'f', 2)
+ UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Max"), l.toString(max() * yScale(), 'f', 2)
+ UNIT_SPACE + yUnits());
#else // Q_OS_ANDROID
GraphView::addInfo(tr("Most used"), l.toString(top() * yScale(), GraphView::addInfo(tr("Most used"), l.toString(top() * yScale(),
'f', 2) + UNIT_SPACE + yUnits()); 'f', 2) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale(), 'f', GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale(), 'f',
2) + UNIT_SPACE + yUnits()); 2) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f', GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f',
2) + UNIT_SPACE + yUnits()); 2) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else } else
clearInfo(); clearInfo();
} }

View File

@ -53,6 +53,7 @@
#include "mapitem.h" #include "mapitem.h"
#include "mapaction.h" #include "mapaction.h"
#include "poiaction.h" #include "poiaction.h"
#include "navigationwidget.h"
#include "gui.h" #include "gui.h"
@ -72,7 +73,11 @@ GUI::GUI()
createStatusBar(); createStatusBar();
createActions(); createActions();
createMenus(); createMenus();
#ifdef Q_OS_ANDROID
createNavigation();
#else // Q_OS_ANDROID
createToolBars(); createToolBars();
#endif // Q_OS_ANDROID
createBrowser(); createBrowser();
_splitter = new QSplitter(); _splitter = new QSplitter();
@ -83,6 +88,7 @@ GUI::GUI()
_splitter->setContentsMargins(0, 0, 0, 0); _splitter->setContentsMargins(0, 0, 0, 0);
_splitter->setStretchFactor(0, 255); _splitter->setStretchFactor(0, 255);
_splitter->setStretchFactor(1, 1); _splitter->setStretchFactor(1, 1);
setCentralWidget(_splitter); setCentralWidget(_splitter);
setWindowIcon(QIcon(APP_ICON)); setWindowIcon(QIcon(APP_ICON));
@ -181,19 +187,23 @@ void GUI::createActions()
_navigationActionGroup->setEnabled(false); _navigationActionGroup->setEnabled(false);
// General actions // General actions
#if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
_exitAction = new QAction(QIcon(QUIT_ICON), tr("Quit"), this); _exitAction = new QAction(QIcon(QUIT_ICON), tr("Quit"), this);
_exitAction->setShortcut(QUIT_SHORTCUT); _exitAction->setShortcut(QUIT_SHORTCUT);
_exitAction->setMenuRole(QAction::QuitRole); _exitAction->setMenuRole(QAction::QuitRole);
connect(_exitAction, &QAction::triggered, this, &GUI::close); connect(_exitAction, &QAction::triggered, this, &GUI::close);
addAction(_exitAction); addAction(_exitAction);
#endif // Q_OS_MAC + Q_OS_ANDROID
// Help & About // Help & About
_pathsAction = new QAction(tr("Paths"), this); _pathsAction = new QAction(tr("Paths"), this);
_pathsAction->setMenuRole(QAction::NoRole); _pathsAction->setMenuRole(QAction::NoRole);
connect(_pathsAction, &QAction::triggered, this, &GUI::paths); connect(_pathsAction, &QAction::triggered, this, &GUI::paths);
#ifndef Q_OS_ANDROID
_keysAction = new QAction(tr("Keyboard controls"), this); _keysAction = new QAction(tr("Keyboard controls"), this);
_keysAction->setMenuRole(QAction::NoRole); _keysAction->setMenuRole(QAction::NoRole);
connect(_keysAction, &QAction::triggered, this, &GUI::keys); connect(_keysAction, &QAction::triggered, this, &GUI::keys);
#endif // Q_OS_ANDROID
_aboutAction = new QAction(QIcon(APP_ICON), tr("About GPXSee"), this); _aboutAction = new QAction(QIcon(APP_ICON), tr("About GPXSee"), this);
_aboutAction->setMenuRole(QAction::AboutRole); _aboutAction->setMenuRole(QAction::AboutRole);
connect(_aboutAction, &QAction::triggered, this, &GUI::about); connect(_aboutAction, &QAction::triggered, this, &GUI::about);
@ -205,6 +215,12 @@ void GUI::createActions()
connect(_openFileAction, &QAction::triggered, this, connect(_openFileAction, &QAction::triggered, this,
QOverload<>::of(&GUI::openFile)); QOverload<>::of(&GUI::openFile));
addAction(_openFileAction); addAction(_openFileAction);
#ifdef Q_OS_ANDROID
_openDirAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Open directory..."),
this);
_openDirAction->setMenuRole(QAction::NoRole);
connect(_openDirAction, &QAction::triggered, this, &GUI::openDir);
#endif // Q_OS_ANDROID
_printFileAction = new QAction(QIcon(PRINT_FILE_ICON), tr("Print..."), _printFileAction = new QAction(QIcon(PRINT_FILE_ICON), tr("Print..."),
this); this);
_printFileAction->setMenuRole(QAction::NoRole); _printFileAction->setMenuRole(QAction::NoRole);
@ -459,10 +475,12 @@ void GUI::createActions()
&GUI::showGraphSliderInfo); &GUI::showGraphSliderInfo);
// Settings actions // Settings actions
#ifndef Q_OS_ANDROID
_showToolbarsAction = new QAction(tr("Show toolbars"), this); _showToolbarsAction = new QAction(tr("Show toolbars"), this);
_showToolbarsAction->setMenuRole(QAction::NoRole); _showToolbarsAction->setMenuRole(QAction::NoRole);
_showToolbarsAction->setCheckable(true); _showToolbarsAction->setCheckable(true);
connect(_showToolbarsAction, &QAction::triggered, this, &GUI::showToolbars); connect(_showToolbarsAction, &QAction::triggered, this, &GUI::showToolbars);
#endif // Q_OS_ANDROID
ag = new QActionGroup(this); ag = new QActionGroup(this);
ag->setExclusive(true); ag->setExclusive(true);
_totalTimeAction = new QAction(tr("Total time"), this); _totalTimeAction = new QAction(tr("Total time"), this);
@ -514,6 +532,7 @@ void GUI::createActions()
_dmsAction->setCheckable(true); _dmsAction->setCheckable(true);
_dmsAction->setActionGroup(ag); _dmsAction->setActionGroup(ag);
connect(_dmsAction, &QAction::triggered, this, &GUI::setDMS); connect(_dmsAction, &QAction::triggered, this, &GUI::setDMS);
#ifndef Q_OS_ANDROID
_fullscreenAction = new QAction(QIcon(FULLSCREEN_ICON), _fullscreenAction = new QAction(QIcon(FULLSCREEN_ICON),
tr("Fullscreen mode"), this); tr("Fullscreen mode"), this);
_fullscreenAction->setMenuRole(QAction::NoRole); _fullscreenAction->setMenuRole(QAction::NoRole);
@ -521,11 +540,13 @@ void GUI::createActions()
_fullscreenAction->setShortcut(FULLSCREEN_SHORTCUT); _fullscreenAction->setShortcut(FULLSCREEN_SHORTCUT);
connect(_fullscreenAction, &QAction::triggered, this, &GUI::showFullscreen); connect(_fullscreenAction, &QAction::triggered, this, &GUI::showFullscreen);
addAction(_fullscreenAction); addAction(_fullscreenAction);
#endif // Q_OS_ANDROID
_openOptionsAction = new QAction(tr("Options..."), this); _openOptionsAction = new QAction(tr("Options..."), this);
_openOptionsAction->setMenuRole(QAction::PreferencesRole); _openOptionsAction->setMenuRole(QAction::PreferencesRole);
connect(_openOptionsAction, &QAction::triggered, this, &GUI::openOptions); connect(_openOptionsAction, &QAction::triggered, this, &GUI::openOptions);
// Navigation actions // Navigation actions
#ifndef Q_OS_ANDROID
_nextAction = new QAction(QIcon(NEXT_FILE_ICON), tr("Next"), this); _nextAction = new QAction(QIcon(NEXT_FILE_ICON), tr("Next"), this);
_nextAction->setActionGroup(_navigationActionGroup); _nextAction->setActionGroup(_navigationActionGroup);
_nextAction->setMenuRole(QAction::NoRole); _nextAction->setMenuRole(QAction::NoRole);
@ -542,6 +563,7 @@ void GUI::createActions()
_firstAction->setMenuRole(QAction::NoRole); _firstAction->setMenuRole(QAction::NoRole);
_firstAction->setActionGroup(_navigationActionGroup); _firstAction->setActionGroup(_navigationActionGroup);
connect(_firstAction, &QAction::triggered, this, &GUI::first); connect(_firstAction, &QAction::triggered, this, &GUI::first);
#endif // Q_OS_ANDROID
} }
void GUI::createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu, void GUI::createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu,
@ -574,8 +596,13 @@ void GUI::createMenus()
{ {
QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(_openFileAction); fileMenu->addAction(_openFileAction);
#ifdef Q_OS_ANDROID
fileMenu->addAction(_openDirAction);
#endif // Q_OS_ANDROID
fileMenu->addSeparator(); fileMenu->addSeparator();
#ifndef Q_OS_ANDROID
fileMenu->addAction(_printFileAction); fileMenu->addAction(_printFileAction);
#endif // Q_OS_ANDROID
fileMenu->addAction(_exportPDFFileAction); fileMenu->addAction(_exportPDFFileAction);
fileMenu->addAction(_exportPNGFileAction); fileMenu->addAction(_exportPNGFileAction);
fileMenu->addSeparator(); fileMenu->addSeparator();
@ -583,10 +610,10 @@ void GUI::createMenus()
fileMenu->addSeparator(); fileMenu->addSeparator();
fileMenu->addAction(_reloadFileAction); fileMenu->addAction(_reloadFileAction);
fileMenu->addAction(_closeFileAction); fileMenu->addAction(_closeFileAction);
#ifndef Q_OS_MAC #if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
fileMenu->addSeparator(); fileMenu->addSeparator();
fileMenu->addAction(_exitAction); fileMenu->addAction(_exitAction);
#endif // Q_OS_MAC #endif // Q_OS_MAC + Q_OS_ANDROID
_mapMenu = menuBar()->addMenu(tr("&Map")); _mapMenu = menuBar()->addMenu(tr("&Map"));
_mapsEnd = _mapMenu->addSeparator(); _mapsEnd = _mapMenu->addSeparator();
@ -659,18 +686,31 @@ void GUI::createMenus()
coordinatesMenu->addAction(_degreesMinutesAction); coordinatesMenu->addAction(_degreesMinutesAction);
coordinatesMenu->addAction(_dmsAction); coordinatesMenu->addAction(_dmsAction);
settingsMenu->addSeparator(); settingsMenu->addSeparator();
#ifndef Q_OS_ANDROID
settingsMenu->addAction(_showToolbarsAction); settingsMenu->addAction(_showToolbarsAction);
settingsMenu->addAction(_fullscreenAction); settingsMenu->addAction(_fullscreenAction);
settingsMenu->addSeparator(); settingsMenu->addSeparator();
#endif // Q_OS_ANDROID
settingsMenu->addAction(_openOptionsAction); settingsMenu->addAction(_openOptionsAction);
QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(_pathsAction); helpMenu->addAction(_pathsAction);
#ifndef Q_OS_ANDROID
helpMenu->addAction(_keysAction); helpMenu->addAction(_keysAction);
#endif // Q_OS_ANDROID
helpMenu->addSeparator(); helpMenu->addSeparator();
helpMenu->addAction(_aboutAction); helpMenu->addAction(_aboutAction);
} }
#ifdef Q_OS_ANDROID
void GUI::createNavigation()
{
_navigation = new NavigationWidget(_mapView);
connect(_navigation, &NavigationWidget::next, this, &GUI::next);
connect(_navigation, &NavigationWidget::prev, this, &GUI::prev);
}
#else // Q_OS_ANDROID
void GUI::createToolBars() void GUI::createToolBars()
{ {
int is = style()->pixelMetric(QStyle::PM_ToolBarIconSize); int is = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
@ -706,6 +746,7 @@ void GUI::createToolBars()
_navigationToolBar->addAction(_nextAction); _navigationToolBar->addAction(_nextAction);
_navigationToolBar->addAction(_lastAction); _navigationToolBar->addAction(_lastAction);
} }
#endif // Q_OS_ANDROID
void GUI::createMapView() void GUI::createMapView()
{ {
@ -713,7 +754,11 @@ void GUI::createMapView()
_mapView = new MapView(_map, _poi, 0, this); _mapView = new MapView(_map, _poi, 0, this);
_mapView->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, _mapView->setSizePolicy(QSizePolicy(QSizePolicy::Ignored,
QSizePolicy::Expanding)); QSizePolicy::Expanding));
#ifdef Q_OS_ANDROID
_mapView->setMinimumHeight(100);
#else // Q_OS_ANDROID
_mapView->setMinimumHeight(200); _mapView->setMinimumHeight(200);
#endif // Q_OS_ANDROID
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
_mapView->setFrameShape(QFrame::NoFrame); _mapView->setFrameShape(QFrame::NoFrame);
#endif // Q_OS_WIN32 #endif // Q_OS_WIN32
@ -765,7 +810,16 @@ void GUI::about()
QUrl homepage(APP_HOMEPAGE); QUrl homepage(APP_HOMEPAGE);
msgBox.setWindowTitle(tr("About GPXSee")); msgBox.setWindowTitle(tr("About GPXSee"));
msgBox.setText("<h2>" + QString(APP_NAME) + "</h2><p><p>" + tr("Version %1") #ifdef Q_OS_ANDROID
msgBox.setText("<h2>" + QString(APP_NAME) + "</h2><p>" + tr("Version %1")
.arg(QString(APP_VERSION) + " (" + QSysInfo::buildCpuArchitecture()
+ ", Qt " + QT_VERSION_STR + ")") + "</p><p>"
+ tr("GPXSee is distributed under the terms of the GNU General Public "
"License version 3. For more info about GPXSee visit the project "
"homepage at %1.").arg("<a href=\"" + homepage.toString() + "\">"
+ homepage.toString(QUrl::RemoveScheme).mid(2) + "</a>") + "</p>");
#else // Q_OS_ANDROID
msgBox.setText("<h2>" + QString(APP_NAME) + "</h2><p>" + tr("Version %1")
.arg(QString(APP_VERSION) + " (" + QSysInfo::buildCpuArchitecture() .arg(QString(APP_VERSION) + " (" + QSysInfo::buildCpuArchitecture()
+ ", Qt " + QT_VERSION_STR + ")") + "</p>"); + ", Qt " + QT_VERSION_STR + ")") + "</p>");
msgBox.setInformativeText("<table width=\"300\"><tr><td>" msgBox.setInformativeText("<table width=\"300\"><tr><td>"
@ -778,10 +832,12 @@ void GUI::about()
QIcon icon = msgBox.windowIcon(); QIcon icon = msgBox.windowIcon();
QSize size = icon.actualSize(QSize(64, 64)); QSize size = icon.actualSize(QSize(64, 64));
msgBox.setIconPixmap(icon.pixmap(size)); msgBox.setIconPixmap(icon.pixmap(size));
#endif // Q_OS_ANDROID
msgBox.exec(); msgBox.exec();
} }
#ifndef Q_OS_ANDROID
void GUI::keys() void GUI::keys()
{ {
QMessageBox msgBox(this); QMessageBox msgBox(this);
@ -820,12 +876,30 @@ void GUI::keys()
msgBox.exec(); msgBox.exec();
} }
#endif // Q_OS_ANDROID
void GUI::paths() void GUI::paths()
{ {
QMessageBox msgBox(this); QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Paths")); msgBox.setWindowTitle(tr("Paths"));
#ifdef Q_OS_ANDROID
msgBox.setText(
+ "<small><b>" + tr("Map directory:") + "</b><br>"
+ QDir::cleanPath(ProgramPaths::mapDir(true)) + "<br><br><b>"
+ tr("POI directory:") + "</b><br>"
+ QDir::cleanPath(ProgramPaths::poiDir(true)) + "<br><br><b>"
+ tr("GCS/PCS directory:") + "</b><br>"
+ QDir::cleanPath(ProgramPaths::csvDir(true)) + "<br><br><b>"
+ tr("DEM directory:") + "</b><br>"
+ QDir::cleanPath(ProgramPaths::demDir(true)) + "<br><br><b>"
+ tr("Styles directory:") + "</b><br>"
+ QDir::cleanPath(ProgramPaths::styleDir(true)) + "<br><br><b>"
+ tr("Symbols directory:") + "</b><br>"
+ QDir::cleanPath(ProgramPaths::symbolsDir(true)) + "<br><br><b>"
+ tr("Tile cache directory:") + "</b><br>"
+ QDir::cleanPath(ProgramPaths::tilesDir()) + "</small>");
#else // Q_OS_ANDROID
msgBox.setText("<h3>" + tr("Paths") + "</h3>"); msgBox.setText("<h3>" + tr("Paths") + "</h3>");
msgBox.setInformativeText( msgBox.setInformativeText(
"<style>td {white-space: pre; padding-right: 1em;}</style><table><tr><td>" "<style>td {white-space: pre; padding-right: 1em;}</style><table><tr><td>"
@ -844,14 +918,20 @@ void GUI::paths()
+ tr("Tile cache directory:") + "</td><td><code>" + tr("Tile cache directory:") + "</td><td><code>"
+ QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>" + QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
); );
#endif // Q_OS_ANDROID
msgBox.exec(); msgBox.exec();
} }
void GUI::openFile() void GUI::openFile()
{ {
#ifdef Q_OS_ANDROID
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open file"),
_dataDir));
#else // Q_OS_ANDROID
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open file"), QStringList files(QFileDialog::getOpenFileNames(this, tr("Open file"),
_dataDir, Data::formats())); _dataDir, Data::formats()));
#endif // Q_OS_ANDROID
for (int i = 0; i < files.size(); i++) for (int i = 0; i < files.size(); i++)
openFile(files.at(i)); openFile(files.at(i));
@ -859,6 +939,19 @@ void GUI::openFile()
_dataDir = QFileInfo(files.last()).path(); _dataDir = QFileInfo(files.last()).path();
} }
#ifdef Q_OS_ANDROID
void GUI::openDir()
{
QString dir(QFileDialog::getExistingDirectory(this, tr("Open directory"),
_dataDir));
if (!dir.isEmpty()) {
_browser->setCurrentDir(dir);
openFile(_browser->current());
}
}
#endif // Q_OS_ANDROID
bool GUI::openFile(const QString &fileName, bool silent) bool GUI::openFile(const QString &fileName, bool silent)
{ {
if (_files.contains(fileName)) if (_files.contains(fileName))
@ -868,7 +961,9 @@ bool GUI::openFile(const QString &fileName, bool silent)
return false; return false;
_files.append(fileName); _files.append(fileName);
#ifndef Q_OS_ANDROID
_browser->setCurrent(fileName); _browser->setCurrent(fileName);
#endif // Q_OS_ANDROID
_fileActionGroup->setEnabled(true); _fileActionGroup->setEnabled(true);
// Explicitly enable the reload action as it may be disabled by loadMapDir() // Explicitly enable the reload action as it may be disabled by loadMapDir()
_reloadFileAction->setEnabled(true); _reloadFileAction->setEnabled(true);
@ -898,7 +993,7 @@ bool GUI::loadFile(const QString &fileName, bool silent)
_fileActionGroup->setEnabled(false); _fileActionGroup->setEnabled(false);
QString error = tr("Error loading data file:") + "\n\n" QString error = tr("Error loading data file:") + "\n\n"
+ fileName + "\n\n" + data.errorString(); + Util::displayName(fileName) + "\n\n" + data.errorString();
if (data.errorLine()) if (data.errorLine())
error.append("\n" + tr("Line: %1").arg(data.errorLine())); error.append("\n" + tr("Line: %1").arg(data.errorLine()));
QMessageBox::critical(this, APP_NAME, error); QMessageBox::critical(this, APP_NAME, error);
@ -967,8 +1062,13 @@ void GUI::loadData(const Data &data)
void GUI::openPOIFile() void GUI::openPOIFile()
{ {
#ifdef Q_OS_ANDROID
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open POI file"),
_poiDir));
#else // Q_OS_ANDROID
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open POI file"), QStringList files(QFileDialog::getOpenFileNames(this, tr("Open POI file"),
_poiDir, Data::formats())); _poiDir, Data::formats()));
#endif // Q_OS_ANDROID
for (int i = 0; i < files.size(); i++) for (int i = 0; i < files.size(); i++)
openPOIFile(files.at(i)); openPOIFile(files.at(i));
@ -994,7 +1094,7 @@ bool GUI::openPOIFile(const QString &fileName)
return true; return true;
} else { } else {
QString error = tr("Error loading POI file:") + "\n\n" QString error = tr("Error loading POI file:") + "\n\n"
+ fileName + "\n\n" + _poi->errorString(); + Util::displayName(fileName) + "\n\n" + _poi->errorString();
if (_poi->errorLine()) if (_poi->errorLine())
error.append("\n" + tr("Line: %1").arg(_poi->errorLine())); error.append("\n" + tr("Line: %1").arg(_poi->errorLine()));
QMessageBox::critical(this, APP_NAME, error); QMessageBox::critical(this, APP_NAME, error);
@ -1207,12 +1307,72 @@ void GUI::exportPNGFile()
void GUI::statistics() void GUI::statistics()
{ {
QLocale l(QLocale::system()); QLocale l(QLocale::system());
QMessageBox msgBox(this);
QString text;
#ifdef Q_OS_ANDROID
if (_showTracksAction->isChecked() && _trackCount > 1)
text.append("<b>" + tr("Tracks") + ":</b> "
+ l.toString(_trackCount) + "<br>");
if (_showRoutesAction->isChecked() && _routeCount > 1)
text.append("<b>" + tr("Routes") + ":</b> "
+ l.toString(_routeCount) + "<br>");
if (_showWaypointsAction->isChecked() && _waypointCount > 1)
text.append("<b>" + tr("Waypoints") + ":</b> "
+ l.toString(_waypointCount) + "<br>");
if (_showAreasAction->isChecked() && _areaCount > 1)
text.append("<b>" + tr("Areas") + ":</b> "
+ l.toString(_areaCount) + "<br>");
if (_dateRange.first.isValid()) {
if (_dateRange.first == _dateRange.second) {
QString format = l.dateFormat(QLocale::LongFormat);
text.append("<b>" + tr("Date") + ":</b> "
+ _dateRange.first.toString(format) + "<br>");
} else {
QString format = l.dateFormat(QLocale::ShortFormat);
text.append("<b>" + tr("Date") + ":</b> "
+ QString("%1 - %2").arg(_dateRange.first.toString(format),
_dateRange.second.toString(format)) + "<br>");
}
}
if (distance() > 0)
text.append("<b>" + tr("Distance") + ":</b> "
+ Format::distance(distance(), units()) + "<br>");
if (time() > 0) {
text.append("<b>" + tr("Time") + ":</b> "
+ Format::timeSpan(time()) + "<br>");
text.append("<b>" + tr("Moving time") + ":</b> "
+ Format::timeSpan(movingTime()) + "<br>");
}
text.append("<br>");
for (int i = 0; i < _tabs.count(); i++) {
const GraphTab *tab = _tabs.at(i);
if (tab->isEmpty())
continue;
text.append("<i>" + tab->label() + "</i><br>");
for (int j = 0; j < tab->info().size(); j++) {
const KV<QString, QString> &kv = tab->info().at(j);
text.append("<b>" + kv.key() + ":</b>&nbsp;" + kv.value());
if (j != tab->info().size() - 1)
text.append(" | ");
}
if (i != _tabs.count() - 1)
text.append("<br><br>");
}
msgBox.setWindowTitle(tr("Statistics"));
msgBox.setText(text);
#else // Q_OS_ANDROID
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
QString text = "<style>td {white-space: pre; padding-right: 4em;}" text = "<style>td {white-space: pre; padding-right: 4em;}"
"th {text-align: left; padding-top: 0.5em;}</style><table>"; "th {text-align: left; padding-top: 0.5em;}</style><table>";
#else // Q_OS_WIN32 #else // Q_OS_WIN32
QString text = "<style>td {white-space: pre; padding-right: 2em;}" text = "<style>td {white-space: pre; padding-right: 2em;}"
"th {text-align: left; padding-top: 0.5em;}</style><table>"; "th {text-align: left; padding-top: 0.5em;}</style><table>";
#endif // Q_OS_WIN32 #endif // Q_OS_WIN32
@ -1267,11 +1427,11 @@ void GUI::statistics()
text.append("</table>"); text.append("</table>");
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Statistics")); msgBox.setWindowTitle(tr("Statistics"));
msgBox.setText("<h3>" + tr("Statistics") + "</h3>"); msgBox.setText("<h3>" + tr("Statistics") + "</h3>");
msgBox.setInformativeText(text); msgBox.setInformativeText(text);
#endif // Q_OS_ANDROID
msgBox.exec(); msgBox.exec();
} }
@ -1430,8 +1590,10 @@ void GUI::reloadFiles()
updateWindowTitle(); updateWindowTitle();
if (_files.isEmpty()) if (_files.isEmpty())
_fileActionGroup->setEnabled(false); _fileActionGroup->setEnabled(false);
#ifndef Q_OS_ANDROID
else else
_browser->setCurrent(_files.last()); _browser->setCurrent(_files.last());
#endif // Q_OS_ANDROID
updateDEMDownloadAction(); updateDEMDownloadAction();
} }
@ -1466,6 +1628,10 @@ void GUI::closeAll()
updateWindowTitle(); updateWindowTitle();
updateGraphTabs(); updateGraphTabs();
updateDEMDownloadAction(); updateDEMDownloadAction();
#ifdef Q_OS_ANDROID
_browser->setCurrentDir(QString());
#endif // Q_OS_ANDROID
} }
void GUI::showGraphs(bool show) void GUI::showGraphs(bool show)
@ -1473,6 +1639,7 @@ void GUI::showGraphs(bool show)
_graphTabWidget->setHidden(!show); _graphTabWidget->setHidden(!show);
} }
#ifndef Q_OS_ANDROID
void GUI::showToolbars(bool show) void GUI::showToolbars(bool show)
{ {
if (show) { if (show) {
@ -1515,6 +1682,7 @@ void GUI::showFullscreen(bool show)
showNormal(); showNormal();
} }
} }
#endif // Q_OS_ANDROID
void GUI::showTracks(bool show) void GUI::showTracks(bool show)
{ {
@ -1583,8 +1751,13 @@ void GUI::showPathMarkerInfo(QAction *action)
void GUI::loadMap() void GUI::loadMap()
{ {
#ifdef Q_OS_ANDROID
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open map file"),
_mapDir));
#else // Q_OS_ANDROID
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open map file"), QStringList files(QFileDialog::getOpenFileNames(this, tr("Open map file"),
_mapDir, MapList::formats())); _mapDir, MapList::formats()));
#endif // Q_OS_ANDROID
MapAction *a, *lastReady = 0; MapAction *a, *lastReady = 0;
for (int i = 0; i < files.size(); i++) { for (int i = 0; i < files.size(); i++) {
@ -1627,7 +1800,8 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
if (!map->isValid()) { if (!map->isValid()) {
if (!silent) if (!silent)
QMessageBox::critical(this, APP_NAME, QMessageBox::critical(this, APP_NAME,
tr("Error loading map:") + "\n\n" + map->path() + "\n\n" tr("Error loading map:") + "\n\n"
+ Util::displayName(map->path()) + "\n\n"
+ map->errorString()); + map->errorString());
delete map; delete map;
} else { } else {
@ -1672,8 +1846,8 @@ void GUI::mapLoaded()
_showMapAction->setEnabled(true); _showMapAction->setEnabled(true);
_clearMapCacheAction->setEnabled(true); _clearMapCacheAction->setEnabled(true);
} else { } else {
QString error = tr("Error loading map:") + "\n\n" + map->path() + "\n\n" QString error = tr("Error loading map:") + "\n\n"
+ map->errorString(); + Util::displayName(map->path()) + "\n\n" + map->errorString();
QMessageBox::critical(this, APP_NAME, error); QMessageBox::critical(this, APP_NAME, error);
action->deleteLater(); action->deleteLater();
} }
@ -1691,8 +1865,8 @@ void GUI::mapLoadedDir()
actions.append(action); actions.append(action);
_mapView->loadMaps(actions); _mapView->loadMaps(actions);
} else { } else {
QString error = tr("Error loading map:") + "\n\n" + map->path() + "\n\n" QString error = tr("Error loading map:") + "\n\n"
+ map->errorString(); + Util::displayName(map->path()) + "\n\n" + map->errorString();
QMessageBox::critical(this, APP_NAME, error); QMessageBox::critical(this, APP_NAME, error);
action->deleteLater(); action->deleteLater();
} }
@ -1714,7 +1888,8 @@ void GUI::loadMapDirNode(const TreeNode<Map *> &node, QList<MapAction*> &actions
if (!(a = findMapAction(existingActions, map))) { if (!(a = findMapAction(existingActions, map))) {
if (!map->isValid()) { if (!map->isValid()) {
QMessageBox::critical(this, APP_NAME, tr("Error loading map:") QMessageBox::critical(this, APP_NAME, tr("Error loading map:")
+ "\n\n" + map->path() + "\n\n" + map->errorString()); + "\n\n" + Util::displayName(map->path()) + "\n\n"
+ map->errorString());
delete map; delete map;
} else { } else {
a = new MapAction(map, _mapsActionGroup); a = new MapAction(map, _mapsActionGroup);
@ -1817,7 +1992,7 @@ void GUI::updateStatusBarInfo()
if (_files.count() == 0) if (_files.count() == 0)
_fileNameLabel->setText(tr("No files loaded")); _fileNameLabel->setText(tr("No files loaded"));
else if (_files.count() == 1) else if (_files.count() == 1)
_fileNameLabel->setText(_files.at(0)); _fileNameLabel->setText(Util::displayName(_files.at(0)));
else else
_fileNameLabel->setText(tr("%n files", "", _files.count())); _fileNameLabel->setText(tr("%n files", "", _files.count()));
@ -1840,6 +2015,10 @@ void GUI::updateStatusBarInfo()
_timeLabel->clear(); _timeLabel->clear();
_timeLabel->setToolTip(QString()); _timeLabel->setToolTip(QString());
} }
#ifdef Q_OS_ANDROID
statusBar()->setVisible(!_files.isEmpty());
#endif // Q_OS_ANDROID
} }
void GUI::updateWindowTitle() void GUI::updateWindowTitle()
@ -1929,10 +2108,17 @@ void GUI::graphChanged(int index)
void GUI::updateNavigationActions() void GUI::updateNavigationActions()
{ {
#ifdef Q_OS_ANDROID
_navigation->enableNext(!_browser->isLast()
&& !_browser->current().isNull());
_navigation->enablePrev(!_browser->isFirst()
&& !_browser->current().isNull());
#else // Q_OS_ANDROID
_lastAction->setEnabled(!_browser->isLast()); _lastAction->setEnabled(!_browser->isLast());
_nextAction->setEnabled(!_browser->isLast()); _nextAction->setEnabled(!_browser->isLast());
_firstAction->setEnabled(!_browser->isFirst()); _firstAction->setEnabled(!_browser->isFirst());
_prevAction->setEnabled(!_browser->isFirst()); _prevAction->setEnabled(!_browser->isFirst());
#endif // Q_OS_ANDROID
} }
bool GUI::updateGraphTabs() bool GUI::updateGraphTabs()
@ -2042,6 +2228,7 @@ void GUI::first()
openFile(file); openFile(file);
} }
#ifndef Q_OS_ANDROID
void GUI::keyPressEvent(QKeyEvent *event) void GUI::keyPressEvent(QKeyEvent *event)
{ {
QString file; QString file;
@ -2096,11 +2283,12 @@ void GUI::keyPressEvent(QKeyEvent *event)
QMainWindow::keyPressEvent(event); QMainWindow::keyPressEvent(event);
} }
#endif // Q_OS_ANDROID
void GUI::closeEvent(QCloseEvent *event) void GUI::closeEvent(QCloseEvent *event)
{ {
writeSettings(); writeSettings();
event->accept(); QMainWindow::closeEvent(event);
} }
void GUI::dragEnterEvent(QDragEnterEvent *event) void GUI::dragEnterEvent(QDragEnterEvent *event)
@ -2167,6 +2355,7 @@ void GUI::writeSettings()
QSettings settings(qApp->applicationName(), qApp->applicationName()); QSettings settings(qApp->applicationName(), qApp->applicationName());
settings.clear(); settings.clear();
#ifndef Q_OS_ANDROID
settings.beginGroup(WINDOW_SETTINGS_GROUP); settings.beginGroup(WINDOW_SETTINGS_GROUP);
if (!_windowStates.isEmpty() && !_windowGeometries.isEmpty()) { if (!_windowStates.isEmpty() && !_windowGeometries.isEmpty()) {
settings.setValue(WINDOW_STATE_SETTING, _windowStates.first()); settings.setValue(WINDOW_STATE_SETTING, _windowStates.first());
@ -2176,6 +2365,7 @@ void GUI::writeSettings()
settings.setValue(WINDOW_GEOMETRY_SETTING, saveGeometry()); settings.setValue(WINDOW_GEOMETRY_SETTING, saveGeometry());
} }
settings.endGroup(); settings.endGroup();
#endif // Q_OS_ANDROID
settings.beginGroup(SETTINGS_SETTINGS_GROUP); settings.beginGroup(SETTINGS_SETTINGS_GROUP);
if ((_movingTimeAction->isChecked() ? Moving : Total) != if ((_movingTimeAction->isChecked() ? Moving : Total) !=
@ -2190,9 +2380,11 @@ void GUI::writeSettings()
: _degreesMinutesAction->isChecked() ? DegreesMinutes : DecimalDegrees; : _degreesMinutesAction->isChecked() ? DegreesMinutes : DecimalDegrees;
if (format != COORDINATES_DEFAULT) if (format != COORDINATES_DEFAULT)
settings.setValue(COORDINATES_SETTING, format); settings.setValue(COORDINATES_SETTING, format);
#ifndef Q_OS_ANDROID
if (_showToolbarsAction->isChecked() != SHOW_TOOLBARS_DEFAULT) if (_showToolbarsAction->isChecked() != SHOW_TOOLBARS_DEFAULT)
settings.setValue(SHOW_TOOLBARS_SETTING, settings.setValue(SHOW_TOOLBARS_SETTING,
_showToolbarsAction->isChecked()); _showToolbarsAction->isChecked());
#endif // Q_OS_ANDROID
settings.endGroup(); settings.endGroup();
settings.beginGroup(MAP_SETTINGS_GROUP); settings.beginGroup(MAP_SETTINGS_GROUP);
@ -2485,10 +2677,12 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
int value; int value;
QSettings settings(qApp->applicationName(), qApp->applicationName()); QSettings settings(qApp->applicationName(), qApp->applicationName());
#ifndef Q_OS_ANDROID
settings.beginGroup(WINDOW_SETTINGS_GROUP); settings.beginGroup(WINDOW_SETTINGS_GROUP);
restoreGeometry(settings.value(WINDOW_GEOMETRY_SETTING).toByteArray()); restoreGeometry(settings.value(WINDOW_GEOMETRY_SETTING).toByteArray());
restoreState(settings.value(WINDOW_STATE_SETTING).toByteArray()); restoreState(settings.value(WINDOW_STATE_SETTING).toByteArray());
settings.endGroup(); settings.endGroup();
#endif // Q_OS_ANDROID
settings.beginGroup(SETTINGS_SETTINGS_GROUP); settings.beginGroup(SETTINGS_SETTINGS_GROUP);
if (settings.value(TIME_TYPE_SETTING, TIME_TYPE_DEFAULT).toInt() == Moving) if (settings.value(TIME_TYPE_SETTING, TIME_TYPE_DEFAULT).toInt() == Moving)
@ -2512,10 +2706,12 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
else else
_decimalDegreesAction->trigger(); _decimalDegreesAction->trigger();
#ifndef Q_OS_ANDROID
if (!settings.value(SHOW_TOOLBARS_SETTING, SHOW_TOOLBARS_DEFAULT).toBool()) if (!settings.value(SHOW_TOOLBARS_SETTING, SHOW_TOOLBARS_DEFAULT).toBool())
showToolbars(false); showToolbars(false);
else else
_showToolbarsAction->setChecked(true); _showToolbarsAction->setChecked(true);
#endif // Q_OS_ANDROID
settings.endGroup(); settings.endGroup();
settings.beginGroup(MAP_SETTINGS_GROUP); settings.beginGroup(MAP_SETTINGS_GROUP);
@ -2523,8 +2719,8 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
_showMapAction->setChecked(true); _showMapAction->setChecked(true);
else else
_mapView->showMap(false); _mapView->showMap(false);
if (settings.value(SHOW_CURSOR_COORDINATES_SETTING, SHOW_CURSOR_COORDINATES_DEFAULT) if (settings.value(SHOW_CURSOR_COORDINATES_SETTING,
.toBool()) { SHOW_CURSOR_COORDINATES_DEFAULT).toBool()) {
_showCoordinatesAction->setChecked(true); _showCoordinatesAction->setChecked(true);
_mapView->showCursorCoordinates(true); _mapView->showCursorCoordinates(true);
} }

View File

@ -35,6 +35,7 @@ class MapAction;
class POIAction; class POIAction;
class Data; class Data;
class DEMLoader; class DEMLoader;
class NavigationWidget;
class GUI : public QMainWindow class GUI : public QMainWindow
{ {
@ -47,15 +48,21 @@ public:
bool loadMap(const QString &fileName, MapAction *&action, bool loadMap(const QString &fileName, MapAction *&action,
bool silent = false); bool silent = false);
void show(); void show();
void writeSettings();
private slots: private slots:
void about(); void about();
#ifndef Q_OS_ANDROID
void keys(); void keys();
#endif // Q_OS_ANDROID
void paths(); void paths();
void printFile(); void printFile();
void exportPDFFile(); void exportPDFFile();
void exportPNGFile(); void exportPNGFile();
void openFile(); void openFile();
#ifdef Q_OS_ANDROID
void openDir();
#endif // Q_OS_ANDROID
void closeAll(); void closeAll();
void reloadFiles(); void reloadFiles();
void statistics(); void statistics();
@ -64,8 +71,10 @@ private slots:
void showGraphGrids(bool show); void showGraphGrids(bool show);
void showGraphSliderInfo(bool show); void showGraphSliderInfo(bool show);
void showPathMarkerInfo(QAction *action); void showPathMarkerInfo(QAction *action);
#ifndef Q_OS_ANDROID
void showToolbars(bool show); void showToolbars(bool show);
void showFullscreen(bool show); void showFullscreen(bool show);
#endif // Q_OS_ANDROID
void showTracks(bool show); void showTracks(bool show);
void showRoutes(bool show); void showRoutes(bool show);
void showAreas(bool show); void showAreas(bool show);
@ -129,7 +138,11 @@ private:
QAction *action = 0); QAction *action = 0);
void createActions(); void createActions();
void createMenus(); void createMenus();
#ifdef Q_OS_ANDROID
void createNavigation();
#else // Q_OS_ANDROID
void createToolBars(); void createToolBars();
#endif // Q_OS_ANDROID
void createStatusBar(); void createStatusBar();
void createMapView(); void createMapView();
void createGraphTabs(); void createGraphTabs();
@ -160,19 +173,24 @@ private:
QAction *mapAction(const QString &name); QAction *mapAction(const QString &name);
QGeoPositionInfoSource *positionSource(const Options &options); QGeoPositionInfoSource *positionSource(const Options &options);
void readSettings(QString &activeMap, QStringList &disabledPOIs); void readSettings(QString &activeMap, QStringList &disabledPOIs);
void writeSettings();
void loadInitialMaps(const QString &selected); void loadInitialMaps(const QString &selected);
void loadInitialPOIs(const QStringList &disabled); void loadInitialPOIs(const QStringList &disabled);
#ifndef Q_OS_ANDROID
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
#endif // Q_OS_ANDROID
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
void dragEnterEvent(QDragEnterEvent *event); void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event); void dropEvent(QDropEvent *event);
#ifdef Q_OS_ANDROID
NavigationWidget *_navigation;
#else // Q_OS_ANDROID
QToolBar *_fileToolBar; QToolBar *_fileToolBar;
QToolBar *_showToolBar; QToolBar *_showToolBar;
QToolBar *_navigationToolBar; QToolBar *_navigationToolBar;
#endif // Q_OS_ANDROID
QMenu *_poiMenu; QMenu *_poiMenu;
QMenu *_mapMenu; QMenu *_mapMenu;
@ -180,15 +198,16 @@ private:
QActionGroup *_navigationActionGroup; QActionGroup *_navigationActionGroup;
QActionGroup *_mapsActionGroup; QActionGroup *_mapsActionGroup;
QActionGroup *_poisActionGroup; QActionGroup *_poisActionGroup;
#if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
QAction *_exitAction; QAction *_exitAction;
QAction *_keysAction; #endif // Q_OS_MAC + Q_OS_ANDROID
QAction *_pathsAction; QAction *_pathsAction;
QAction *_aboutAction; QAction *_aboutAction;
QAction *_aboutQtAction;
QAction *_printFileAction; QAction *_printFileAction;
QAction *_exportPDFFileAction; QAction *_exportPDFFileAction;
QAction *_exportPNGFileAction; QAction *_exportPNGFileAction;
QAction *_openFileAction; QAction *_openFileAction;
QAction *_openDirAction;
QAction *_closeFileAction; QAction *_closeFileAction;
QAction *_reloadFileAction; QAction *_reloadFileAction;
QAction *_statisticsAction; QAction *_statisticsAction;
@ -204,7 +223,6 @@ private:
QAction *_followPositionAction; QAction *_followPositionAction;
QAction *_showPositionCoordinatesAction; QAction *_showPositionCoordinatesAction;
QAction *_showMotionInfo; QAction *_showMotionInfo;
QAction *_fullscreenAction;
QAction *_loadMapAction; QAction *_loadMapAction;
QAction *_loadMapDirAction; QAction *_loadMapDirAction;
QAction *_clearMapCacheAction; QAction *_clearMapCacheAction;
@ -213,11 +231,15 @@ private:
QAction *_showGraphSliderInfoAction; QAction *_showGraphSliderInfoAction;
QAction *_distanceGraphAction; QAction *_distanceGraphAction;
QAction *_timeGraphAction; QAction *_timeGraphAction;
#ifndef Q_OS_ANDROID
QAction *_keysAction;
QAction *_fullscreenAction;
QAction *_showToolbarsAction; QAction *_showToolbarsAction;
QAction *_nextAction; QAction *_nextAction;
QAction *_prevAction; QAction *_prevAction;
QAction *_lastAction; QAction *_lastAction;
QAction *_firstAction; QAction *_firstAction;
#endif // Q_OS_ANDROID
QAction *_metricUnitsAction; QAction *_metricUnitsAction;
QAction *_imperialUnitsAction; QAction *_imperialUnitsAction;
QAction *_nauticalUnitsAction; QAction *_nauticalUnitsAction;
@ -271,9 +293,11 @@ private:
DateTimeRange _dateRange; DateTimeRange _dateRange;
QString _pathName; QString _pathName;
#ifndef Q_OS_ANDROID
QList<QByteArray> _windowStates; QList<QByteArray> _windowStates;
QList<QByteArray> _windowGeometries; QList<QByteArray> _windowGeometries;
int _frameStyle; int _frameStyle;
#endif // Q_OS_ANDROID
PDFExport _pdfExport; PDFExport _pdfExport;
PNGExport _pngExport; PNGExport _pngExport;

View File

@ -24,10 +24,17 @@ void HeartRateGraph::setInfo()
if (_showTracks) { if (_showTracks) {
QLocale l(QLocale::system()); QLocale l(QLocale::system());
#ifdef Q_OS_ANDROID
GraphView::addInfo(tr("Avg"), l.toString(avg() * yScale(), 'f', 0)
+ UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Max"), l.toString(max() * yScale(), 'f', 0)
+ UNIT_SPACE + yUnits());
#else // Q_OS_ANDROID
GraphView::addInfo(tr("Average"), l.toString(avg() * yScale(), 'f', GraphView::addInfo(tr("Average"), l.toString(avg() * yScale(), 'f',
0) + UNIT_SPACE + yUnits()); 0) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f', GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f',
0) + UNIT_SPACE + yUnits()); 0) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else } else
clearInfo(); clearInfo();
} }

View File

@ -662,20 +662,8 @@ void MapView::wheelEvent(QWheelEvent *event)
#else // QT 5.15 #else // QT 5.15
zoom((delta > 0) ? 1 : -1, event->position().toPoint(), shift); zoom((delta > 0) ? 1 : -1, event->position().toPoint(), shift);
#endif // QT 5.15 #endif // QT 5.15
}
void MapView::mouseDoubleClickEvent(QMouseEvent *event) QGraphicsView::wheelEvent(event);
{
bool shift = (event->modifiers() & MODIFIER) ? true : false;
QGraphicsView::mouseDoubleClickEvent(event);
if (event->isAccepted())
return;
if (event->button() != Qt::LeftButton && event->button() != Qt::RightButton)
return;
zoom((event->button() == Qt::LeftButton) ? 1 : -1, event->pos(), shift);
} }
void MapView::keyPressEvent(QKeyEvent *event) void MapView::keyPressEvent(QKeyEvent *event)
@ -713,15 +701,6 @@ void MapView::keyReleaseEvent(QKeyEvent *event)
QGraphicsView::keyReleaseEvent(event); QGraphicsView::keyReleaseEvent(event);
} }
void MapView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && event->modifiers() & MODIFIER)
QApplication::clipboard()->setText(Format::coordinates(
_map->xy2ll(mapToScene(event->pos())), _cursorCoordinates->format()));
else
QGraphicsView::mousePressEvent(event);
}
void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
PlotFlags flags) PlotFlags flags)
{ {
@ -1200,6 +1179,12 @@ void MapView::scrollContentsBy(int dx, int dy)
} }
} }
void MapView::leaveEvent(QEvent *event)
{
_cursorCoordinates->setCoordinates(Coordinates());
QGraphicsView::leaveEvent(event);
}
void MapView::mouseMoveEvent(QMouseEvent *event) void MapView::mouseMoveEvent(QMouseEvent *event)
{ {
if (_cursorCoordinates->isVisible()) { if (_cursorCoordinates->isVisible()) {
@ -1210,10 +1195,30 @@ void MapView::mouseMoveEvent(QMouseEvent *event)
QGraphicsView::mouseMoveEvent(event); QGraphicsView::mouseMoveEvent(event);
} }
void MapView::leaveEvent(QEvent *event)
void MapView::mousePressEvent(QMouseEvent *event)
{ {
_cursorCoordinates->setCoordinates(Coordinates()); if (event->button() == Qt::LeftButton) {
QGraphicsView::leaveEvent(event); if (event->modifiers() & MODIFIER)
QApplication::clipboard()->setText(Format::coordinates(_map->xy2ll(
mapToScene(event->pos())), _cursorCoordinates->format()));
#ifdef Q_OS_ANDROID
else
emit clicked(event->pos());
#endif // Q_OS_ANDROID
}
QGraphicsView::mousePressEvent(event);
}
void MapView::mouseDoubleClickEvent(QMouseEvent *event)
{
bool shift = (event->modifiers() & MODIFIER) ? true : false;
if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton)
zoom((event->button() == Qt::LeftButton) ? 1 : -1, event->pos(), shift);
QGraphicsView::mouseDoubleClickEvent(event);
} }
bool MapView::event(QEvent *event) bool MapView::event(QEvent *event)

View File

@ -102,6 +102,11 @@ public:
RectC boundingRect() const; RectC boundingRect() const;
#ifdef Q_OS_ANDROID
signals:
void clicked(const QPoint &pos);
#endif // Q_OS_ANDROID
public slots: public slots:
void showMap(bool show); void showMap(bool show);
void showPOI(bool show); void showPOI(bool show);
@ -162,6 +167,7 @@ private:
void drawBackground(QPainter *painter, const QRectF &rect); void drawBackground(QPainter *painter, const QRectF &rect);
void paintEvent(QPaintEvent *event); void paintEvent(QPaintEvent *event);
void leaveEvent(QEvent *event); void leaveEvent(QEvent *event);
bool event(QEvent *event); bool event(QEvent *event);
void scrollContentsBy(int dx, int dy); void scrollContentsBy(int dx, int dy);

View File

@ -0,0 +1,101 @@
#include "navigationwidget.h"
#include <QEvent>
#include <QResizeEvent>
#include <QPainter>
#define MARGIN 5
#define SIZE 40
#ifdef Q_OS_ANDROID
NavigationWidget::NavigationWidget(MapView *view)
: QWidget(view), _showPrev(false), _showNext(false)
{
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
newParent();
connect(view, &MapView::clicked, this, &NavigationWidget::viewClicked);
}
bool NavigationWidget::eventFilter(QObject *obj, QEvent *ev)
{
if (obj == parent()) {
if (ev->type() == QEvent::Resize)
resize(static_cast<QResizeEvent*>(ev)->size());
else if (ev->type() == QEvent::ChildAdded)
raise();
}
return QWidget::eventFilter(obj, ev);
}
bool NavigationWidget::event(QEvent* ev)
{
if (ev->type() == QEvent::ParentAboutToChange) {
if (parent())
parent()->removeEventFilter(this);
} else if (ev->type() == QEvent::ParentChange)
newParent();
return QWidget::event(ev);
}
void NavigationWidget::paintEvent(QPaintEvent *ev)
{
Q_UNUSED(ev);
QPainter p(this);
QColor c(Qt::black);
c.setAlpha(64);
p.setBrush(c);
p.setPen(Qt::NoPen);
if (_showPrev) {
QPainterPath path;
path.addEllipse(QRect(MARGIN, rect().center().y() - SIZE/2, SIZE, SIZE));
path.moveTo(QPointF(MARGIN + 0.66*SIZE, rect().center().y() - SIZE/4));
path.lineTo(QPointF(MARGIN + SIZE/4, rect().center().y()));
path.lineTo(QPointF(MARGIN + 0.66*SIZE, rect().center().y() + SIZE/4));
path.closeSubpath();
p.drawPath(path);
}
if (_showNext) {
QPainterPath path;
path.addEllipse(QRect(rect().right() - (MARGIN + SIZE),
rect().center().y() - SIZE/2, SIZE, SIZE));
path.moveTo(QPointF(rect().right() - (MARGIN + 0.66*SIZE),
rect().center().y() - SIZE/4));
path.lineTo(QPointF(rect().right() - (MARGIN + SIZE/4),
rect().center().y()));
path.lineTo(QPointF(rect().right() - (MARGIN + 0.66*SIZE),
rect().center().y() + SIZE/4));
path.closeSubpath();
p.drawPath(path);
}
}
void NavigationWidget::newParent()
{
if (!parent())
return;
parent()->installEventFilter(this);
raise();
}
void NavigationWidget::viewClicked(const QPoint &pos)
{
QRect prevRect(MARGIN, rect().center().y() - SIZE/2, SIZE, SIZE);
QRect nextRect(rect().right() - (MARGIN + SIZE), rect().center().y()
- SIZE/2, SIZE, SIZE);
if (prevRect.contains(pos))
emit prev();
else if (nextRect.contains(pos))
emit next();
}
#endif // Q_OS_ANDROID

View File

@ -0,0 +1,35 @@
#ifndef NAVIGATIONWIDGET_H
#define NAVIGATIONWIDGET_H
#include <QWidget>
#include "mapview.h"
#ifdef Q_OS_ANDROID
class NavigationWidget : public QWidget
{
Q_OBJECT
public:
NavigationWidget(MapView *view);
void enableNext(bool enable) {_showNext = enable; update();}
void enablePrev(bool enable) {_showPrev = enable; update();}
signals:
void next();
void prev();
private slots:
void viewClicked(const QPoint &pos);
private:
bool eventFilter(QObject *obj, QEvent *ev);
bool event(QEvent *ev);
void paintEvent(QPaintEvent *ev);
void newParent();
bool _showPrev, _showNext;
};
#endif // Q_OS_ANDROID
#endif // NAVIGATIONWIDGET_H

View File

@ -26,8 +26,11 @@
#include "pluginparameters.h" #include "pluginparameters.h"
#include "optionsdialog.h" #include "optionsdialog.h"
#ifdef Q_OS_ANDROID
#define MENU_MARGIN 0
#else // Q_OS_ANDROID
#define MENU_MARGIN 20 #define MENU_MARGIN 20
#endif // Q_OS_ANDROID
#define MENU_ICON_SIZE 32 #define MENU_ICON_SIZE 32
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -779,6 +782,11 @@ QWidget *OptionsDialog::createSystemPage()
OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent) OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
: QDialog(parent), _options(options), _units(units) : QDialog(parent), _options(options), _units(units)
{ {
#ifdef Q_OS_ANDROID
setWindowFlags(Qt::Window);
setWindowState(Qt::WindowFullScreen);
#endif /* Q_OS_ANDROID */
QStackedWidget *pages = new QStackedWidget(); QStackedWidget *pages = new QStackedWidget();
pages->addWidget(createAppearancePage()); pages->addWidget(createAppearancePage());
pages->addWidget(createMapPage()); pages->addWidget(createMapPage());
@ -791,16 +799,25 @@ OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
QListWidget *menu = new QListWidget(); QListWidget *menu = new QListWidget();
menu->setIconSize(QSize(MENU_ICON_SIZE, MENU_ICON_SIZE)); menu->setIconSize(QSize(MENU_ICON_SIZE, MENU_ICON_SIZE));
new QListWidgetItem(QIcon(APPEARANCE_ICON), tr("Appearance"), #ifdef Q_OS_ANDROID
menu); new QListWidgetItem(QIcon(APPEARANCE_ICON), QString(), menu);
new QListWidgetItem(QIcon(MAPS_ICON), QString(), menu);
new QListWidgetItem(QIcon(DATA_ICON), QString(), menu);
new QListWidgetItem(QIcon(POI_ICON), QString(), menu);
new QListWidgetItem(QIcon(DEM_ICON), QString(), menu);
new QListWidgetItem(QIcon(POSITION_ICON), QString(), menu);
new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), QString(), menu);
new QListWidgetItem(QIcon(SYSTEM_ICON), QString(), menu);
#else // Q_OS_ANDROID
new QListWidgetItem(QIcon(APPEARANCE_ICON), tr("Appearance"), menu);
new QListWidgetItem(QIcon(MAPS_ICON), tr("Maps"), menu); new QListWidgetItem(QIcon(MAPS_ICON), tr("Maps"), menu);
new QListWidgetItem(QIcon(DATA_ICON), tr("Data"), menu); new QListWidgetItem(QIcon(DATA_ICON), tr("Data"), menu);
new QListWidgetItem(QIcon(POI_ICON), tr("POI"), menu); new QListWidgetItem(QIcon(POI_ICON), tr("POI"), menu);
new QListWidgetItem(QIcon(DEM_ICON), tr("DEM"), menu); new QListWidgetItem(QIcon(DEM_ICON), tr("DEM"), menu);
new QListWidgetItem(QIcon(POSITION_ICON), tr("Position"), menu); new QListWidgetItem(QIcon(POSITION_ICON), tr("Position"), menu);
new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"), new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"), menu);
menu);
new QListWidgetItem(QIcon(SYSTEM_ICON), tr("System"), menu); new QListWidgetItem(QIcon(SYSTEM_ICON), tr("System"), menu);
#endif // Q_OS_ANDROID
QHBoxLayout *contentLayout = new QHBoxLayout(); QHBoxLayout *contentLayout = new QHBoxLayout();
contentLayout->addWidget(menu); contentLayout->addWidget(menu);

View File

@ -18,9 +18,16 @@ PDFExportDialog::PDFExportDialog(PDFExport &exp, Units units, QWidget *parent)
{ {
int index; int index;
#ifdef Q_OS_ANDROID
setWindowFlags(Qt::Window);
setWindowState(Qt::WindowFullScreen);
#endif /* Q_OS_ANDROID */
_fileSelect = new FileSelectWidget(); _fileSelect = new FileSelectWidget();
#ifndef Q_OS_ANDROID
_fileSelect->setFilter(tr("PDF files") + " (*.pdf);;" + tr("All files") _fileSelect->setFilter(tr("PDF files") + " (*.pdf);;" + tr("All files")
+ " (*)"); + " (*)");
#endif // Q_OS_ANDROID
_fileSelect->setFile(_export.fileName); _fileSelect->setFile(_export.fileName);
_paperSize = new QComboBox(); _paperSize = new QComboBox();
@ -102,6 +109,9 @@ PDFExportDialog::PDFExportDialog(PDFExport &exp, Units units, QWidget *parent)
#else // Q_OS_MAC #else // Q_OS_MAC
layout->addWidget(pageSetupBox); layout->addWidget(pageSetupBox);
layout->addWidget(outputFileBox); layout->addWidget(outputFileBox);
#ifdef Q_OS_ANDROID
layout->addStretch();
#endif // Q_OS_ANDROID
#endif // Q_OS_MAC #endif // Q_OS_MAC
layout->addWidget(buttonBox); layout->addWidget(buttonBox);
setLayout(layout); setLayout(layout);

View File

@ -15,9 +15,16 @@
PNGExportDialog::PNGExportDialog(PNGExport &exp, QWidget *parent) PNGExportDialog::PNGExportDialog(PNGExport &exp, QWidget *parent)
: QDialog(parent), _export(exp) : QDialog(parent), _export(exp)
{ {
#ifdef Q_OS_ANDROID
setWindowFlags(Qt::Window);
setWindowState(Qt::WindowFullScreen);
#endif /* Q_OS_ANDROID */
_fileSelect = new FileSelectWidget(); _fileSelect = new FileSelectWidget();
#ifndef Q_OS_ANDROID
_fileSelect->setFilter(tr("PNG files") + " (*.png);;" + tr("All files") _fileSelect->setFilter(tr("PNG files") + " (*.png);;" + tr("All files")
+ " (*)"); + " (*)");
#endif // Q_OS_ANDROID
_fileSelect->setFile(_export.fileName); _fileSelect->setFile(_export.fileName);
_width = new QSpinBox(); _width = new QSpinBox();
@ -78,6 +85,9 @@ PNGExportDialog::PNGExportDialog(PNGExport &exp, QWidget *parent)
#else // Q_OS_MAC #else // Q_OS_MAC
layout->addWidget(pageSetupBox); layout->addWidget(pageSetupBox);
layout->addWidget(outputFileBox); layout->addWidget(outputFileBox);
#ifdef Q_OS_ANDROID
layout->addStretch();
#endif // Q_OS_ANDROID
#endif // Q_OS_MAC #endif // Q_OS_MAC
layout->addWidget(buttonBox); layout->addWidget(buttonBox);
setLayout(layout); setLayout(layout);

View File

@ -24,10 +24,17 @@ void PowerGraph::setInfo()
if (_showTracks) { if (_showTracks) {
QLocale l(QLocale::system()); QLocale l(QLocale::system());
#ifdef Q_OS_ANDROID
GraphView::addInfo(tr("Avg"), l.toString(avg() * yScale() + yOffset(),
'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Max"), l.toString(max() * yScale() + yOffset(),
'f', 1) + UNIT_SPACE + yUnits());
#else // Q_OS_ANDROID
GraphView::addInfo(tr("Average"), l.toString(avg() * yScale() GraphView::addInfo(tr("Average"), l.toString(avg() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits()); + yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale() GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits()); + yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else } else
clearInfo(); clearInfo();
} }

View File

@ -1,6 +1,8 @@
#ifndef SETTINGS_H #ifndef SETTINGS_H
#define SETTINGS_H #define SETTINGS_H
#include <QtGlobal>
#define IMPERIAL_UNITS() \ #define IMPERIAL_UNITS() \
(QLocale::system().measurementSystem() == QLocale::ImperialSystem) (QLocale::system().measurementSystem() == QLocale::ImperialSystem)
#define POSITION_PLUGIN() \ #define POSITION_PLUGIN() \

View File

@ -31,10 +31,17 @@ void SpeedGraph::setInfo()
QString pu = (_units == Metric) ? tr("min/km") : (_units == Imperial) ? QString pu = (_units == Metric) ? tr("min/km") : (_units == Imperial) ?
tr("min/mi") : tr("min/nmi"); tr("min/mi") : tr("min/nmi");
#ifdef Q_OS_ANDROID
GraphView::addInfo(tr("Avg"), l.toString(avg() * yScale(), 'f', 1)
+ UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Max"), l.toString(max() * yScale(), 'f', 1)
+ UNIT_SPACE + yUnits());
#else // Q_OS_ANDROID
GraphView::addInfo(tr("Average"), l.toString(avg() * yScale(), 'f', GraphView::addInfo(tr("Average"), l.toString(avg() * yScale(), 'f',
1) + UNIT_SPACE + yUnits()); 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f', GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f',
1) + UNIT_SPACE + yUnits()); 1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
GraphView::addInfo(tr("Pace"), pace + UNIT_SPACE + pu); GraphView::addInfo(tr("Pace"), pace + UNIT_SPACE + pu);
} else } else
clearInfo(); clearInfo();

View File

@ -24,12 +24,21 @@ void TemperatureGraph::setInfo()
if (_showTracks) { if (_showTracks) {
QLocale l(QLocale::system()); QLocale l(QLocale::system());
#ifdef Q_OS_ANDROID
GraphView::addInfo(tr("Avg"), l.toString(avg() * yScale() + yOffset(),
'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Min"), l.toString(min() * yScale() + yOffset(),
'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Max"), l.toString(max() * yScale() + yOffset(),
'f', 1) + UNIT_SPACE + yUnits());
#else // Q_OS_ANDROID
GraphView::addInfo(tr("Average"), l.toString(avg() * yScale() GraphView::addInfo(tr("Average"), l.toString(avg() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits()); + yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale() GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits()); + yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale() GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits()); + yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else } else
clearInfo(); clearInfo();
} }

View File

@ -32,11 +32,21 @@ Thumbnail::Thumbnail(const QString &path, int limit, QWidget *parent)
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
#ifdef Q_OS_ANDROID
_path = path;
#else //Q_OS_ANDROID
_path = QFileInfo(path).absoluteFilePath(); _path = QFileInfo(path).absoluteFilePath();
#endif // Q_OS_ANDROID
} }
void Thumbnail::mousePressEvent(QMouseEvent *event) void Thumbnail::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) if (event->button() == Qt::LeftButton)
#ifdef Q_OS_ANDROID
QDesktopServices::openUrl(_path);
#else // Q_OS_ANDROID
QDesktopServices::openUrl(QUrl::fromLocalFile(_path)); QDesktopServices::openUrl(QUrl::fromLocalFile(_path));
#endif // Q_OS_ANDROID
QLabel::mousePressEvent(event);
} }

View File

@ -19,65 +19,97 @@
#define TYP_FILE "style.typ" #define TYP_FILE "style.typ"
#define RENDERTHEME_FILE "style.xml" #define RENDERTHEME_FILE "style.xml"
#ifdef Q_OS_ANDROID
#define DATA_LOCATION QStandardPaths::GenericDataLocation
#else // Q_OS_ANDROID
#define DATA_LOCATION QStandardPaths::AppDataLocation
#endif // Q_OS_ANDROID
#ifdef Q_OS_ANDROID
static QString assetsPath(const QString &path, const QString &dir)
{
QDir pd(path);
if (pd.isAbsolute() && pd.exists())
return pd.absolutePath();
else
return QString("assets://") + dir;
}
#endif // Q_OS_ANDROID
QString ProgramPaths::mapDir(bool writable) QString ProgramPaths::mapDir(bool writable)
{ {
if (writable) if (writable)
return QDir(QStandardPaths::writableLocation( return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
QStandardPaths::AppDataLocation)).filePath(MAP_DIR); .filePath(MAP_DIR);
else else
return QStandardPaths::locate(QStandardPaths::AppDataLocation, #ifdef Q_OS_ANDROID
return assetsPath(QStandardPaths::locate(DATA_LOCATION, MAP_DIR,
QStandardPaths::LocateDirectory), MAP_DIR);
#else // Q_OS_ANDROID
return QStandardPaths::locate(DATA_LOCATION,
MAP_DIR, QStandardPaths::LocateDirectory); MAP_DIR, QStandardPaths::LocateDirectory);
#endif // Q_OS_ANDROID
} }
QString ProgramPaths::poiDir(bool writable) QString ProgramPaths::poiDir(bool writable)
{ {
if (writable) if (writable)
return QDir(QStandardPaths::writableLocation( return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
QStandardPaths::AppDataLocation)).filePath(POI_DIR); .filePath(POI_DIR);
else else
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QStandardPaths::locate(DATA_LOCATION, POI_DIR,
POI_DIR, QStandardPaths::LocateDirectory); QStandardPaths::LocateDirectory);
} }
QString ProgramPaths::csvDir(bool writable) QString ProgramPaths::csvDir(bool writable)
{ {
if (writable) if (writable)
return QDir(QStandardPaths::writableLocation( return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
QStandardPaths::AppDataLocation)).filePath(CSV_DIR); .filePath(CSV_DIR);
else else
return QStandardPaths::locate(QStandardPaths::AppDataLocation, #ifdef Q_OS_ANDROID
CSV_DIR, QStandardPaths::LocateDirectory); return assetsPath(QStandardPaths::locate(DATA_LOCATION, CSV_DIR,
QStandardPaths::LocateDirectory), CSV_DIR);
#else // Q_OS_ANDROID
return QStandardPaths::locate(DATA_LOCATION, CSV_DIR,
QStandardPaths::LocateDirectory);
#endif // Q_OS_ANDROID
} }
QString ProgramPaths::demDir(bool writable) QString ProgramPaths::demDir(bool writable)
{ {
if (writable) if (writable)
return QDir(QStandardPaths::writableLocation( return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
QStandardPaths::AppDataLocation)).filePath(DEM_DIR); .filePath(DEM_DIR);
else else
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QStandardPaths::locate(DATA_LOCATION, DEM_DIR,
DEM_DIR, QStandardPaths::LocateDirectory); QStandardPaths::LocateDirectory);
} }
QString ProgramPaths::styleDir(bool writable) QString ProgramPaths::styleDir(bool writable)
{ {
if (writable) if (writable)
return QDir(QStandardPaths::writableLocation( return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
QStandardPaths::AppDataLocation)).filePath(STYLE_DIR); .filePath(STYLE_DIR);
else else
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QStandardPaths::locate(DATA_LOCATION, STYLE_DIR,
STYLE_DIR, QStandardPaths::LocateDirectory); QStandardPaths::LocateDirectory);
} }
QString ProgramPaths::symbolsDir(bool writable) QString ProgramPaths::symbolsDir(bool writable)
{ {
if (writable) if (writable)
return QDir(QStandardPaths::writableLocation( return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
QStandardPaths::AppDataLocation)).filePath(SYMBOLS_DIR); .filePath(SYMBOLS_DIR);
else else
return QStandardPaths::locate(QStandardPaths::AppDataLocation, #ifdef Q_OS_ANDROID
SYMBOLS_DIR, QStandardPaths::LocateDirectory); return assetsPath(QStandardPaths::locate(DATA_LOCATION, SYMBOLS_DIR,
QStandardPaths::LocateDirectory), SYMBOLS_DIR);
#else // Q_OS_ANDROID
return QStandardPaths::locate(DATA_LOCATION, SYMBOLS_DIR,
QStandardPaths::LocateDirectory);
#endif // Q_OS_ANDROID
} }
QString ProgramPaths::tilesDir() QString ProgramPaths::tilesDir()
@ -88,36 +120,31 @@ QString ProgramPaths::tilesDir()
QString ProgramPaths::translationsDir() QString ProgramPaths::translationsDir()
{ {
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QStandardPaths::locate(DATA_LOCATION, TRANSLATIONS_DIR,
TRANSLATIONS_DIR, QStandardPaths::LocateDirectory); QStandardPaths::LocateDirectory);
} }
QString ProgramPaths::ellipsoidsFile() QString ProgramPaths::ellipsoidsFile()
{ {
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QDir(csvDir()).filePath(ELLIPSOID_FILE);
CSV_DIR "/" ELLIPSOID_FILE, QStandardPaths::LocateFile);
} }
QString ProgramPaths::gcsFile() QString ProgramPaths::gcsFile()
{ {
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QDir(csvDir()).filePath(GCS_FILE);
CSV_DIR "/" GCS_FILE, QStandardPaths::LocateFile);
} }
QString ProgramPaths::pcsFile() QString ProgramPaths::pcsFile()
{ {
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QDir(csvDir()).filePath(PCS_FILE);
CSV_DIR "/" PCS_FILE, QStandardPaths::LocateFile);
} }
QString ProgramPaths::typFile() QString ProgramPaths::typFile()
{ {
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QDir(styleDir()).filePath(TYP_FILE);
STYLE_DIR "/" TYP_FILE, QStandardPaths::LocateFile);
} }
QString ProgramPaths::renderthemeFile() QString ProgramPaths::renderthemeFile()
{ {
return QStandardPaths::locate(QStandardPaths::AppDataLocation, return QDir(styleDir()).filePath(RENDERTHEME_FILE);
STYLE_DIR "/" RENDERTHEME_FILE, QStandardPaths::LocateFile);
} }

View File

@ -1,9 +1,71 @@
#include <cctype> #include <cctype>
#include <cmath> #include <cmath>
#include <QFileInfo> #include <QFileInfo>
#ifdef Q_OS_ANDROID
#include <QUrl>
#include <QCoreApplication>
#include <QJniEnvironment>
#include <QJniObject>
#endif // Q_OS_ANDROID
#include "util.h" #include "util.h"
#ifdef Q_OS_ANDROID
static QString documentName(const QString &path)
{
QJniEnvironment env;
QJniObject urlString = QJniObject::fromString(path);
QJniObject uri = QJniObject::callStaticObjectMethod("android/net/Uri",
"parse", "(Ljava/lang/String;)Landroid/net/Uri;",
urlString.object<jstring>());
if (!uri.isValid()) {
env->ExceptionClear();
return QString();
}
QJniObject context = QNativeInterface::QAndroidApplication::context();
if (!context.isValid()) {
env->ExceptionClear();
return QString();
}
QJniObject contentResolver = context.callObjectMethod(
"getContentResolver", "()Landroid/content/ContentResolver;");
if (!contentResolver.isValid()) {
env->ExceptionClear();
return QString();
}
QJniObject columnName = QJniObject::getStaticObjectField<jstring>(
"android/provider/MediaStore$MediaColumns", "DISPLAY_NAME");
if (!columnName.isValid()) {
env->ExceptionClear();
return QString();
}
jobjectArray stringArray = env->NewObjectArray(
1, env->FindClass("java/lang/String"), 0);
env->SetObjectArrayElement(stringArray, 0, columnName.object<jstring>());
QJniObject cursor = contentResolver.callObjectMethod("query",
"(Landroid/net/Uri;[Ljava/lang/String;Landroid/os/Bundle;"
"Landroid/os/CancellationSignal;)Landroid/database/Cursor;",
uri.object(), stringArray, 0, 0);
if (!cursor.isValid()) {
env->ExceptionClear();
return QString();
}
if (!cursor.callMethod<jboolean>("moveToFirst")) {
env->ExceptionClear();
return QString();
}
QJniObject str = cursor.callObjectMethod("getString",
"(I)Ljava/lang/String;", 0);
if (!str.isValid()) {
env->ExceptionClear();
return QString();
}
return str.toString();
}
#endif // Q_OS_ANDROID
int Util::str2int(const char *str, int len) int Util::str2int(const char *str, int len)
{ {
int res = 0; int res = 0;
@ -52,6 +114,28 @@ double Util::niceNum(double x, bool round)
QString Util::file2name(const QString &path) QString Util::file2name(const QString &path)
{ {
QFileInfo fi(path); QFileInfo fi(displayName(path));
return fi.baseName().replace('_', ' '); return fi.baseName().replace('_', ' ');
} }
QString Util::displayName(const QString &path)
{
#ifdef Q_OS_ANDROID
QUrl url(path);
// Not an Android URL, return standard filename.
if (url.scheme() != "content") {
QFileInfo fi(path);
return fi.fileName();
// Directory browsing URLs. Those can not be translated using the Android
// content resolver but we can get the filename from the URL path.
} else if (url.path().startsWith("/tree/")) {
QFileInfo fi(url.fileName());
return fi.fileName();
// Translate all "regular" android URLs using the Android content resolver.
} else
return documentName(path);
#else
return path;
#endif // Q_OS_ANDROID
}

View File

@ -8,6 +8,7 @@ namespace Util
int str2int(const char *str, int len); int str2int(const char *str, int len);
double niceNum(double x, bool round); double niceNum(double x, bool round);
QString file2name(const QString &path); QString file2name(const QString &path);
QString displayName(const QString &path);
} }
#endif // UTIL_H #endif // UTIL_H