diff --git a/src/app/applicationcontroller.cpp b/src/app/applicationcontroller.cpp index 9e15543..4e178ec 100644 --- a/src/app/applicationcontroller.cpp +++ b/src/app/applicationcontroller.cpp @@ -1,512 +1,508 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "applicationcontroller.h" #include "documentmanager.h" #include "logging.h" #include "pkpassmanager.h" #include "reservationmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_ANDROID #include #include #include #include #include #else #include #endif #include using namespace KItinerary; #ifdef Q_OS_ANDROID // ### obsolete with Qt 5.13 class ActivityResultReceiver : public QAndroidActivityResultReceiver { public: explicit inline ActivityResultReceiver(const std::function &callback) : m_callback(callback) {} inline void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &intent) override { m_callback(receiverRequestCode, resultCode, intent); // ### we leak memory here, but deleting will hang the app // but since this is gone with Qt 5.13 anyway we can ignore that for now //delete this; } private: std::function m_callback; }; #define PERMISSION_CALENDAR QStringLiteral("android.permission.READ_CALENDAR") static void importReservation(JNIEnv *env, jobject that, jstring data) { Q_UNUSED(that); const char *str = env->GetStringUTFChars(data, nullptr); ApplicationController::instance()->importData(str); env->ReleaseStringUTFChars(data, str); } static void importDavDroidJson(JNIEnv *env, jobject that, jstring data) { Q_UNUSED(that); const char *str = env->GetStringUTFChars(data, nullptr); const auto doc = QJsonDocument::fromJson(str); env->ReleaseStringUTFChars(data, str); const auto array = doc.array(); if (array.size() < 2 || array.at(0).toString() != QLatin1String("X-KDE-KITINERARY-RESERVATION")) { return; } ApplicationController::instance()->importData(array.at(1).toString().toUtf8()); } static void importFromIntent(JNIEnv *env, jobject that, jobject data) { - Q_UNUSED(that); + Q_UNUSED(that) Q_UNUSED(env) - ApplicationController::instance()->importFromIntent(data); + + KAndroidExtras::Intent intent(data); + ApplicationController::instance()->importFromUrl(intent.getData()); } static const JNINativeMethod methods[] = { {"importReservation", "(Ljava/lang/String;)V", (void*)importReservation}, {"importFromIntent", "(Landroid/content/Intent;)V", (void*)importFromIntent}, {"importDavDroidJson", "(Ljava/lang/String;)V", (void*)importDavDroidJson} }; Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void*) { static bool initialized = false; if (initialized) return JNI_VERSION_1_6; initialized = true; JNIEnv *env = nullptr; if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) { qCWarning(Log) << "Failed to get JNI environment."; return -1; } jclass cls = env->FindClass("org/kde/itinerary/Activity"); if (env->RegisterNatives(cls, methods, sizeof(methods) / sizeof(JNINativeMethod)) < 0) { qCWarning(Log) << "Failed to register native functions."; return -1; } return JNI_VERSION_1_4; } #endif ApplicationController* ApplicationController::s_instance = nullptr; ApplicationController::ApplicationController(QObject* parent) : QObject(parent) { s_instance = this; connect(QGuiApplication::clipboard(), &QClipboard::dataChanged, this, &ApplicationController::clipboardContentChanged); } ApplicationController::~ApplicationController() { s_instance = nullptr; } ApplicationController* ApplicationController::instance() { return s_instance; } void ApplicationController::setReservationManager(ReservationManager* resMgr) { m_resMgr = resMgr; } void ApplicationController::setPkPassManager(PkPassManager* pkPassMgr) { m_pkPassMgr = pkPassMgr; } void ApplicationController::setDocumentManager(DocumentManager* docMgr) { m_docMgr = docMgr; } -#ifdef Q_OS_ANDROID -void ApplicationController::importFromIntent(const QAndroidJniObject &intent) -{ - KAndroidExtras::Intent i(intent); - importFromUrl(i.getData()); -} -#endif - void ApplicationController::showImportFileDialog() { #ifdef Q_OS_ANDROID using namespace KAndroidExtras; Intent intent; intent.setAction(Intent::ACTION_OPEN_DOCUMENT()); intent.addCategory(Intent::CATEGORY_OPENABLE()); intent.setType(QStringLiteral("*/*")); - QtAndroid::startActivity(intent, 0, new ActivityResultReceiver([this](int, int, const QAndroidJniObject &intent) { importFromIntent(intent); })); + QtAndroid::startActivity(intent, 0, new ActivityResultReceiver([this](int, int, const QAndroidJniObject &intent) { + importFromUrl(KAndroidExtras::Intent(intent).getData()); + })); #else const auto url = QFileDialog::getOpenFileUrl(nullptr, i18n("Import Reservation"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)), i18n("All Files (*.*);;PkPass files (*.pkpass);;PDF files (*.pdf);;KDE Itinerary files (*.itinerary)")); if (url.isValid()) { importFromUrl(url); } #endif } void ApplicationController::importFromClipboard() { if (QGuiApplication::clipboard()->mimeData()->hasUrls()) { const auto urls = QGuiApplication::clipboard()->mimeData()->urls(); for (const auto &url : urls) importFromUrl(url); return; } if (QGuiApplication::clipboard()->mimeData()->hasText()) { const auto content = QGuiApplication::clipboard()->mimeData()->data(QLatin1String("text/plain")); importData(content); } } void ApplicationController::importFromUrl(const QUrl &url) { qCDebug(Log) << url; if (url.isLocalFile() || url.scheme() == QLatin1String("content")) { importLocalFile(url); return; } if (url.scheme().startsWith(QLatin1String("http"))) { if (!m_nam ) { m_nam = new QNetworkAccessManager(this); } auto reqUrl(url); reqUrl.setScheme(QLatin1String("https")); QNetworkRequest req(reqUrl); req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); auto reply = m_nam->get(req); connect(reply, &QNetworkReply::finished, this, [this, reply]() { if (reply->error() != QNetworkReply::NoError) { qCDebug(Log) << reply->url() << reply->errorString(); return; } importData(reply->readAll()); }); return; } qCDebug(Log) << "Unhandled URL type:" << url; } void ApplicationController::importLocalFile(const QUrl &url) { qCDebug(Log) << url; if (url.isEmpty()) { return; } QFile f(url.isLocalFile() ? url.toLocalFile() : url.toString()); if (!f.open(QFile::ReadOnly)) { qCWarning(Log) << "Failed to open" << f.fileName() << f.errorString(); return; } if (f.size() > 4000000) { qCWarning(Log) << "File too large, ignoring" << f.fileName() << f.size(); return; } const auto head = f.peek(4); if (url.fileName().endsWith(QLatin1String(".pkpass"), Qt::CaseInsensitive)) { m_pkPassMgr->importPass(url); } else if (url.fileName().endsWith(QLatin1String(".itinerary"), Qt::CaseInsensitive)) { importBundle(url); } else if (strncmp(head.constData(), "PK\x03\x04", 4) == 0) { if (m_pkPassMgr->importPass(url).isEmpty()) { importBundle(url); } } else { const auto data = f.readAll(); const auto resIds = m_resMgr->importReservation(data, f.fileName()); if (resIds.empty()) { return; } // check if there is a document we want to attach here QMimeDatabase db; const auto mt = db.mimeTypeForFileNameAndData(f.fileName(), data); if (mt.name() != QLatin1String("application/pdf")) { // TODO support more file types (however we certainly want to exclude pkpass and json here) return; } DigitalDocument docInfo; docInfo.setName(f.fileName()); docInfo.setEncodingFormat(mt.name()); const auto docId = DocumentUtil::idForContent(data); m_docMgr->addDocument(docId, docInfo, data); for (const auto &resId : resIds) { auto res = m_resMgr->reservation(resId); if (DocumentUtil::addDocumentId(res, docId)) { m_resMgr->updateReservation(resId, res); } } } } void ApplicationController::importData(const QByteArray &data) { qCDebug(Log); if (data.size() < 4) { return; } if (strncmp(data.constData(), "PK\x03\x04", 4) == 0) { if (m_pkPassMgr->importPassFromData(data).isEmpty()) { importBundle(data); } } else { m_resMgr->importReservation(data); } } void ApplicationController::checkCalendar() { #ifdef Q_OS_ANDROID if (QtAndroid::checkPermission(PERMISSION_CALENDAR) == QtAndroid::PermissionResult::Granted) { const auto activity = QtAndroid::androidActivity(); if (activity.isValid()) { activity.callMethod("checkCalendar"); } } else { QtAndroid::requestPermissions({PERMISSION_CALENDAR}, [this] (const QtAndroid::PermissionResultMap &result){ if (result[PERMISSION_CALENDAR] == QtAndroid::PermissionResult::Granted) { checkCalendar(); } }); } #endif } bool ApplicationController::hasClipboardContent() const { return QGuiApplication::clipboard()->mimeData()->hasText() || QGuiApplication::clipboard()->mimeData()->hasUrls(); } void ApplicationController::exportData() { qCDebug(Log); #ifdef Q_OS_ANDROID using namespace KAndroidExtras; Intent intent; intent.setAction(Intent::ACTION_CREATE_DOCUMENT()); intent.addCategory(Intent::CATEGORY_OPENABLE()); intent.setType(QStringLiteral("*/*")); QtAndroid::startActivity(intent, 0, new ActivityResultReceiver([this](int, int, const QAndroidJniObject &jniIntent) { Intent intent(jniIntent); exportToFile(intent.getData().toString()); })); #else const auto filePath = QFileDialog::getSaveFileName(nullptr, i18n("Export Itinerary Data"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), i18n("KDE Itinerary files (*.itinerary)")); exportToFile(filePath); #endif } void ApplicationController::exportToFile(const QString &filePath) { qCDebug(Log) << filePath; if (filePath.isEmpty()) { return; } File f(filePath); if (!f.open(File::Write)) { qCWarning(Log) << f.errorString(); // TODO show error in UI return; } // export reservation data for (const auto &batchId : m_resMgr->batches()) { const auto resIds = m_resMgr->reservationsForBatch(batchId); for (const auto &resId : resIds) { f.addReservation(resId, m_resMgr->reservation(resId)); } } // export passes const auto passIds = m_pkPassMgr->passes(); for (const auto &passId : passIds) { f.addPass(passId, m_pkPassMgr->rawData(passId)); } // export documents const auto docIds = m_docMgr->documents(); for (const auto &docId : docIds) { const auto fileName = m_docMgr->documentFilePath(docId); QFile file(fileName); if (!file.open(QFile::ReadOnly)) { qCWarning(Log) << "failed to open" << fileName << "for exporting" << file.errorString(); continue; } f.addDocument(docId, m_docMgr->documentInfo(docId), file.readAll()); } // TODO export settings } void ApplicationController::importBundle(const QUrl &url) { KItinerary::File f(url.isLocalFile() ? url.toLocalFile() : url.toString()); if (!f.open(File::Read)) { // TODO show error in the ui qCWarning(Log) << "Failed to open bundle file:" << url << f.errorString(); return; } importBundle(&f); } void ApplicationController::importBundle(const QByteArray &data) { QBuffer buffer; buffer.setData(data); buffer.open(QBuffer::ReadOnly); KItinerary::File f(&buffer); if (!f.open(File::Read)) { // TODO show error in the ui qCWarning(Log) << "Failed to open bundle data:" << f.errorString(); return; } importBundle(&f); } void ApplicationController::importBundle(KItinerary::File *file) { const auto resIds = file->reservations(); for (const auto &resId : resIds) { m_resMgr->addReservation(file->reservation(resId)); } const auto passIds = file->passes(); for (const auto &passId : passIds) { m_pkPassMgr->importPassFromData(file->passData(passId)); } const auto docIds = file->documents(); for (const auto &docId : docIds) { m_docMgr->addDocument(docId, file->documentInfo(docId), file->documentData(docId)); } } void ApplicationController::addDocument(const QString &batchId) { // TODO Android support #ifndef Q_OS_ANDROID const auto url = QFileDialog::getOpenFileUrl(nullptr, i18n("Add Document"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)), i18n("All Files (*.*)")); addDocument(batchId, url); #else using namespace KAndroidExtras; Intent intent; intent.setAction(Intent::ACTION_OPEN_DOCUMENT()); intent.addCategory(Intent::CATEGORY_OPENABLE()); intent.setType(QStringLiteral("*/*")); QtAndroid::startActivity(intent, 0, new ActivityResultReceiver([this, batchId](int, int, const QAndroidJniObject &jniIntent) { Intent intent(jniIntent); addDocument(batchId, intent.getData()); })); #endif } void ApplicationController::addDocument(const QString &batchId, const QUrl &url) { if (!url.isValid()) { return; } const auto docId = QUuid::createUuid().toString(); auto res = m_resMgr->reservation(batchId); DocumentUtil::addDocumentId(res, docId); DigitalDocument docInfo; #ifdef Q_OS_ANDROID docInfo.setEncodingFormat(KAndroidExtras::ContentResolver::mimeType(url)); docInfo.setName(KAndroidExtras::ContentResolver::fileName(url)); #else QMimeDatabase db; docInfo.setEncodingFormat(db.mimeTypeForFile(url.isLocalFile() ? url.toLocalFile() : url.toString()).name()); docInfo.setName(url.fileName()); #endif m_docMgr->addDocument(docId, docInfo, url.isLocalFile() ? url.toLocalFile() : url.toString()); const auto resIds = m_resMgr->reservationsForBatch(batchId); for (const auto &resId : resIds) { m_resMgr->updateReservation(resId, res); } } void ApplicationController::removeDocument(const QString &batchId, const QString &docId) { const auto resIds = m_resMgr->reservationsForBatch(batchId); for (const auto &resId : resIds) { auto res = m_resMgr->reservation(batchId); if (DocumentUtil::removeDocumentId(res, docId)) { m_resMgr->updateReservation(resId, res); } } m_docMgr->removeDocument(docId); } diff --git a/src/app/applicationcontroller.h b/src/app/applicationcontroller.h index 7328353..501b38b 100644 --- a/src/app/applicationcontroller.h +++ b/src/app/applicationcontroller.h @@ -1,92 +1,88 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef APPLICATIONCONTROLLER_H #define APPLICATIONCONTROLLER_H #include #ifdef Q_OS_ANDROID #include #endif class DocumentManager; class PkPassManager; class ReservationManager; namespace KItinerary { class File; } class QNetworkAccessManager; class ApplicationController : public QObject { Q_OBJECT Q_PROPERTY(bool hasClipboardContent READ hasClipboardContent NOTIFY clipboardContentChanged) public: explicit ApplicationController(QObject *parent = nullptr); ~ApplicationController(); void setReservationManager(ReservationManager *resMgr); void setPkPassManager(PkPassManager *pkPassMgr); void setDocumentManager(DocumentManager *docMgr); // data import Q_INVOKABLE void showImportFileDialog(); Q_INVOKABLE void importFromClipboard(); Q_INVOKABLE void importFromUrl(const QUrl &url); void importData(const QByteArray &data); Q_INVOKABLE void checkCalendar(); static ApplicationController* instance(); bool hasClipboardContent() const; void importBundle(const QUrl &url); void importBundle(const QByteArray &data); // data export Q_INVOKABLE void exportData(); void exportToFile(const QString &filePath); // document attaching Q_INVOKABLE void addDocument(const QString &batchId); Q_INVOKABLE void removeDocument(const QString &batchId, const QString &docId); - // for internal use -#ifdef Q_OS_ANDROID - void importFromIntent(const QAndroidJniObject &intent); -#endif Q_SIGNALS: void clipboardContentChanged(); private: void importLocalFile(const QUrl &url); void importBundle(KItinerary::File *file); void addDocument(const QString &batchId, const QUrl &url); static ApplicationController *s_instance; ReservationManager *m_resMgr = nullptr; PkPassManager *m_pkPassMgr = nullptr; DocumentManager *m_docMgr = nullptr; QNetworkAccessManager *m_nam = nullptr; }; #endif // APPLICATIONCONTROLLER_H diff --git a/src/app/main.cpp b/src/app/main.cpp index 8e0a6cf..e94c934 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -1,247 +1,246 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "itinerary_version.h" #include "logging.h" #include "applicationcontroller.h" #include "brightnessmanager.h" #include "countryinformation.h" #include "countrymodel.h" #include "documentmanager.h" #include "documentsmodel.h" #include "livedatamanager.h" #include "localizer.h" #include "lockmanager.h" #include "navigationcontroller.h" #include "pkpassmanager.h" #include "timelinemodel.h" #include "pkpassimageprovider.h" #include "publictransport.h" #include "reservationmanager.h" #include "settings.h" #include "tickettokenmodel.h" #include "tripgroupinfoprovider.h" #include "tripgroupmanager.h" #include "tripgroupproxymodel.h" #include "util.h" #include "timelinedelegatecontroller.h" #include "weatherforecastmodel.h" #include #include #include #include #include #include #include #ifndef Q_OS_ANDROID #include #endif #include #include #include #include #ifdef Q_OS_ANDROID +#include +#include + #include "androidcontentfileengine.h" #include #include #else #include #endif #include #include #include #include #include #include void handleViewIntent(ApplicationController *appController) { #ifdef Q_OS_ANDROID // handle opened files - const auto activity = QtAndroid::androidActivity(); - if (!activity.isValid()) - return; - - const auto intent = activity.callObjectMethod("getIntent", "()Landroid/content/Intent;"); - appController->importFromIntent(intent); + using namespace KAndroidExtras; + appController->importFromUrl(Activity::getIntent().getData()); #else Q_UNUSED(appController); #endif } void handlePositionalArguments(ApplicationController *appController, const QStringList &args) { for (const auto &file : args) { const auto localUrl = QUrl::fromLocalFile(file); if (QFile::exists(localUrl.toLocalFile())) appController->importFromUrl(localUrl); else appController->importFromUrl(QUrl::fromUserInput(file)); } } #ifdef Q_OS_ANDROID Q_DECL_EXPORT #endif int main(int argc, char **argv) { QCoreApplication::setApplicationName(QStringLiteral("itinerary")); QCoreApplication::setOrganizationName(QStringLiteral("KDE")); QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); QCoreApplication::setApplicationVersion(QStringLiteral(ITINERARY_VERSION_STRING)); QGuiApplication::setApplicationDisplayName(i18n("KDE Itinerary")); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #ifdef Q_OS_ANDROID AndroidContentFileEngineHandler fsEngineHandler; QGuiApplication app(argc, argv); #else QApplication app(argc, argv); // for native file dialogs #endif QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("map-globe"))); QCommandLineParser parser; parser.addHelpOption(); parser.addVersionOption(); parser.addPositionalArgument(QStringLiteral("file"), i18n("PkPass or JSON-LD file to import.")); parser.process(app); #ifndef Q_OS_ANDROID KDBusService service(KDBusService::Unique); #endif Settings settings; PkPassManager passMgr; ReservationManager resMgr; DocumentManager docMgr; resMgr.setPkPassManager(&passMgr); TripGroupManager tripGroupMgr; tripGroupMgr.setReservationManager(&resMgr); ApplicationController appController; appController.setReservationManager(&resMgr); appController.setPkPassManager(&passMgr); appController.setDocumentManager(&docMgr); BrightnessManager brightnessManager; LockManager lockManager; KPublicTransport::Manager ptMgr; ptMgr.setAllowInsecureBackends(settings.allowInsecureServices()); QObject::connect(&settings, &Settings::allowInsecureServicesChanged, [&ptMgr](bool insec) { ptMgr.setAllowInsecureBackends(insec); }); LiveDataManager liveDataMgr; liveDataMgr.setPublicTransportManager(&ptMgr); liveDataMgr.setPkPassManager(&passMgr); liveDataMgr.setReservationManager(&resMgr); liveDataMgr.setPollingEnabled(settings.queryLiveData()); QObject::connect(&settings, &Settings::queryLiveDataChanged, &liveDataMgr, &LiveDataManager::setPollingEnabled); #ifndef Q_OS_ANDROID QObject::connect(&service, &KDBusService::activateRequested, [&parser, &appController](const QStringList &args, const QString &workingDir) { qCDebug(Log) << "remote activation" << args << workingDir; if (!args.isEmpty()) { QDir::setCurrent(workingDir); parser.parse(args); handlePositionalArguments(&appController, parser.positionalArguments()); } if (!QGuiApplication::allWindows().isEmpty()) { QGuiApplication::allWindows().at(0)->requestActivate(); } }); #endif TimelineModel timelineModel; timelineModel.setHomeCountryIsoCode(settings.homeCountryIsoCode()); timelineModel.setReservationManager(&resMgr); QObject::connect(&settings, &Settings::homeCountryIsoCodeChanged, &timelineModel, &TimelineModel::setHomeCountryIsoCode); WeatherForecastManager weatherForecastMgr; weatherForecastMgr.setAllowNetworkAccess(settings.weatherForecastEnabled()); QObject::connect(&settings, &Settings::weatherForecastEnabledChanged, &weatherForecastMgr, &WeatherForecastManager::setAllowNetworkAccess); timelineModel.setWeatherForecastManager(&weatherForecastMgr); timelineModel.setTripGroupManager(&tripGroupMgr); TripGroupProxyModel tripGroupProxy; tripGroupProxy.setSourceModel(&timelineModel); TripGroupInfoProvider tripGroupInfoProvider; tripGroupInfoProvider.setReservationManager(&resMgr); tripGroupInfoProvider.setWeatherForecastManager(&weatherForecastMgr); qmlRegisterUncreatableType("org.kde.pkpass", 1, 0, "Barcode", {}); qmlRegisterUncreatableType("org.kde.pkpass", 1, 0, "Field", {}); qmlRegisterUncreatableType("org.kde.pkpass", 1, 0, "Pass", {}); qmlRegisterUncreatableType("org.kde.pkpass", 1, 0, "BoardingPass", {}); qRegisterMetaType(); qmlRegisterUncreatableType("org.kde.kitinerary", 1, 0, "Ticket", {}); qmlRegisterUncreatableMetaObject(KItinerary::KnowledgeDb::staticMetaObject, "org.kde.kitinerary", 1, 0, "KnowledgeDb", {}); qmlRegisterUncreatableType("org.kde.itinerary", 1, 0, "CountryInformation", {}); qmlRegisterType("org.kde.itinerary", 1, 0, "CountryModel"); qmlRegisterType("org.kde.itinerary", 1, 0, "DocumentsModel"); qmlRegisterSingletonType("org.kde.itinerary", 1, 0, "Localizer", [](QQmlEngine*, QJSEngine *engine) -> QJSValue { return engine->toScriptValue(Localizer()); }); qmlRegisterType("org.kde.itinerary", 1, 0, "TicketTokenModel"); qmlRegisterUncreatableType("org.kde.itinerary", 1, 0, "TimelineModel", {}); qmlRegisterType("org.kde.itinerary", 1, 0, "TimelineDelegateController"); qmlRegisterSingletonType("org.kde.itinerary", 1, 0, "Util", [](QQmlEngine*, QJSEngine*) -> QObject*{ return new Util; }); qmlRegisterType("org.kde.itinerary", 1, 0, "WeatherForecastModel"); qmlRegisterSingletonType("org.kde.itinerary", 1, 0, "PublicTransport", [](QQmlEngine*, QJSEngine *engine) -> QJSValue { return engine->toScriptValue(PublicTransport()); }); qmlRegisterSingletonType("org.kde.itinerary", 1, 0, "NavigationController", [](QQmlEngine*, QJSEngine *engine) -> QJSValue { return engine->toScriptValue(NavigationController()); }); qmlRegisterSingletonType("org.kde.itinerary", 1, 0, "DocumentManager", [](QQmlEngine *engine, QJSEngine*) -> QObject* { engine->setObjectOwnership(DocumentManager::instance(), QQmlEngine::CppOwnership); return DocumentManager::instance(); }); QQmlApplicationEngine engine; engine.addImageProvider(QStringLiteral("org.kde.pkpass"), new PkPassImageProvider(&passMgr)); engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); engine.rootContext()->setContextProperty(QStringLiteral("_pkpassManager"), &passMgr); engine.rootContext()->setContextProperty(QStringLiteral("_reservationManager"), &resMgr); engine.rootContext()->setContextProperty(QStringLiteral("_timelineModel"), &tripGroupProxy); engine.rootContext()->setContextProperty(QStringLiteral("_appController"), &appController); engine.rootContext()->setContextProperty(QStringLiteral("_settings"), &settings); engine.rootContext()->setContextProperty(QStringLiteral("_weatherForecastManager"), &weatherForecastMgr); engine.rootContext()->setContextProperty(QStringLiteral("_brightnessManager"), &brightnessManager); engine.rootContext()->setContextProperty(QStringLiteral("_lockManager"), &lockManager); engine.rootContext()->setContextProperty(QStringLiteral("_liveDataManager"), &liveDataMgr); engine.rootContext()->setContextProperty(QStringLiteral("_tripGroupInfoProvider"), QVariant::fromValue(tripGroupInfoProvider)); engine.load(QStringLiteral("qrc:/main.qml")); handlePositionalArguments(&appController, parser.positionalArguments()); handleViewIntent(&appController); return app.exec(); } diff --git a/src/kandroidextras/CMakeLists.txt b/src/kandroidextras/CMakeLists.txt index c3b5183..d9517dd 100644 --- a/src/kandroidextras/CMakeLists.txt +++ b/src/kandroidextras/CMakeLists.txt @@ -1,7 +1,8 @@ add_library(KAndroidExtras STATIC + activity.cpp contentresolver.cpp intent.cpp uri.cpp ) target_include_directories(KAndroidExtras INTERFACE "$") target_link_libraries(KAndroidExtras PRIVATE Qt5::AndroidExtras) diff --git a/src/kandroidextras/activity.cpp b/src/kandroidextras/activity.cpp new file mode 100644 index 0000000..3395f88 --- /dev/null +++ b/src/kandroidextras/activity.cpp @@ -0,0 +1,33 @@ +/* + Copyright (C) 2019 Volker Krause + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "activity.h" +#include "intent.h" + +#include + +using namespace KAndroidExtras; + +Intent Activity::getIntent() +{ + const auto activity = QtAndroid::androidActivity(); + if (!activity.isValid()) + return {}; + + const auto intent = activity.callObjectMethod("getIntent", "()Landroid/content/Intent;"); + return Intent(intent); +} diff --git a/src/kandroidextras/activity.h b/src/kandroidextras/activity.h new file mode 100644 index 0000000..25da367 --- /dev/null +++ b/src/kandroidextras/activity.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2019 Volker Krause + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef KANDROIDEXTRAS_ACTIVITY_H +#define KANDROIDEXTRAS_ACTIVITY_H + +namespace KAndroidExtras { + +class Intent; + +/** Methods around android.app.Activity. */ +namespace Activity +{ + /** Returns the Intent that started the activity. */ + Intent getIntent(); +} + +} + +#endif // KANDROIDEXTRAS_ACTIVITY_H