2017-01-27 15:55:38 +03:00
|
|
|
#include <QApplication>
|
|
|
|
#include <QQmlApplicationEngine>
|
|
|
|
#include <QQmlContext>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <QtGlobal>
|
|
|
|
#include <QtWidgets>
|
2017-03-30 15:52:13 +03:00
|
|
|
#include <QQuickWindow>
|
2017-01-27 15:55:38 +03:00
|
|
|
#ifndef Q_OS_DARWIN
|
|
|
|
#include <QtSingleApplication>
|
|
|
|
#endif
|
2017-02-13 15:03:58 +03:00
|
|
|
#include "screenshot.h"
|
2017-08-14 13:27:04 +03:00
|
|
|
#include "systemtray.h"
|
2017-01-27 15:55:38 +03:00
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2017-03-16 13:23:06 +03:00
|
|
|
// Global menubar is broken for qt5 apps in Ubuntu Unity, see:
|
|
|
|
// https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853
|
|
|
|
// This workaround enables a local menubar.
|
2017-03-16 15:32:32 +03:00
|
|
|
qputenv("UBUNTU_MENUPROXY","0");
|
2017-03-16 15:42:20 +03:00
|
|
|
|
|
|
|
// Don't write .pyc files.
|
2017-03-16 14:42:32 +03:00
|
|
|
qputenv("PYTHONDONTWRITEBYTECODE", "1");
|
2017-03-16 13:23:06 +03:00
|
|
|
|
2017-01-27 15:55:38 +03:00
|
|
|
// Non Darwin platforms uses QSingleApplication to ensure only one running instance.
|
|
|
|
#ifndef Q_OS_DARWIN
|
|
|
|
QtSingleApplication app(argc, argv);
|
|
|
|
if (app.sendMessage("")) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
QApplication app(argc, argv);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
QString app_dir = app.applicationDirPath();
|
2017-03-19 00:24:38 +03:00
|
|
|
QString main_qml = "/qml/main.qml";
|
2017-01-27 15:55:38 +03:00
|
|
|
QString path_prefix;
|
|
|
|
QString url_prefix;
|
|
|
|
|
2017-03-22 15:14:06 +03:00
|
|
|
app.setApplicationName("Yubico Authenticator");
|
|
|
|
app.setOrganizationName("Yubico");
|
|
|
|
app.setOrganizationDomain("com.yubico");
|
|
|
|
|
2017-01-27 15:55:38 +03:00
|
|
|
if (QFileInfo::exists(":" + main_qml)) {
|
|
|
|
// Embedded resources
|
|
|
|
path_prefix = ":";
|
|
|
|
url_prefix = "qrc://";
|
|
|
|
} else if (QFileInfo::exists(app_dir + main_qml)) {
|
|
|
|
// Try relative to executable
|
|
|
|
path_prefix = app_dir;
|
|
|
|
url_prefix = app_dir;
|
|
|
|
} else { //Assume qml/main.qml in cwd.
|
|
|
|
app_dir = ".";
|
|
|
|
path_prefix = ".";
|
|
|
|
url_prefix = ".";
|
|
|
|
}
|
|
|
|
|
2017-02-13 15:03:58 +03:00
|
|
|
ScreenShot screenshot;
|
2017-01-27 15:55:38 +03:00
|
|
|
QQmlApplicationEngine engine;
|
2017-03-30 14:14:24 +03:00
|
|
|
|
2017-08-14 13:27:04 +03:00
|
|
|
SystemTray *trayIcon = new SystemTray();
|
2017-03-30 14:14:24 +03:00
|
|
|
trayIcon->setIcon(QIcon(path_prefix + "/images/windowicon.png"));
|
|
|
|
|
2017-01-27 15:55:38 +03:00
|
|
|
engine.rootContext()->setContextProperty("appDir", app_dir);
|
|
|
|
engine.rootContext()->setContextProperty("urlPrefix", url_prefix);
|
|
|
|
engine.rootContext()->setContextProperty("appVersion", APP_VERSION);
|
2017-02-13 15:03:58 +03:00
|
|
|
engine.rootContext()->setContextProperty("ScreenShot", &screenshot);
|
2017-03-30 14:14:24 +03:00
|
|
|
engine.rootContext()->setContextProperty("SysTrayIcon", trayIcon);
|
2017-03-31 12:14:22 +03:00
|
|
|
engine.rootContext()->setContextProperty("app", &app);
|
2017-01-27 15:55:38 +03:00
|
|
|
engine.load(QUrl(url_prefix + main_qml));
|
|
|
|
|
2017-03-30 15:52:13 +03:00
|
|
|
// This is the current system tray icon.
|
|
|
|
// Should probably be replaced by QML when all supported platforms are on > Qt 5.8
|
|
|
|
// See http://doc-snapshots.qt.io/qt5-5.8/qml-qt-labs-platform-systemtrayicon.html
|
|
|
|
QObject *root = engine.rootObjects().first();
|
2017-12-01 17:38:08 +03:00
|
|
|
|
|
|
|
if (argc > 2 && strcmp(argv[1], "--log-level") == 0) {
|
|
|
|
QMetaObject::invokeMethod(root, "enableLogging", Q_ARG(QVariant, argv[2]));
|
|
|
|
}
|
|
|
|
|
2017-03-30 15:52:13 +03:00
|
|
|
QQuickWindow *qmlWindow = qobject_cast<QQuickWindow *>(root);
|
2017-08-28 13:43:50 +03:00
|
|
|
|
|
|
|
// Set icon in the window, doesn't effect desktop icons.
|
|
|
|
qmlWindow->setIcon(QIcon(path_prefix + "/images/windowicon.png"));
|
2017-10-23 20:02:33 +03:00
|
|
|
// Show root window unless explicitly hidden in settings.
|
2017-11-16 20:01:53 +03:00
|
|
|
if (qmlWindow->property("hideOnLaunch").toBool() == false) {
|
2017-10-23 20:02:33 +03:00
|
|
|
qmlWindow->show();
|
|
|
|
}
|
2017-08-28 13:43:50 +03:00
|
|
|
|
2017-03-30 15:52:13 +03:00
|
|
|
QAction *showAction = new QAction(QObject::tr("&Show credentials"), qmlWindow);
|
2017-03-31 16:35:19 +03:00
|
|
|
// The call to hide doesn't make much sense but makes it work on macOS when hidden from the dock.
|
|
|
|
root->connect(showAction, &QAction::triggered, qmlWindow, &QQuickWindow::hide);
|
2017-03-31 10:24:24 +03:00
|
|
|
root->connect(showAction, &QAction::triggered, qmlWindow, &QQuickWindow::show);
|
2017-03-30 15:52:13 +03:00
|
|
|
root->connect(showAction, &QAction::triggered, qmlWindow, &QQuickWindow::raise);
|
2017-03-31 16:35:19 +03:00
|
|
|
root->connect(showAction, &QAction::triggered, qmlWindow, &QQuickWindow::requestActivate);
|
2017-03-30 15:52:13 +03:00
|
|
|
QAction *quitAction = new QAction(QObject::tr("&Quit"), qmlWindow);
|
|
|
|
root->connect(quitAction, &QAction::triggered, qApp, &QApplication::quit);
|
|
|
|
QMenu *trayIconMenu = new QMenu();
|
|
|
|
trayIconMenu->addAction(showAction);
|
|
|
|
trayIconMenu->addSeparator();
|
|
|
|
trayIconMenu->addAction(quitAction);
|
|
|
|
trayIcon->setContextMenu(trayIconMenu);
|
|
|
|
trayIcon->setToolTip("Yubico Authenticator");
|
2017-08-14 13:53:28 +03:00
|
|
|
#ifndef Q_OS_DARWIN
|
|
|
|
// Double-click should show credentials.
|
|
|
|
// Double-click in systemtray icons is not supported on macOS.
|
2017-08-14 13:27:04 +03:00
|
|
|
root->connect(trayIcon,SIGNAL(doubleClicked()), qmlWindow,SLOT(show()));
|
|
|
|
root->connect(trayIcon,SIGNAL(doubleClicked()), qmlWindow,SLOT(raise()));
|
2017-08-14 13:34:06 +03:00
|
|
|
root->connect(trayIcon,SIGNAL(doubleClicked()), qmlWindow,SLOT(requestActivate()));
|
2017-08-14 13:53:28 +03:00
|
|
|
#endif
|
2017-03-30 15:52:13 +03:00
|
|
|
|
2017-01-27 15:55:38 +03:00
|
|
|
#ifndef Q_OS_DARWIN
|
|
|
|
// Wake up the root window on a message from new instance.
|
|
|
|
for (auto object : engine.rootObjects()) {
|
|
|
|
if (QWindow *window = qobject_cast<QWindow*>(object)) {
|
|
|
|
QObject::connect(&app, &QtSingleApplication::messageReceived, [window]() {
|
|
|
|
window->show();
|
|
|
|
window->raise();
|
|
|
|
window->requestActivate();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2017-11-22 17:04:42 +03:00
|
|
|
|
|
|
|
const int status = app.exec();
|
|
|
|
trayIcon->hide();
|
|
|
|
return status;
|
2017-01-27 15:55:38 +03:00
|
|
|
}
|