diff --git a/src/dialogs/tlevelcreatoritem.cpp b/src/dialogs/tlevelcreatoritem.cpp index a3d776031031f87787dbece94c442f3afc344d80..0aec202d6c1a1160abc6d3ca496ffc6705fa782b 100644 --- a/src/dialogs/tlevelcreatoritem.cpp +++ b/src/dialogs/tlevelcreatoritem.cpp @@ -24,6 +24,9 @@ #include <tglobals.h> #include <texamparams.h> #include <Android/tfiledialog.h> +#if defined (Q_OS_ANDROID) + #include <Android/tandroid.h> +#endif #include <QtCore/qtimer.h> #include <QtCore/qfileinfo.h> @@ -92,6 +95,10 @@ void TlevelCreatorItem::continueLevelSave(const QString& name, const QString& de m_level->name = name; m_level->desc = desc; +#if defined (Q_OS_ANDROID) + if (GLOB->E->levelsDir.isEmpty()) + GLOB->E->levelsDir = Tandroid::getExternalPath(); +#endif // Saving to file QLatin1String dotNel(".nel"); QString fName = QDir::toNativeSeparators(GLOB->E->levelsDir + QLatin1String("/") + m_level->name); diff --git a/src/dialogs/tlevelselector.cpp b/src/dialogs/tlevelselector.cpp index 47efd0d1c543f544d6f3b5cf6729a3173ad100cd..9784384bac766094c3d743899df6022519f914fa 100644 --- a/src/dialogs/tlevelselector.cpp +++ b/src/dialogs/tlevelselector.cpp @@ -24,6 +24,9 @@ #include <tglobals.h> #include <tpath.h> #include <Android/tfiledialog.h> +#if defined (Q_OS_ANDROID) + #include <Android/tandroid.h> +#endif #include <QtCore/qsettings.h> #include <QtCore/qdiriterator.h> @@ -177,7 +180,9 @@ QString TlevelSelector::levelFile(int id) const { void TlevelSelector::loadFromFile(QString levelFile) { if (levelFile.isEmpty()) #if defined (Q_OS_ANDROID) - levelFile = TfileDialog::getOpenFileName(GLOB->E->levelsDir, QStringLiteral("nel")); + if (GLOB->E->levelsDir.isEmpty()) + GLOB->E->levelsDir = Tandroid::getExternalPath(); + levelFile = TfileDialog::getOpenFileName(GLOB->E->levelsDir, QStringLiteral("nel")); #else levelFile = TfileDialog::getOpenFileName(tr("Load exam level"), GLOB->E->levelsDir, levelFilterTxt() + QLatin1String(" (*.nel)")); #endif diff --git a/src/libs/core/Android/tandroid.cpp b/src/libs/core/Android/tandroid.cpp index 40a1e8310fd3e34e689a9fdf56968041b90ac34e..05503d5fa1b8e68c59cda76520145a4db25e3436 100644 --- a/src/libs/core/Android/tandroid.cpp +++ b/src/libs/core/Android/tandroid.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2015-2020 by Tomasz Bojczuk * + * Copyright (C) 2015-2021 by Tomasz Bojczuk * * seelook@gmail.com * * * * This program is free software; you can redistribute it and/or modify * @@ -24,6 +24,7 @@ #include <QtCore/qfileinfo.h> #include <QtWidgets/qmessagebox.h> #include <QtWidgets/qapplication.h> +#include <QtCore/qstandardpaths.h> #include <QtCore/qdebug.h> @@ -76,13 +77,20 @@ bool Tandroid::hasWriteAccess() { } +void Tandroid::askForWriteAcces() { + if (QtAndroid::androidSdkVersion() >= 23) { + const QString writeID("android.permission.WRITE_EXTERNAL_STORAGE"); + if (QtAndroid::checkPermission(writeID) != QtAndroid::PermissionResult::Granted) { + auto perms = QtAndroid::requestPermissionsSync(QStringList() << writeID); + qDebug() << writeID << (perms[writeID] == QtAndroid::PermissionResult::Granted); + } + } +} + QString Tandroid::getExternalPath() { QString extPath; if (getAPIlevelNr() < 19) { // look for SD card only before Kitkat, otherwise it is inaccessible extPath = qgetenv("SECONDARY_STORAGE"); - // QAndroidJniObject mediaDir = QAndroidJniObject::callStaticObjectMethod("android/os/Environment", - // "getExternalStorageDirectory", "()Ljava/io/File;"); - // QString extPath = mediaDir.callObjectMethod("getAbsolutePath", "()Ljava/lang/String;").toString(); if (!extPath.isEmpty()) { if (!QFileInfo(extPath).isWritable()) { qDebug() << "[Tandroid] No write access to secondary storage!"; @@ -91,16 +99,11 @@ QString Tandroid::getExternalPath() { } } - if(QtAndroid::androidSdkVersion() >= 23) { - const QString PermissionID("android.permission.WRITE_EXTERNAL_STORAGE"); - if (QtAndroid::checkPermission(PermissionID) != QtAndroid::PermissionResult::Granted) { - auto perms = QtAndroid::requestPermissionsSync(QStringList() << PermissionID); - qDebug() << PermissionID << (perms[PermissionID] == QtAndroid::PermissionResult::Granted); - } - } + askForWriteAcces(); if (extPath.isEmpty()) - extPath = qgetenv("EXTERNAL_STORAGE"); // return primary storage path (device internal) + extPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); +// extPath = qgetenv("EXTERNAL_STORAGE"); // return primary storage path (device internal) if (!QFileInfo(extPath).isWritable()) { qDebug() << "[Tandroid] No write access to primary storage!"; extPath.clear(); diff --git a/src/libs/core/Android/tandroid.h b/src/libs/core/Android/tandroid.h index 0a23c04a8487ae3697f9ccc7bc97b7098436be66..6f66871ff7e6c611c3b24a076724adf70638fda2 100644 --- a/src/libs/core/Android/tandroid.h +++ b/src/libs/core/Android/tandroid.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2015-2020 by Tomasz Bojczuk * + * Copyright (C) 2015-2021 by Tomasz Bojczuk * * seelook@gmail.com * * * * This program is free software; you can redistribute it and/or modify * @@ -47,6 +47,8 @@ namespace Tandroid { */ bool hasWriteAccess(); + void askForWriteAcces(); + /** * Returns command line argument (usually exam/level file name. */ diff --git a/src/libs/core/Android/tfiledialog.cpp b/src/libs/core/Android/tfiledialog.cpp index 9233ae0076e8b74a2e1d963a6c944e150675900a..70f2772032b5fba3dfa035f6111a3cc8369e10ea 100644 --- a/src/libs/core/Android/tfiledialog.cpp +++ b/src/libs/core/Android/tfiledialog.cpp @@ -163,6 +163,7 @@ TfileDialog::TfileDialog(const QString& directory, const QString& filter, Eaccep { showMaximized(); + Tandroid::askForWriteAcces(); // left side menu m_menu = new QListWidget(this); m_menu->setIconSize(QSize(60, 60)); diff --git a/src/libs/core/exam/texam.cpp b/src/libs/core/exam/texam.cpp index a522d37cd2f4f1cebb3404a414de0d88fa518083..7a28a32decdb493dfb95f75217727a62ae4e7621 100644 --- a/src/libs/core/exam/texam.cpp +++ b/src/libs/core/exam/texam.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2011-2020 by Tomasz Bojczuk * + * Copyright (C) 2011-2021 by Tomasz Bojczuk * * seelook@gmail.com * * * * This program is free software; you can redistribute it and/or modify * @@ -26,6 +26,9 @@ #include <QtCore/qdir.h> #include <QtCore/qsettings.h> #include <QtWidgets/qmessagebox.h> +#if defined (Q_OS_ANDROID) + #include <Android/tandroid.h> +#endif #include <QtCore/qdebug.h> @@ -202,6 +205,9 @@ void Texam::skipLast(bool skip) { Texam::EerrorType Texam::loadFromFile(const QString& fileName) { +#if defined (Q_OS_ANDROID) + Tandroid::askForWriteAcces(); +#endif m_okTime = 0; m_tmpMist = 0; m_tmpHalf = 0; diff --git a/src/libs/core/tglobals.cpp b/src/libs/core/tglobals.cpp index 5188aceed6f476acbb5fad4117100606411cd86b..d43a7258308e76bb62ead38861633f15bee63118 100755 --- a/src/libs/core/tglobals.cpp +++ b/src/libs/core/tglobals.cpp @@ -517,9 +517,12 @@ void Tglobals::loadSettings(QSettings* cfg) { S->scientificOctaves = cfg->value(QStringLiteral("scientificOctaves"), false).toBool(); Tnote::scientificOctaves = S->scientificOctaves; #if defined (Q_OS_ANDROID) - S->lastXmlDir = cfg->value(QStringLiteral("lastXmlDir"), Tandroid::getExternalPath()).toString(); - if (!QFileInfo::exists(S->lastXmlDir)) // reset if doesn't exist - S->lastXmlDir = Tandroid::getExternalPath(); + bool hasWriteAccess = Tandroid::hasWriteAccess(); + if (hasWriteAccess) { + S->lastXmlDir = cfg->value(QStringLiteral("lastXmlDir"), Tandroid::getExternalPath()).toString(); + if (!QFileInfo::exists(S->lastXmlDir) || !QFileInfo(S->lastXmlDir).isWritable()) // reset if doesn't exist + S->lastXmlDir = Tandroid::getExternalPath(); + } #endif cfg->endGroup(); @@ -614,12 +617,14 @@ void Tglobals::loadSettings(QSettings* cfg) { if (E->studentName.isEmpty()) E->studentName = systemUserName(); #if defined (Q_OS_ANDROID) - E->examsDir = cfg->value(QStringLiteral("examsDir"), Tandroid::getExternalPath()).toString(); - if (!QFileInfo::exists(E->examsDir)) // reset if doesn't exist - E->examsDir = Tandroid::getExternalPath(); - E->levelsDir = cfg->value(QStringLiteral("levelsDir"), Tandroid::getExternalPath()).toString(); - if (!QFileInfo::exists(E->levelsDir)) - E->levelsDir = Tandroid::getExternalPath(); + if (hasWriteAccess) { + E->examsDir = cfg->value(QStringLiteral("examsDir"), Tandroid::getExternalPath()).toString(); + if (!QFileInfo::exists(E->examsDir) || !QFileInfo(E->examsDir).isWritable()) // reset if doesn't exist + E->examsDir = Tandroid::getExternalPath(); + E->levelsDir = cfg->value(QStringLiteral("levelsDir"), Tandroid::getExternalPath()).toString(); + if (!QFileInfo::exists(E->levelsDir) || !QFileInfo(E->levelsDir).isWritable()) + E->levelsDir = Tandroid::getExternalPath(); + } #else E->examsDir = cfg->value(QStringLiteral("examsDir"), QDir::homePath()).toString(); if (!QFileInfo::exists(E->examsDir)) // reset if doesn't exist diff --git a/src/libs/core/tnootkaqml.cpp b/src/libs/core/tnootkaqml.cpp index 5645c7b3b89c35088c4df3b528dd6ff81b4b8a0d..dc1d1dd1a503a65b7e6614504bfb8ba1c3b41b03 100755 --- a/src/libs/core/tnootkaqml.cpp +++ b/src/libs/core/tnootkaqml.cpp @@ -37,6 +37,10 @@ #include "music/ttuneobject.h" #include "tmtr.h" #include "tcolor.h" +#if defined (Q_OS_ANDROID) + #include <Android/tandroid.h> +#endif + #include <QtQml/qqmlengine.h> #include <QtCore/qtimer.h> @@ -290,6 +294,8 @@ Tinstrument TnootkaQML::instr(int type) { QString TnootkaQML::getXmlToOpen() { QString openFile; #if defined (Q_OS_ANDROID) + if (GLOB->lastXmlDir().isEmpty()) + GLOB->setLastXmlDir(Tandroid::getExternalPath()); openFile = TfileDialog::getOpenFileName(GLOB->lastXmlDir(), QStringLiteral("xml|musicxml")); #else openFile = TfileDialog::getOpenFileName(qApp->translate("TmainScoreObject", "Open melody file"), GLOB->lastXmlDir(), @@ -305,6 +311,8 @@ QString TnootkaQML::getXmlToSave(const QString& fileName) { QString saveFile; QString filter; #if defined (Q_OS_ANDROID) + if (GLOB->lastXmlDir().isEmpty()) + GLOB->setLastXmlDir(Tandroid::getExternalPath()); saveFile = TfileDialog::getSaveFileName(GLOB->lastXmlDir() + QLatin1String("/") + fileName, QStringLiteral("musicxml|xml")); #else diff --git a/src/main.cpp b/src/main.cpp index 050523ee9332acaa5a7a69c58599d5d1b2fa4f64..c95004e93ace31e45f9431a03b82c9359e529ff3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -90,11 +90,14 @@ int main(int argc, char *argv[]) qputenv("QT_ANDROID_VOLUME_KEYS", "1"); // Handle volume keys by Qt, lock native Android behavior // log to any writable storage - logFile = Tandroid::getExternalPath() + QStringLiteral("/nootka-log.txt"); - if (QFile::exists(logFile)) - QFile::remove(logFile); - qInstallMessageHandler(myMessageOutput); - qDebug() << "==== NOOTKA LOG =======\n" << QDateTime::currentDateTime().toString(); + if (Tandroid::hasWriteAccess()) { + logFile = Tandroid::getExternalPath() + QStringLiteral("/nootka-log.txt"); + Tandroid::askForWriteAcces(); + if (QFile::exists(logFile)) + QFile::remove(logFile); + qInstallMessageHandler(myMessageOutput); + qDebug() << "==== NOOTKA LOG =======\n" << QDateTime::currentDateTime().toString(); + } #else qputenv("QT_QUICK_CONTROLS_STYLE", ""); // reset style environment var - other styles can cause crashes #endif diff --git a/src/main/texamexecutor.cpp b/src/main/texamexecutor.cpp index 3e29655f2dbb53e29dfa0e947d4fc08e456110b2..f5526144d65cd8c1f89d6bfa0ddae7d8a177dcc1 100644 --- a/src/main/texamexecutor.cpp +++ b/src/main/texamexecutor.cpp @@ -44,6 +44,9 @@ #include "tnameitem.h" #include "tmainscoreobject.h" #include <Android/tfiledialog.h> +#if defined (Q_OS_ANDROID) + #include <Android/tandroid.h> +#endif #include <QtCore/qdatetime.h> #include <QtCore/qtimer.h> @@ -79,6 +82,10 @@ void debugStyle(TQAunit &qa) { * but when such a file exists in current exam directory some time mark is added. */ QString getExamFileName(Texam* e) { +#if defined (Q_OS_ANDROID) + if (GLOB->E->examsDir.isEmpty()) + GLOB->E->examsDir = Tandroid::getExternalPath(); +#endif auto fName = QDir::toNativeSeparators(GLOB->E->examsDir + QLatin1String("/") + e->userName() + QLatin1String("-") + e->level()->name); fName = fName.replace(QLatin1String("."), QLatin1String("")); //HACK: file dialogues don't like dots in the names if (QFileInfo::exists(fName + QLatin1String(".noo"))) diff --git a/src/main/tstartexamitem.cpp b/src/main/tstartexamitem.cpp index 52d27266e5bd4cb5ddb539f01a81ed7baaa93645..2d6ab1c41ed9ba7fae7ad9c19d79edace5c7339d 100644 --- a/src/main/tstartexamitem.cpp +++ b/src/main/tstartexamitem.cpp @@ -124,6 +124,8 @@ void TstartExamItem::continuePrevExam() { void TstartExamItem::examFromFileDialog() { #if defined (Q_OS_ANDROID) + if (GLOB->E->examsDir.isEmpty()) + GLOB->E->examsDir = Tandroid::getExternalPath(); QString fileName = TfileDialog::getOpenFileName(GLOB->E->examsDir, QStringLiteral("noo")); #else QString fileName = TfileDialog::getOpenFileName(TexTrans::loadExamFileTxt(), GLOB->E->examsDir, TexTrans::examFilterTxt());