main.cpp 13.9 KB
Newer Older
1
/*
2
    SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
3

4
    SPDX-License-Identifier: LGPL-2.0-or-later
5
6
*/

7
#include "config-itinerary.h"
8
#include "itinerary_version.h"
Volker Krause's avatar
Volker Krause committed
9
#include "logging.h"
10

11
#include "applicationcontroller.h"
12
#include "countrymodel.h"
13
#include "developmentmodecontroller.h"
14
#include "documentmanager.h"
15
#include "documentsmodel.h"
16
#include "favoritelocationmodel.h"
17
#include "livedatamanager.h"
18
#include "localizer.h"
19
#include "locationinformation.h"
20
#include "mapdownloadmanager.h"
21
#include "navigationcontroller.h"
22
#include "notificationconfigcontroller.h"
23
24
25
#include "pkpassmanager.h"
#include "timelinemodel.h"
#include "pkpassimageprovider.h"
26
#include "publictransport.h"
Volker Krause's avatar
Volker Krause committed
27
#include "reservationmanager.h"
Volker Krause's avatar
Volker Krause committed
28
#include "settings.h"
Volker Krause's avatar
Volker Krause committed
29
30
#include "statisticsmodel.h"
#include "statisticstimerangemodel.h"
31
#include "tickettokenmodel.h"
Volker Krause's avatar
Volker Krause committed
32
#include "timelinedelegatecontroller.h"
33
#include "transfermanager.h"
34
#include "tripgroupinfoprovider.h"
35
#include "tripgroupmanager.h"
36
#include "tripgroupproxymodel.h"
37
#include "util.h"
38
#include "weatherforecastmodel.h"
Volker Krause's avatar
Volker Krause committed
39
40

#include <weatherforecastmanager.h>
41

42
#include <KItinerary/CountryDb>
43
44
#include <KItinerary/Ticket>

45
46
#include <KPkPass/Field>
#include <KPkPass/Barcode>
47
#include <KPkPass/BoardingPass>
48

49
50
51
52
#ifndef Q_OS_ANDROID
#include <KDBusService>
#endif

Volker Krause's avatar
Volker Krause committed
53
54
55
#include <KLocalizedContext>
#include <KLocalizedString>

Volker Krause's avatar
Volker Krause committed
56
#include <KAboutData>
57
#if HAVE_KCRASH
Jonathan Riddell's avatar
Jonathan Riddell committed
58
59
#include <KCrash>
#endif
Volker Krause's avatar
Volker Krause committed
60

61
#include <QQuickStyle>
62
63
64
#include <QQmlApplicationEngine>
#include <QQmlContext>

65
#ifdef Q_OS_ANDROID
66
67
68
#include <kandroidextras/activity.h>
#include <kandroidextras/intent.h>

69
70
#include <QtAndroid>
#include <QAndroidJniObject>
71
72
#else
#include <QApplication>
73
74
#endif

75
#include <QCommandLineParser>
Volker Krause's avatar
Volker Krause committed
76
#include <QDebug>
77
#include <QDir>
78
79
#include <QGuiApplication>
#include <QIcon>
80
#include <QWindow>
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
void registerKPkPassTypes()
{
    qmlRegisterUncreatableType<KPkPass::Barcode>("org.kde.pkpass", 1, 0, "Barcode", {});
    qmlRegisterUncreatableType<KPkPass::Field>("org.kde.pkpass", 1, 0, "Field", {});
    qmlRegisterUncreatableType<KPkPass::Pass>("org.kde.pkpass", 1, 0, "Pass", {});
    qmlRegisterUncreatableType<KPkPass::BoardingPass>("org.kde.pkpass", 1, 0, "BoardingPass", {});
}

void registerKItineraryTypes()
{
    qRegisterMetaType<KItinerary::KnowledgeDb::DrivingSide>();
    qmlRegisterUncreatableType<KItinerary::Ticket>("org.kde.kitinerary", 1, 0, "Ticket", {});
    qmlRegisterUncreatableMetaObject(KItinerary::KnowledgeDb::staticMetaObject, "org.kde.kitinerary", 1, 0, "KnowledgeDb", {});
}

