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

Compare commits

..

2 Commits

Author SHA1 Message Date
844607f6ce Added missing QT SVG devel package dependency 2022-05-28 14:14:59 +02:00
ba0b7c62a4 Android port 2022-05-28 14:05:14 +02:00
42 changed files with 914 additions and 113 deletions

View File

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

View File

@ -15,7 +15,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qt5-qmake qttools5-dev-tools libqt5opengl5-dev qtpositioning5-dev
sudo apt-get install qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qt5-qmake qttools5-dev-tools libqt5opengl5-dev qtpositioning5-dev libqt5svg5-dev
- name: Create localization
run: lrelease gpxsee.pro
- name: Configure build

View File

@ -1,9 +1,9 @@
unix:!macx {
unix:!macx:!android {
TARGET = gpxsee
} else {
TARGET = GPXSee
}
VERSION = 10.8
VERSION = 11.0
QT += core \
gui \
@ -13,7 +13,8 @@ QT += core \
concurrent \
widgets \
printsupport \
positioning
positioning \
svg
greaterThan(QT_MAJOR_VERSION, 5) {
QT += openglwidgets \
core5compat
@ -24,6 +25,7 @@ INCLUDEPATH += ./src
HEADERS += src/common/config.h \
src/GUI/crosshairitem.h \
src/GUI/motioninfoitem.h \
src/GUI/navigationwidget.h \
src/GUI/pluginparameters.h \
src/common/garmin.h \
src/common/coordinates.h \
@ -246,6 +248,7 @@ HEADERS += src/common/config.h \
SOURCES += src/main.cpp \
src/GUI/crosshairitem.cpp \
src/GUI/motioninfoitem.cpp \
src/GUI/navigationwidget.cpp \
src/GUI/pluginparameters.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
@ -504,7 +507,7 @@ win32 {
NOGDI
}
unix:!macx {
unix:!macx:!android {
isEmpty(PREFIX):PREFIX = /usr/local
maps.files = $$files(pkg/maps/*)
@ -524,3 +527,39 @@ unix:!macx {
target.path = $$PREFIX/bin
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
Name "GPXSee"
; Program version
!define VERSION "10.8"
!define VERSION "11.0"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -61,6 +61,10 @@ App::App(int &argc, char **argv) : QApplication(argc, argv)
Waypoint::loadSymbolIcons(ProgramPaths::symbolsDir());
_gui = new GUI();
#ifdef Q_OS_ANDROID
connect(this, &App::applicationStateChanged, this, &App::appStateChanged);
#endif // Q_OS_ANDROID
}
App::~App()
@ -93,6 +97,14 @@ int App::run()
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)
{
if (event->type() == QEvent::FileOpen) {

View File

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

View File

@ -24,10 +24,17 @@ void CadenceGraph::setInfo()
if (_showTracks) {
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()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else
clearInfo();
}

View File

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

View File

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

View File

@ -54,6 +54,16 @@ void ElevationGraph::setInfo()
else {
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(),
'f', 0) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Descent"), l.toString(descent() * yScale(),
@ -62,6 +72,7 @@ void ElevationGraph::setInfo()
0) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale(), 'f',
0) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
}
}

View File

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

View File

@ -14,9 +14,14 @@ class FileBrowser : public QObject
public:
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);
#endif // Q_OS_ANDROID
void setFilter(const QStringList &filter);
QString current();
QString next();
QString prev();
QString last();
@ -32,7 +37,9 @@ private slots:
void reloadDirectory(const QString &path);
private:
#ifndef Q_OS_ANDROID
QFileSystemWatcher *_watcher;
#endif // Q_OS_ANDROID
QStringList _filter;
QFileInfoList _files;
int _index;

View File

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

View File

@ -24,12 +24,21 @@ void GearRatioGraph::setInfo()
if (_showTracks) {
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(),
'f', 2) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale(), 'f',
2) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f',
2) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else
clearInfo();
}

View File

@ -53,6 +53,7 @@
#include "mapitem.h"
#include "mapaction.h"
#include "poiaction.h"
#include "navigationwidget.h"
#include "gui.h"
@ -72,7 +73,11 @@ GUI::GUI()
createStatusBar();
createActions();
createMenus();
#ifdef Q_OS_ANDROID
createNavigation();
#else // Q_OS_ANDROID
createToolBars();
#endif // Q_OS_ANDROID
createBrowser();
_splitter = new QSplitter();
@ -83,6 +88,7 @@ GUI::GUI()
_splitter->setContentsMargins(0, 0, 0, 0);
_splitter->setStretchFactor(0, 255);
_splitter->setStretchFactor(1, 1);
setCentralWidget(_splitter);
setWindowIcon(QIcon(APP_ICON));
@ -181,19 +187,23 @@ void GUI::createActions()
_navigationActionGroup->setEnabled(false);
// General actions
#if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
_exitAction = new QAction(QIcon(QUIT_ICON), tr("Quit"), this);
_exitAction->setShortcut(QUIT_SHORTCUT);
_exitAction->setMenuRole(QAction::QuitRole);
connect(_exitAction, &QAction::triggered, this, &GUI::close);
addAction(_exitAction);
#endif // Q_OS_MAC + Q_OS_ANDROID
// Help & About
_pathsAction = new QAction(tr("Paths"), this);
_pathsAction->setMenuRole(QAction::NoRole);
connect(_pathsAction, &QAction::triggered, this, &GUI::paths);
#ifndef Q_OS_ANDROID
_keysAction = new QAction(tr("Keyboard controls"), this);
_keysAction->setMenuRole(QAction::NoRole);
connect(_keysAction, &QAction::triggered, this, &GUI::keys);
#endif // Q_OS_ANDROID
_aboutAction = new QAction(QIcon(APP_ICON), tr("About GPXSee"), this);
_aboutAction->setMenuRole(QAction::AboutRole);
connect(_aboutAction, &QAction::triggered, this, &GUI::about);
@ -205,6 +215,12 @@ void GUI::createActions()
connect(_openFileAction, &QAction::triggered, this,
QOverload<>::of(&GUI::openFile));
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..."),
this);
_printFileAction->setMenuRole(QAction::NoRole);
@ -459,10 +475,12 @@ void GUI::createActions()
&GUI::showGraphSliderInfo);
// Settings actions
#ifndef Q_OS_ANDROID
_showToolbarsAction = new QAction(tr("Show toolbars"), this);
_showToolbarsAction->setMenuRole(QAction::NoRole);
_showToolbarsAction->setCheckable(true);
connect(_showToolbarsAction, &QAction::triggered, this, &GUI::showToolbars);
#endif // Q_OS_ANDROID
ag = new QActionGroup(this);
ag->setExclusive(true);
_totalTimeAction = new QAction(tr("Total time"), this);
@ -514,6 +532,7 @@ void GUI::createActions()
_dmsAction->setCheckable(true);
_dmsAction->setActionGroup(ag);
connect(_dmsAction, &QAction::triggered, this, &GUI::setDMS);
#ifndef Q_OS_ANDROID
_fullscreenAction = new QAction(QIcon(FULLSCREEN_ICON),
tr("Fullscreen mode"), this);
_fullscreenAction->setMenuRole(QAction::NoRole);
@ -521,11 +540,13 @@ void GUI::createActions()
_fullscreenAction->setShortcut(FULLSCREEN_SHORTCUT);
connect(_fullscreenAction, &QAction::triggered, this, &GUI::showFullscreen);
addAction(_fullscreenAction);
#endif // Q_OS_ANDROID
_openOptionsAction = new QAction(tr("Options..."), this);
_openOptionsAction->setMenuRole(QAction::PreferencesRole);
connect(_openOptionsAction, &QAction::triggered, this, &GUI::openOptions);
// Navigation actions
#ifndef Q_OS_ANDROID
_nextAction = new QAction(QIcon(NEXT_FILE_ICON), tr("Next"), this);
_nextAction->setActionGroup(_navigationActionGroup);
_nextAction->setMenuRole(QAction::NoRole);
@ -542,6 +563,7 @@ void GUI::createActions()
_firstAction->setMenuRole(QAction::NoRole);
_firstAction->setActionGroup(_navigationActionGroup);
connect(_firstAction, &QAction::triggered, this, &GUI::first);
#endif // Q_OS_ANDROID
}
void GUI::createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu,
@ -574,8 +596,13 @@ void GUI::createMenus()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(_openFileAction);
#ifdef Q_OS_ANDROID
fileMenu->addAction(_openDirAction);
#endif // Q_OS_ANDROID
fileMenu->addSeparator();
#ifndef Q_OS_ANDROID
fileMenu->addAction(_printFileAction);
#endif // Q_OS_ANDROID
fileMenu->addAction(_exportPDFFileAction);
fileMenu->addAction(_exportPNGFileAction);
fileMenu->addSeparator();
@ -583,10 +610,10 @@ void GUI::createMenus()
fileMenu->addSeparator();
fileMenu->addAction(_reloadFileAction);
fileMenu->addAction(_closeFileAction);
#ifndef Q_OS_MAC
#if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
fileMenu->addSeparator();
fileMenu->addAction(_exitAction);
#endif // Q_OS_MAC
#endif // Q_OS_MAC + Q_OS_ANDROID
_mapMenu = menuBar()->addMenu(tr("&Map"));
_mapsEnd = _mapMenu->addSeparator();
@ -659,18 +686,31 @@ void GUI::createMenus()
coordinatesMenu->addAction(_degreesMinutesAction);
coordinatesMenu->addAction(_dmsAction);
settingsMenu->addSeparator();
#ifndef Q_OS_ANDROID
settingsMenu->addAction(_showToolbarsAction);
settingsMenu->addAction(_fullscreenAction);
settingsMenu->addSeparator();
#endif // Q_OS_ANDROID
settingsMenu->addAction(_openOptionsAction);
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(_pathsAction);
#ifndef Q_OS_ANDROID
helpMenu->addAction(_keysAction);
#endif // Q_OS_ANDROID
helpMenu->addSeparator();
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()
{
int is = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
@ -706,6 +746,7 @@ void GUI::createToolBars()
_navigationToolBar->addAction(_nextAction);
_navigationToolBar->addAction(_lastAction);
}
#endif // Q_OS_ANDROID
void GUI::createMapView()
{
@ -713,7 +754,11 @@ void GUI::createMapView()
_mapView = new MapView(_map, _poi, 0, this);
_mapView->setSizePolicy(QSizePolicy(QSizePolicy::Ignored,
QSizePolicy::Expanding));
#ifdef Q_OS_ANDROID
_mapView->setMinimumHeight(100);
#else // Q_OS_ANDROID
_mapView->setMinimumHeight(200);
#endif // Q_OS_ANDROID
#ifdef Q_OS_WIN32
_mapView->setFrameShape(QFrame::NoFrame);
#endif // Q_OS_WIN32
@ -765,7 +810,16 @@ void GUI::about()
QUrl homepage(APP_HOMEPAGE);
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()
+ ", Qt " + QT_VERSION_STR + ")") + "</p>");
msgBox.setInformativeText("<table width=\"300\"><tr><td>"
@ -778,10 +832,12 @@ void GUI::about()
QIcon icon = msgBox.windowIcon();
QSize size = icon.actualSize(QSize(64, 64));
msgBox.setIconPixmap(icon.pixmap(size));
#endif // Q_OS_ANDROID
msgBox.exec();
}
#ifndef Q_OS_ANDROID
void GUI::keys()
{
QMessageBox msgBox(this);
@ -820,12 +876,30 @@ void GUI::keys()
msgBox.exec();
}
#endif // Q_OS_ANDROID
void GUI::paths()
{
QMessageBox msgBox(this);
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.setInformativeText(
"<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>"
+ QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
);
#endif // Q_OS_ANDROID
msgBox.exec();
}
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"),
_dataDir, Data::formats()));
#endif // Q_OS_ANDROID
for (int i = 0; i < files.size(); i++)
openFile(files.at(i));
@ -859,6 +939,19 @@ void GUI::openFile()
_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)
{
if (_files.contains(fileName))
@ -868,7 +961,9 @@ bool GUI::openFile(const QString &fileName, bool silent)
return false;
_files.append(fileName);
#ifndef Q_OS_ANDROID
_browser->setCurrent(fileName);
#endif // Q_OS_ANDROID
_fileActionGroup->setEnabled(true);
// Explicitly enable the reload action as it may be disabled by loadMapDir()
_reloadFileAction->setEnabled(true);
@ -898,7 +993,7 @@ bool GUI::loadFile(const QString &fileName, bool silent)
_fileActionGroup->setEnabled(false);
QString error = tr("Error loading data file:") + "\n\n"
+ fileName + "\n\n" + data.errorString();
+ Util::displayName(fileName) + "\n\n" + data.errorString();
if (data.errorLine())
error.append("\n" + tr("Line: %1").arg(data.errorLine()));
QMessageBox::critical(this, APP_NAME, error);
@ -967,8 +1062,13 @@ void GUI::loadData(const Data &data)
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"),
_poiDir, Data::formats()));
#endif // Q_OS_ANDROID
for (int i = 0; i < files.size(); i++)
openPOIFile(files.at(i));
@ -994,7 +1094,7 @@ bool GUI::openPOIFile(const QString &fileName)
return true;
} else {
QString error = tr("Error loading POI file:") + "\n\n"
+ fileName + "\n\n" + _poi->errorString();
+ Util::displayName(fileName) + "\n\n" + _poi->errorString();
if (_poi->errorLine())
error.append("\n" + tr("Line: %1").arg(_poi->errorLine()));
QMessageBox::critical(this, APP_NAME, error);
@ -1207,12 +1307,72 @@ void GUI::exportPNGFile()
void GUI::statistics()
{
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
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>";
#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>";
#endif // Q_OS_WIN32
@ -1267,11 +1427,11 @@ void GUI::statistics()
text.append("</table>");
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Statistics"));
msgBox.setText("<h3>" + tr("Statistics") + "</h3>");
msgBox.setInformativeText(text);
#endif // Q_OS_ANDROID
msgBox.exec();
}
@ -1430,8 +1590,10 @@ void GUI::reloadFiles()
updateWindowTitle();
if (_files.isEmpty())
_fileActionGroup->setEnabled(false);
#ifndef Q_OS_ANDROID
else
_browser->setCurrent(_files.last());
#endif // Q_OS_ANDROID
updateDEMDownloadAction();
}
@ -1466,6 +1628,10 @@ void GUI::closeAll()
updateWindowTitle();
updateGraphTabs();
updateDEMDownloadAction();
#ifdef Q_OS_ANDROID
_browser->setCurrentDir(QString());
#endif // Q_OS_ANDROID
}
void GUI::showGraphs(bool show)
@ -1473,6 +1639,7 @@ void GUI::showGraphs(bool show)
_graphTabWidget->setHidden(!show);
}
#ifndef Q_OS_ANDROID
void GUI::showToolbars(bool show)
{
if (show) {
@ -1515,6 +1682,7 @@ void GUI::showFullscreen(bool show)
showNormal();
}
}
#endif // Q_OS_ANDROID
void GUI::showTracks(bool show)
{
@ -1583,8 +1751,13 @@ void GUI::showPathMarkerInfo(QAction *action)
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"),
_mapDir, MapList::formats()));
#endif // Q_OS_ANDROID
MapAction *a, *lastReady = 0;
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 (!silent)
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());
delete map;
} else {
@ -1672,8 +1846,8 @@ void GUI::mapLoaded()
_showMapAction->setEnabled(true);
_clearMapCacheAction->setEnabled(true);
} else {
QString error = tr("Error loading map:") + "\n\n" + map->path() + "\n\n"
+ map->errorString();
QString error = tr("Error loading map:") + "\n\n"
+ Util::displayName(map->path()) + "\n\n" + map->errorString();
QMessageBox::critical(this, APP_NAME, error);
action->deleteLater();
}
@ -1691,8 +1865,8 @@ void GUI::mapLoadedDir()
actions.append(action);
_mapView->loadMaps(actions);
} else {
QString error = tr("Error loading map:") + "\n\n" + map->path() + "\n\n"
+ map->errorString();
QString error = tr("Error loading map:") + "\n\n"
+ Util::displayName(map->path()) + "\n\n" + map->errorString();
QMessageBox::critical(this, APP_NAME, error);
action->deleteLater();
}
@ -1714,7 +1888,8 @@ void GUI::loadMapDirNode(const TreeNode<Map *> &node, QList<MapAction*> &actions
if (!(a = findMapAction(existingActions, map))) {
if (!map->isValid()) {
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;
} else {
a = new MapAction(map, _mapsActionGroup);
@ -1817,7 +1992,7 @@ void GUI::updateStatusBarInfo()
if (_files.count() == 0)
_fileNameLabel->setText(tr("No files loaded"));
else if (_files.count() == 1)
_fileNameLabel->setText(_files.at(0));
_fileNameLabel->setText(Util::displayName(_files.at(0)));
else
_fileNameLabel->setText(tr("%n files", "", _files.count()));
@ -1840,6 +2015,10 @@ void GUI::updateStatusBarInfo()
_timeLabel->clear();
_timeLabel->setToolTip(QString());
}
#ifdef Q_OS_ANDROID
statusBar()->setVisible(!_files.isEmpty());
#endif // Q_OS_ANDROID
}
void GUI::updateWindowTitle()
@ -1929,10 +2108,17 @@ void GUI::graphChanged(int index)
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());
_nextAction->setEnabled(!_browser->isLast());
_firstAction->setEnabled(!_browser->isFirst());
_prevAction->setEnabled(!_browser->isFirst());
#endif // Q_OS_ANDROID
}
bool GUI::updateGraphTabs()
@ -2042,6 +2228,7 @@ void GUI::first()
openFile(file);
}
#ifndef Q_OS_ANDROID
void GUI::keyPressEvent(QKeyEvent *event)
{
QString file;
@ -2096,11 +2283,12 @@ void GUI::keyPressEvent(QKeyEvent *event)
QMainWindow::keyPressEvent(event);
}
#endif // Q_OS_ANDROID
void GUI::closeEvent(QCloseEvent *event)
{
writeSettings();
event->accept();
QMainWindow::closeEvent(event);
}
void GUI::dragEnterEvent(QDragEnterEvent *event)
@ -2167,6 +2355,7 @@ void GUI::writeSettings()
QSettings settings(qApp->applicationName(), qApp->applicationName());
settings.clear();
#ifndef Q_OS_ANDROID
settings.beginGroup(WINDOW_SETTINGS_GROUP);
if (!_windowStates.isEmpty() && !_windowGeometries.isEmpty()) {
settings.setValue(WINDOW_STATE_SETTING, _windowStates.first());
@ -2176,6 +2365,7 @@ void GUI::writeSettings()
settings.setValue(WINDOW_GEOMETRY_SETTING, saveGeometry());
}
settings.endGroup();
#endif // Q_OS_ANDROID
settings.beginGroup(SETTINGS_SETTINGS_GROUP);
if ((_movingTimeAction->isChecked() ? Moving : Total) !=
@ -2190,9 +2380,11 @@ void GUI::writeSettings()
: _degreesMinutesAction->isChecked() ? DegreesMinutes : DecimalDegrees;
if (format != COORDINATES_DEFAULT)
settings.setValue(COORDINATES_SETTING, format);
#ifndef Q_OS_ANDROID
if (_showToolbarsAction->isChecked() != SHOW_TOOLBARS_DEFAULT)
settings.setValue(SHOW_TOOLBARS_SETTING,
_showToolbarsAction->isChecked());
#endif // Q_OS_ANDROID
settings.endGroup();
settings.beginGroup(MAP_SETTINGS_GROUP);
@ -2485,10 +2677,12 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
int value;
QSettings settings(qApp->applicationName(), qApp->applicationName());
#ifndef Q_OS_ANDROID
settings.beginGroup(WINDOW_SETTINGS_GROUP);
restoreGeometry(settings.value(WINDOW_GEOMETRY_SETTING).toByteArray());
restoreState(settings.value(WINDOW_STATE_SETTING).toByteArray());
settings.endGroup();
#endif // Q_OS_ANDROID
settings.beginGroup(SETTINGS_SETTINGS_GROUP);
if (settings.value(TIME_TYPE_SETTING, TIME_TYPE_DEFAULT).toInt() == Moving)
@ -2512,10 +2706,12 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
else
_decimalDegreesAction->trigger();
#ifndef Q_OS_ANDROID
if (!settings.value(SHOW_TOOLBARS_SETTING, SHOW_TOOLBARS_DEFAULT).toBool())
showToolbars(false);
else
_showToolbarsAction->setChecked(true);
#endif // Q_OS_ANDROID
settings.endGroup();
settings.beginGroup(MAP_SETTINGS_GROUP);
@ -2523,8 +2719,8 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
_showMapAction->setChecked(true);
else
_mapView->showMap(false);
if (settings.value(SHOW_CURSOR_COORDINATES_SETTING, SHOW_CURSOR_COORDINATES_DEFAULT)
.toBool()) {
if (settings.value(SHOW_CURSOR_COORDINATES_SETTING,
SHOW_CURSOR_COORDINATES_DEFAULT).toBool()) {
_showCoordinatesAction->setChecked(true);
_mapView->showCursorCoordinates(true);
}

View File

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

View File

@ -24,10 +24,17 @@ void HeartRateGraph::setInfo()
if (_showTracks) {
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',
0) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f',
0) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else
clearInfo();
}

View File

@ -662,20 +662,8 @@ void MapView::wheelEvent(QWheelEvent *event)
#else // QT 5.15
zoom((delta > 0) ? 1 : -1, event->position().toPoint(), shift);
#endif // QT 5.15
}
void MapView::mouseDoubleClickEvent(QMouseEvent *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);
QGraphicsView::wheelEvent(event);
}
void MapView::keyPressEvent(QKeyEvent *event)
@ -713,15 +701,6 @@ void MapView::keyReleaseEvent(QKeyEvent *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,
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)
{
if (_cursorCoordinates->isVisible()) {
@ -1210,10 +1195,30 @@ void MapView::mouseMoveEvent(QMouseEvent *event)
QGraphicsView::mouseMoveEvent(event);
}
void MapView::leaveEvent(QEvent *event)
void MapView::mousePressEvent(QMouseEvent *event)
{
_cursorCoordinates->setCoordinates(Coordinates());
QGraphicsView::leaveEvent(event);
if (event->button() == Qt::LeftButton) {
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)

View File

@ -102,6 +102,11 @@ public:
RectC boundingRect() const;
#ifdef Q_OS_ANDROID
signals:
void clicked(const QPoint &pos);
#endif // Q_OS_ANDROID
public slots:
void showMap(bool show);
void showPOI(bool show);
@ -162,6 +167,7 @@ private:
void drawBackground(QPainter *painter, const QRectF &rect);
void paintEvent(QPaintEvent *event);
void leaveEvent(QEvent *event);
bool event(QEvent *event);
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 "optionsdialog.h"
#ifdef Q_OS_ANDROID
#define MENU_MARGIN 0
#else // Q_OS_ANDROID
#define MENU_MARGIN 20
#endif // Q_OS_ANDROID
#define MENU_ICON_SIZE 32
#ifdef Q_OS_MAC
@ -779,6 +782,11 @@ QWidget *OptionsDialog::createSystemPage()
OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
: QDialog(parent), _options(options), _units(units)
{
#ifdef Q_OS_ANDROID
setWindowFlags(Qt::Window);
setWindowState(Qt::WindowFullScreen);
#endif /* Q_OS_ANDROID */
QStackedWidget *pages = new QStackedWidget();
pages->addWidget(createAppearancePage());
pages->addWidget(createMapPage());
@ -791,16 +799,25 @@ OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
QListWidget *menu = new QListWidget();
menu->setIconSize(QSize(MENU_ICON_SIZE, MENU_ICON_SIZE));
new QListWidgetItem(QIcon(APPEARANCE_ICON), tr("Appearance"),
menu);
#ifdef Q_OS_ANDROID
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(DATA_ICON), tr("Data"), menu);
new QListWidgetItem(QIcon(POI_ICON), tr("POI"), menu);
new QListWidgetItem(QIcon(DEM_ICON), tr("DEM"), menu);
new QListWidgetItem(QIcon(POSITION_ICON), tr("Position"), menu);
new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"),
menu);
new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"), menu);
new QListWidgetItem(QIcon(SYSTEM_ICON), tr("System"), menu);
#endif // Q_OS_ANDROID
QHBoxLayout *contentLayout = new QHBoxLayout();
contentLayout->addWidget(menu);

View File

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

View File

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

View File

@ -24,10 +24,17 @@ void PowerGraph::setInfo()
if (_showTracks) {
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()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else
clearInfo();
}

View File

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

View File

@ -31,10 +31,17 @@ void SpeedGraph::setInfo()
QString pu = (_units == Metric) ? tr("min/km") : (_units == Imperial) ?
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',
1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale(), 'f',
1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
GraphView::addInfo(tr("Pace"), pace + UNIT_SPACE + pu);
} else
clearInfo();

View File

@ -24,12 +24,21 @@ void TemperatureGraph::setInfo()
if (_showTracks) {
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()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Minimum"), l.toString(min() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), l.toString(max() * yScale()
+ yOffset(), 'f', 1) + UNIT_SPACE + yUnits());
#endif // Q_OS_ANDROID
} else
clearInfo();
}

