2016-09-24 16:19:23 +02:00
|
|
|
#include "./singleinstance.h"
|
|
|
|
|
2016-09-01 16:34:30 +02:00
|
|
|
#include "../gui/trayicon.h"
|
|
|
|
#include "../gui/traywidget.h"
|
2016-09-24 16:19:23 +02:00
|
|
|
|
2018-04-11 23:15:15 +02:00
|
|
|
#include "../../widgets/misc/syncthinglauncher.h"
|
2017-04-23 18:27:31 +02:00
|
|
|
#include "../../widgets/settings/settings.h"
|
|
|
|
|
2016-09-30 23:55:25 +02:00
|
|
|
#include "../../connector/syncthingprocess.h"
|
2016-12-18 16:50:35 +01:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
2017-05-01 03:34:43 +02:00
|
|
|
#include "../../connector/syncthingservice.h"
|
2016-12-18 16:50:35 +01:00
|
|
|
#endif
|
2016-09-01 16:34:30 +02:00
|
|
|
|
|
|
|
#include "resources/config.h"
|
2019-06-16 15:57:03 +02:00
|
|
|
#include "resources/qtconfig.h"
|
2016-09-01 16:34:30 +02:00
|
|
|
|
|
|
|
#include <c++utilities/application/argumentparser.h>
|
|
|
|
#include <c++utilities/application/commandlineutils.h>
|
2019-06-10 22:48:26 +02:00
|
|
|
#include <c++utilities/misc/parseerror.h>
|
2016-09-01 16:34:30 +02:00
|
|
|
|
2017-05-01 03:34:43 +02:00
|
|
|
#include <qtutilities/resources/importplugin.h>
|
2016-09-01 16:34:30 +02:00
|
|
|
#include <qtutilities/resources/qtconfigarguments.h>
|
|
|
|
#include <qtutilities/resources/resources.h>
|
|
|
|
#include <qtutilities/settingsdialog/qtsettings.h>
|
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QMessageBox>
|
2017-05-01 03:34:43 +02:00
|
|
|
#include <QNetworkAccessManager>
|
2016-12-18 16:50:35 +01:00
|
|
|
#include <QStringBuilder>
|
2016-09-01 16:34:30 +02:00
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using namespace std;
|
2019-06-10 22:48:26 +02:00
|
|
|
using namespace CppUtilities;
|
2016-09-01 16:34:30 +02:00
|
|
|
using namespace QtGui;
|
2016-09-03 19:39:43 +02:00
|
|
|
using namespace Data;
|
2016-09-01 16:34:30 +02:00
|
|
|
|
2017-02-11 02:42:10 +01:00
|
|
|
ENABLE_QT_RESOURCES_OF_STATIC_DEPENDENCIES
|
|
|
|
|
2016-12-18 16:50:35 +01:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
|
|
|
void handleSystemdServiceError(const QString &context, const QString &name, const QString &message)
|
|
|
|
{
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
|
|
msgBox.setText(QCoreApplication::translate("main", "Unable to ") + context);
|
2016-12-27 16:16:12 +01:00
|
|
|
msgBox.setInformativeText(name % QStringLiteral(":\n") % message);
|
2016-12-18 16:50:35 +01:00
|
|
|
msgBox.exec();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-08-09 01:11:47 +02:00
|
|
|
int initSyncthingTray(bool windowed, bool waitForTray, const char *connectionConfig)
|
2016-09-01 16:34:30 +02:00
|
|
|
{
|
2018-04-02 20:26:00 +02:00
|
|
|
// get settings
|
|
|
|
auto &settings = Settings::values();
|
|
|
|
const auto connectionConfigQStr(connectionConfig ? QString::fromLocal8Bit(connectionConfig) : QString());
|
|
|
|
|
|
|
|
// handle "windowed" case
|
2017-05-01 03:34:43 +02:00
|
|
|
if (windowed) {
|
2018-04-02 20:26:00 +02:00
|
|
|
settings.launcher.autostart();
|
2018-05-15 22:01:03 +02:00
|
|
|
auto *const trayWidget = new TrayWidget();
|
2016-09-24 16:19:23 +02:00
|
|
|
trayWidget->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
trayWidget->show();
|
2018-05-15 22:01:03 +02:00
|
|
|
trayWidget->applySettings(connectionConfigQStr);
|
2018-04-02 20:26:00 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-24 16:19:23 +02:00
|
|
|
#ifndef QT_NO_SYSTEMTRAYICON
|
2018-04-02 20:26:00 +02:00
|
|
|
// check whether system tray is available
|
|
|
|
if (!QSystemTrayIcon::isSystemTrayAvailable() && !waitForTray) {
|
2017-05-01 03:34:43 +02:00
|
|
|
QMessageBox::critical(nullptr, QApplication::applicationName(),
|
2018-04-02 20:26:00 +02:00
|
|
|
QApplication::translate(
|
|
|
|
"main", "The system tray is (currently) not available. You could open the tray menu as a regular window using the -w flag, though."));
|
|
|
|
return -1;
|
2016-09-24 16:19:23 +02:00
|
|
|
}
|
2018-04-02 20:26:00 +02:00
|
|
|
|
|
|
|
// show tray icon
|
|
|
|
settings.launcher.autostart();
|
|
|
|
auto *const trayIcon = new TrayIcon(connectionConfigQStr, QApplication::instance());
|
|
|
|
trayIcon->show();
|
|
|
|
if (!settings.firstLaunch) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// show "first launch" message box
|
|
|
|
QMessageBox msgBox;
|
|
|
|
msgBox.setIcon(QMessageBox::Information);
|
|
|
|
msgBox.setText(QCoreApplication::translate("main", "You must configure how to connect to Syncthing when using Syncthing Tray the first time."));
|
|
|
|
msgBox.setInformativeText(QCoreApplication::translate(
|
|
|
|
"main", "Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration."));
|
|
|
|
msgBox.exec();
|
|
|
|
trayIcon->trayMenu().widget().showSettingsDialog();
|
2016-09-24 16:19:23 +02:00
|
|
|
return 0;
|
2018-04-02 20:26:00 +02:00
|
|
|
|
|
|
|
#else
|
|
|
|
// show error if system tray is not supported by Qt
|
|
|
|
QMessageBox::critical(nullptr, QApplication::applicationName(),
|
|
|
|
QApplication::translate("main",
|
|
|
|
"The Qt libraries have not been built with tray icon support. You could open the tray menu as a regular "
|
|
|
|
"window using the -w flag, though."));
|
|
|
|
return -2;
|
|
|
|
#endif
|
2016-09-24 16:19:23 +02:00
|
|
|
}
|
|
|
|
|
2016-12-26 19:50:10 +01:00
|
|
|
void trigger(bool tray, bool webUi)
|
|
|
|
{
|
2018-04-02 20:26:00 +02:00
|
|
|
if (TrayWidget::instances().empty() || !(tray || webUi)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto *const trayWidget = TrayWidget::instances().front();
|
|
|
|
if (webUi) {
|
|
|
|
trayWidget->showWebUi();
|
|
|
|
}
|
|
|
|
if (tray) {
|
2019-06-22 17:28:09 +02:00
|
|
|
trayWidget->showUsingPositioningSettings();
|
2016-12-26 19:50:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-24 16:19:23 +02:00
|
|
|
int runApplication(int argc, const char *const *argv)
|
|
|
|
{
|
2016-09-01 16:34:30 +02:00
|
|
|
// setup argument parser
|
2016-09-24 16:19:23 +02:00
|
|
|
SET_APPLICATION_INFO;
|
2017-01-02 23:25:58 +01:00
|
|
|
CMD_UTILS_CONVERT_ARGS_TO_UTF8;
|
2016-09-01 16:34:30 +02:00
|
|
|
ArgumentParser parser;
|
|
|
|
// Qt configuration arguments
|
|
|
|
QT_CONFIG_ARGUMENTS qtConfigArgs;
|
|
|
|
Argument windowedArg("windowed", 'w', "opens the tray menu as a regular window");
|
|
|
|
windowedArg.setCombinable(true);
|
2016-12-26 19:50:10 +01:00
|
|
|
Argument showWebUiArg("webui", '\0', "instantly shows the web UI - meant for creating shortcut to web UI");
|
|
|
|
showWebUiArg.setCombinable(true);
|
|
|
|
Argument triggerArg("trigger", '\0', "instantly shows the left-click tray menu - meant for creating a shortcut");
|
|
|
|
triggerArg.setCombinable(true);
|
2017-05-01 03:34:43 +02:00
|
|
|
Argument waitForTrayArg("wait", '\0',
|
|
|
|
"wait until the system tray becomes available instead of showing an error message if the system tray is not available on start-up");
|
2016-09-14 19:34:14 +02:00
|
|
|
waitForTrayArg.setCombinable(true);
|
2017-08-09 01:11:47 +02:00
|
|
|
ConfigValueArgument connectionArg("connection", '\0', "specifies the connection configuration to be used", { "config name" });
|
2016-12-26 19:50:10 +01:00
|
|
|
Argument &widgetsGuiArg = qtConfigArgs.qtWidgetsGuiArg();
|
|
|
|
widgetsGuiArg.addSubArgument(&windowedArg);
|
|
|
|
widgetsGuiArg.addSubArgument(&showWebUiArg);
|
|
|
|
widgetsGuiArg.addSubArgument(&triggerArg);
|
|
|
|
widgetsGuiArg.addSubArgument(&waitForTrayArg);
|
2017-08-09 01:11:47 +02:00
|
|
|
widgetsGuiArg.addSubArgument(&connectionArg);
|
2016-12-26 19:50:10 +01:00
|
|
|
|
2019-03-13 19:12:23 +01:00
|
|
|
parser.setMainArguments({ &qtConfigArgs.qtWidgetsGuiArg(), &parser.noColorArg(), &parser.helpArg() });
|
2019-06-10 22:48:26 +02:00
|
|
|
parser.parseArgs(argc, argv);
|
2017-09-29 17:18:21 +02:00
|
|
|
if (!qtConfigArgs.qtWidgetsGuiArg().isPresent()) {
|
|
|
|
return 0;
|
|
|
|
}
|
2018-04-02 20:26:00 +02:00
|
|
|
|
|
|
|
// check whether runApplication() has been called for the first time
|
|
|
|
static auto firstRun = true;
|
2017-09-29 17:18:21 +02:00
|
|
|
if (firstRun) {
|
|
|
|
firstRun = false;
|
|
|
|
|
2018-04-02 20:26:00 +02:00
|
|
|
// do first-time initializations
|
2017-09-29 17:18:21 +02:00
|
|
|
SET_QT_APPLICATION_INFO;
|
|
|
|
QApplication application(argc, const_cast<char **>(argv));
|
|
|
|
QGuiApplication::setQuitOnLastWindowClosed(false);
|
|
|
|
SingleInstance singleInstance(argc, argv);
|
|
|
|
networkAccessManager().setParent(&singleInstance);
|
|
|
|
QObject::connect(&singleInstance, &SingleInstance::newInstance, &runApplication);
|
|
|
|
Settings::restore();
|
|
|
|
Settings::values().qt.apply();
|
|
|
|
qtConfigArgs.applySettings(true);
|
|
|
|
LOAD_QT_TRANSLATIONS;
|
2018-04-11 23:15:15 +02:00
|
|
|
SyncthingLauncher launcher;
|
|
|
|
SyncthingLauncher::setMainInstance(&launcher);
|
2018-04-02 20:26:00 +02:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
2018-04-11 23:15:15 +02:00
|
|
|
SyncthingService service;
|
|
|
|
SyncthingService::setMainInstance(&service);
|
2018-04-02 20:26:00 +02:00
|
|
|
service.setUnitName(Settings::values().systemd.syncthingUnit);
|
|
|
|
QObject::connect(&service, &SyncthingService::errorOccurred, &handleSystemdServiceError);
|
|
|
|
#endif
|
2017-09-29 17:18:21 +02:00
|
|
|
|
2018-04-02 20:26:00 +02:00
|
|
|
// show (first) tray icon and enter main event loop
|
|
|
|
auto res = initSyncthingTray(windowedArg.isPresent(), waitForTrayArg.isPresent(), connectionArg.firstValue());
|
2017-09-29 17:18:21 +02:00
|
|
|
if (!res) {
|
|
|
|
trigger(triggerArg.isPresent(), showWebUiArg.isPresent());
|
|
|
|
res = application.exec();
|
|
|
|
}
|
|
|
|
|
2018-04-02 20:26:00 +02:00
|
|
|
// perform cleanup, then terminate
|
2017-09-29 17:18:21 +02:00
|
|
|
Settings::Launcher::terminate();
|
|
|
|
Settings::save();
|
|
|
|
return res;
|
2016-09-01 16:34:30 +02:00
|
|
|
}
|
|
|
|
|
2018-04-02 20:26:00 +02:00
|
|
|
// trigger actions if --webui or --trigger is present but don't create a new tray icon
|
|
|
|
if (!TrayWidget::instances().empty() && (showWebUiArg.isPresent() || triggerArg.isPresent())) {
|
|
|
|
trigger(triggerArg.isPresent(), showWebUiArg.isPresent());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create new/additional tray icon
|
|
|
|
const auto res = initSyncthingTray(windowedArg.isPresent(), waitForTrayArg.isPresent(), connectionArg.firstValue());
|
|
|
|
if (!res) {
|
|
|
|
trigger(triggerArg.isPresent(), showWebUiArg.isPresent());
|
|
|
|
}
|
|
|
|
return res;
|
2016-09-01 16:34:30 +02:00
|
|
|
}
|
|
|
|
|
2016-09-24 16:19:23 +02:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
return runApplication(argc, argv);
|
|
|
|
}
|