void registerApplicationTypes()
{
    qRegisterMetaType<ReservationManager*>();
    qRegisterMetaType<Transfer::Alignment>();
    qRegisterMetaType<TripGroupManager*>();
    qRegisterMetaType<WeatherForecast>();

104
    qmlRegisterUncreatableType<LocationInformation>("org.kde.itinerary", 1, 0, "LocationInformation", {});
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    qmlRegisterUncreatableType<StatisticsItem>("org.kde.itinerary", 1, 0, "StatisticsItem", {});
    qmlRegisterUncreatableType<TimelineElement>("org.kde.itinerary", 1, 0, "TimelineElement", {});
    qmlRegisterUncreatableType<TimelineModel>("org.kde.itinerary", 1, 0, "TimelineModel", {});
    qmlRegisterUncreatableType<Transfer>("org.kde.itinerary", 1, 0, "Transfer", {});

    qmlRegisterType<CountryModel>("org.kde.itinerary", 1, 0, "CountryModel");
    qmlRegisterType<DocumentsModel>("org.kde.itinerary", 1, 0, "DocumentsModel");
    qmlRegisterType<QSortFilterProxyModel>("org.kde.itinerary", 1, 0, "SortFilterProxyModel"); // TODO use this from kitemmodels?
    qmlRegisterType<StatisticsModel>("org.kde.itinerary", 1, 0, "StatisticsModel");
    qmlRegisterType<StatisticsTimeRangeModel>("org.kde.itinerary", 1, 0, "StatisticsTimeRangeModel");
    qmlRegisterType<TicketTokenModel>("org.kde.itinerary", 1, 0, "TicketTokenModel");
    qmlRegisterType<TimelineDelegateController>("org.kde.itinerary", 1, 0, "TimelineDelegateController");
    qmlRegisterType<WeatherForecastModel>("org.kde.itinerary", 1, 0, "WeatherForecastModel");
}

// for registering QML singletons only
121
static ReservationManager *s_reservationManager = nullptr;
122
static DocumentManager *s_documentManager = nullptr;
123
static FavoriteLocationModel *s_favoriteLocationModel = nullptr;
124
125
126
127
static PkPassManager *s_pkPassManager = nullptr;
static Settings *s_settings = nullptr;
static TransferManager *s_tranferManager = nullptr;
static TripGroupManager *s_tripGroupManager = nullptr;
128
static LiveDataManager *s_liveDataMnager = nullptr;
129
static WeatherForecastManager *s_weatherForecastManager = nullptr;
130
static TripGroupInfoProvider s_tripGroupInfoProvider;
131
static TripGroupProxyModel *s_tripGroupProxyModel = nullptr;
132
static MapDownloadManager *s_mapDownloadManager = nullptr;
133
134
135
136
137
138
139

#define REGISTER_SINGLETON_INSTANCE(Class, Instance) \
    qmlRegisterSingletonType<Class>("org.kde.itinerary", 1, 0, #Class, [](QQmlEngine *engine, QJSEngine*) -> QObject* { \
        engine->setObjectOwnership(Instance, QQmlEngine::CppOwnership); \
        return Instance; \
    });

140
141
142
143
144
145
#define REGISTER_SINGLETON_GADGET_INSTANCE(Class, Instance) \
    qmlRegisterSingletonType("org.kde.itinerary", 1, 0, #Class, [](QQmlEngine *engine, QJSEngine*) -> QJSValue { \
        return engine->toScriptValue(Instance); \
    });

#define REGISTER_SINGLETON_GADGET_FACTORY(Class) \
146
147
148
149
    qmlRegisterSingletonType("org.kde.itinerary", 1, 0, #Class, [](QQmlEngine*, QJSEngine *engine) -> QJSValue { \
        return engine->toScriptValue(Class()); \
    });

