/* * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2019 Bhushan Shah * SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk * SPDX-FileCopyrightText: 2021 Devin Lin */ #include #include #include #include #include #ifdef Q_OS_ANDROID #include #else #include #endif #include #include #include #include "app/cli.h" #include "app/keysmith.h" #include "app/vms.h" #include "model/accounts.h" #include "model/input.h" #include "validators/countervalidator.h" #include "validators/datetimevalidator.h" #include "validators/issuervalidator.h" #include "validators/secretvalidator.h" #include "keysmith-features.h" #include "version.h" /* * Integrate QML debugging/profiling support, conditional on building Keysmith in Debug mode. * NDEBUG is defined by the C standard and automatically set by CMake during a Release type build, hence the double negative. */ #ifndef NDEBUG #include static QQmlDebuggingEnabler enabler; #endif #ifdef ENABLE_DBUS_INTERFACE #include #endif Q_DECL_EXPORT int main(int argc, char *argv[]) { #ifdef Q_OS_ANDROID QGuiApplication app(argc, argv); QQuickStyle::setStyle(QStringLiteral("org.kde.breeze")); #else QApplication app(argc, argv); if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) { QQuickStyle::setStyle(QStringLiteral("org.kde.desktop")); } #endif KLocalizedString::setApplicationDomain("keysmith"); QCoreApplication::setOrganizationName(QStringLiteral("KDE")); QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); QCoreApplication::setApplicationName(QStringLiteral("keysmith")); QCoreApplication::setApplicationVersion(KEYSMITH_VERSION_STRING); QGuiApplication::setApplicationDisplayName(i18nc("@title", "Keysmith")); // about const QString applicationDescription = i18n("generate two-factor authentication (2FA) tokens"); KAboutData about(QStringLiteral("keysmith"), i18n("Keysmith"), KEYSMITH_VERSION_STRING, applicationDescription, KAboutLicense::GPL_V3, i18n("© 2019 KDE Community")); about.addAuthor(QStringLiteral("Bhushan Shah"), QString(), QStringLiteral("bshah@kde.org")); about.addAuthor(QStringLiteral("Johan Ouwerkerk"), QString(), QStringLiteral("jm.ouwerkerk@gmail.com")); about.addAuthor(QStringLiteral("Devin Lin"), QString(), QStringLiteral("espidev@gmail.com")); KAboutData::setApplicationData(about); QCommandLineParser cliParser; // default/boilerplate options handled entirely via command line const auto helpOption = cliParser.addHelpOption(); const auto versionOption = cliParser.addVersionOption(); bool parseOk = app::Proxy::parseCommandLine(cliParser, QCoreApplication::arguments()); /* * First check for pure command line options and handle these. * If any are found, the application should not bother with an UI. */ if (cliParser.isSet(helpOption)) { int ret = parseOk ? 0 : 1; cliParser.showHelp(ret); return ret; // just to be explicit: showHelp() is documented to call exit() } if (cliParser.isSet(versionOption)) { cliParser.showVersion(); return 0; // just to be explicit: showVersion() is documented to call exit() } app::Proxy proxy(&app); #ifdef ENABLE_DBUS_INTERFACE KDBusService service(KDBusService::Unique); QObject::connect(&service, &KDBusService::activateRequested, &proxy, &app::Proxy::handleDBusActivation); #endif QQmlApplicationEngine engine; engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); qmlRegisterUncreatableType("Keysmith.Application", 1, 0, "AddAccountViewModel", QStringLiteral("Should be automatically provided through Keysmith.Application.Navigation signals")); qmlRegisterUncreatableType("Keysmith.Application", 1, 0, "RenameAccountViewModel", QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")); qmlRegisterUncreatableType("Keysmith.Application", 1, 0, "ErrorViewModel", QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")); qmlRegisterUncreatableType("Keysmith.Application", 1, 0, "SetupPasswordViewModel", QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")); qmlRegisterUncreatableType("Keysmith.Application", 1, 0, "UnlockAccountsViewModel", QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")); qmlRegisterUncreatableType("Keysmith.Application", 1, 0, "AccountsOverviewViewModel", QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")); qmlRegisterUncreatableType("Keysmith.Application", 1, 0, "Navigation", QStringLiteral("Use the Keysmith singleton to obtain a Navigation")); qmlRegisterUncreatableType("Keysmith.Models", 1, 0, "AccountListModel", QStringLiteral("Use the Keysmith singleton to obtain an AccountListModel")); qmlRegisterUncreatableType("Keysmith.Models", 1, 0, "PasswordRequestModel", QStringLiteral("Use the Keysmith singleton to obtain an PasswordRequestModel")); qmlRegisterUncreatableType("Keysmith.Models", 1, 0, "Account", QStringLiteral("Use an AccountListModel from the Keysmith singleton to obtain an Account")); qmlRegisterType("Keysmith.Models", 1, 0, "ValidatedAccountInput"); qmlRegisterType("Keysmith.Models", 1, 0, "SortedAccountListModel"); qmlRegisterType("Keysmith.Validators", 1, 0, "AccountNameValidator"); qmlRegisterType("Keysmith.Validators", 1, 0, "TOTPEpochValidator"); qmlRegisterType("Keysmith.Validators", 1, 0, "AccountIssuerValidator"); qmlRegisterType("Keysmith.Validators", 1, 0, "Base32SecretValidator"); qmlRegisterType("Keysmith.Validators", 1, 0, "HOTPCounterValidator"); qmlRegisterSingletonType("Keysmith.Application", 1, 0, "Keysmith", [&proxy](QQmlEngine *qml, QJSEngine *js) -> QObject * { Q_UNUSED(js); auto app = new app::Keysmith(new app::Navigation(qml)); proxy.enable(app); return app; }); qmlRegisterSingletonType("Keysmith.Application", 1, 0, "CommandLine", [parseOk, &cliParser](QQmlEngine *qml, QJSEngine *js) -> QObject * { Q_UNUSED(qml); Q_UNUSED(js); return new app::CommandLineOptions(cliParser, parseOk); }); engine.loadFromModule("org.kde.keysmith", "Main"); if (engine.rootObjects().isEmpty()) { return -1; } proxy.proxy(cliParser, parseOk); return app.exec(); }