2011-04-06 13:48:02 +04:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
|
2013-07-05 15:14:48 +04:00
|
|
|
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
|
|
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
2011-04-06 13:48:02 +04:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*/
|
|
|
|
|
2014-12-17 16:09:57 +03:00
|
|
|
#include "application.h"
|
|
|
|
|
2012-06-15 15:36:38 +04:00
|
|
|
#include <iostream>
|
2017-07-13 12:06:04 +03:00
|
|
|
#include <random>
|
2012-06-05 17:11:29 +04:00
|
|
|
|
2013-08-22 11:40:15 +04:00
|
|
|
#include "config.h"
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "account.h"
|
2022-12-29 14:50:17 +03:00
|
|
|
#include "accountsetupcommandlinemanager.h"
|
2014-12-17 16:09:57 +03:00
|
|
|
#include "accountstate.h"
|
2022-10-28 20:40:06 +03:00
|
|
|
#include "editlocallymanager.h"
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "connectionvalidator.h"
|
|
|
|
#include "folder.h"
|
|
|
|
#include "folderman.h"
|
|
|
|
#include "logger.h"
|
2014-11-10 01:25:57 +03:00
|
|
|
#include "configfile.h"
|
2021-02-17 17:41:32 +03:00
|
|
|
#include "socketapi/socketapi.h"
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "sslerrordialog.h"
|
|
|
|
#include "theme.h"
|
|
|
|
#include "clientproxy.h"
|
2015-04-09 17:19:17 +03:00
|
|
|
#include "accountmanager.h"
|
2013-07-30 13:19:22 +04:00
|
|
|
#include "creds/abstractcredentials.h"
|
2021-11-03 15:53:45 +03:00
|
|
|
#include "pushnotifications.h"
|
2022-07-04 15:36:06 +03:00
|
|
|
#include "shellextensionsserver.h"
|
2020-03-09 03:48:07 +03:00
|
|
|
|
|
|
|
#if defined(BUILD_UPDATER)
|
2015-07-23 12:34:12 +03:00
|
|
|
#include "updater/ocupdater.h"
|
2020-03-09 03:48:07 +03:00
|
|
|
#endif
|
|
|
|
|
2015-12-01 18:30:57 +03:00
|
|
|
#include "owncloudsetupwizard.h"
|
2017-03-10 17:32:25 +03:00
|
|
|
#include "version.h"
|
2018-01-26 15:14:54 +03:00
|
|
|
#include "csync_exclude.h"
|
2018-11-13 13:46:26 +03:00
|
|
|
#include "common/vfs.h"
|
2013-07-29 16:28:19 +04:00
|
|
|
|
2014-02-12 15:17:32 +04:00
|
|
|
#include "config.h"
|
|
|
|
|
2014-01-28 18:49:19 +04:00
|
|
|
#if defined(Q_OS_WIN)
|
2013-06-05 18:14:20 +04:00
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2015-03-12 18:49:47 +03:00
|
|
|
#if defined(WITH_CRASHREPORTER)
|
|
|
|
#include <libcrashreporter-handler/Handler.h>
|
|
|
|
#endif
|
|
|
|
|
2012-05-21 18:48:49 +04:00
|
|
|
#include <QTranslator>
|
2013-08-28 22:58:22 +04:00
|
|
|
#include <QMenu>
|
|
|
|
#include <QMessageBox>
|
2018-01-29 16:17:52 +03:00
|
|
|
#include <QDesktopServices>
|
2019-09-26 13:36:05 +03:00
|
|
|
#include <QGuiApplication>
|
2022-10-12 19:01:15 +03:00
|
|
|
#include <QUrlQuery>
|
2023-01-31 20:43:57 +03:00
|
|
|
#include <QVersionNumber>
|
2012-05-21 18:48:49 +04:00
|
|
|
|
2014-05-21 14:31:44 +04:00
|
|
|
class QSocket;
|
|
|
|
|
2014-11-10 00:34:07 +03:00
|
|
|
namespace OCC {
|
2011-02-17 02:21:45 +03:00
|
|
|
|
2017-12-28 22:33:10 +03:00
|
|
|
Q_LOGGING_CATEGORY(lcApplication, "nextcloud.gui.application", QtInfoMsg)
|
2017-05-09 15:24:11 +03:00
|
|
|
|
2013-02-14 21:27:44 +04:00
|
|
|
namespace {
|
2013-06-06 18:00:51 +04:00
|
|
|
|
|
|
|
static const char optionsC[] =
|
|
|
|
"Options:\n"
|
2020-06-06 21:04:48 +03:00
|
|
|
" --help, -h : show this help screen.\n"
|
|
|
|
" --version, -v : show version information.\n"
|
2019-11-28 13:57:51 +03:00
|
|
|
" -q --quit : quit the running instance\n"
|
2020-06-06 21:04:48 +03:00
|
|
|
" --logwindow, -l : open a window to show log output.\n"
|
2013-06-06 18:00:51 +04:00
|
|
|
" --logfile <filename> : write log output to file <filename>.\n"
|
|
|
|
" --logdir <name> : write each sync log output in a new file\n"
|
2015-09-07 09:51:22 +03:00
|
|
|
" in folder <name>.\n"
|
2013-06-07 20:57:45 +04:00
|
|
|
" --logexpire <hours> : removes logs older than <hours> hours.\n"
|
|
|
|
" (to be used with --logdir)\n"
|
2013-06-06 18:00:51 +04:00
|
|
|
" --logflush : flush the log file after every write.\n"
|
2018-07-16 10:53:33 +03:00
|
|
|
" --logdebug : also output debug-level messages in the log.\n"
|
2018-11-02 15:57:10 +03:00
|
|
|
" --confdir <dirname> : Use the given configuration folder.\n"
|
2022-12-29 14:50:17 +03:00
|
|
|
" --background : launch the application in the background.\n"
|
2023-01-13 19:55:35 +03:00
|
|
|
" --overrideserverurl : specify a server URL to use for the force override to be used in the account setup wizard.\n"
|
|
|
|
" --overridelocaldir : specify a local dir to be used in the account setup wizard.\n"
|
2022-12-29 14:50:17 +03:00
|
|
|
" --userid : userId (username as on the server) to pass when creating an account via command-line.\n"
|
|
|
|
" --apppassword : appPassword to pass when creating an account via command-line.\n"
|
|
|
|
" --localdirpath : (optional) path where to create a local sync folder when creating an account via command-line.\n"
|
2022-12-29 20:28:28 +03:00
|
|
|
" --isvfsenabled : whether to set a VFS or non-VFS folder (1 for 'yes' or 0 for 'no') when creating an account via command-line.\n"
|
2022-12-29 14:50:17 +03:00
|
|
|
" --remotedirpath : (optional) path to a remote subfolder when creating an account via command-line.\n"
|
|
|
|
" --serverurl : a server URL to use when creating an account via command-line.\n";
|
2013-06-06 18:00:51 +04:00
|
|
|
|
2013-02-14 21:27:44 +04:00
|
|
|
QString applicationTrPath()
|
|
|
|
{
|
2015-09-10 02:25:16 +03:00
|
|
|
QString devTrPath = qApp->applicationDirPath() + QString::fromLatin1("/../src/gui/");
|
|
|
|
if (QDir(devTrPath).exists()) {
|
|
|
|
// might miss Qt, QtKeyChain, etc.
|
2017-03-30 14:46:20 +03:00
|
|
|
qCWarning(lcApplication) << "Running from build location! Translations may be incomplete!";
|
2015-09-10 02:25:16 +03:00
|
|
|
return devTrPath;
|
|
|
|
}
|
2014-04-29 13:02:44 +04:00
|
|
|
#if defined(Q_OS_WIN)
|
2018-06-27 00:28:37 +03:00
|
|
|
return QApplication::applicationDirPath() + QLatin1String("/i18n/");
|
2014-04-29 13:02:44 +04:00
|
|
|
#elif defined(Q_OS_MAC)
|
|
|
|
return QApplication::applicationDirPath() + QLatin1String("/../Resources/Translations"); // path defaults to app dir.
|
|
|
|
#elif defined(Q_OS_UNIX)
|
2015-07-30 17:37:22 +03:00
|
|
|
return QString::fromLatin1(SHAREDIR "/" APPLICATION_EXECUTABLE "/i18n/");
|
2013-02-14 21:27:44 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-05 17:11:29 +04:00
|
|
|
// ----------------------------------------------------------------------------------
|
|
|
|
|
2022-03-21 19:34:21 +03:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
class WindowsNativeEventFilter : public QAbstractNativeEventFilter {
|
|
|
|
public:
|
|
|
|
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
|
|
|
|
const auto msg = static_cast<MSG *>(message);
|
|
|
|
if(msg->message == WM_SYSCOLORCHANGE || msg->message == WM_SETTINGCHANGE) {
|
2022-03-31 16:18:54 +03:00
|
|
|
if (const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance())) {
|
|
|
|
emit ptr->paletteChanged(ptr->palette());
|
2022-03-21 19:34:21 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2018-05-14 15:37:48 +03:00
|
|
|
bool Application::configVersionMigration()
|
2018-05-02 16:40:54 +03:00
|
|
|
{
|
2018-05-14 15:37:48 +03:00
|
|
|
QStringList deleteKeys, ignoreKeys;
|
|
|
|
AccountManager::backwardMigrationSettingsKeys(&deleteKeys, &ignoreKeys);
|
|
|
|
FolderMan::backwardMigrationSettingsKeys(&deleteKeys, &ignoreKeys);
|
2018-05-02 16:40:54 +03:00
|
|
|
|
2018-05-14 15:37:48 +03:00
|
|
|
ConfigFile configFile;
|
2018-05-02 16:40:54 +03:00
|
|
|
|
2018-05-14 15:37:48 +03:00
|
|
|
// Did the client version change?
|
|
|
|
// (The client version is adjusted further down)
|
2023-01-31 20:43:57 +03:00
|
|
|
const auto currentVersion = QVersionNumber::fromString(MIRALL_VERSION_STRING);
|
|
|
|
const auto previousVersion = QVersionNumber::fromString(configFile.clientVersionString());
|
|
|
|
const auto versionChanged = previousVersion != currentVersion;
|
|
|
|
const auto downgrading = previousVersion > currentVersion;
|
2022-12-27 20:25:23 +03:00
|
|
|
|
2023-02-01 19:25:24 +03:00
|
|
|
if (!versionChanged && !(!deleteKeys.isEmpty() || (!ignoreKeys.isEmpty() && versionChanged))) {
|
2018-05-02 16:40:54 +03:00
|
|
|
return true;
|
2022-12-28 00:19:17 +03:00
|
|
|
}
|
2018-05-02 16:40:54 +03:00
|
|
|
|
2023-02-01 19:25:24 +03:00
|
|
|
// back up all old config files
|
2022-12-28 00:19:17 +03:00
|
|
|
QStringList backupFilesList;
|
2023-01-23 19:30:59 +03:00
|
|
|
QDir configDir(configFile.configPath());
|
|
|
|
const auto anyConfigFileNameList = configDir.entryInfoList({"*.cfg"}, QDir::Files);
|
|
|
|
for (const auto &oldConfig : anyConfigFileNameList) {
|
|
|
|
const auto oldConfigFileName = oldConfig.fileName();
|
2023-01-31 20:41:43 +03:00
|
|
|
const auto oldConfigFilePath = oldConfig.filePath();
|
2023-01-23 19:30:59 +03:00
|
|
|
const auto newConfigFileName = configFile.configFile();
|
|
|
|
backupFilesList.append(configFile.backup(oldConfigFileName));
|
2023-01-31 20:41:43 +03:00
|
|
|
if (oldConfigFilePath != newConfigFileName) {
|
|
|
|
if (!QFile::rename(oldConfigFilePath, newConfigFileName)) {
|
|
|
|
qCWarning(lcApplication) << "Failed to rename configuration file from" << oldConfigFilePath << "to" << newConfigFileName;
|
2022-12-28 00:19:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 15:37:48 +03:00
|
|
|
|
2023-02-01 19:25:24 +03:00
|
|
|
// We want to message the user either for destructive changes,
|
|
|
|
// or if we're ignoring something and the client version changed.
|
|
|
|
if (configFile.showConfigBackupWarning() && backupFilesList.count() > 0) {
|
2018-05-14 15:37:48 +03:00
|
|
|
QMessageBox box(
|
|
|
|
QMessageBox::Warning,
|
|
|
|
APPLICATION_SHORTNAME,
|
2023-01-31 20:43:57 +03:00
|
|
|
tr("Some settings were configured in %1 versions of this client and "
|
2018-05-14 15:37:48 +03:00
|
|
|
"use features that are not available in this version.<br>"
|
|
|
|
"<br>"
|
2023-02-01 18:21:25 +03:00
|
|
|
"Continuing will mean <b>%2 these settings</b><br>"
|
2018-05-14 15:37:48 +03:00
|
|
|
"<br>"
|
2023-01-31 20:43:57 +03:00
|
|
|
"The current configuration file was already backed up to <i>%3</i>.")
|
2023-02-01 18:21:25 +03:00
|
|
|
.arg((downgrading ? tr("newer", "newer software version") : tr("older", "older software version")),
|
|
|
|
deleteKeys.isEmpty()? tr("ignoring") : tr("deleting"),
|
|
|
|
backupFilesList.join("<br>")));
|
2018-05-14 15:37:48 +03:00
|
|
|
box.addButton(tr("Quit"), QMessageBox::AcceptRole);
|
|
|
|
auto continueBtn = box.addButton(tr("Continue"), QMessageBox::DestructiveRole);
|
|
|
|
|
|
|
|
box.exec();
|
|
|
|
if (box.clickedButton() != continueBtn) {
|
|
|
|
QTimer::singleShot(0, qApp, SLOT(quit()));
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-02 16:40:54 +03:00
|
|
|
|
2018-05-14 15:37:48 +03:00
|
|
|
auto settings = ConfigFile::settingsWithGroup("foo");
|
|
|
|
settings->endGroup();
|
2018-05-02 16:40:54 +03:00
|
|
|
|
2018-05-14 15:37:48 +03:00
|
|
|
// Wipe confusing keys from the future, ignore the others
|
2022-10-24 18:53:40 +03:00
|
|
|
for (const auto &badKey : qAsConst(deleteKeys)) {
|
2018-05-14 15:37:48 +03:00
|
|
|
settings->remove(badKey);
|
2022-10-24 18:53:40 +03:00
|
|
|
}
|
2018-05-14 15:37:48 +03:00
|
|
|
}
|
2018-05-02 16:40:54 +03:00
|
|
|
|
2018-05-14 15:37:48 +03:00
|
|
|
configFile.setClientVersionString(MIRALL_VERSION_STRING);
|
2018-05-02 16:40:54 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:53:40 +03:00
|
|
|
ownCloudGui *Application::gui() const
|
|
|
|
{
|
|
|
|
return _gui;
|
|
|
|
}
|
|
|
|
|
2012-04-20 15:17:48 +04:00
|
|
|
Application::Application(int &argc, char **argv)
|
2014-05-20 19:12:56 +04:00
|
|
|
: SharedTools::QtSingleApplication(Theme::instance()->appName(), argc, argv)
|
2018-11-11 12:56:22 +03:00
|
|
|
, _gui(nullptr)
|
2012-09-24 19:55:10 +04:00
|
|
|
, _theme(Theme::instance())
|
2013-10-02 17:28:33 +04:00
|
|
|
, _helpOnly(false)
|
2015-07-16 19:12:45 +03:00
|
|
|
, _versionOnly(false)
|
2012-10-16 21:05:28 +04:00
|
|
|
, _showLogWindow(false)
|
2013-10-02 17:28:33 +04:00
|
|
|
, _logExpire(0)
|
2013-11-27 17:15:56 +04:00
|
|
|
, _logFlush(false)
|
2021-10-27 15:10:16 +03:00
|
|
|
, _logDebug(true)
|
2014-08-26 17:46:24 +04:00
|
|
|
, _userTriggeredConnect(false)
|
|
|
|
, _debugMode(false)
|
2018-11-02 15:57:10 +03:00
|
|
|
, _backgroundMode(false)
|
2011-02-17 02:21:45 +03:00
|
|
|
{
|
2015-09-28 23:51:16 +03:00
|
|
|
_startedAt.start();
|
|
|
|
|
2017-07-13 12:06:04 +03:00
|
|
|
qsrand(std::random_device()());
|
|
|
|
|
2016-08-05 13:36:21 +03:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
// Ensure OpenSSL config file is only loaded from app directory
|
|
|
|
QString opensslConf = QCoreApplication::applicationDirPath() + QString("/openssl.cnf");
|
|
|
|
qputenv("OPENSSL_CONF", opensslConf.toLocal8Bit());
|
2022-03-21 19:34:21 +03:00
|
|
|
|
|
|
|
// Set up event listener for Windows theme changing
|
|
|
|
installNativeEventFilter(new WindowsNativeEventFilter());
|
2016-08-05 13:36:21 +03:00
|
|
|
#endif
|
|
|
|
|
2015-10-05 07:21:19 +03:00
|
|
|
// TODO: Can't set this without breaking current config paths
|
2014-02-12 15:17:32 +04:00
|
|
|
// setOrganizationName(QLatin1String(APPLICATION_VENDOR));
|
|
|
|
setOrganizationDomain(QLatin1String(APPLICATION_REV_DOMAIN));
|
2019-09-26 13:36:05 +03:00
|
|
|
|
|
|
|
// setDesktopFilename to provide wayland compatibility (in general: conformance with naming standards)
|
|
|
|
// but only on Qt >= 5.7, where setDesktopFilename was introduced
|
|
|
|
#if (QT_VERSION >= 0x050700)
|
2019-09-30 10:45:41 +03:00
|
|
|
QString desktopFileName = QString(QLatin1String(LINUX_APPLICATION_ID)
|
2019-09-26 13:36:05 +03:00
|
|
|
+ QLatin1String(".desktop"));
|
|
|
|
setDesktopFileName(desktopFileName);
|
|
|
|
#endif
|
|
|
|
|
2017-12-06 17:29:07 +03:00
|
|
|
setApplicationName(_theme->appName());
|
2012-03-31 13:31:28 +04:00
|
|
|
setWindowIcon(_theme->applicationIcon());
|
2016-01-11 17:27:13 +03:00
|
|
|
|
2018-10-24 16:42:42 +03:00
|
|
|
if (!ConfigFile().exists()) {
|
2017-12-06 17:29:07 +03:00
|
|
|
// Migrate from version <= 2.4
|
|
|
|
setApplicationName(_theme->appNameGUI());
|
2017-12-14 17:10:33 +03:00
|
|
|
#ifndef QT_WARNING_DISABLE_DEPRECATED // Was added in Qt 5.9
|
|
|
|
#define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
|
|
|
|
#endif
|
|
|
|
QT_WARNING_PUSH
|
|
|
|
QT_WARNING_DISABLE_DEPRECATED
|
2022-12-27 19:27:09 +03:00
|
|
|
QString oldDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
2022-12-27 20:24:41 +03:00
|
|
|
|
|
|
|
// macOS 10.11.x does not like trailing slash for rename/move.
|
|
|
|
if (oldDir.endsWith('/')) {
|
|
|
|
oldDir.chop(1);
|
|
|
|
}
|
|
|
|
|
2017-12-14 17:10:33 +03:00
|
|
|
QT_WARNING_POP
|
2017-12-06 17:29:07 +03:00
|
|
|
setApplicationName(_theme->appName());
|
|
|
|
if (QFileInfo(oldDir).isDir()) {
|
2018-10-24 16:42:42 +03:00
|
|
|
auto confDir = ConfigFile().configPath();
|
2022-12-27 20:24:41 +03:00
|
|
|
|
|
|
|
// macOS 10.11.x does not like trailing slash for rename/move.
|
|
|
|
if (confDir.endsWith('/')) {
|
|
|
|
confDir.chop(1);
|
|
|
|
}
|
|
|
|
|
2017-12-06 17:29:07 +03:00
|
|
|
qCInfo(lcApplication) << "Migrating old config from" << oldDir << "to" << confDir;
|
2018-10-24 16:42:42 +03:00
|
|
|
|
2017-12-06 17:29:07 +03:00
|
|
|
if (!QFile::rename(oldDir, confDir)) {
|
2018-10-24 16:42:42 +03:00
|
|
|
qCWarning(lcApplication) << "Failed to move the old config directory to its new location (" << oldDir << "to" << confDir << ")";
|
|
|
|
|
|
|
|
// Try to move the files one by one
|
|
|
|
if (QFileInfo(confDir).isDir() || QDir().mkdir(confDir)) {
|
|
|
|
const QStringList filesList = QDir(oldDir).entryList(QDir::Files);
|
|
|
|
qCInfo(lcApplication) << "Will move the individual files" << filesList;
|
|
|
|
for (const auto &name : filesList) {
|
|
|
|
if (!QFile::rename(oldDir + "/" + name, confDir + "/" + name)) {
|
|
|
|
qCWarning(lcApplication) << "Fallback move of " << name << "also failed";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-06 17:29:07 +03:00
|
|
|
} else {
|
|
|
|
#ifndef Q_OS_WIN
|
|
|
|
// Create a symbolic link so a downgrade of the client would still find the config.
|
|
|
|
QFile::link(confDir, oldDir);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-28 18:35:28 +03:00
|
|
|
if (_theme->doNotUseProxy()) {
|
|
|
|
ConfigFile().setProxyType(QNetworkProxy::NoProxy);
|
|
|
|
}
|
|
|
|
|
2012-10-16 21:05:28 +04:00
|
|
|
parseOptions(arguments());
|
|
|
|
//no need to waste time;
|
2015-07-16 19:12:45 +03:00
|
|
|
if (_helpOnly || _versionOnly)
|
|
|
|
return;
|
2012-04-18 14:10:14 +04:00
|
|
|
|
2019-11-28 13:57:51 +03:00
|
|
|
if (_quitInstance) {
|
|
|
|
QTimer::singleShot(0, qApp, &QApplication::quit);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-10 15:46:00 +04:00
|
|
|
if (isRunning())
|
|
|
|
return;
|
|
|
|
|
2015-03-12 18:49:47 +03:00
|
|
|
#if defined(WITH_CRASHREPORTER)
|
2020-10-21 17:48:22 +03:00
|
|
|
if (ConfigFile().crashReporter()) {
|
|
|
|
auto reporter = QStringLiteral(CRASHREPORTER_EXECUTABLE);
|
|
|
|
#ifdef Q_OS_WIN
|
2020-10-22 13:10:24 +03:00
|
|
|
if (!reporter.endsWith(QLatin1String(".exe"))) {
|
2020-10-21 17:48:22 +03:00
|
|
|
reporter.append(QLatin1String(".exe"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
_crashHandler.reset(new CrashReporter::Handler(QDir::tempPath(), true, reporter));
|
|
|
|
}
|
2015-03-12 18:49:47 +03:00
|
|
|
#endif
|
|
|
|
|
2013-10-02 17:28:33 +04:00
|
|
|
setupLogging();
|
2013-08-15 15:02:27 +04:00
|
|
|
setupTranslations();
|
|
|
|
|
2018-05-14 15:37:48 +03:00
|
|
|
if (!configVersionMigration()) {
|
2018-05-02 16:40:54 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-05 20:11:09 +03:00
|
|
|
ConfigFile cfg;
|
2018-05-02 16:40:54 +03:00
|
|
|
// The timeout is initialized with an environment variable, if not, override with the value from the config
|
2017-12-05 20:11:09 +03:00
|
|
|
if (!AbstractNetworkJob::httpTimeout)
|
|
|
|
AbstractNetworkJob::httpTimeout = cfg.timeout();
|
|
|
|
|
2018-11-13 13:46:26 +03:00
|
|
|
// Check vfs plugins
|
|
|
|
if (Theme::instance()->showVirtualFilesOption() && bestAvailableVfsMode() == Vfs::Off) {
|
|
|
|
qCWarning(lcApplication) << "Theme wants to show vfs mode, but no vfs plugins are available";
|
|
|
|
}
|
|
|
|
if (isVfsPluginAvailable(Vfs::WindowsCfApi))
|
|
|
|
qCInfo(lcApplication) << "VFS windows plugin is available";
|
|
|
|
if (isVfsPluginAvailable(Vfs::WithSuffix))
|
|
|
|
qCInfo(lcApplication) << "VFS suffix plugin is available";
|
|
|
|
|
2015-01-08 18:52:23 +03:00
|
|
|
_folderManager.reset(new FolderMan);
|
2022-07-04 15:36:06 +03:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
_shellExtensionsServer.reset(new ShellExtensionsServer);
|
|
|
|
#endif
|
2015-01-08 18:52:23 +03:00
|
|
|
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(this, &SharedTools::QtSingleApplication::messageReceived, this, &Application::slotParseMessage);
|
2013-07-31 00:22:43 +04:00
|
|
|
|
2023-01-13 19:55:35 +03:00
|
|
|
if (!AccountManager::instance()->restore(cfg.overrideServerUrl().isEmpty())) {
|
2017-02-08 16:28:50 +03:00
|
|
|
// If there is an error reading the account settings, try again
|
|
|
|
// after a couple of seconds, if that fails, give up.
|
|
|
|
// (non-existence is not an error)
|
|
|
|
Utility::sleep(5);
|
2023-01-13 19:55:35 +03:00
|
|
|
if (!AccountManager::instance()->restore(cfg.overrideServerUrl().isEmpty())) {
|
2017-03-30 14:46:20 +03:00
|
|
|
qCCritical(lcApplication) << "Could not read the account settings, quitting";
|
2017-02-08 16:28:50 +03:00
|
|
|
QMessageBox::critical(
|
2018-11-11 12:56:22 +03:00
|
|
|
nullptr,
|
2017-02-08 16:28:50 +03:00
|
|
|
tr("Error accessing the configuration file"),
|
|
|
|
tr("There was an error while accessing the configuration "
|
2022-06-23 12:13:18 +03:00
|
|
|
"file at %1. Please make sure the file can be accessed by your system account.")
|
2017-02-08 16:28:50 +03:00
|
|
|
.arg(ConfigFile().configFile()),
|
2018-11-13 12:50:28 +03:00
|
|
|
tr("Quit %1").arg(Theme::instance()->appNameGUI()));
|
2017-02-08 16:28:50 +03:00
|
|
|
QTimer::singleShot(0, qApp, SLOT(quit()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2013-10-24 02:29:08 +04:00
|
|
|
|
2015-07-01 12:39:57 +03:00
|
|
|
FolderMan::instance()->setSyncEnabled(true);
|
2012-02-19 00:21:58 +04:00
|
|
|
|
2011-04-05 20:31:14 +04:00
|
|
|
setQuitOnLastWindowClosed(false);
|
|
|
|
|
2023-01-27 14:00:40 +03:00
|
|
|
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
|
|
|
|
connect(_theme, &Theme::systrayUseMonoIconsChanged, this, &Application::slotUseMonoIconsChanged);
|
|
|
|
|
2018-04-24 10:52:15 +03:00
|
|
|
// Setting up the gui class will allow tray notifications for the
|
|
|
|
// setup that follows, like folder setup
|
2013-11-18 12:34:57 +04:00
|
|
|
_gui = new ownCloudGui(this);
|
|
|
|
if (_showLogWindow) {
|
|
|
|
_gui->slotToggleLogBrowser(); // _showLogWindow is set in parseOptions.
|
|
|
|
}
|
2017-07-23 21:58:00 +03:00
|
|
|
#if WITH_LIBCLOUDPROVIDERS
|
|
|
|
_gui->setupCloudProviders();
|
|
|
|
#endif
|
2014-01-16 15:07:58 +04:00
|
|
|
|
2018-04-24 10:52:15 +03:00
|
|
|
FolderMan::instance()->setupFolders();
|
|
|
|
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
|
|
|
|
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(AccountManager::instance(), &AccountManager::accountAdded,
|
|
|
|
this, &Application::slotAccountStateAdded);
|
|
|
|
connect(AccountManager::instance(), &AccountManager::accountRemoved,
|
|
|
|
this, &Application::slotAccountStateRemoved);
|
2022-10-24 18:53:40 +03:00
|
|
|
const auto accounts = AccountManager::instance()->accounts();
|
|
|
|
for (const auto &ai : accounts) {
|
2015-04-17 18:56:17 +03:00
|
|
|
slotAccountStateAdded(ai.data());
|
2013-11-23 03:14:02 +04:00
|
|
|
}
|
2013-11-18 12:34:57 +04:00
|
|
|
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived,
|
|
|
|
_gui.data(), &ownCloudGui::slotShowShareDialog);
|
2014-09-03 18:12:21 +04:00
|
|
|
|
2021-08-20 16:17:06 +03:00
|
|
|
connect(FolderMan::instance()->socketApi(), &SocketApi::fileActivityCommandReceived,
|
2022-07-25 19:57:18 +03:00
|
|
|
_gui.data(), &ownCloudGui::slotShowFileActivityDialog);
|
2021-08-20 16:17:06 +03:00
|
|
|
|
2013-07-05 15:14:48 +04:00
|
|
|
// startup procedure.
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(&_checkConnectionTimer, &QTimer::timeout, this, &Application::slotCheckConnection);
|
2016-02-10 14:35:26 +03:00
|
|
|
_checkConnectionTimer.setInterval(ConnectionValidator::DefaultCallingIntervalMsec); // check for connection every 32 seconds.
|
2014-04-19 11:45:54 +04:00
|
|
|
_checkConnectionTimer.start();
|
2015-10-05 07:21:19 +03:00
|
|
|
// Also check immediately
|
2017-09-20 11:14:48 +03:00
|
|
|
QTimer::singleShot(0, this, &Application::slotCheckConnection);
|
2012-02-23 14:44:44 +04:00
|
|
|
|
2015-11-23 23:47:30 +03:00
|
|
|
// Can't use onlineStateChanged because it is always true on modern systems because of many interfaces
|
2017-09-20 12:48:13 +03:00
|
|
|
connect(&_networkConfigurationManager, &QNetworkConfigurationManager::configurationChanged,
|
|
|
|
this, &Application::slotSystemOnlineConfigurationChanged);
|
2015-11-23 23:47:30 +03:00
|
|
|
|
2020-03-09 03:48:07 +03:00
|
|
|
#if defined(BUILD_UPDATER)
|
2015-06-03 10:04:12 +03:00
|
|
|
// Update checks
|
2020-05-27 21:23:36 +03:00
|
|
|
auto *updaterScheduler = new UpdaterScheduler(this);
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(updaterScheduler, &UpdaterScheduler::updaterAnnouncement,
|
2022-05-10 17:12:15 +03:00
|
|
|
_gui.data(), &ownCloudGui::slotShowTrayUpdateMessage);
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(updaterScheduler, &UpdaterScheduler::requestRestart,
|
|
|
|
_folderManager.data(), &FolderMan::slotScheduleAppRestart);
|
2020-03-09 03:48:07 +03:00
|
|
|
#endif
|
2012-04-02 22:10:29 +04:00
|
|
|
|
2015-07-20 13:10:54 +03:00
|
|
|
// Cleanup at Quit.
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(this, &QCoreApplication::aboutToQuit, this, &Application::slotCleanup);
|
2019-12-21 05:04:31 +03:00
|
|
|
|
|
|
|
// Allow other classes to hook into isShowingSettingsDialog() signals (re-auth widgets, for example)
|
|
|
|
connect(_gui.data(), &ownCloudGui::isShowingSettingsDialog, this, &Application::slotGuiIsShowingSettings);
|
2020-01-12 23:19:18 +03:00
|
|
|
|
|
|
|
_gui->createTray();
|
2022-07-19 13:05:20 +03:00
|
|
|
|
|
|
|
handleEditLocallyFromOptions();
|
2022-12-23 17:24:19 +03:00
|
|
|
|
2022-12-30 16:45:47 +03:00
|
|
|
if (AccountSetupCommandLineManager::instance()->isCommandLineParsed()) {
|
|
|
|
AccountSetupCommandLineManager::instance()->setupAccountFromCommandLine();
|
2022-12-23 17:24:19 +03:00
|
|
|
}
|
2022-12-30 16:45:47 +03:00
|
|
|
AccountSetupCommandLineManager::destroy();
|
2011-02-17 02:21:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Application::~Application()
|
|
|
|
{
|
2015-09-18 12:58:10 +03:00
|
|
|
// Make sure all folders are gone, otherwise removing the
|
|
|
|
// accounts will remove the associated folders from the settings.
|
2015-09-30 12:40:33 +03:00
|
|
|
if (_folderManager) {
|
|
|
|
_folderManager->unloadAndDeleteAllFolders();
|
|
|
|
}
|
2015-09-18 12:58:10 +03:00
|
|
|
|
2015-03-27 12:30:35 +03:00
|
|
|
// Remove the account from the account manager so it can be deleted.
|
2019-10-09 08:07:00 +03:00
|
|
|
disconnect(AccountManager::instance(), &AccountManager::accountRemoved,
|
|
|
|
this, &Application::slotAccountStateRemoved);
|
2015-04-17 18:56:17 +03:00
|
|
|
AccountManager::instance()->shutdown();
|
2012-03-29 11:41:30 +04:00
|
|
|
}
|
|
|
|
|
2014-12-17 16:09:57 +03:00
|
|
|
void Application::slotAccountStateRemoved(AccountState *accountState)
|
2013-11-23 03:14:02 +04:00
|
|
|
{
|
2015-04-23 15:24:54 +03:00
|
|
|
if (_gui) {
|
2017-09-20 11:14:48 +03:00
|
|
|
disconnect(accountState, &AccountState::stateChanged,
|
|
|
|
_gui.data(), &ownCloudGui::slotAccountStateChanged);
|
|
|
|
disconnect(accountState->account().data(), &Account::serverVersionChanged,
|
|
|
|
_gui.data(), &ownCloudGui::slotTrayMessageIfServerUnsupported);
|
2015-07-01 12:39:57 +03:00
|
|
|
}
|
|
|
|
if (_folderManager) {
|
2017-09-20 11:14:48 +03:00
|
|
|
disconnect(accountState, &AccountState::stateChanged,
|
|
|
|
_folderManager.data(), &FolderMan::slotAccountStateChanged);
|
|
|
|
disconnect(accountState->account().data(), &Account::serverVersionChanged,
|
|
|
|
_folderManager.data(), &FolderMan::slotServerVersionChanged);
|
2015-04-23 15:24:54 +03:00
|
|
|
}
|
2015-12-01 18:30:57 +03:00
|
|
|
|
|
|
|
// if there is no more account, show the wizard.
|
2020-07-03 11:02:53 +03:00
|
|
|
if (_gui && AccountManager::instance()->accounts().isEmpty()) {
|
2015-12-01 18:30:57 +03:00
|
|
|
// allow to add a new account if there is non any more. Always think
|
|
|
|
// about single account theming!
|
|
|
|
OwncloudSetupWizard::runWizard(this, SLOT(slotownCloudWizardDone(int)));
|
|
|
|
}
|
2013-11-23 03:14:02 +04:00
|
|
|
}
|
|
|
|
|
2014-12-17 16:09:57 +03:00
|
|
|
void Application::slotAccountStateAdded(AccountState *accountState)
|
|
|
|
{
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(accountState, &AccountState::stateChanged,
|
|
|
|
_gui.data(), &ownCloudGui::slotAccountStateChanged);
|
|
|
|
connect(accountState->account().data(), &Account::serverVersionChanged,
|
|
|
|
_gui.data(), &ownCloudGui::slotTrayMessageIfServerUnsupported);
|
|
|
|
connect(accountState, &AccountState::stateChanged,
|
|
|
|
_folderManager.data(), &FolderMan::slotAccountStateChanged);
|
|
|
|
connect(accountState->account().data(), &Account::serverVersionChanged,
|
|
|
|
_folderManager.data(), &FolderMan::slotServerVersionChanged);
|
2016-03-02 13:59:36 +03:00
|
|
|
|
|
|
|
_gui->slotTrayMessageIfServerUnsupported(accountState->account().data());
|
2014-12-17 16:09:57 +03:00
|
|
|
}
|
2013-11-23 03:14:02 +04:00
|
|
|
|
2013-10-01 15:52:07 +04:00
|
|
|
void Application::slotCleanup()
|
|
|
|
{
|
2015-04-09 17:19:17 +03:00
|
|
|
AccountManager::instance()->save();
|
2015-02-27 12:42:59 +03:00
|
|
|
FolderMan::instance()->unloadAndDeleteAllFolders();
|
2014-08-20 18:27:44 +04:00
|
|
|
|
2013-10-02 17:28:33 +04:00
|
|
|
_gui->slotShutdown();
|
2013-10-01 15:52:07 +04:00
|
|
|
_gui->deleteLater();
|
|
|
|
}
|
|
|
|
|
2015-11-23 23:47:30 +03:00
|
|
|
// FIXME: This is not ideal yet since a ConnectionValidator might already be running and is in
|
|
|
|
// progress of timing out in some seconds.
|
|
|
|
// Maybe we need 2 validators, one triggered by timer, one by network configuration changes?
|
|
|
|
void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
|
|
|
{
|
|
|
|
if (cnf.state() & QNetworkConfiguration::Active) {
|
2022-04-13 00:43:19 +03:00
|
|
|
const auto list = AccountManager::instance()->accounts();
|
|
|
|
for (const auto &accountState : list) {
|
|
|
|
accountState->systemOnlineConfigurationChanged();
|
|
|
|
}
|
2015-11-23 23:47:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-05 15:14:48 +04:00
|
|
|
void Application::slotCheckConnection()
|
2013-07-29 16:28:19 +04:00
|
|
|
{
|
2022-04-13 00:43:19 +03:00
|
|
|
if (AccountManager::instance()->accounts().isEmpty()) {
|
2013-11-29 19:12:58 +04:00
|
|
|
// let gui open the setup wizard
|
2015-09-02 12:10:01 +03:00
|
|
|
_gui->slotOpenSettingsDialog();
|
2014-05-27 13:04:16 +04:00
|
|
|
|
|
|
|
_checkConnectionTimer.stop(); // don't popup the wizard on interval;
|
2013-07-29 16:28:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-26 17:46:24 +04:00
|
|
|
void Application::slotCrash()
|
|
|
|
{
|
|
|
|
Utility::crash();
|
|
|
|
}
|
|
|
|
|
2012-11-28 22:25:12 +04:00
|
|
|
void Application::slotownCloudWizardDone(int res)
|
|
|
|
{
|
2013-07-22 15:59:52 +04:00
|
|
|
FolderMan *folderMan = FolderMan::instance();
|
2015-12-08 16:37:37 +03:00
|
|
|
|
|
|
|
// During the wizard, scheduling of new syncs is disabled
|
|
|
|
folderMan->setSyncEnabled(true);
|
|
|
|
|
2012-11-28 22:25:12 +04:00
|
|
|
if (res == QDialog::Accepted) {
|
2015-12-08 16:37:37 +03:00
|
|
|
// Check connectivity of the newly created account
|
2014-05-27 13:04:16 +04:00
|
|
|
_checkConnectionTimer.start();
|
2013-07-05 15:14:48 +04:00
|
|
|
slotCheckConnection();
|
|
|
|
|
2016-10-11 21:28:14 +03:00
|
|
|
// If one account is configured: enable autostart
|
2021-02-17 15:30:10 +03:00
|
|
|
#ifndef QT_DEBUG
|
2021-07-23 18:41:02 +03:00
|
|
|
bool shouldSetAutoStart = AccountManager::instance()->accounts().size() == 1;
|
2021-02-17 15:30:10 +03:00
|
|
|
#else
|
|
|
|
bool shouldSetAutoStart = false;
|
|
|
|
#endif
|
2016-10-11 21:28:14 +03:00
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
// Don't auto start when not being 'installed'
|
|
|
|
shouldSetAutoStart = shouldSetAutoStart
|
|
|
|
&& QCoreApplication::applicationDirPath().startsWith("/Applications/");
|
|
|
|
#endif
|
2018-02-20 13:03:46 +03:00
|
|
|
if (shouldSetAutoStart) {
|
|
|
|
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), true);
|
|
|
|
}
|
2017-04-26 19:31:12 +03:00
|
|
|
|
2020-01-11 19:34:56 +03:00
|
|
|
Systray::instance()->showWindow();
|
2015-12-08 16:37:37 +03:00
|
|
|
}
|
2012-11-28 22:25:12 +04:00
|
|
|
}
|
|
|
|
|
2013-10-02 17:28:33 +04:00
|
|
|
void Application::setupLogging()
|
2012-06-05 17:49:53 +04:00
|
|
|
{
|
2012-10-16 21:05:28 +04:00
|
|
|
// might be called from second instance
|
2018-04-10 14:07:20 +03:00
|
|
|
auto logger = Logger::instance();
|
|
|
|
logger->setLogFile(_logFile);
|
2020-10-05 20:34:46 +03:00
|
|
|
if (_logFile.isEmpty()) {
|
|
|
|
logger->setLogDir(_logDir.isEmpty() ? ConfigFile().logDir() : _logDir);
|
|
|
|
}
|
2020-07-01 17:03:45 +03:00
|
|
|
logger->setLogExpire(_logExpire > 0 ? _logExpire : ConfigFile().logExpire());
|
2020-07-01 17:10:10 +03:00
|
|
|
logger->setLogFlush(_logFlush || ConfigFile().logFlush());
|
2020-07-01 16:56:23 +03:00
|
|
|
logger->setLogDebug(_logDebug || ConfigFile().logDebug());
|
2018-04-10 14:07:20 +03:00
|
|
|
if (!logger->isLoggingToFile() && ConfigFile().automaticLogDir()) {
|
|
|
|
logger->setupTemporaryFolderLogDir();
|
|
|
|
}
|
2012-06-05 17:49:53 +04:00
|
|
|
|
2018-04-10 14:07:20 +03:00
|
|
|
logger->enterNextLogFile();
|
2012-06-15 15:04:23 +04:00
|
|
|
|
2021-02-16 11:56:16 +03:00
|
|
|
qCInfo(lcApplication) << "##################" << _theme->appName()
|
|
|
|
<< "locale:" << QLocale::system().name()
|
|
|
|
<< "ui_lang:" << property("ui_lang")
|
|
|
|
<< "version:" << _theme->version()
|
|
|
|
<< "os:" << Utility::platformName();
|
|
|
|
qCInfo(lcApplication) << "Arguments:" << qApp->arguments();
|
2012-06-05 17:49:53 +04:00
|
|
|
}
|
2012-07-31 12:17:52 +04:00
|
|
|
|
2023-01-27 14:00:40 +03:00
|
|
|
void Application::slotUseMonoIconsChanged(bool)
|
|
|
|
{
|
|
|
|
_gui->slotComputeOverallSyncStatus();
|
|
|
|
}
|
|
|
|
|
2015-02-19 18:54:34 +03:00
|
|
|
void Application::slotParseMessage(const QString &msg, QObject *)
|
2012-10-16 21:05:28 +04:00
|
|
|
{
|
2015-02-19 18:54:34 +03:00
|
|
|
if (msg.startsWith(QLatin1String("MSG_PARSEOPTIONS:"))) {
|
|
|
|
const int lengthOfMsgPrefix = 17;
|
|
|
|
QStringList options = msg.mid(lengthOfMsgPrefix).split(QLatin1Char('|'));
|
2018-12-03 13:20:46 +03:00
|
|
|
_showLogWindow = false;
|
2015-02-19 18:54:34 +03:00
|
|
|
parseOptions(options);
|
|
|
|
setupLogging();
|
2018-12-03 13:20:46 +03:00
|
|
|
if (_showLogWindow) {
|
|
|
|
_gui->slotToggleLogBrowser(); // _showLogWindow is set in parseOptions.
|
|
|
|
}
|
2019-11-28 13:57:51 +03:00
|
|
|
if (_quitInstance) {
|
|
|
|
qApp->quit();
|
|
|
|
}
|
|
|
|
|
2022-07-19 13:05:20 +03:00
|
|
|
handleEditLocallyFromOptions();
|
|
|
|
|
2022-12-30 16:45:47 +03:00
|
|
|
if (AccountSetupCommandLineManager::instance()->isCommandLineParsed()) {
|
|
|
|
AccountSetupCommandLineManager::instance()->setupAccountFromCommandLine();
|
2022-12-29 14:50:17 +03:00
|
|
|
}
|
2022-12-30 16:45:47 +03:00
|
|
|
AccountSetupCommandLineManager::destroy();
|
2022-12-29 14:50:17 +03:00
|
|
|
|
2020-06-16 19:59:16 +03:00
|
|
|
} else if (msg.startsWith(QLatin1String("MSG_SHOWMAINDIALOG"))) {
|
2017-03-30 14:46:20 +03:00
|
|
|
qCInfo(lcApplication) << "Running for" << _startedAt.elapsed() / 1000.0 << "sec";
|
2015-10-15 15:19:46 +03:00
|
|
|
if (_startedAt.elapsed() < 10 * 1000) {
|
2015-09-28 23:51:16 +03:00
|
|
|
// This call is mirrored with the one in int main()
|
2020-06-16 19:59:16 +03:00
|
|
|
qCWarning(lcApplication) << "Ignoring MSG_SHOWMAINDIALOG, possibly double-invocation of client via session restore and auto start";
|
2015-09-28 23:51:16 +03:00
|
|
|
return;
|
|
|
|
}
|
2021-06-21 14:33:22 +03:00
|
|
|
|
|
|
|
// Show the main dialog only if there is at least one account configured
|
|
|
|
if (!AccountManager::instance()->accounts().isEmpty()) {
|
|
|
|
showMainDialog();
|
|
|
|
} else {
|
|
|
|
_gui->slotNewAccountWizard();
|
|
|
|
}
|
2015-02-19 18:54:34 +03:00
|
|
|
}
|
2012-01-24 01:10:01 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 21:05:28 +04:00
|
|
|
void Application::parseOptions(const QStringList &options)
|
|
|
|
{
|
|
|
|
QStringListIterator it(options);
|
|
|
|
// skip file name;
|
|
|
|
if (it.hasNext())
|
|
|
|
it.next();
|
|
|
|
|
2023-01-13 19:55:35 +03:00
|
|
|
bool shouldExit = false;
|
|
|
|
|
2013-01-29 08:19:14 +04:00
|
|
|
//parse options; if help or bad option exit
|
2012-10-16 21:05:28 +04:00
|
|
|
while (it.hasNext()) {
|
|
|
|
QString option = it.next();
|
2013-07-29 16:28:19 +04:00
|
|
|
if (option == QLatin1String("--help") || option == QLatin1String("-h")) {
|
2013-01-29 08:19:14 +04:00
|
|
|
setHelp();
|
|
|
|
break;
|
2019-11-28 13:57:51 +03:00
|
|
|
} else if (option == QLatin1String("--quit") || option == QLatin1String("-q")) {
|
|
|
|
_quitInstance = true;
|
2012-10-16 21:05:28 +04:00
|
|
|
} else if (option == QLatin1String("--logwindow") || option == QLatin1String("-l")) {
|
|
|
|
_showLogWindow = true;
|
|
|
|
} else if (option == QLatin1String("--logfile")) {
|
|
|
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
2013-10-02 17:28:33 +04:00
|
|
|
_logFile = it.next();
|
2012-10-16 21:05:28 +04:00
|
|
|
} else {
|
2015-07-03 17:01:24 +03:00
|
|
|
showHint("Log file not specified");
|
2012-10-16 21:05:28 +04:00
|
|
|
}
|
2013-06-03 18:23:29 +04:00
|
|
|
} else if (option == QLatin1String("--logdir")) {
|
|
|
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
2013-10-02 17:28:33 +04:00
|
|
|
_logDir = it.next();
|
2013-06-03 18:23:29 +04:00
|
|
|
} else {
|
2015-07-03 17:01:24 +03:00
|
|
|
showHint("Log dir not specified");
|
2013-06-03 18:23:29 +04:00
|
|
|
}
|
2013-06-07 20:57:45 +04:00
|
|
|
} else if (option == QLatin1String("--logexpire")) {
|
|
|
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
|
|
|
_logExpire = it.next().toInt();
|
|
|
|
} else {
|
2015-07-03 17:01:24 +03:00
|
|
|
showHint("Log expiration not specified");
|
2013-06-07 20:57:45 +04:00
|
|
|
}
|
2012-10-16 21:05:28 +04:00
|
|
|
} else if (option == QLatin1String("--logflush")) {
|
|
|
|
_logFlush = true;
|
2017-05-09 18:04:04 +03:00
|
|
|
} else if (option == QLatin1String("--logdebug")) {
|
|
|
|
_logDebug = true;
|
2013-01-02 21:43:40 +04:00
|
|
|
} else if (option == QLatin1String("--confdir")) {
|
|
|
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
2013-04-03 16:42:13 +04:00
|
|
|
QString confDir = it.next();
|
2015-03-23 16:59:29 +03:00
|
|
|
if (!ConfigFile::setConfDir(confDir)) {
|
2015-07-03 17:01:24 +03:00
|
|
|
showHint("Invalid path passed to --confdir");
|
2015-03-23 16:59:29 +03:00
|
|
|
}
|
2013-01-02 21:43:40 +04:00
|
|
|
} else {
|
2015-07-03 17:01:24 +03:00
|
|
|
showHint("Path for confdir not specified");
|
2013-01-02 21:43:40 +04:00
|
|
|
}
|
2014-08-26 17:46:24 +04:00
|
|
|
} else if (option == QLatin1String("--debug")) {
|
2017-05-22 18:54:57 +03:00
|
|
|
_logDebug = true;
|
2014-08-26 17:46:24 +04:00
|
|
|
_debugMode = true;
|
2018-11-02 15:57:10 +03:00
|
|
|
} else if (option == QLatin1String("--background")) {
|
|
|
|
_backgroundMode = true;
|
2020-06-06 21:04:48 +03:00
|
|
|
} else if (option == QLatin1String("--version") || option == QLatin1String("-v")) {
|
2015-07-16 19:12:45 +03:00
|
|
|
_versionOnly = true;
|
2018-05-18 09:29:40 +03:00
|
|
|
} else if (option.endsWith(QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX))) {
|
|
|
|
// virtual file, open it after the Folder were created (if the app is not terminated)
|
|
|
|
QTimer::singleShot(0, this, [this, option] { openVirtualFile(option); });
|
2022-07-19 13:05:20 +03:00
|
|
|
} else if (option.startsWith(QStringLiteral(APPLICATION_URI_HANDLER_SCHEME "://open"))) {
|
|
|
|
// see the section Local file editing of the Architecture page of the user documenation
|
|
|
|
_editFileLocallyUrl = QUrl::fromUserInput(option);
|
|
|
|
if (!_editFileLocallyUrl.isValid()) {
|
|
|
|
_editFileLocallyUrl.clear();
|
|
|
|
const auto errorParsingLocalFileEditingUrl = QStringLiteral("The supplied url for local file editing '%1' is invalid!").arg(option);
|
|
|
|
qCInfo(lcApplication) << errorParsingLocalFileEditingUrl;
|
|
|
|
showHint(errorParsingLocalFileEditingUrl.toStdString());
|
|
|
|
}
|
2023-01-13 19:55:35 +03:00
|
|
|
} else if (option == QStringLiteral("--overrideserverurl")) {
|
|
|
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
|
|
|
const auto overrideUrl = it.next();
|
|
|
|
const auto isUrlValid = (overrideUrl.startsWith(QStringLiteral("http://")) || overrideUrl.startsWith(QStringLiteral("https://")))
|
|
|
|
&& QUrl::fromUserInput(overrideUrl).isValid();
|
|
|
|
if (!isUrlValid) {
|
|
|
|
showHint("Invalid URL passed to --overrideserverurl");
|
|
|
|
} else {
|
|
|
|
ConfigFile().setOverrideServerUrl(overrideUrl);
|
|
|
|
shouldExit = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
showHint("Invalid URL passed to --overrideserverurl");
|
|
|
|
}
|
|
|
|
} else if (option == QStringLiteral("--overridelocaldir")) {
|
|
|
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
|
|
|
ConfigFile().setOverrideLocalDir(it.next());
|
|
|
|
} else {
|
|
|
|
showHint("Invalid URL passed to --overridelocaldir");
|
|
|
|
}
|
2022-12-29 14:50:17 +03:00
|
|
|
}
|
2022-07-19 13:05:20 +03:00
|
|
|
else {
|
2022-12-29 14:50:17 +03:00
|
|
|
QString errorMessage;
|
2022-12-30 16:45:47 +03:00
|
|
|
if (!AccountSetupCommandLineManager::instance()->parseCommandlineOption(option, it, errorMessage)) {
|
2022-12-29 14:50:17 +03:00
|
|
|
if (!errorMessage.isEmpty()) {
|
|
|
|
showHint(errorMessage.toStdString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
showHint("Unrecognized option '" + option.toStdString() + "'");
|
|
|
|
}
|
2012-10-16 21:05:28 +04:00
|
|
|
}
|
2013-10-02 17:28:33 +04:00
|
|
|
}
|
2023-01-13 19:55:35 +03:00
|
|
|
if (shouldExit) {
|
|
|
|
std::exit(0);
|
|
|
|
}
|
2012-10-16 21:05:28 +04:00
|
|
|
}
|
|
|
|
|
2013-06-06 18:00:51 +04:00
|
|
|
// Helpers for displaying messages. Note that there is no console on Windows.
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
// Format as <pre> HTML
|
|
|
|
static inline void toHtml(QString &t)
|
|
|
|
{
|
|
|
|
t.replace(QLatin1Char('&'), QLatin1String("&"));
|
|
|
|
t.replace(QLatin1Char('<'), QLatin1String("<"));
|
|
|
|
t.replace(QLatin1Char('>'), QLatin1String(">"));
|
|
|
|
t.insert(0, QLatin1String("<html><pre>"));
|
|
|
|
t.append(QLatin1String("</pre></html>"));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void displayHelpText(QString t) // No console on Windows.
|
|
|
|
{
|
|
|
|
toHtml(t);
|
|
|
|
QMessageBox::information(0, Theme::instance()->appNameGUI(), t);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
static void displayHelpText(const QString &t)
|
|
|
|
{
|
2017-09-27 13:03:16 +03:00
|
|
|
std::cout << qUtf8Printable(t);
|
2013-06-06 18:00:51 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-06-15 15:36:38 +04:00
|
|
|
void Application::showHelp()
|
|
|
|
{
|
2013-06-06 18:00:51 +04:00
|
|
|
setHelp();
|
|
|
|
QString helpText;
|
|
|
|
QTextStream stream(&helpText);
|
2017-09-27 13:03:16 +03:00
|
|
|
stream << _theme->appName()
|
2013-06-06 18:00:51 +04:00
|
|
|
<< QLatin1String(" version ")
|
2017-09-27 13:03:16 +03:00
|
|
|
<< _theme->version() << endl;
|
2013-06-06 18:00:51 +04:00
|
|
|
|
|
|
|
stream << QLatin1String("File synchronisation desktop utility.") << endl
|
|
|
|
<< endl
|
|
|
|
<< QLatin1String(optionsC);
|
|
|
|
|
2012-09-24 19:55:10 +04:00
|
|
|
if (_theme->appName() == QLatin1String("ownCloud"))
|
2013-10-02 17:28:33 +04:00
|
|
|
stream << endl
|
|
|
|
<< "For more information, see http://www.owncloud.org" << endl
|
|
|
|
<< endl;
|
2013-06-06 18:00:51 +04:00
|
|
|
|
|
|
|
displayHelpText(helpText);
|
2013-01-29 08:19:14 +04:00
|
|
|
}
|
|
|
|
|
2015-07-16 19:12:45 +03:00
|
|
|
void Application::showVersion()
|
|
|
|
{
|
2017-09-22 11:16:26 +03:00
|
|
|
displayHelpText(Theme::instance()->versionSwitchOutput());
|
2015-07-16 19:12:45 +03:00
|
|
|
}
|
|
|
|
|
2015-07-03 17:01:24 +03:00
|
|
|
void Application::showHint(std::string errorHint)
|
|
|
|
{
|
|
|
|
static QString binName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
|
|
|
|
std::cerr << errorHint << std::endl;
|
|
|
|
std::cerr << "Try '" << binName.toStdString() << " --help' for more information" << std::endl;
|
|
|
|
std::exit(1);
|
|
|
|
}
|
|
|
|
|
2014-08-26 17:46:24 +04:00
|
|
|
bool Application::debugMode()
|
|
|
|
{
|
|
|
|
return _debugMode;
|
|
|
|
}
|
|
|
|
|
2018-11-02 15:57:10 +03:00
|
|
|
bool Application::backgroundMode() const
|
|
|
|
{
|
|
|
|
return _backgroundMode;
|
|
|
|
}
|
|
|
|
|
2013-01-29 08:19:14 +04:00
|
|
|
void Application::setHelp()
|
|
|
|
{
|
2012-06-15 15:36:38 +04:00
|
|
|
_helpOnly = true;
|
|
|
|
}
|
|
|
|
|
2022-07-19 13:05:20 +03:00
|
|
|
void Application::handleEditLocallyFromOptions()
|
|
|
|
{
|
|
|
|
if (!_editFileLocallyUrl.isValid()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-28 20:40:06 +03:00
|
|
|
EditLocallyManager::instance()->editLocally(_editFileLocallyUrl);
|
2022-07-19 13:05:20 +03:00
|
|
|
_editFileLocallyUrl.clear();
|
|
|
|
}
|
|
|
|
|
2013-02-24 18:22:21 +04:00
|
|
|
QString substLang(const QString &lang)
|
|
|
|
{
|
2015-10-05 07:21:19 +03:00
|
|
|
// Map the more appropriate script codes
|
2013-02-24 18:22:21 +04:00
|
|
|
// to country codes as used by Qt and
|
|
|
|
// transifex translation conventions.
|
|
|
|
|
|
|
|
// Simplified Chinese
|
|
|
|
if (lang == QLatin1String("zh_Hans"))
|
|
|
|
return QLatin1String("zh_CN");
|
|
|
|
// Traditional Chinese
|
|
|
|
if (lang == QLatin1String("zh_Hant"))
|
|
|
|
return QLatin1String("zh_TW");
|
|
|
|
return lang;
|
|
|
|
}
|
|
|
|
|
2013-02-14 21:27:44 +04:00
|
|
|
void Application::setupTranslations()
|
|
|
|
{
|
|
|
|
QStringList uiLanguages;
|
|
|
|
// uiLanguages crashes on Windows with 4.8.0 release builds
|
|
|
|
#if (QT_VERSION >= 0x040801) || (QT_VERSION >= 0x040800 && !defined(Q_OS_WIN))
|
|
|
|
uiLanguages = QLocale::system().uiLanguages();
|
|
|
|
#else
|
|
|
|
// older versions need to fall back to the systems locale
|
|
|
|
uiLanguages << QLocale::system().name();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
QString enforcedLocale = Theme::instance()->enforcedLocale();
|
|
|
|
if (!enforcedLocale.isEmpty())
|
|
|
|
uiLanguages.prepend(enforcedLocale);
|
|
|
|
|
2020-05-18 21:54:23 +03:00
|
|
|
auto *translator = new QTranslator(this);
|
|
|
|
auto *qtTranslator = new QTranslator(this);
|
|
|
|
auto *qtkeychainTranslator = new QTranslator(this);
|
2013-02-14 21:27:44 +04:00
|
|
|
|
2020-09-27 14:11:22 +03:00
|
|
|
for (QString lang : qAsConst(uiLanguages)) {
|
2013-02-14 21:27:44 +04:00
|
|
|
lang.replace(QLatin1Char('-'), QLatin1Char('_')); // work around QTBUG-25973
|
2013-02-24 18:22:21 +04:00
|
|
|
lang = substLang(lang);
|
2013-02-14 21:27:44 +04:00
|
|
|
const QString trPath = applicationTrPath();
|
2015-02-06 17:15:33 +03:00
|
|
|
const QString trFile = QLatin1String("client_") + lang;
|
2013-02-24 18:20:59 +04:00
|
|
|
if (translator->load(trFile, trPath) || lang.startsWith(QLatin1String("en"))) {
|
|
|
|
// Permissive approach: Qt and keychain translations
|
|
|
|
// may be missing, but Qt translations must be there in order
|
|
|
|
// for us to accept the language. Otherwise, we try with the next.
|
2015-10-05 07:21:19 +03:00
|
|
|
// "en" is an exception as it is the default language and may not
|
2013-02-24 18:20:59 +04:00
|
|
|
// have a translation file provided.
|
2017-03-30 14:46:20 +03:00
|
|
|
qCInfo(lcApplication) << "Using" << lang << "translation";
|
2013-02-24 18:20:59 +04:00
|
|
|
setProperty("ui_lang", lang);
|
2013-02-14 21:27:44 +04:00
|
|
|
const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
|
|
|
const QString qtTrFile = QLatin1String("qt_") + lang;
|
2014-10-15 19:10:41 +04:00
|
|
|
const QString qtBaseTrFile = QLatin1String("qtbase_") + lang;
|
2014-10-15 11:32:44 +04:00
|
|
|
if (!qtTranslator->load(qtTrFile, qtTrPath)) {
|
2014-10-15 19:10:41 +04:00
|
|
|
if (!qtTranslator->load(qtTrFile, trPath)) {
|
2016-01-04 13:47:11 +03:00
|
|
|
if (!qtTranslator->load(qtBaseTrFile, qtTrPath)) {
|
|
|
|
qtTranslator->load(qtBaseTrFile, trPath);
|
|
|
|
}
|
2014-10-15 19:10:41 +04:00
|
|
|
}
|
2013-02-24 18:20:59 +04:00
|
|
|
}
|
2014-10-15 19:10:41 +04:00
|
|
|
const QString qtkeychainTrFile = QLatin1String("qtkeychain_") + lang;
|
|
|
|
if (!qtkeychainTranslator->load(qtkeychainTrFile, qtTrPath)) {
|
|
|
|
qtkeychainTranslator->load(qtkeychainTrFile, trPath);
|
2013-02-24 18:20:59 +04:00
|
|
|
}
|
|
|
|
if (!translator->isEmpty())
|
2013-02-14 21:27:44 +04:00
|
|
|
installTranslator(translator);
|
2013-02-24 18:20:59 +04:00
|
|
|
if (!qtTranslator->isEmpty())
|
2013-02-14 21:27:44 +04:00
|
|
|
installTranslator(qtTranslator);
|
2013-02-24 18:20:59 +04:00
|
|
|
if (!qtkeychainTranslator->isEmpty())
|
|
|
|
installTranslator(qtkeychainTranslator);
|
2013-02-21 18:16:02 +04:00
|
|
|
break;
|
2013-02-14 21:27:44 +04:00
|
|
|
}
|
|
|
|
if (property("ui_lang").isNull())
|
|
|
|
setProperty("ui_lang", "C");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-15 15:36:38 +04:00
|
|
|
bool Application::giveHelp()
|
|
|
|
{
|
|
|
|
return _helpOnly;
|
|
|
|
}
|
2015-01-26 15:00:45 +03:00
|
|
|
|
2015-07-16 19:12:45 +03:00
|
|
|
bool Application::versionOnly()
|
|
|
|
{
|
|
|
|
return _versionOnly;
|
|
|
|
}
|
|
|
|
|
2020-06-16 19:59:16 +03:00
|
|
|
void Application::showMainDialog()
|
2015-01-26 15:00:45 +03:00
|
|
|
{
|
2020-06-16 19:59:16 +03:00
|
|
|
_gui->slotOpenMainDialog();
|
2015-01-26 15:00:45 +03:00
|
|
|
}
|
|
|
|
|
2019-12-21 05:04:31 +03:00
|
|
|
void Application::slotGuiIsShowingSettings()
|
|
|
|
{
|
|
|
|
emit isShowingSettingsDialog();
|
|
|
|
}
|
2015-01-26 15:00:45 +03:00
|
|
|
|
2018-05-18 09:29:40 +03:00
|
|
|
void Application::openVirtualFile(const QString &filename)
|
2018-01-15 18:46:52 +03:00
|
|
|
{
|
2018-05-18 09:29:40 +03:00
|
|
|
QString virtualFileExt = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX);
|
|
|
|
if (!filename.endsWith(virtualFileExt)) {
|
2018-01-15 18:46:52 +03:00
|
|
|
qWarning(lcApplication) << "Can only handle file ending in .owncloud. Unable to open" << filename;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto folder = FolderMan::instance()->folderForPath(filename);
|
|
|
|
if (!folder) {
|
|
|
|
qWarning(lcApplication) << "Can't find sync folder for" << filename;
|
|
|
|
// TODO: show a QMessageBox for errors
|
|
|
|
return;
|
|
|
|
}
|
2018-01-25 18:25:11 +03:00
|
|
|
QString relativePath = QDir::cleanPath(filename).mid(folder->cleanPath().length() + 1);
|
2019-04-03 14:32:05 +03:00
|
|
|
folder->implicitlyHydrateFile(relativePath);
|
2018-05-18 09:29:40 +03:00
|
|
|
QString normalName = filename.left(filename.size() - virtualFileExt.size());
|
2018-01-15 18:46:52 +03:00
|
|
|
auto con = QSharedPointer<QMetaObject::Connection>::create();
|
2020-07-14 13:49:18 +03:00
|
|
|
*con = connect(folder, &Folder::syncFinished, folder, [folder, con, normalName] {
|
|
|
|
folder->disconnect(*con);
|
2018-01-15 18:46:52 +03:00
|
|
|
if (QFile::exists(normalName)) {
|
|
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(normalName));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-06 12:55:45 +03:00
|
|
|
void Application::tryTrayAgain()
|
|
|
|
{
|
|
|
|
qCInfo(lcApplication) << "Trying tray icon, tray available:" << QSystemTrayIcon::isSystemTrayAvailable();
|
|
|
|
_gui->hideAndShowTray();
|
|
|
|
}
|
|
|
|
|
2018-04-19 14:34:02 +03:00
|
|
|
bool Application::event(QEvent *event)
|
|
|
|
{
|
|
|
|
if (event->type() == QEvent::FileOpen) {
|
2022-09-30 22:36:58 +03:00
|
|
|
const auto openEvent = dynamic_cast<QFileOpenEvent *>(event);
|
2022-07-19 13:05:20 +03:00
|
|
|
qCDebug(lcApplication) << "macOS: Received a QFileOpenEvent";
|
|
|
|
|
|
|
|
if(!openEvent->file().isEmpty()) {
|
|
|
|
qCDebug(lcApplication) << "QFileOpenEvent" << openEvent->file();
|
|
|
|
// virtual file, open it after the Folder were created (if the app is not terminated)
|
|
|
|
const auto fn = openEvent->file();
|
|
|
|
QTimer::singleShot(0, this, [this, fn] { openVirtualFile(fn); });
|
|
|
|
} else if (!openEvent->url().isEmpty() && openEvent->url().isValid()) {
|
|
|
|
// On macOS, Qt does not handle receiving a custom URI as it does on other systems (as an application argument).
|
|
|
|
// Instead, it sends out a QFileOpenEvent. We therefore need custom handling for our URI handling on macOS.
|
|
|
|
qCInfo(lcApplication) << "macOS: Opening local file for editing: " << openEvent->url();
|
2022-10-28 20:40:06 +03:00
|
|
|
EditLocallyManager::instance()->editLocally(openEvent->url());
|
2022-07-19 13:05:20 +03:00
|
|
|
} else {
|
|
|
|
const auto errorParsingLocalFileEditingUrl = QStringLiteral("The supplied url for local file editing '%1' is invalid!").arg(openEvent->url().toString());
|
|
|
|
qCInfo(lcApplication) << errorParsingLocalFileEditingUrl;
|
|
|
|
showHint(errorParsingLocalFileEditingUrl.toStdString());
|
|
|
|
}
|
2018-04-19 14:34:02 +03:00
|
|
|
}
|
|
|
|
return SharedTools::QtSingleApplication::event(event);
|
|
|
|
}
|
|
|
|
|
2014-11-10 00:34:07 +03:00
|
|
|
} // namespace OCC
|