150
151
152
void registerApplicationSingletons()
{
    REGISTER_SINGLETON_INSTANCE(ApplicationController, ApplicationController::instance())
153
    REGISTER_SINGLETON_INSTANCE(ReservationManager, s_reservationManager)
154
    REGISTER_SINGLETON_INSTANCE(DocumentManager, s_documentManager)
155
    REGISTER_SINGLETON_INSTANCE(FavoriteLocationModel, s_favoriteLocationModel)
156
157
158
159
    REGISTER_SINGLETON_INSTANCE(PkPassManager, s_pkPassManager)
    REGISTER_SINGLETON_INSTANCE(Settings, s_settings)
    REGISTER_SINGLETON_INSTANCE(TransferManager, s_tranferManager)
    REGISTER_SINGLETON_INSTANCE(TripGroupManager, s_tripGroupManager)
160
    REGISTER_SINGLETON_INSTANCE(LiveDataManager, s_liveDataMnager)
161
    REGISTER_SINGLETON_INSTANCE(WeatherForecastManager, s_weatherForecastManager)
162
    REGISTER_SINGLETON_INSTANCE(TripGroupProxyModel, s_tripGroupProxyModel)
163
    REGISTER_SINGLETON_INSTANCE(MapDownloadManager, s_mapDownloadManager)
164

165
166
    REGISTER_SINGLETON_GADGET_INSTANCE(TripGroupInfoProvider, s_tripGroupInfoProvider)

167
    REGISTER_SINGLETON_GADGET_FACTORY(DevelopmentModeController)
168
169
170
171
    REGISTER_SINGLETON_GADGET_FACTORY(Localizer)
    REGISTER_SINGLETON_GADGET_FACTORY(NavigationController)
    REGISTER_SINGLETON_GADGET_FACTORY(NotificationConfigController)
    REGISTER_SINGLETON_GADGET_FACTORY(PublicTransport)
172
173
174
175
176
177
178
179

    qmlRegisterSingletonType<Util>("org.kde.itinerary", 1, 0, "Util", [](QQmlEngine*, QJSEngine*) -> QObject*{
        return new Util;
    });
}

#undef REGISTER_SINGLETON_INSTANCE

180
void handlePositionalArguments(ApplicationController *appController, const QStringList &args, bool isTemporary)
Volker Krause's avatar
Volker Krause committed
181
182
183
{
    for (const auto &file : args) {
        const auto localUrl = QUrl::fromLocalFile(file);
184
        if (QFile::exists(localUrl.toLocalFile())) {
Volker Krause's avatar
Volker Krause committed
185
            appController->importFromUrl(localUrl);
186
187
188
189
            if (isTemporary) {
                QFile::remove(localUrl.toLocalFile());
            }
        } else {
Volker Krause's avatar
Volker Krause committed
190
            appController->importFromUrl(QUrl::fromUserInput(file));
191
        }
Volker Krause's avatar
Volker Krause committed
192
193
    }
}
Volker Krause's avatar
Volker Krause committed
194

Volker Krause's avatar
Volker Krause committed
195
196
197
#ifdef Q_OS_ANDROID
Q_DECL_EXPORT
#endif
198
199
int main(int argc, char **argv)
{
200
    QCoreApplication::setApplicationName(QStringLiteral("itinerary"));
201
202
203
204
205
206
    QCoreApplication::setOrganizationName(QStringLiteral("KDE"));
    QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
    QCoreApplication::setApplicationVersion(QStringLiteral(ITINERARY_VERSION_STRING));

    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
207
#ifdef Q_OS_ANDROID
208
    QGuiApplication app(argc, argv);
209
    QQuickStyle::setStyle(QStringLiteral("Material"));
210
211
#else
    QApplication app(argc, argv); // for native file dialogs
212

213
214
215
216
    // Default to org.kde.desktop style unless the user forces another style
    if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) {
        QQuickStyle::setStyle(QStringLiteral("org.kde.desktop"));
    }
