Refactor wizard code
* Move code for setup detection into its own class * Use separate wizard page to show setup detection report
This commit is contained in:
parent
352d161144
commit
c31b7b9ca8
|
@ -26,6 +26,8 @@ set(WIDGETS_HEADER_FILES
|
|||
set(WIDGETS_SRC_FILES
|
||||
settings/settings.cpp
|
||||
settings/settingsdialog.cpp
|
||||
settings/setupdetection.h
|
||||
settings/setupdetection.cpp
|
||||
settings/wizard.cpp
|
||||
webview/webpage.cpp
|
||||
webview/webviewdialog.cpp
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
#include "./setupdetection.h"
|
||||
|
||||
#if defined(LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD) && (defined(PLATFORM_UNIX) || defined(PLATFORM_MINGW) || defined(PLATFORM_CYGWIN))
|
||||
#define PLATFORM_HAS_GETLOGIN
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
SetupDetection::SetupDetection(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
// assume default service names
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
userService.setUnitName(QStringLiteral("syncthing.service"));
|
||||
systemService.setUnitName(QStringLiteral("syncthing@") %
|
||||
#ifdef PLATFORM_HAS_GETLOGIN
|
||||
QString::fromLocal8Bit(getlogin()) %
|
||||
#endif
|
||||
QStringLiteral(".service"));
|
||||
#endif
|
||||
|
||||
// configure launcher to test invocation of "syncthing --version" capturing output
|
||||
launcherSettings.syncthingArgs = QStringLiteral("--version");
|
||||
launcher.setEmittingOutput(true);
|
||||
|
||||
// configure timeout
|
||||
timeout.setInterval(2500);
|
||||
timeout.setSingleShot(true);
|
||||
|
||||
// connect signals & slots
|
||||
connect(&connection, &Data::SyncthingConnection::error, this, &SetupDetection::handleConnectionError);
|
||||
connect(&connection, &Data::SyncthingConnection::statusChanged, this, &SetupDetection::checkDone);
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
connect(&userService, &Data::SyncthingService::unitFileStateChanged, this, &SetupDetection::checkDone);
|
||||
connect(&systemService, &Data::SyncthingService::unitFileStateChanged, this, &SetupDetection::checkDone);
|
||||
#endif
|
||||
connect(&launcher, &Data::SyncthingLauncher::outputAvailable, this, &SetupDetection::handleLauncherOutput);
|
||||
connect(&launcher, &Data::SyncthingLauncher::exited, this, &SetupDetection::handleLauncherExit);
|
||||
connect(&launcher, &Data::SyncthingLauncher::errorOccurred, this, &SetupDetection::handleLauncherError);
|
||||
connect(&timeout, &QTimer::timeout, this, &SetupDetection::handleTimeout);
|
||||
}
|
||||
|
||||
void SetupDetection::determinePaths()
|
||||
{
|
||||
configFilePath = Data::SyncthingConfig::locateConfigFile();
|
||||
certPath = Data::SyncthingConfig::locateHttpsCertificate();
|
||||
}
|
||||
|
||||
void SetupDetection::restoreConfig()
|
||||
{
|
||||
configOk = config.restore(configFilePath);
|
||||
}
|
||||
|
||||
void SetupDetection::initConnection()
|
||||
{
|
||||
connection.setSyncthingUrl(config.syncthingUrl());
|
||||
connection.setApiKey(config.guiApiKey.toLocal8Bit());
|
||||
}
|
||||
|
||||
bool SetupDetection::hasConfig() const
|
||||
{
|
||||
return configOk && !config.guiAddress.isEmpty() && !config.guiApiKey.isEmpty();
|
||||
}
|
||||
|
||||
bool SetupDetection::isDone() const
|
||||
{
|
||||
return timedOut
|
||||
|| (!connection.isConnecting() && (launcherExitCode.has_value() || launcherError.has_value())
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
&& !userService.unitFileState().isEmpty() && !systemService.unitFileState().isEmpty()
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void SetupDetection::reset()
|
||||
{
|
||||
timeout.stop();
|
||||
timedOut = false;
|
||||
configOk = false;
|
||||
connection.abortAllRequests();
|
||||
launcher.terminate();
|
||||
connectionErrors.clear();
|
||||
launcherExitCode.reset();
|
||||
launcherExitStatus.reset();
|
||||
launcherError.reset();
|
||||
launcherOutput.clear();
|
||||
}
|
||||
|
||||
void SetupDetection::startTest()
|
||||
{
|
||||
restoreConfig();
|
||||
initConnection();
|
||||
connection.reconnect();
|
||||
launcher.launch(launcherSettings);
|
||||
timeout.start();
|
||||
}
|
||||
|
||||
void SetupDetection::handleConnectionError(const QString &error)
|
||||
{
|
||||
connectionErrors << QStringLiteral(" - ") + error;
|
||||
}
|
||||
|
||||
void SetupDetection::handleLauncherExit(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
launcherExitCode = exitCode;
|
||||
launcherExitStatus = exitStatus;
|
||||
checkDone();
|
||||
}
|
||||
|
||||
void SetupDetection::handleLauncherError(QProcess::ProcessError error)
|
||||
{
|
||||
launcherError = error;
|
||||
checkDone();
|
||||
}
|
||||
|
||||
void SetupDetection::handleLauncherOutput(const QByteArray &output)
|
||||
{
|
||||
launcherOutput.append(output);
|
||||
}
|
||||
|
||||
void SetupDetection::handleTimeout()
|
||||
{
|
||||
timedOut = true;
|
||||
checkDone();
|
||||
}
|
||||
|
||||
void SetupDetection::checkDone()
|
||||
{
|
||||
if (isDone()) {
|
||||
timeout.stop();
|
||||
emit done();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QtGui
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef SETTINGS_SETUP_DETECTION_H
|
||||
#define SETTINGS_SETUP_DETECTION_H
|
||||
|
||||
#include "./settings.h"
|
||||
|
||||
#include "../misc/syncthinglauncher.h"
|
||||
|
||||
#include <syncthingconnector/syncthingconfig.h>
|
||||
#include <syncthingconnector/syncthingconnection.h>
|
||||
#include <syncthingconnector/syncthingconnectionsettings.h>
|
||||
#include <syncthingconnector/syncthingservice.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QProcess>
|
||||
#include <QStringBuilder>
|
||||
#include <QTimer>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
class SetupDetection : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SetupDetection(QObject *parent = nullptr);
|
||||
bool hasConfig() const;
|
||||
bool isDone() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void determinePaths();
|
||||
void restoreConfig();
|
||||
void initConnection();
|
||||
void reset();
|
||||
void startTest();
|
||||
|
||||
Q_SIGNALS:
|
||||
void done();
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleConnectionError(const QString &error);
|
||||
void handleLauncherExit(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void handleLauncherError(QProcess::ProcessError error);
|
||||
void handleLauncherOutput(const QByteArray &output);
|
||||
void handleTimeout();
|
||||
void checkDone();
|
||||
|
||||
public:
|
||||
QString configFilePath;
|
||||
QString certPath;
|
||||
QStringList connectionErrors;
|
||||
Data::SyncthingConfig config;
|
||||
Data::SyncthingConnection connection;
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
Data::SyncthingService userService = Data::SyncthingService(Data::SystemdScope::User);
|
||||
Data::SyncthingService systemService = Data::SyncthingService(Data::SystemdScope::System);
|
||||
#endif
|
||||
Settings::Launcher launcherSettings;
|
||||
Data::SyncthingLauncher launcher;
|
||||
std::optional<int> launcherExitCode;
|
||||
std::optional<QProcess::ExitStatus> launcherExitStatus;
|
||||
std::optional<QProcess::ProcessError> launcherError;
|
||||
QByteArray launcherOutput;
|
||||
QTimer timeout;
|
||||
bool timedOut = false;
|
||||
bool configOk = false;
|
||||
};
|
||||
|
||||
} // namespace QtGui
|
||||
|
||||
#endif // SETTINGS_SETUP_DETECTION_H
|
|
@ -1,17 +1,12 @@
|
|||
#include "./wizard.h"
|
||||
#include "./settings.h"
|
||||
#include "./setupdetection.h"
|
||||
|
||||
#include "../misc/statusinfo.h"
|
||||
#include "../misc/syncthinglauncher.h"
|
||||
|
||||
// use meta-data of syncthingtray application here
|
||||
#include "resources/../../tray/resources/config.h"
|
||||
|
||||
#include <syncthingconnector/syncthingconfig.h>
|
||||
#include <syncthingconnector/syncthingconnection.h>
|
||||
#include <syncthingconnector/syncthingconnectionsettings.h>
|
||||
#include <syncthingconnector/syncthingservice.h>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QCommandLinkButton>
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
|
@ -20,20 +15,12 @@
|
|||
#include <QMessageBox>
|
||||
#include <QProgressBar>
|
||||
#include <QPushButton>
|
||||
#include <QStringBuilder>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <string_view>
|
||||
|
||||
#if defined(LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD) && (defined(PLATFORM_UNIX) || defined(PLATFORM_MINGW) || defined(PLATFORM_CYGWIN))
|
||||
#define PLATFORM_HAS_GETLOGIN
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
Wizard *Wizard::s_instance = nullptr;
|
||||
|
@ -47,7 +34,11 @@ Wizard::Wizard(QWidget *parent, Qt::WindowFlags flags)
|
|||
if (settings.firstLaunch || settings.fakeFirstLaunch) {
|
||||
addPage(new WelcomeWizardPage(this));
|
||||
}
|
||||
addPage(m_detectionPage = new DetectionWizardPage(this));
|
||||
auto *const detectionPage = new DetectionWizardPage(this);
|
||||
auto *const mainConfigPage = new MainConfigWizardPage(this);
|
||||
connect(mainConfigPage, &MainConfigWizardPage::retry, detectionPage, &DetectionWizardPage::refresh);
|
||||
addPage(detectionPage);
|
||||
addPage(mainConfigPage);
|
||||
}
|
||||
|
||||
Wizard::~Wizard()
|
||||
|
@ -66,6 +57,14 @@ Wizard *Wizard::instance()
|
|||
return s_instance;
|
||||
}
|
||||
|
||||
SetupDetection &Wizard::setupDetection()
|
||||
{
|
||||
if (!m_setupDetection) {
|
||||
m_setupDetection = std::make_unique<SetupDetection>();
|
||||
}
|
||||
return *m_setupDetection;
|
||||
}
|
||||
|
||||
WelcomeWizardPage::WelcomeWizardPage(QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
{
|
||||
|
@ -83,13 +82,9 @@ WelcomeWizardPage::WelcomeWizardPage(QWidget *parent)
|
|||
startWizardCommand = new QCommandLinkButton(this);
|
||||
startWizardCommand->setText(tr("Start guided setup"));
|
||||
startWizardCommand->setDescription(
|
||||
tr("Allows to configure Syncthing Tray automatically for the local Syncthing instance, helps you starting Syncthing if wanted"));
|
||||
tr("Allows to configure Syncthing Tray automatically for the local Syncthing instance and helps you starting Syncthing if wanted."));
|
||||
startWizardCommand->setIcon(QIcon::fromTheme(QStringLiteral("quickwizard")));
|
||||
connect(startWizardCommand, &QCommandLinkButton::clicked, this, [this] {
|
||||
if (auto *const wizard = qobject_cast<Wizard *>(this->wizard())) {
|
||||
wizard->next();
|
||||
}
|
||||
});
|
||||
connect(startWizardCommand, &QCommandLinkButton::clicked, this, [this] { this->wizard()->next(); });
|
||||
}
|
||||
|
||||
auto *const showSettingsCommand = new QCommandLinkButton(this);
|
||||
|
@ -147,78 +142,54 @@ bool WelcomeWizardPage::isComplete() const
|
|||
|
||||
DetectionWizardPage::DetectionWizardPage(QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
, m_connection(nullptr)
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
, m_userService(nullptr)
|
||||
, m_systemService(nullptr)
|
||||
#endif
|
||||
, m_launcher(nullptr)
|
||||
, m_timedOut(false)
|
||||
, m_configOk(false)
|
||||
{
|
||||
setTitle(tr("Checking current Syncthing setup"));
|
||||
setSubTitle(tr("Initializing …"));
|
||||
setSubTitle(tr("Checking Syncthing configuration and whether Syncthing is already running or can be started …"));
|
||||
|
||||
m_timeoutTimer.setInterval(1000);
|
||||
m_timeoutTimer.setSingleShot(true);
|
||||
|
||||
m_progressBar = new QProgressBar(this);
|
||||
m_progressBar->setMinimum(0);
|
||||
m_progressBar->setMaximum(0);
|
||||
m_progressBar->setVisible(false);
|
||||
m_logLabel = new QLabel(this);
|
||||
auto *const progressBar = new QProgressBar(this);
|
||||
progressBar->setMinimum(0);
|
||||
progressBar->setMaximum(0);
|
||||
|
||||
auto *const layout = new QVBoxLayout;
|
||||
layout->addWidget(m_progressBar);
|
||||
layout->addWidget(m_logLabel);
|
||||
layout->addWidget(progressBar);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
bool DetectionWizardPage::isComplete() const
|
||||
{
|
||||
return m_configOk && !m_config.guiAddress.isEmpty() && !m_config.guiApiKey.isEmpty();
|
||||
return m_setupDetection && m_setupDetection->isDone();
|
||||
}
|
||||
|
||||
void DetectionWizardPage::initializePage()
|
||||
{
|
||||
m_progressBar->setVisible(true);
|
||||
m_configOk = false;
|
||||
m_connectionErrors.clear();
|
||||
m_launcherExitCode.reset();
|
||||
m_launcherExitStatus.reset();
|
||||
m_launcherError.reset();
|
||||
m_launcherOutput.clear();
|
||||
|
||||
auto *const wizard = qobject_cast<Wizard *>(this->wizard());
|
||||
if (!wizard) {
|
||||
return;
|
||||
}
|
||||
m_setupDetection = &wizard->setupDetection();
|
||||
m_setupDetection->reset();
|
||||
emit completeChanged();
|
||||
QTimer::singleShot(0, this, &DetectionWizardPage::tryToConnect);
|
||||
}
|
||||
|
||||
void DetectionWizardPage::cleanupPage()
|
||||
{
|
||||
m_progressBar->setVisible(false);
|
||||
if (m_connection) {
|
||||
m_connection->abortAllRequests();
|
||||
}
|
||||
if (m_launcher && m_launcher->isRunning()) {
|
||||
m_launcher->terminate();
|
||||
if (m_setupDetection) {
|
||||
m_setupDetection->disconnect(this);
|
||||
m_setupDetection->reset();
|
||||
}
|
||||
}
|
||||
|
||||
void DetectionWizardPage::refresh()
|
||||
{
|
||||
initializePage();
|
||||
}
|
||||
|
||||
void DetectionWizardPage::tryToConnect()
|
||||
{
|
||||
setSubTitle(tr("Checking whether Syncthing is already running …"));
|
||||
|
||||
// cleanup old instances possibly still present from previous check
|
||||
for (auto *instance : std::initializer_list<QObject *>{ m_connection, m_userService, m_systemService, m_launcher }) {
|
||||
if (instance) {
|
||||
instance->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
// read Syncthing's config file
|
||||
m_configFilePath = Data::SyncthingConfig::locateConfigFile();
|
||||
m_certPath = Data::SyncthingConfig::locateHttpsCertificate();
|
||||
if (m_configFilePath.isEmpty()) {
|
||||
// determine path of Syncthing's config file, possibly ask user to select it
|
||||
m_setupDetection->determinePaths();
|
||||
if (m_setupDetection->configFilePath.isEmpty()) {
|
||||
auto msgbox = QMessageBox(wizard());
|
||||
auto yesButton = QPushButton(tr("Yes, continue configuration"));
|
||||
auto noButton = QPushButton(tr("No, let me select Syncthing's configuration file manually"));
|
||||
|
@ -229,107 +200,61 @@ void DetectionWizardPage::tryToConnect()
|
|||
msgbox.addButton(&noButton, QMessageBox::NoRole);
|
||||
msgbox.exec();
|
||||
if (msgbox.clickedButton() == &noButton) {
|
||||
m_configFilePath = QFileDialog::getOpenFileName(
|
||||
m_setupDetection->configFilePath = QFileDialog::getOpenFileName(
|
||||
wizard(), tr("Select Syncthing's configuration file"), QString(), QStringLiteral("XML files (*.xml);All files (*.*)"));
|
||||
}
|
||||
}
|
||||
m_configOk = m_config.restore(m_configFilePath);
|
||||
|
||||
// attempt connecting to Syncthing
|
||||
m_connection = new Data::SyncthingConnection(
|
||||
m_config.syncthingUrl(), m_config.guiApiKey.toUtf8(), Data::SyncthingConnectionLoggingFlags::FromEnvironment, this);
|
||||
connect(m_connection, &Data::SyncthingConnection::error, this, &DetectionWizardPage::handleConnectionError);
|
||||
connect(m_connection, &Data::SyncthingConnection::statusChanged, this, &DetectionWizardPage::handleConnectionStatusChanged);
|
||||
m_connection->connect();
|
||||
|
||||
// checkout availability of systemd services
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
m_userService = new Data::SyncthingService(Data::SystemdScope::User, this);
|
||||
m_userService->setUnitName(QStringLiteral("syncthing.service"));
|
||||
m_systemService = new Data::SyncthingService(Data::SystemdScope::System, this);
|
||||
m_systemService->setUnitName(QStringLiteral("syncthing@") %
|
||||
#ifdef PLATFORM_HAS_GETLOGIN
|
||||
QString::fromLocal8Bit(getlogin()) %
|
||||
#endif
|
||||
QStringLiteral(".service"));
|
||||
connect(m_userService, &Data::SyncthingService::unitFileStateChanged, this, &DetectionWizardPage::continueWithSummaryIfDone);
|
||||
connect(m_systemService, &Data::SyncthingService::unitFileStateChanged, this, &DetectionWizardPage::continueWithSummaryIfDone);
|
||||
#endif
|
||||
|
||||
// check whether we could launch Syncthing as external binary
|
||||
auto launcherSettings = Settings::Launcher();
|
||||
launcherSettings.syncthingArgs = QStringLiteral("--version");
|
||||
m_launcher = new Data::SyncthingLauncher(this);
|
||||
m_launcher->setEmittingOutput(true);
|
||||
connect(m_launcher, &Data::SyncthingLauncher::outputAvailable, this, &DetectionWizardPage::handleLauncherOutput);
|
||||
connect(m_launcher, &Data::SyncthingLauncher::exited, this, &DetectionWizardPage::handleLauncherExit);
|
||||
connect(m_launcher, &Data::SyncthingLauncher::errorOccurred, this, &DetectionWizardPage::handleLauncherError);
|
||||
m_launcher->launch(launcherSettings);
|
||||
|
||||
// setup a timeout
|
||||
m_timeoutTimer.stop();
|
||||
m_timedOut = false;
|
||||
m_timeoutTimer.start();
|
||||
// start setup detection tests
|
||||
connect(m_setupDetection, &SetupDetection::done, this, &DetectionWizardPage::continueIfDone);
|
||||
m_setupDetection->startTest();
|
||||
}
|
||||
|
||||
void DetectionWizardPage::handleConnectionStatusChanged()
|
||||
void DetectionWizardPage::continueIfDone()
|
||||
{
|
||||
if (m_connection->isConnecting()) {
|
||||
m_setupDetection->disconnect(this);
|
||||
emit completeChanged();
|
||||
wizard()->next();
|
||||
}
|
||||
|
||||
MainConfigWizardPage::MainConfigWizardPage(QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
, m_detailsLabel(new QLabel(this))
|
||||
{
|
||||
setTitle(tr("Select what configuration to apply"));
|
||||
setSubTitle(tr("Something when wrong when checking the Syncthing setup."));
|
||||
|
||||
auto *const showDetailsCheckBox = new QCheckBox(this);
|
||||
showDetailsCheckBox->setText(tr("Show report from detecting the local Syncthing setup"));
|
||||
m_detailsLabel->setVisible(false);
|
||||
m_detailsLabel->setWordWrap(true);
|
||||
connect(showDetailsCheckBox, &QCheckBox::toggled, m_detailsLabel, &QLabel::setVisible);
|
||||
|
||||
auto *const layout = new QVBoxLayout;
|
||||
layout->addWidget(showDetailsCheckBox);
|
||||
layout->addWidget(m_detailsLabel);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
bool MainConfigWizardPage::isComplete() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainConfigWizardPage::initializePage()
|
||||
{
|
||||
auto *const wizard = qobject_cast<Wizard *>(this->wizard());
|
||||
if (!wizard) {
|
||||
return;
|
||||
}
|
||||
showSummary();
|
||||
}
|
||||
|
||||
void DetectionWizardPage::handleConnectionError(const QString &error)
|
||||
{
|
||||
m_connectionErrors << QStringLiteral(" - ") + error;
|
||||
}
|
||||
|
||||
void DetectionWizardPage::handleLauncherExit(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
m_launcherExitCode = exitCode;
|
||||
m_launcherExitStatus = exitStatus;
|
||||
continueWithSummaryIfDone();
|
||||
}
|
||||
|
||||
void DetectionWizardPage::handleLauncherError(QProcess::ProcessError error)
|
||||
{
|
||||
m_launcherError = error;
|
||||
continueWithSummaryIfDone();
|
||||
}
|
||||
|
||||
void DetectionWizardPage::handleLauncherOutput(const QByteArray &output)
|
||||
{
|
||||
m_launcherOutput.append(output);
|
||||
}
|
||||
|
||||
void DetectionWizardPage::handleTimeout()
|
||||
{
|
||||
m_timedOut = true;
|
||||
continueWithSummaryIfDone();
|
||||
}
|
||||
|
||||
void DetectionWizardPage::continueWithSummaryIfDone()
|
||||
{
|
||||
if (m_timedOut
|
||||
|| (!m_connection->isConnecting() && (m_launcherExitCode.has_value() || m_launcherError.has_value())
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
&& !m_userService->unitFileState().isEmpty() && !m_systemService->unitFileState().isEmpty()
|
||||
#endif
|
||||
)) {
|
||||
showSummary();
|
||||
}
|
||||
}
|
||||
|
||||
void DetectionWizardPage::showSummary()
|
||||
{
|
||||
auto info = QStringList();
|
||||
|
||||
// add config info
|
||||
if (m_configFilePath.isEmpty()) {
|
||||
auto const &detection = wizard->setupDetection();
|
||||
auto info = QStringList();
|
||||
if (detection.configFilePath.isEmpty()) {
|
||||
info << tr("Unable to locate Syncthing config file.");
|
||||
} else {
|
||||
info << tr("Located Syncthing config file: ") + m_configFilePath;
|
||||
info << tr("Located Syncthing config file: ") + detection.configFilePath;
|
||||
if (isComplete()) {
|
||||
info << tr("Syncthing config file looks ok.");
|
||||
} else {
|
||||
|
@ -338,43 +263,56 @@ void DetectionWizardPage::showSummary()
|
|||
}
|
||||
|
||||
// add connection info
|
||||
if (m_connection->isConnected()) {
|
||||
if (detection.connection.isConnected()) {
|
||||
auto statusInfo = StatusInfo();
|
||||
statusInfo.updateConnectionStatus(*m_connection);
|
||||
statusInfo.updateConnectionStatus(*m_connection);
|
||||
info << tr("Could connect to Syncthing under: ") + m_connection->syncthingUrl();
|
||||
info << tr("Syncthing's version: ") + m_connection->syncthingVersion();
|
||||
info << tr("Syncthing's device ID: ") + m_connection->myId();
|
||||
info << tr("Syncthing's status: ") + statusInfo.statusText();
|
||||
statusInfo.updateConnectionStatus(detection.connection);
|
||||
statusInfo.updateConnectionStatus(detection.connection);
|
||||
info << tr("Could connect to Syncthing under: ") + detection.connection.syncthingUrl();
|
||||
info << tr("Syncthing version: ") + detection.connection.syncthingVersion();
|
||||
info << tr("Syncthing device ID: ") + detection.connection.myId();
|
||||
info << tr("Syncthing status: ") + statusInfo.statusText();
|
||||
if (!statusInfo.additionalStatusText().isEmpty()) {
|
||||
info << tr("Additional Syncthing status info: ") + statusInfo.additionalStatusText();
|
||||
}
|
||||
}
|
||||
if (!m_connectionErrors.isEmpty()) {
|
||||
if (!detection.connectionErrors.isEmpty()) {
|
||||
info << tr("Connection errors:");
|
||||
info << m_connectionErrors;
|
||||
info << detection.connectionErrors;
|
||||
}
|
||||
|
||||
// add systemd service info
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
info << tr("State of systemd user service \"%1\": ").arg(m_userService->unitName()) + m_userService->unitFileState();
|
||||
info << tr("State of systemd system service \"%1\": ").arg(m_systemService->unitName()) + m_systemService->unitFileState();
|
||||
info << tr("State of systemd user unit file \"%1\": ").arg(detection.userService.unitName()) + detection.userService.unitFileState();
|
||||
info << tr("State of systemd system unit file \"%1\": ").arg(detection.systemService.unitName()) + detection.systemService.unitFileState();
|
||||
#endif
|
||||
|
||||
// add launcher info
|
||||
if (m_launcherExitCode.has_value() && m_launcherExitStatus.value() == QProcess::NormalExit) {
|
||||
info << tr("Could test-launch Syncthing successfully, exit code: ") + QString::number(m_launcherExitCode.value());
|
||||
info << tr("Syncthing version returned from test-launch: ") + QString::fromLocal8Bit(m_launcherOutput.trimmed());
|
||||
const auto successfulTestLaunch = detection.launcherExitCode.has_value() && detection.launcherExitStatus.value() == QProcess::NormalExit;
|
||||
if (successfulTestLaunch) {
|
||||
info << tr("Could test-launch Syncthing successfully, exit code: ") + QString::number(detection.launcherExitCode.value());
|
||||
info << tr("Syncthing version returned from test-launch: ") + QString::fromLocal8Bit(detection.launcherOutput.trimmed());
|
||||
} else {
|
||||
info << tr("Unable to test-launch Syncthing: ") + m_launcher->errorString();
|
||||
info << tr("Unable to test-launch Syncthing: ") + detection.launcher.errorString();
|
||||
}
|
||||
info << tr("Built-in Syncthing available: ") + (Data::SyncthingLauncher::isLibSyncthingAvailable() ? tr("yes") : tr("no"));
|
||||
|
||||
// update UI
|
||||
emit completeChanged();
|
||||
setSubTitle(tr("[Some summary should go here]. Select how to proceed."));
|
||||
m_logLabel->setText(info.join(QChar('\n')));
|
||||
m_progressBar->setVisible(false);
|
||||
// add details info
|
||||
m_detailsLabel->setText(QStringLiteral("<ul><li>") % info.join(QStringLiteral("</li><li>")) % QStringLiteral("</ul>"));
|
||||
|
||||
// add short summary
|
||||
if (detection.connection.isConnected()) {
|
||||
setSubTitle(tr("Looks like Syncthing is already running and Syncthing Tray can be configured accordingly automatically."));
|
||||
} else if (successfulTestLaunch || Data::SyncthingLauncher::isLibSyncthingAvailable()) {
|
||||
setSubTitle(tr("Looks like Syncthing is not running yet. You can launch it via Syncthing Tray."));
|
||||
} else {
|
||||
setSubTitle(tr("Looks like Syncthing is not running yet and needs to be installed before Syncthing Tray can be configured."));
|
||||
}
|
||||
}
|
||||
|
||||
void MainConfigWizardPage::cleanupPage()
|
||||
{
|
||||
m_detailsLabel->clear();
|
||||
emit retry();
|
||||
}
|
||||
|
||||
} // namespace QtGui
|
||||
|
|
|
@ -3,29 +3,16 @@
|
|||
|
||||
#include "../global.h"
|
||||
|
||||
#include <syncthingconnector/syncthingconfig.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
#include <QWizard>
|
||||
#include <QWizardPage>
|
||||
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QProgressBar)
|
||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||
|
||||
namespace Data {
|
||||
class SyncthingConnection;
|
||||
class SyncthingService;
|
||||
class SyncthingProcess;
|
||||
class SyncthingLauncher;
|
||||
} // namespace Data
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
class DetectionWizardPage;
|
||||
class SetupDetection;
|
||||
|
||||
class SYNCTHINGWIDGETS_EXPORT Wizard : public QWizard {
|
||||
Q_OBJECT
|
||||
|
@ -35,21 +22,16 @@ public:
|
|||
~Wizard() override;
|
||||
|
||||
static Wizard *instance();
|
||||
DetectionWizardPage *detectionPage() const;
|
||||
SetupDetection &setupDetection();
|
||||
|
||||
Q_SIGNALS:
|
||||
void settingsRequested();
|
||||
|
||||
private:
|
||||
static Wizard *s_instance;
|
||||
DetectionWizardPage *m_detectionPage;
|
||||
std::unique_ptr<SetupDetection> m_setupDetection;
|
||||
};
|
||||
|
||||
inline DetectionWizardPage *Wizard::detectionPage() const
|
||||
{
|
||||
return m_detectionPage;
|
||||
}
|
||||
|
||||
class SYNCTHINGWIDGETS_EXPORT WelcomeWizardPage final : public QWizardPage {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -69,36 +51,32 @@ public:
|
|||
void initializePage() override;
|
||||
void cleanupPage() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void refresh();
|
||||
|
||||
private Q_SLOTS:
|
||||
void tryToConnect();
|
||||
void handleConnectionStatusChanged();
|
||||
void handleConnectionError(const QString &error);
|
||||
void handleLauncherExit(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void handleLauncherError(QProcess::ProcessError error);
|
||||
void handleLauncherOutput(const QByteArray &output);
|
||||
void handleTimeout();
|
||||
void continueWithSummaryIfDone();
|
||||
void showSummary();
|
||||
void continueIfDone();
|
||||
|
||||
private:
|
||||
QString m_configFilePath;
|
||||
QString m_certPath;
|
||||
QStringList m_connectionErrors;
|
||||
Data::SyncthingConfig m_config;
|
||||
Data::SyncthingConnection *m_connection;
|
||||
Data::SyncthingService *m_userService;
|
||||
Data::SyncthingService *m_systemService;
|
||||
Data::SyncthingLauncher *m_launcher;
|
||||
QTimer m_timeoutTimer;
|
||||
SetupDetection *m_setupDetection;
|
||||
};
|
||||
|
||||
QProgressBar *m_progressBar;
|
||||
QLabel *m_logLabel;
|
||||
std::optional<int> m_launcherExitCode;
|
||||
std::optional<QProcess::ExitStatus> m_launcherExitStatus;
|
||||
std::optional<QProcess::ProcessError> m_launcherError;
|
||||
QByteArray m_launcherOutput;
|
||||
bool m_timedOut;
|
||||
bool m_configOk;
|
||||
class SYNCTHINGWIDGETS_EXPORT MainConfigWizardPage final : public QWizardPage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainConfigWizardPage(QWidget *parent = nullptr);
|
||||
|
||||
bool isComplete() const override;
|
||||
void initializePage() override;
|
||||
void cleanupPage() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void retry();
|
||||
|
||||
private:
|
||||
QLabel *m_detailsLabel;
|
||||
};
|
||||
|
||||
} // namespace QtGui
|
||||
|
|
Loading…
Reference in New Issue