keysmith/src/main.cpp

167 lines
6.6 KiB
C++

/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2019 Bhushan Shah <bshah@kde.org>
* SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
*/
#include <QCommandLineParser>
#include <QQmlApplicationEngine>
#include <QQuickStyle>
#include <QtQml>
#include <QUrl>
#ifdef Q_OS_ANDROID
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include <KLocalizedContext>
#include <KLocalizedString>
#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 <QQmlDebuggingEnabler>
static QQmlDebuggingEnabler enabler;
#endif
#ifdef ENABLE_DBUS_INTERFACE
#include <KDBusService>
#endif
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#ifdef Q_OS_ANDROID
QGuiApplication app(argc, argv);
QQuickStyle::setStyle(QStringLiteral("Material"));
#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"));
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<app::AddAccountViewModel>("Keysmith.Application", 1, 0, "AddAccountViewModel",
QStringLiteral("Should be automatically provided through Keysmith.Application.Navigation signals")
);
qmlRegisterUncreatableType<app::RenameAccountViewModel>("Keysmith.Application", 1, 0, "RenameAccountViewModel",
QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")
);
qmlRegisterUncreatableType<app::ErrorViewModel>("Keysmith.Application", 1, 0, "ErrorViewModel",
QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")
);
qmlRegisterUncreatableType<app::SetupPasswordViewModel>("Keysmith.Application", 1, 0, "SetupPasswordViewModel",
QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")
);
qmlRegisterUncreatableType<app::UnlockAccountsViewModel>("Keysmith.Application", 1, 0, "UnlockAccountsViewModel",
QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")
);
qmlRegisterUncreatableType<app::AccountsOverviewViewModel>("Keysmith.Application", 1, 0, "AccountsOverviewViewModel",
QStringLiteral("Should be automatically provided through Keysmith.Navigation signals")
);
qmlRegisterUncreatableType<app::Navigation>("Keysmith.Application", 1, 0, "Navigation",
QStringLiteral("Use the Keysmith singleton to obtain a Navigation")
);
qmlRegisterUncreatableType<model::SimpleAccountListModel>("Keysmith.Models", 1, 0, "AccountListModel",
QStringLiteral("Use the Keysmith singleton to obtain an AccountListModel")
);
qmlRegisterUncreatableType<model::PasswordRequest>("Keysmith.Models", 1, 0, "PasswordRequestModel",
QStringLiteral("Use the Keysmith singleton to obtain an PasswordRequestModel")
);
qmlRegisterUncreatableType<model::AccountView>("Keysmith.Models", 1, 0, "Account",
QStringLiteral("Use an AccountListModel from the Keysmith singleton to obtain an Account")
);
qmlRegisterType<model::AccountInput>("Keysmith.Models", 1, 0, "ValidatedAccountInput");
qmlRegisterType<model::SortedAccountsListModel>("Keysmith.Models", 1, 0, "SortedAccountListModel");
qmlRegisterType<model::AccountNameValidator>("Keysmith.Validators", 1, 0, "AccountNameValidator");
qmlRegisterType<validators::EpochValidator>("Keysmith.Validators", 1, 0, "TOTPEpochValidator");
qmlRegisterType<validators::IssuerValidator>("Keysmith.Validators", 1, 0, "AccountIssuerValidator");
qmlRegisterType<validators::Base32Validator>("Keysmith.Validators", 1, 0, "Base32SecretValidator");
qmlRegisterType<validators::UnsignedLongValidator>("Keysmith.Validators", 1, 0, "HOTPCounterValidator");
qmlRegisterSingletonType<app::Keysmith>("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<app::CommandLineOptions>("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.load(QUrl(QStringLiteral("qrc:///main.qml")));
if (engine.rootObjects().isEmpty()) {
return -1;
}
proxy.proxy(cliParser, parseOk);
int ret = app.exec();
return ret;
}