View File

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

View File

@ -19,65 +19,97 @@
#define TYP_FILE "style.typ"
#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)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(MAP_DIR);
return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
.filePath(MAP_DIR);
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);
#endif // Q_OS_ANDROID
}
QString ProgramPaths::poiDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(POI_DIR);
return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
.filePath(POI_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
POI_DIR, QStandardPaths::LocateDirectory);
return QStandardPaths::locate(DATA_LOCATION, POI_DIR,
QStandardPaths::LocateDirectory);
}
QString ProgramPaths::csvDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(CSV_DIR);
return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
.filePath(CSV_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR, QStandardPaths::LocateDirectory);
#ifdef Q_OS_ANDROID
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)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(DEM_DIR);
return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
.filePath(DEM_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
DEM_DIR, QStandardPaths::LocateDirectory);
return QStandardPaths::locate(DATA_LOCATION, DEM_DIR,
QStandardPaths::LocateDirectory);
}
QString ProgramPaths::styleDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(STYLE_DIR);
return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
.filePath(STYLE_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
STYLE_DIR, QStandardPaths::LocateDirectory);
return QStandardPaths::locate(DATA_LOCATION, STYLE_DIR,
QStandardPaths::LocateDirectory);
}
QString ProgramPaths::symbolsDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(SYMBOLS_DIR);
return QDir(QStandardPaths::writableLocation(DATA_LOCATION))
.filePath(SYMBOLS_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
SYMBOLS_DIR, QStandardPaths::LocateDirectory);
#ifdef Q_OS_ANDROID
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()
@ -88,36 +120,31 @@ QString ProgramPaths::tilesDir()
QString ProgramPaths::translationsDir()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
TRANSLATIONS_DIR, QStandardPaths::LocateDirectory);
return QStandardPaths::locate(DATA_LOCATION, TRANSLATIONS_DIR,
QStandardPaths::LocateDirectory);
}
QString ProgramPaths::ellipsoidsFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR "/" ELLIPSOID_FILE, QStandardPaths::LocateFile);
return QDir(csvDir()).filePath(ELLIPSOID_FILE);
}
QString ProgramPaths::gcsFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR "/" GCS_FILE, QStandardPaths::LocateFile);
return QDir(csvDir()).filePath(GCS_FILE);
}
QString ProgramPaths::pcsFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR "/" PCS_FILE, QStandardPaths::LocateFile);
return QDir(csvDir()).filePath(PCS_FILE);
}
QString ProgramPaths::typFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
STYLE_DIR "/" TYP_FILE, QStandardPaths::LocateFile);
return QDir(styleDir()).filePath(TYP_FILE);
}
QString ProgramPaths::renderthemeFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
STYLE_DIR "/" RENDERTHEME_FILE, QStandardPaths::LocateFile);
return QDir(styleDir()).filePath(RENDERTHEME_FILE);
}

View File

@ -1,9 +1,71 @@
#include <cctype>
#include <cmath>
#include <QFileInfo>
#ifdef Q_OS_ANDROID
#include <QUrl>
#include <QCoreApplication>
#include <QJniEnvironment>
#include <QJniObject>
#endif // Q_OS_ANDROID
#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 res = 0;
@ -52,6 +114,28 @@ double Util::niceNum(double x, bool round)
QString Util::file2name(const QString &path)
{
QFileInfo fi(path);
QFileInfo fi(displayName(path));
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);
double niceNum(double x, bool round);
QString file2name(const QString &path);
QString displayName(const QString &path);
}
#endif // UTIL_H