217
#endif
218
    QGuiApplication::setApplicationDisplayName(i18n("KDE Itinerary"));
219
    QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("itinerary")));
220

Volker Krause's avatar
Volker Krause committed
221
222
223
224
225
    auto aboutData = KAboutData::applicationData();
    aboutData.setProductName("KDE Itinerary/general"); // Bugzilla product/component name
    aboutData.setLicense(KAboutLicense::LGPL);
    KAboutData::setApplicationData(aboutData);

226
    QCommandLineParser parser;
227
228
    QCommandLineOption isTemporaryOpt(QStringLiteral("delete-after-use"), QStringLiteral("Input file is a temporary file that needs to be deleted after importing."));
    parser.addOption(isTemporaryOpt);
Volker Krause's avatar
Volker Krause committed
229
    aboutData.setupCommandLine(&parser);
Volker Krause's avatar
Volker Krause committed
230
    parser.addPositionalArgument(QStringLiteral("file"), i18n("PkPass or JSON-LD file to import."));
231
    parser.process(app);
Volker Krause's avatar
Volker Krause committed
232
    aboutData.processCommandLine(&parser);
233
#if HAVE_KCRASH
Jonathan Riddell's avatar
Jonathan Riddell committed
234
    KCrash::initialize();
235
#endif
Jonathan Riddell's avatar
Jonathan Riddell committed
236

237
#ifndef Q_OS_ANDROID
238
239
240
    KDBusService service(KDBusService::Unique);
#endif

241
    Settings settings;
242
243
    s_settings = &settings;

244
    PkPassManager passMgr;
245
246
    s_pkPassManager = &passMgr;

Volker Krause's avatar
Volker Krause committed
247
    ReservationManager resMgr;
248
    resMgr.setPkPassManager(&passMgr);
249
    s_reservationManager = &resMgr;
250
251
252
253

    DocumentManager docMgr;
    s_documentManager = &docMgr;

254
255
256
    FavoriteLocationModel favLocModel;
    s_favoriteLocationModel = &favLocModel;

257
258
    TripGroupManager tripGroupMgr;
    tripGroupMgr.setReservationManager(&resMgr);
259
260
    s_tripGroupManager = &tripGroupMgr;

261
262
263
    LiveDataManager liveDataMgr;
    liveDataMgr.setPkPassManager(&passMgr);
    liveDataMgr.setReservationManager(&resMgr);
264
    liveDataMgr.setPollingEnabled(settings.queryLiveData());
265
    liveDataMgr.setShowNotificationsOnLockScreen(settings.showNotificationOnLockScreen());
266
    QObject::connect(&settings, &Settings::queryLiveDataChanged, &liveDataMgr, &LiveDataManager::setPollingEnabled);
267
    QObject::connect(&settings, &Settings::showNotificationOnLockScreenChanged, &liveDataMgr, &LiveDataManager::setShowNotificationsOnLockScreen);
268
    s_liveDataMnager = &liveDataMgr;
269

Volker Krause's avatar
Volker Krause committed
270
271
272
    WeatherForecastManager weatherForecastMgr;
    weatherForecastMgr.setAllowNetworkAccess(settings.weatherForecastEnabled());
    QObject::connect(&settings, &Settings::weatherForecastEnabledChanged, &weatherForecastMgr, &WeatherForecastManager::setAllowNetworkAccess);
273
274
    s_weatherForecastManager = &weatherForecastMgr;

275
276
277
278
    TransferManager transferManager;
    transferManager.setReservationManager(&resMgr);
    transferManager.setTripGroupManager(&tripGroupMgr);
    transferManager.setFavoriteLocationModel(&favLocModel);
279
    transferManager.setPublicTransportManager(liveDataMgr.publicTransportManager());
