diff --git a/CMakeLists.txt b/CMakeLists.txt index 60c4474..3ceadf9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,57 +1,58 @@ cmake_minimum_required(VERSION 3.0) project(itinerary VERSION 0.0.1) find_package(ECM 5.38 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DIR}/cmake) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMAddTests) include(ECMGenerateHeaders) include(ECMQtDeclareLoggingCategory) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(GenerateExportHeader) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) ecm_setup_version(PROJECT VARIABLE_PREFIX ITINERARY VERSION_HEADER itinerary_version.h) # build-time dependencies find_package(Qt5 REQUIRED COMPONENTS Test Quick) find_package(KF5 REQUIRED COMPONENTS I18n) find_package(KF5Contacts CONFIG REQUIRED) find_package(KPimPkPass CONFIG REQUIRED) find_package(KPimItinerary CONFIG REQUIRED) find_package(QmlLint) set_package_properties(QmlLint PROPERTIES URL "https://qt.io" PURPOSE "Validate QML code.") find_package(SharedMimeInfo 1.0 REQUIRED) find_package(ZLIB REQUIRED) set_package_properties("ZLIB" PROPERTIES PURPOSE "Needed for retrieving weather forecast data.") include(ECMQMLModules) ecm_find_qmlmodule(org.kde.prison 1.0) +ecm_find_qmlmodule(Qt.labs.platform 1.0) # runtime dependencies are build-time dependencies on Android if (ANDROID) find_package(Qt5 REQUIRED COMPONENTS AndroidExtras Svg) find_package(KF5 REQUIRED COMPONENTS Archive Kirigami2 Prison) if (NOT DEFINED BREEZEICONS_DIR AND EXISTS ${CMAKE_SOURCE_DIR}/../breeze-icons) set(BREEZEICONS_DIR ${CMAKE_SOURCE_DIR}/../breeze-icons) endif() find_package(OpenSSL REQUIRED) else() - find_package(Qt5 REQUIRED COMPONENTS Positioning) + find_package(Qt5 REQUIRED COMPONENTS Widgets Positioning) endif() add_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII -DQT_NO_URL_CAST_FROM_STRING) add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT) add_definitions(-DQT_USE_QSTRINGBUILDER) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) add_subdirectory(src) add_subdirectory(autotests) install(FILES org_kde_itinerary.categories DESTINATION ${KDE_INSTALL_CONFDIR}) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 258ec94..a10ccfe 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -1,116 +1,116 @@ set(itinerary_srcs countryinformation.cpp pkpassmanager.cpp reservationmanager.cpp timelinemodel.cpp ) ecm_qt_declare_logging_category(itinerary_srcs HEADER logging.h IDENTIFIER Log CATEGORY_NAME org.kde.itinerary ) add_library(itinerary STATIC ${itinerary_srcs}) target_link_libraries(itinerary PUBLIC itinerary-weather KPim::Itinerary KPim::PkPass KF5::I18n Qt5::Network ) add_executable(itinerary-app main.cpp applicationcontroller.cpp countrymodel.cpp localizer.cpp pkpassimageprovider.cpp settings.cpp qml.qrc ) target_include_directories(itinerary-app PRIVATE ${CMAKE_BINARY_DIR}) target_link_libraries(itinerary-app PRIVATE itinerary Qt5::Quick KF5::Contacts ) if (ANDROID) # explicitly add runtime dependencies and transitive link dependencies, # so androiddeployqt picks them up target_link_libraries(itinerary-app PRIVATE KF5::Archive KF5::Kirigami2 Qt5::AndroidExtras Qt5::Svg KF5::Prison OpenSSL::SSL ) kirigami_package_breeze_icons(ICONS document-open edit-delete go-next-symbolic map-symbolic settings-configure view-calendar-day view-refresh weather-clear weather-clear-night weather-few-clouds weather-few-clouds-night weather-clouds weather-clouds-night weather-showers-day weather-showers-night weather-showers-scattered-day weather-showers-scattered-night weather-snow-scattered-day weather-snow-scattered-night weather-storm-day weather-storm-night weather-many-clouds weather-fog weather-showers weather-showers-scattered weather-hail weather-snow weather-snow-scattered weather-storm ) else () - target_link_libraries(itinerary-app PRIVATE Qt5::Positioning) + target_link_libraries(itinerary-app PRIVATE Qt5::Positioning Qt5::Widgets) set_target_properties(itinerary-app PROPERTIES OUTPUT_NAME "itinerary") endif() qml_lint( main.qml BoardingPass.qml BusDelegate.qml BusPage.qml CountryInfoDelegate.qml DetailsPage.qml FlightDelegate.qml FlightPage.qml HotelDelegate.qml HotelPage.qml ImportDialog.qml PkPassPage.qml PlaceDelegate.qml RestaurantDelegate.qml RestaurantPage.qml SettingsPage.qml TicketTokenDelegate.qml TimelineDelegate.qml TimelinePage.qml TouristAttractionDelegate.qml TrainDelegate.qml TrainPage.qml WeatherForecastDelegate.qml +android/ImportDialog.qml ) install(TARGETS itinerary-app ${INSTALL_TARGETS_DEFAULT_ARGS}) if (NOT ANDROID) install(PROGRAMS org.kde.itinerary.desktop DESTINATION ${KDE_INSTALL_APPDIR}) endif() diff --git a/src/app/ImportDialog.qml b/src/app/ImportDialog.qml index 4d849c0..f017a30 100644 --- a/src/app/ImportDialog.qml +++ b/src/app/ImportDialog.qml @@ -1,47 +1,48 @@ /* 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 . */ import QtQuick 2.0 -import QtQuick.Dialogs 1.0 +import Qt.labs.platform 1.0 as Platform Item { function importReservation() { fileDialog.loadPass = false; fileDialog.visible = true; } function importPass() { fileDialog.loadPass = true; fileDialog.visible = true; } - FileDialog { + Platform.FileDialog { property bool loadPass: false id: fileDialog - title: i18n("Please choose a file") - folder: shortcuts.home + title: loadPass ? i18n("Import PkPass File") : i18n("Import Itinerary File") + nameFilters: loadPass ? [i18n("PkPass files (*.pkpass)")] : [i18n("JSON files (*.json)")] + folder: Platform.StandardPaths.writableLocation(Platform.StandardPaths.DocumentsLocation) onAccepted: { console.log(fileDialog.fileUrls); if (loadPass) _pkpassManager.importPass(fileDialog.fileUrl); else _reservationManager.importReservation(fileDialog.fileUrl); } } } diff --git a/src/app/main.cpp b/src/app/main.cpp index a4715f6..edef6b5 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -1,145 +1,151 @@ /* 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 "countryinformation.h" #include "countrymodel.h" #include "localizer.h" #include "pkpassmanager.h" #include "timelinemodel.h" #include "pkpassimageprovider.h" #include "reservationmanager.h" #include "settings.h" #include #include #include #include #include #include #include #include #include #ifdef Q_OS_ANDROID #include #include +#else +#include #endif #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); #else Q_UNUSED(appController); #endif } #ifdef Q_OS_ANDROID Q_DECL_EXPORT #endif int main(int argc, char **argv) { QCoreApplication::setApplicationName(QStringLiteral("kde-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 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); Settings settings; PkPassManager passMgr; ReservationManager resMgr; resMgr.setPkPassManager(&passMgr); ApplicationController appController; appController.setReservationManager(&resMgr); appController.setPkPassManager(&passMgr); 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); qmlRegisterUncreatableType("org.kde.pkpass", 1, 0, "Barcode", {}); qmlRegisterUncreatableType("org.kde.pkpass", 1, 0, "Field", {}); 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", {}); qmlRegisterUncreatableType("org.kde.itinerary", 1, 0, "TimelineModel", {}); qmlRegisterSingletonType("org.kde.itinerary", 1, 0, "Localizer", [](QQmlEngine*, QJSEngine*) -> QObject*{ return new Localizer; }); qmlRegisterType("org.kde.itinerary", 1, 0, "CountryModel"); 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"), &timelineModel); engine.rootContext()->setContextProperty(QStringLiteral("_appController"), &appController); engine.rootContext()->setContextProperty(QStringLiteral("_settings"), &settings); engine.load(QStringLiteral(":/main.qml")); for (const auto &file : parser.positionalArguments()) { if (file.endsWith(QLatin1String(".pkpass"))) passMgr.importPass(QUrl::fromLocalFile(file)); else resMgr.importReservation(QUrl::fromLocalFile(file)); } handleViewIntent(&appController); return app.exec(); }