Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Müller <fmueller@owncloud.com>2022-03-30 21:54:47 +0300
committerHannah von Reth <vonreth@kde.org>2022-04-12 15:51:18 +0300
commita25f0068e1353f116c8ca251bf608fe2e4e794b1 (patch)
treef813f18abb5f43392315e2007dcccd38c1b3bdeb /src/gui/newwizard
parent44db53318351b061ba2db4c7bf6b30a789b8f8b1 (diff)
Implement advanced sync options in wizard
Diffstat (limited to 'src/gui/newwizard')
-rw-r--r--src/gui/newwizard/CMakeLists.txt2
-rw-r--r--src/gui/newwizard/pages/accountconfiguredwizardpage.cpp146
-rw-r--r--src/gui/newwizard/pages/accountconfiguredwizardpage.h9
-rw-r--r--src/gui/newwizard/pages/accountconfiguredwizardpage.ui196
-rw-r--r--src/gui/newwizard/setupwizardcontroller.cpp48
-rw-r--r--src/gui/newwizard/setupwizardcontroller.h3
-rw-r--r--src/gui/newwizard/syncmode.cpp2
-rw-r--r--src/gui/newwizard/syncmode.h15
8 files changed, 410 insertions, 11 deletions
diff --git a/src/gui/newwizard/CMakeLists.txt b/src/gui/newwizard/CMakeLists.txt
index 28e188870..df390431e 100644
--- a/src/gui/newwizard/CMakeLists.txt
+++ b/src/gui/newwizard/CMakeLists.txt
@@ -33,6 +33,8 @@ add_library(newwizard OBJECT
jobs/resolveurljobfactory.cpp
jobs/resolveurljobfactory.h
+
+ syncmode.cpp
)
target_link_libraries(newwizard PUBLIC Qt5::Widgets libsync)
set_target_properties(newwizard PROPERTIES AUTOUIC ON AUTORCC ON)
diff --git a/src/gui/newwizard/pages/accountconfiguredwizardpage.cpp b/src/gui/newwizard/pages/accountconfiguredwizardpage.cpp
index f0bf2077c..3e1bc1739 100644
--- a/src/gui/newwizard/pages/accountconfiguredwizardpage.cpp
+++ b/src/gui/newwizard/pages/accountconfiguredwizardpage.cpp
@@ -1,20 +1,160 @@
#include "accountconfiguredwizardpage.h"
-#include <QMessageBox>
-#include "gui/selectivesyncdialog.h"
#include "theme.h"
#include "ui_accountconfiguredwizardpage.h"
+#include <QDir>
+#include <QFileDialog>
+#include <QMessageBox>
+
namespace OCC::Wizard {
-AccountConfiguredWizardPage::AccountConfiguredWizardPage()
+AccountConfiguredWizardPage::AccountConfiguredWizardPage(const QString &defaultSyncTargetDir, bool vfsIsAvailable, bool enableVfsByDefault, bool vfsModeIsExperimental)
: _ui(new ::Ui::AccountConfiguredWizardPage)
{
_ui->setupUi(this);
+
+ // by default, sync everything to an automatically chosen directory, VFS use depends on the OS
+ // the defaults are provided by the controller
+ _ui->localDirectoryLineEdit->setText(QDir::toNativeSeparators(defaultSyncTargetDir));
+ _ui->syncEverythingRadioButton->setChecked(true);
+
+ // could also make it invisible, but then the UX is different for different installations
+ // this may be overwritten by a branding option (see below)
+ _ui->useVfsRadioButton->setEnabled(vfsIsAvailable);
+
+ _ui->useVfsRadioButton->setText(tr("Use &virtual files instead of downloading content immediately"));
+ if (vfsModeIsExperimental) {
+ _ui->useVfsRadioButton->setIcon(QIcon(QStringLiteral(":/client/resources/light/warning.svg")));
+ }
+
+ // just adjusting the visibility should be sufficient for these branding options
+ if (Theme::instance()->wizardSkipAdvancedPage()) {
+ _ui->advancedConfigSeparatorLine->setVisible(false);
+ _ui->advancedConfigGroupBox->setVisible(false);
+ }
+
+ if (!Theme::instance()->showVirtualFilesOption()) {
+ _ui->useVfsRadioButton->setVisible(false);
+ vfsIsAvailable = false;
+ }
+
+ if (!vfsIsAvailable) {
+ enableVfsByDefault = false;
+ }
+
+ if (enableVfsByDefault) {
+ _ui->useVfsRadioButton->setChecked(true);
+
+ // move up top
+ _ui->syncModeGroupBoxLayout->removeWidget(_ui->useVfsRadioButton);
+ _ui->syncModeGroupBoxLayout->insertWidget(0, _ui->useVfsRadioButton);
+ }
+
+ if (!vfsIsAvailable) {
+ // fallback: it's set as default option in Qt Designer, but we should make sure the option is selected if VFS is not available
+ _ui->syncEverythingRadioButton->setChecked(true);
+
+ _ui->useVfsRadioButton->setToolTip(tr("The virtual filesystem feature is not available for this installation."));
+ } else if (vfsModeIsExperimental) {
+ _ui->useVfsRadioButton->setToolTip(tr("The virtual filesystem feature is not stable yet. Use with caution."));
+ }
+
+ connect(_ui->chooseLocalDirectoryButton, &QToolButton::clicked, this, [=]() {
+ auto dialog = new QFileDialog(this, tr("Choose"), defaultSyncTargetDir);
+ dialog->setFileMode(QFileDialog::Directory);
+ dialog->setOption(QFileDialog::ShowDirsOnly);
+
+ connect(dialog, &QFileDialog::fileSelected, this, [this](const QString &directory) {
+ // the directory chooser should guarantee that the directory exists
+ Q_ASSERT(QDir(directory).exists());
+
+ _ui->localDirectoryLineEdit->setText(QDir::toNativeSeparators(directory));
+ });
+
+ dialog->show();
+ });
+
+ // this should be handled on application startup, too
+ OC_ENFORCE(!Theme::instance()->forceVirtualFilesOption() || vfsIsAvailable);
+
+ if (Theme::instance()->forceVirtualFilesOption()) {
+ // this has no visual effect, but is needed for syncMode()
+ _ui->useVfsRadioButton->setChecked(true);
+
+ // we want to hide the entire sync mode selection from the user, not just disable it
+ _ui->syncModeGroupBox->setVisible(false);
+ }
+
+ connect(_ui->advancedConfigGroupBox, &QGroupBox::toggled, this, [this](bool enabled) {
+ // layouts cannot be hidden, therefore we use a plain widget within the group box to "house" the contained widgets
+ _ui->advancedConfigGroupBoxContentWidget->setVisible(enabled);
+
+ // could not find a better way to hide the frame on demand, which is needed to hide the widget completely
+ _ui->advancedConfigGroupBox->setStyleSheet(enabled ? QString() : QStringLiteral("QGroupBox#advancedConfigGroupBox{border: 0}"));
+ });
+
+ if (vfsModeIsExperimental) {
+ connect(_ui->useVfsRadioButton, &QRadioButton::clicked, this, [this]() {
+ auto messageBox = new QMessageBox(
+ QMessageBox::Warning,
+ tr("Enable experimental feature?"),
+ tr("When the \"virtual files\" mode is enabled no files will be downloaded initially. "
+ "Instead, a tiny file will be created for each file that exists on the server. "
+ "The contents can be downloaded by running these files or by using their context menu."
+ "\n\n"
+ "The virtual files mode is mutually exclusive with selective sync. "
+ "Currently unselected folders will be translated to online-only folders "
+ "and your selective sync settings will be reset."
+ "\n\n"
+ "Switching to this mode will abort any currently running synchronization."
+ "\n\n"
+ "This is a new, experimental mode. If you decide to use it, please report any "
+ "issues that come up."),
+ QMessageBox::NoButton,
+ this);
+
+ messageBox->addButton(tr("Enable experimental placeholder mode"), QMessageBox::AcceptRole);
+ messageBox->addButton(tr("Stay safe"), QMessageBox::RejectRole);
+
+ messageBox->setAttribute(Qt::WA_DeleteOnClose);
+
+ connect(messageBox, &QMessageBox::rejected, this, [this]() {
+ // bring back to "safety"
+ _ui->syncEverythingRadioButton->setChecked(true);
+ });
+
+ messageBox->show();
+ });
+ }
+
+ // toggle once to have the according handlers set up the initial UI state
+ _ui->advancedConfigGroupBox->setChecked(true);
+ _ui->advancedConfigGroupBox->setChecked(false);
}
AccountConfiguredWizardPage::~AccountConfiguredWizardPage() noexcept
{
delete _ui;
}
+
+QString AccountConfiguredWizardPage::syncTargetDir() const
+{
+ return QDir::toNativeSeparators(_ui->localDirectoryLineEdit->text());
+}
+
+SyncMode AccountConfiguredWizardPage::syncMode() const
+{
+ if (_ui->syncEverythingRadioButton->isChecked()) {
+ return SyncMode::SyncEverything;
+ }
+ if (_ui->selectiveSyncRadioButton->isChecked()) {
+ return SyncMode::SelectiveSync;
+ }
+ if (_ui->useVfsRadioButton->isChecked()) {
+ return SyncMode::UseVfs;
+ }
+
+ Q_UNREACHABLE();
+}
}
diff --git a/src/gui/newwizard/pages/accountconfiguredwizardpage.h b/src/gui/newwizard/pages/accountconfiguredwizardpage.h
index b75c3e22c..9c905dba7 100644
--- a/src/gui/newwizard/pages/accountconfiguredwizardpage.h
+++ b/src/gui/newwizard/pages/accountconfiguredwizardpage.h
@@ -1,6 +1,9 @@
#pragma once
+#include <QSharedPointer>
+
#include "abstractsetupwizardpage.h"
+#include "setupwizardcontroller.h"
namespace Ui {
class AccountConfiguredWizardPage;
@@ -13,9 +16,13 @@ class AccountConfiguredWizardPage : public AbstractSetupWizardPage
Q_OBJECT
public:
- AccountConfiguredWizardPage();
+ explicit AccountConfiguredWizardPage(const QString &defaultSyncTargetDir, bool vfsIsAvailable, bool enableVfsByDefault, bool vfsModeIsExperimental);
~AccountConfiguredWizardPage() noexcept override;
+ QString syncTargetDir() const;
+
+ SyncMode syncMode() const;
+
private:
::Ui::AccountConfiguredWizardPage *_ui;
};
diff --git a/src/gui/newwizard/pages/accountconfiguredwizardpage.ui b/src/gui/newwizard/pages/accountconfiguredwizardpage.ui
index f56a74d7c..ca88b9749 100644
--- a/src/gui/newwizard/pages/accountconfiguredwizardpage.ui
+++ b/src/gui/newwizard/pages/accountconfiguredwizardpage.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>732</width>
- <height>434</height>
+ <width>689</width>
+ <height>513</height>
</rect>
</property>
<property name="windowTitle">
@@ -50,8 +50,198 @@
</property>
</spacer>
</item>
+ <item>
+ <widget class="Line" name="advancedConfigSeparatorLine">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="advancedConfigGroupBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Advanced configuration</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>60</number>
+ </property>
+ <item>
+ <widget class="QWidget" name="advancedConfigGroupBoxContentWidget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>50</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="syncModeGroupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QGroupBox {border:0;}</string>
+ </property>
+ <property name="title">
+ <string notr="true"/>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="syncModeGroupBoxLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="syncEverythingRadioButton">
+ <property name="text">
+ <string>Download everything</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="selectiveSyncRadioButton">
+ <property name="toolTip">
+ <string>You can configure which directories to download from the server in a dialog once the wizard has finished.</string>
+ </property>
+ <property name="text">
+ <string>Choose what to download</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="useVfsRadioButton">
+ <property name="text">
+ <string notr="true">Enable virtual filesystem (placeholder)</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QGroupBox {border:0;}</string>
+ </property>
+ <property name="title">
+ <string notr="true"/>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Choose local download directory:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLineEdit" name="localDirectoryLineEdit"/>
+ </item>
+ <item>
+ <widget class="QToolButton" name="chooseLocalDirectoryButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="../../../../client.qrc"/>
+ </resources>
<connections/>
</ui>
diff --git a/src/gui/newwizard/setupwizardcontroller.cpp b/src/gui/newwizard/setupwizardcontroller.cpp
index 5d35e4411..2b08715c5 100644
--- a/src/gui/newwizard/setupwizardcontroller.cpp
+++ b/src/gui/newwizard/setupwizardcontroller.cpp
@@ -7,12 +7,32 @@
#include "pages/oauthcredentialssetupwizardpage.h"
#include "pages/serverurlsetupwizardpage.h"
+#include "gui/folderman.h"
+#include "theme.h"
+
+#include <QDir>
#include <QTimer>
#include <chrono>
using namespace std::chrono_literals;
+namespace {
+
+QString initLocalFolder()
+{
+ auto localFolder = OCC::Theme::instance()->defaultClientFolder();
+ // Update the local folder - this is not guaranteed to find a good one
+ // if its a relative path, prepend with users home dir, otherwise use as absolute path
+
+ if (!QDir(localFolder).isAbsolute()) {
+ localFolder = QDir::homePath() + QDir::separator() + localFolder;
+ }
+ return OCC::FolderMan::instance()->findGoodPathForNewSyncFolder(localFolder);
+}
+
+}
+
namespace OCC::Wizard {
SetupWizardController::SetupWizardController(QWidget *parent)
@@ -28,7 +48,7 @@ SetupWizardController::SetupWizardController(QWidget *parent)
// allow settings dialog to clean up the wizard controller and all the objects it created
connect(_wizardWindow, &SetupWizardWindow::rejected, this, [this]() {
- Q_EMIT finished(nullptr);
+ Q_EMIT finished(nullptr, {}, SyncMode::Invalid);
});
connect(_wizardWindow, &SetupWizardWindow::paginationEntryClicked, this, [this, paginationEntries](PageIndex currentPage, PageIndex clickedPageIndex) {
@@ -129,9 +149,11 @@ void SetupWizardController::nextStep(std::optional<PageIndex> currentPage, std::
// final step
if (currentPage == 2) {
+ const auto *pagePtr = qobject_cast<AccountConfiguredWizardPage *>(_currentPage);
+
auto account = _accountBuilder.build();
Q_ASSERT(account != nullptr);
- emit finished(account);
+ Q_EMIT finished(account, pagePtr->syncTargetDir(), pagePtr->syncMode());
return;
}
}
@@ -240,7 +262,27 @@ void SetupWizardController::nextStep(std::optional<PageIndex> currentPage, std::
}
if (desiredPage == 2) {
- _currentPage = new AccountConfiguredWizardPage;
+ // being pessimistic by default
+ bool vfsIsAvailable = false;
+ bool enableVfsByDefault = false;
+ bool vfsModeIsExperimental = false;
+
+ switch (bestAvailableVfsMode()) {
+ case Vfs::WindowsCfApi:
+ vfsIsAvailable = true;
+ enableVfsByDefault = true;
+ vfsModeIsExperimental = false;
+ break;
+ case Vfs::WithSuffix:
+ vfsIsAvailable = true;
+ enableVfsByDefault = false;
+ vfsModeIsExperimental = true;
+ break;
+ default:
+ break;
+ }
+
+ _currentPage = new AccountConfiguredWizardPage(initLocalFolder(), vfsIsAvailable, enableVfsByDefault, vfsModeIsExperimental);
_wizardWindow->displayPage(_currentPage, 2);
return;
}
diff --git a/src/gui/newwizard/setupwizardcontroller.h b/src/gui/newwizard/setupwizardcontroller.h
index 097150b78..4b3ccb124 100644
--- a/src/gui/newwizard/setupwizardcontroller.h
+++ b/src/gui/newwizard/setupwizardcontroller.h
@@ -1,6 +1,7 @@
#pragma once
#include "pages/abstractsetupwizardpage.h"
+#include "syncmode.h"
#include <QDialog>
#include <account.h>
#include <optional>
@@ -31,7 +32,7 @@ Q_SIGNALS:
/**
* Emitted when the wizard has finished. It passes the built account object.
*/
- void finished(AccountPtr newAccount);
+ void finished(AccountPtr newAccount, const QString &localFolder, SyncMode syncMode);
private:
void nextStep(std::optional<PageIndex> currentPage, std::optional<PageIndex> desiredPage);
diff --git a/src/gui/newwizard/syncmode.cpp b/src/gui/newwizard/syncmode.cpp
new file mode 100644
index 000000000..63a336a42
--- /dev/null
+++ b/src/gui/newwizard/syncmode.cpp
@@ -0,0 +1,2 @@
+// just a stub so the MOC file can be included somewhere
+#include "moc_syncmode.cpp"
diff --git a/src/gui/newwizard/syncmode.h b/src/gui/newwizard/syncmode.h
new file mode 100644
index 000000000..fd1bbd16d
--- /dev/null
+++ b/src/gui/newwizard/syncmode.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <QObject>
+
+namespace OCC::Wizard {
+Q_NAMESPACE
+
+enum class SyncMode {
+ Invalid = 0,
+ SyncEverything,
+ SelectiveSync,
+ UseVfs,
+};
+Q_ENUM_NS(SyncMode)
+}