280
281
282
283
    transferManager.setAutoAddTransfers(settings.autoAddTransfers());
    transferManager.setAutoFillTransfers(settings.autoFillTransfers());
    QObject::connect(&settings, &Settings::autoAddTransfersChanged, &transferManager, &TransferManager::setAutoAddTransfers);
    QObject::connect(&settings, &Settings::autoFillTransfersChanged, &transferManager, &TransferManager::setAutoFillTransfers);
284
285
    s_tranferManager = &transferManager;

286
287
288
    TimelineModel timelineModel;
    timelineModel.setHomeCountryIsoCode(settings.homeCountryIsoCode());
    timelineModel.setReservationManager(&resMgr);
289
    timelineModel.setWeatherForecastManager(&weatherForecastMgr);
290
    timelineModel.setTransferManager(&transferManager);
291
    timelineModel.setTripGroupManager(&tripGroupMgr);
292
    QObject::connect(&settings, &Settings::homeCountryIsoCodeChanged, &timelineModel, &TimelineModel::setHomeCountryIsoCode);
293

294
295
    TripGroupProxyModel tripGroupProxy;
    tripGroupProxy.setSourceModel(&timelineModel);
296
    s_tripGroupProxyModel = &tripGroupProxy;
297

298
299
    s_tripGroupInfoProvider.setReservationManager(&resMgr);
    s_tripGroupInfoProvider.setWeatherForecastManager(&weatherForecastMgr);
300

301
302
    MapDownloadManager mapDownloadMgr;
    mapDownloadMgr.setReservationManager(&resMgr);
303
304
    mapDownloadMgr.setAutomaticDownloadEnabled(s_settings->preloadMapData());
    QObject::connect(s_settings, &Settings::preloadMapDataChanged, &mapDownloadMgr, &MapDownloadManager::setAutomaticDownloadEnabled);
305
306
    s_mapDownloadManager = &mapDownloadMgr;

307
308
309
310
311
    ApplicationController appController;
    appController.setReservationManager(&resMgr);
    appController.setPkPassManager(&passMgr);
    appController.setDocumentManager(&docMgr);
    appController.setFavoriteLocationModel(&favLocModel);
312
    appController.setTransferManager(&transferManager);
Volker Krause's avatar
Volker Krause committed
313
    appController.setLiveDataManager(&liveDataMgr);
Volker Krause's avatar
Volker Krause committed
314
    appController.setTripGroupManager(&tripGroupMgr);
315
#ifndef Q_OS_ANDROID
316
    QObject::connect(&service, &KDBusService::activateRequested, [&](const QStringList &args, const QString &workingDir) {
317
318
319
320
        qCDebug(Log) << "remote activation" << args << workingDir;
        if (!args.isEmpty()) {
            QDir::setCurrent(workingDir);
            parser.parse(args);
321
            handlePositionalArguments(&appController, parser.positionalArguments(), parser.isSet(isTemporaryOpt));
322
323
324
325
326
327
        }
        if (!QGuiApplication::allWindows().isEmpty()) {
            QGuiApplication::allWindows().at(0)->requestActivate();
        }
    });
#endif
328

329
330
331
332
    registerKPkPassTypes();
    registerKItineraryTypes();
    registerApplicationTypes();
    registerApplicationSingletons();
333

334
335
    QQmlApplicationEngine engine;
    engine.addImageProvider(QStringLiteral("org.kde.pkpass"), new PkPassImageProvider(&passMgr));
336
337
338
    auto l10nContext = new KLocalizedContext(&engine);
    l10nContext->setTranslationDomain(QStringLiteral(TRANSLATION_DOMAIN));
    engine.rootContext()->setContextObject(l10nContext);
339
    engine.load(QStringLiteral("qrc:/main.qml"));
340

341
    handlePositionalArguments(&appController, parser.positionalArguments(), parser.isSet(isTemporaryOpt));
342
343
344
345
#ifdef Q_OS_ANDROID
    using namespace KAndroidExtras;
    appController.importFromIntent(Activity::getIntent());
#endif
346

347
348
    return app.exec();
}