2011-04-06 13:48:02 +04:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
|
|
|
|
*
|
|
|
|
* 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-07-11 02:31:24 +04:00
|
|
|
#include "folderwizard.h"
|
|
|
|
#include "folderman.h"
|
2014-11-10 01:25:57 +03:00
|
|
|
#include "configfile.h"
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "theme.h"
|
|
|
|
#include "networkjobs.h"
|
|
|
|
#include "account.h"
|
2014-08-15 18:26:38 +04:00
|
|
|
#include "selectivesyncdialog.h"
|
2015-04-28 12:29:35 +03:00
|
|
|
#include "accountstate.h"
|
2015-03-10 14:14:14 +03:00
|
|
|
#include "creds/abstractcredentials.h"
|
2017-05-09 15:24:11 +03:00
|
|
|
#include "wizard/owncloudwizard.h"
|
2017-09-01 19:11:43 +03:00
|
|
|
#include "common/asserts.h"
|
2012-05-21 18:48:49 +04:00
|
|
|
|
2011-04-05 20:31:14 +04:00
|
|
|
#include <QDesktopServices>
|
2013-07-22 20:07:44 +04:00
|
|
|
#include <QDir>
|
2011-04-05 20:31:14 +04:00
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QFileInfo>
|
2013-08-01 20:22:13 +04:00
|
|
|
#include <QFileIconProvider>
|
2013-07-22 20:07:44 +04:00
|
|
|
#include <QInputDialog>
|
2011-04-05 20:31:14 +04:00
|
|
|
#include <QUrl>
|
|
|
|
#include <QValidator>
|
|
|
|
#include <QWizardPage>
|
2013-08-06 23:50:06 +04:00
|
|
|
#include <QTreeWidget>
|
2014-08-15 18:26:38 +04:00
|
|
|
#include <QVBoxLayout>
|
2017-11-21 18:13:06 +03:00
|
|
|
#include <QEvent>
|
2018-01-15 19:30:33 +03:00
|
|
|
#include <QCheckBox>
|
2011-10-06 18:55:28 +04:00
|
|
|
|
2020-08-13 14:00:56 +03:00
|
|
|
#include <cstdlib>
|
2011-09-26 15:12:00 +04:00
|
|
|
|
2014-11-10 00:34:07 +03:00
|
|
|
namespace OCC {
|
2011-04-05 13:10:44 +04:00
|
|
|
|
2013-11-26 05:02:56 +04:00
|
|
|
QString FormatWarningsWizardPage::formatWarnings(const QStringList &warnings) const
|
|
|
|
{
|
|
|
|
QString ret;
|
|
|
|
if (warnings.count() == 1) {
|
2015-02-06 00:00:13 +03:00
|
|
|
ret = tr("<b>Warning:</b> %1").arg(warnings.first());
|
2013-11-26 05:02:56 +04:00
|
|
|
} else if (warnings.count() > 1) {
|
2015-02-06 00:00:13 +03:00
|
|
|
ret = tr("<b>Warning:</b>") + " <ul>";
|
2013-11-26 05:02:56 +04:00
|
|
|
Q_FOREACH (QString warning, warnings) {
|
|
|
|
ret += QString::fromLatin1("<li>%1</li>").arg(warning);
|
|
|
|
}
|
|
|
|
ret += "</ul>";
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-11-29 12:39:20 +03:00
|
|
|
FolderWizardLocalPath::FolderWizardLocalPath(const AccountPtr &account)
|
2016-09-30 15:08:00 +03:00
|
|
|
: FormatWarningsWizardPage()
|
|
|
|
, _account(account)
|
2011-04-05 20:31:14 +04:00
|
|
|
{
|
|
|
|
_ui.setupUi(this);
|
2012-08-17 19:13:17 +04:00
|
|
|
registerField(QLatin1String("sourceFolder*"), _ui.localFolderLineEdit);
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(_ui.localFolderChooseBtn, &QAbstractButton::clicked, this, &FolderWizardLocalPath::slotChooseLocalFolder);
|
2014-01-14 20:40:42 +04:00
|
|
|
_ui.localFolderChooseBtn->setToolTip(tr("Click to select a local folder to sync."));
|
|
|
|
|
2018-07-16 13:46:03 +03:00
|
|
|
QUrl serverUrl = _account->url();
|
|
|
|
serverUrl.setUserName(_account->credentials()->user());
|
2017-02-23 16:54:17 +03:00
|
|
|
QString defaultPath = QDir::homePath() + QLatin1Char('/') + Theme::instance()->appName();
|
2018-07-16 13:46:03 +03:00
|
|
|
defaultPath = FolderMan::instance()->findGoodPathForNewSyncFolder(defaultPath, serverUrl);
|
2013-06-11 20:18:38 +04:00
|
|
|
_ui.localFolderLineEdit->setText(QDir::toNativeSeparators(defaultPath));
|
2014-01-14 20:40:42 +04:00
|
|
|
_ui.localFolderLineEdit->setToolTip(tr("Enter the path to the local folder."));
|
|
|
|
|
2013-11-26 05:02:56 +04:00
|
|
|
_ui.warnLabel->setTextFormat(Qt::RichText);
|
2011-10-11 17:39:25 +04:00
|
|
|
_ui.warnLabel->hide();
|
2011-04-05 20:31:14 +04:00
|
|
|
}
|
|
|
|
|
2020-05-25 22:33:24 +03:00
|
|
|
FolderWizardLocalPath::~FolderWizardLocalPath() = default;
|
2011-04-05 20:31:14 +04:00
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardLocalPath::initializePage()
|
2011-10-26 15:59:06 +04:00
|
|
|
{
|
|
|
|
_ui.warnLabel->hide();
|
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardLocalPath::cleanupPage()
|
2011-10-26 15:59:06 +04:00
|
|
|
{
|
|
|
|
_ui.warnLabel->hide();
|
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
bool FolderWizardLocalPath::isComplete() const
|
2011-04-05 20:31:14 +04:00
|
|
|
{
|
2016-09-30 15:08:00 +03:00
|
|
|
QUrl serverUrl = _account->url();
|
|
|
|
serverUrl.setUserName(_account->credentials()->user());
|
|
|
|
|
2015-07-13 15:35:19 +03:00
|
|
|
QString errorStr = FolderMan::instance()->checkPathValidityForNewFolder(
|
2016-09-30 15:08:00 +03:00
|
|
|
QDir::fromNativeSeparators(_ui.localFolderLineEdit->text()), serverUrl);
|
|
|
|
|
|
|
|
|
2015-07-13 15:35:19 +03:00
|
|
|
bool isOk = errorStr.isEmpty();
|
|
|
|
QStringList warnStrings;
|
|
|
|
if (!isOk) {
|
|
|
|
warnStrings << errorStr;
|
2011-10-11 16:23:32 +04:00
|
|
|
}
|
|
|
|
|
2013-11-26 05:02:56 +04:00
|
|
|
_ui.warnLabel->setWordWrap(true);
|
2011-10-11 17:39:25 +04:00
|
|
|
if (isOk) {
|
|
|
|
_ui.warnLabel->hide();
|
2017-12-08 12:58:55 +03:00
|
|
|
_ui.warnLabel->setText(QString());
|
2011-10-11 17:39:25 +04:00
|
|
|
} else {
|
|
|
|
_ui.warnLabel->show();
|
2013-11-26 05:02:56 +04:00
|
|
|
QString warnings = formatWarnings(warnStrings);
|
|
|
|
_ui.warnLabel->setText(warnings);
|
2011-10-11 16:23:32 +04:00
|
|
|
}
|
|
|
|
return isOk;
|
2011-04-05 20:31:14 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardLocalPath::slotChooseLocalFolder()
|
2011-04-05 20:31:14 +04:00
|
|
|
{
|
2017-12-08 15:02:05 +03:00
|
|
|
QString sf = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
|
2014-01-14 20:40:42 +04:00
|
|
|
QDir d(sf);
|
|
|
|
|
|
|
|
// open the first entry of the home dir. Otherwise the dir picker comes
|
|
|
|
// up with the closed home dir icon, stupid Qt default...
|
|
|
|
QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks,
|
|
|
|
QDir::DirsFirst | QDir::Name);
|
|
|
|
|
|
|
|
if (dirs.count() > 0)
|
|
|
|
sf += "/" + dirs.at(0); // Take the first dir in home dir.
|
|
|
|
|
2011-04-05 20:31:14 +04:00
|
|
|
QString dir = QFileDialog::getExistingDirectory(this,
|
|
|
|
tr("Select the source folder"),
|
2014-01-14 20:40:42 +04:00
|
|
|
sf);
|
2011-04-05 20:31:14 +04:00
|
|
|
if (!dir.isEmpty()) {
|
2014-01-14 20:40:42 +04:00
|
|
|
// set the last directory component name as alias
|
2013-06-11 20:18:38 +04:00
|
|
|
_ui.localFolderLineEdit->setText(QDir::toNativeSeparators(dir));
|
2011-04-05 20:31:14 +04:00
|
|
|
}
|
|
|
|
emit completeChanged();
|
|
|
|
}
|
|
|
|
|
2011-10-11 16:23:32 +04:00
|
|
|
// =================================================================================
|
2016-11-29 12:39:20 +03:00
|
|
|
FolderWizardRemotePath::FolderWizardRemotePath(const AccountPtr &account)
|
2013-11-26 05:02:56 +04:00
|
|
|
: FormatWarningsWizardPage()
|
|
|
|
, _warnWasVisible(false)
|
2015-01-28 12:38:54 +03:00
|
|
|
, _account(account)
|
2014-06-20 15:38:36 +04:00
|
|
|
|
2011-04-05 20:31:14 +04:00
|
|
|
{
|
|
|
|
_ui.setupUi(this);
|
2011-10-26 15:59:06 +04:00
|
|
|
_ui.warnFrame->hide();
|
2011-04-06 12:40:15 +04:00
|
|
|
|
2014-10-10 18:56:05 +04:00
|
|
|
_ui.folderTreeWidget->setSortingEnabled(true);
|
|
|
|
_ui.folderTreeWidget->sortByColumn(0, Qt::AscendingOrder);
|
|
|
|
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(_ui.addFolderButton, &QAbstractButton::clicked, this, &FolderWizardRemotePath::slotAddRemoteFolder);
|
|
|
|
connect(_ui.refreshButton, &QAbstractButton::clicked, this, &FolderWizardRemotePath::slotRefreshFolders);
|
|
|
|
connect(_ui.folderTreeWidget, &QTreeWidget::itemExpanded, this, &FolderWizardRemotePath::slotItemExpanded);
|
|
|
|
connect(_ui.folderTreeWidget, &QTreeWidget::currentItemChanged, this, &FolderWizardRemotePath::slotCurrentItemChanged);
|
|
|
|
connect(_ui.folderEntry, &QLineEdit::textEdited, this, &FolderWizardRemotePath::slotFolderEntryEdited);
|
2013-10-23 16:48:44 +04:00
|
|
|
|
2015-03-12 17:59:59 +03:00
|
|
|
_lscolTimer.setInterval(500);
|
|
|
|
_lscolTimer.setSingleShot(true);
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(&_lscolTimer, &QTimer::timeout, this, &FolderWizardRemotePath::slotLsColFolderEntry);
|
2015-03-23 18:28:42 +03:00
|
|
|
|
|
|
|
_ui.folderTreeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
|
|
// Make sure that there will be a scrollbar when the contents is too wide
|
|
|
|
_ui.folderTreeWidget->header()->setStretchLastSection(false);
|
2011-04-05 20:31:14 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::slotAddRemoteFolder()
|
2011-10-06 18:55:28 +04:00
|
|
|
{
|
2013-08-06 23:50:06 +04:00
|
|
|
QTreeWidgetItem *current = _ui.folderTreeWidget->currentItem();
|
|
|
|
|
|
|
|
QString parent('/');
|
|
|
|
if (current) {
|
|
|
|
parent = current->data(0, Qt::UserRole).toString();
|
|
|
|
}
|
|
|
|
|
2020-05-18 21:54:23 +03:00
|
|
|
auto *dlg = new QInputDialog(this);
|
2013-08-06 23:50:06 +04:00
|
|
|
|
2014-12-04 12:47:26 +03:00
|
|
|
dlg->setWindowTitle(tr("Create Remote Folder"));
|
|
|
|
dlg->setLabelText(tr("Enter the name of the new folder to be created below '%1':")
|
|
|
|
.arg(parent));
|
2013-07-22 20:07:44 +04:00
|
|
|
dlg->open(this, SLOT(slotCreateRemoteFolder(QString)));
|
|
|
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
2011-10-06 18:55:28 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::slotCreateRemoteFolder(const QString &folder)
|
2011-10-06 18:55:28 +04:00
|
|
|
{
|
2012-04-14 21:08:53 +04:00
|
|
|
if (folder.isEmpty())
|
|
|
|
return;
|
2013-10-23 16:48:44 +04:00
|
|
|
|
2014-12-04 12:47:26 +03:00
|
|
|
QTreeWidgetItem *current = _ui.folderTreeWidget->currentItem();
|
|
|
|
QString fullPath;
|
|
|
|
if (current) {
|
|
|
|
fullPath = current->data(0, Qt::UserRole).toString();
|
|
|
|
}
|
|
|
|
fullPath += "/" + folder;
|
|
|
|
|
2020-05-18 21:54:23 +03:00
|
|
|
auto *job = new MkColJob(_account, fullPath, this);
|
2013-10-23 16:48:44 +04:00
|
|
|
/* check the owncloud configuration file and query the ownCloud */
|
2017-09-20 12:48:13 +03:00
|
|
|
connect(job, static_cast<void (MkColJob::*)(QNetworkReply::NetworkError)>(&MkColJob::finished),
|
|
|
|
this, &FolderWizardRemotePath::slotCreateRemoteFolderFinished);
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(job, &AbstractNetworkJob::networkError, this, &FolderWizardRemotePath::slotHandleMkdirNetworkError);
|
2013-11-14 22:20:09 +04:00
|
|
|
job->start();
|
2011-10-26 15:59:06 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::slotCreateRemoteFolderFinished(QNetworkReply::NetworkError error)
|
2011-10-26 15:59:06 +04:00
|
|
|
{
|
2013-11-11 18:20:07 +04:00
|
|
|
if (error == QNetworkReply::NoError) {
|
2017-05-09 15:24:11 +03:00
|
|
|
qCDebug(lcWizard) << "webdav mkdir request finished";
|
2013-11-11 18:20:07 +04:00
|
|
|
showWarn(tr("Folder was successfully created on %1.").arg(Theme::instance()->appNameGUI()));
|
|
|
|
slotRefreshFolders();
|
2015-03-23 18:50:37 +03:00
|
|
|
_ui.folderEntry->setText(static_cast<MkColJob *>(sender())->path());
|
|
|
|
slotLsColFolderEntry();
|
2013-11-11 18:20:07 +04:00
|
|
|
}
|
2013-10-23 16:48:44 +04:00
|
|
|
}
|
|
|
|
|
2015-08-21 12:46:38 +03:00
|
|
|
void FolderWizardRemotePath::slotHandleMkdirNetworkError(QNetworkReply *reply)
|
2013-10-23 16:48:44 +04:00
|
|
|
{
|
2017-03-30 14:46:20 +03:00
|
|
|
qCWarning(lcWizard) << "webdav mkdir request failed:" << reply->error();
|
2017-03-23 17:53:22 +03:00
|
|
|
if (!_account->credentials()->stillValid(reply)) {
|
2015-03-10 14:14:14 +03:00
|
|
|
showWarn(tr("Authentication failed accessing %1").arg(Theme::instance()->appNameGUI()));
|
|
|
|
} else {
|
|
|
|
showWarn(tr("Failed to create the folder on %1. Please check manually.")
|
|
|
|
.arg(Theme::instance()->appNameGUI()));
|
|
|
|
}
|
2011-10-26 15:59:06 +04:00
|
|
|
}
|
2011-10-06 18:55:28 +04:00
|
|
|
|
2017-03-23 17:53:22 +03:00
|
|
|
void FolderWizardRemotePath::slotHandleLsColNetworkError(QNetworkReply * /*reply*/)
|
2015-08-21 12:46:38 +03:00
|
|
|
{
|
2017-07-28 11:13:07 +03:00
|
|
|
auto job = qobject_cast<LsColJob *>(sender());
|
|
|
|
ASSERT(job);
|
2015-08-21 12:46:38 +03:00
|
|
|
showWarn(tr("Failed to list a folder. Error: %1")
|
2017-03-23 17:53:22 +03:00
|
|
|
.arg(job->errorStringParsingBody()));
|
2015-08-21 12:46:38 +03:00
|
|
|
}
|
|
|
|
|
2013-08-06 23:50:06 +04:00
|
|
|
static QTreeWidgetItem *findFirstChild(QTreeWidgetItem *parent, const QString &text)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < parent->childCount(); ++i) {
|
|
|
|
QTreeWidgetItem *child = parent->child(i);
|
|
|
|
if (child->text(0) == text) {
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
}
|
2018-11-11 12:56:22 +03:00
|
|
|
return nullptr;
|
2013-08-06 23:50:06 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path)
|
2013-08-06 23:50:06 +04:00
|
|
|
{
|
2015-03-12 17:59:59 +03:00
|
|
|
if (pathTrail.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const QString parentPath = parent->data(0, Qt::UserRole).toString();
|
|
|
|
const QString folderName = pathTrail.first();
|
|
|
|
QString folderPath;
|
|
|
|
if (parentPath == QLatin1String("/")) {
|
|
|
|
folderPath = folderName;
|
2013-08-06 23:50:06 +04:00
|
|
|
} else {
|
2015-03-12 17:59:59 +03:00
|
|
|
folderPath = parentPath + "/" + folderName;
|
|
|
|
}
|
|
|
|
QTreeWidgetItem *item = findFirstChild(parent, folderName);
|
|
|
|
if (!item) {
|
|
|
|
item = new QTreeWidgetItem(parent);
|
|
|
|
QFileIconProvider prov;
|
|
|
|
QIcon folderIcon = prov.icon(QFileIconProvider::Folder);
|
|
|
|
item->setIcon(0, folderIcon);
|
|
|
|
item->setText(0, folderName);
|
|
|
|
item->setData(0, Qt::UserRole, folderPath);
|
|
|
|
item->setToolTip(0, folderPath);
|
|
|
|
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
|
|
|
|
}
|
|
|
|
|
|
|
|
pathTrail.removeFirst();
|
|
|
|
recursiveInsert(item, pathTrail, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FolderWizardRemotePath::selectByPath(QString path)
|
|
|
|
{
|
|
|
|
if (path.startsWith(QLatin1Char('/'))) {
|
|
|
|
path = path.mid(1);
|
|
|
|
}
|
|
|
|
if (path.endsWith(QLatin1Char('/'))) {
|
|
|
|
path.chop(1);
|
|
|
|
}
|
2013-08-06 23:50:06 +04:00
|
|
|
|
2015-03-12 17:59:59 +03:00
|
|
|
QTreeWidgetItem *it = _ui.folderTreeWidget->topLevelItem(0);
|
|
|
|
if (!path.isEmpty()) {
|
|
|
|
const QStringList pathTrail = path.split(QLatin1Char('/'));
|
|
|
|
foreach (const QString &path, pathTrail) {
|
|
|
|
if (!it) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
it = findFirstChild(it, path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!it) {
|
|
|
|
return false;
|
2013-08-06 23:50:06 +04:00
|
|
|
}
|
2015-03-12 17:59:59 +03:00
|
|
|
|
|
|
|
_ui.folderTreeWidget->setCurrentItem(it);
|
2016-04-27 11:37:17 +03:00
|
|
|
_ui.folderTreeWidget->scrollToItem(it);
|
2015-03-12 17:59:59 +03:00
|
|
|
return true;
|
2013-08-06 23:50:06 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list)
|
2013-07-22 20:07:44 +04:00
|
|
|
{
|
2015-01-28 12:38:54 +03:00
|
|
|
QString webdavFolder = QUrl(_account->davUrl()).path();
|
2013-08-06 23:50:06 +04:00
|
|
|
|
|
|
|
QTreeWidgetItem *root = _ui.folderTreeWidget->topLevelItem(0);
|
|
|
|
if (!root) {
|
|
|
|
root = new QTreeWidgetItem(_ui.folderTreeWidget);
|
2013-09-16 00:46:32 +04:00
|
|
|
root->setText(0, Theme::instance()->appNameGUI());
|
|
|
|
root->setIcon(0, Theme::instance()->applicationIcon());
|
2013-08-06 23:50:06 +04:00
|
|
|
root->setToolTip(0, tr("Choose this to sync the entire account"));
|
|
|
|
root->setData(0, Qt::UserRole, "/");
|
|
|
|
}
|
2016-04-28 10:21:42 +03:00
|
|
|
QStringList sortedList = list;
|
2016-05-19 16:36:46 +03:00
|
|
|
Utility::sortFilenames(sortedList);
|
2016-04-28 10:21:42 +03:00
|
|
|
foreach (QString path, sortedList) {
|
2013-08-05 16:28:05 +04:00
|
|
|
path.remove(webdavFolder);
|
2020-06-30 19:18:06 +03:00
|
|
|
|
|
|
|
// Don't allow to select subfolders of encrypted subfolders
|
|
|
|
if (_account->capabilities().clientSideEncryptionAvailable() &&
|
|
|
|
_account->e2e()->isAnyParentFolderEncrypted(path)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-08-06 23:50:06 +04:00
|
|
|
QStringList paths = path.split('/');
|
|
|
|
if (paths.last().isEmpty())
|
|
|
|
paths.removeLast();
|
|
|
|
recursiveInsert(root, paths, path);
|
2013-07-22 20:07:44 +04:00
|
|
|
}
|
2013-08-06 23:50:06 +04:00
|
|
|
root->setExpanded(true);
|
2013-07-22 20:07:44 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::slotRefreshFolders()
|
2013-07-22 20:07:44 +04:00
|
|
|
{
|
2015-08-21 12:46:38 +03:00
|
|
|
runLsColJob("/");
|
2013-08-06 23:50:06 +04:00
|
|
|
_ui.folderTreeWidget->clear();
|
2015-03-12 17:59:59 +03:00
|
|
|
_ui.folderEntry->clear();
|
2013-08-06 23:50:06 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::slotItemExpanded(QTreeWidgetItem *item)
|
2013-08-06 23:50:06 +04:00
|
|
|
{
|
2013-10-23 16:48:44 +04:00
|
|
|
QString dir = item->data(0, Qt::UserRole).toString();
|
2015-08-21 12:46:38 +03:00
|
|
|
runLsColJob(dir);
|
2013-07-22 20:07:44 +04:00
|
|
|
}
|
|
|
|
|
2015-03-12 17:59:59 +03:00
|
|
|
void FolderWizardRemotePath::slotCurrentItemChanged(QTreeWidgetItem *item)
|
|
|
|
{
|
|
|
|
if (item) {
|
|
|
|
QString dir = item->data(0, Qt::UserRole).toString();
|
2020-06-30 19:18:06 +03:00
|
|
|
|
|
|
|
// We don't want to allow creating subfolders in encrypted folders outside of the sync logic
|
|
|
|
const auto encrypted = _account->capabilities().clientSideEncryptionAvailable() &&
|
|
|
|
_account->e2e()->isFolderEncrypted(dir + '/');
|
|
|
|
_ui.addFolderButton->setEnabled(!encrypted);
|
|
|
|
|
2015-03-12 17:59:59 +03:00
|
|
|
if (!dir.startsWith(QLatin1Char('/'))) {
|
|
|
|
dir.prepend(QLatin1Char('/'));
|
|
|
|
}
|
|
|
|
_ui.folderEntry->setText(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
emit completeChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderWizardRemotePath::slotFolderEntryEdited(const QString &text)
|
|
|
|
{
|
|
|
|
if (selectByPath(text)) {
|
|
|
|
_lscolTimer.stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-18 21:39:16 +03:00
|
|
|
_ui.folderTreeWidget->setCurrentItem(nullptr);
|
2015-03-12 17:59:59 +03:00
|
|
|
_lscolTimer.start(); // avoid sending a request on each keystroke
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderWizardRemotePath::slotLsColFolderEntry()
|
|
|
|
{
|
|
|
|
QString path = _ui.folderEntry->text();
|
|
|
|
if (path.startsWith(QLatin1Char('/')))
|
|
|
|
path = path.mid(1);
|
|
|
|
|
2015-08-21 12:46:38 +03:00
|
|
|
LsColJob *job = runLsColJob(path);
|
2016-04-27 11:37:17 +03:00
|
|
|
// No error handling, no updating, we do this manually
|
|
|
|
// because of extra logic in the typed-path case.
|
2020-05-18 21:39:16 +03:00
|
|
|
disconnect(job, nullptr, this, nullptr);
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(job, &LsColJob::finishedWithError,
|
|
|
|
this, &FolderWizardRemotePath::slotTypedPathError);
|
|
|
|
connect(job, &LsColJob::directoryListingSubfolders,
|
|
|
|
this, &FolderWizardRemotePath::slotTypedPathFound);
|
2015-03-12 17:59:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void FolderWizardRemotePath::slotTypedPathFound(const QStringList &subpaths)
|
|
|
|
{
|
|
|
|
slotUpdateDirectories(subpaths);
|
|
|
|
selectByPath(_ui.folderEntry->text());
|
|
|
|
}
|
|
|
|
|
2016-04-27 11:37:17 +03:00
|
|
|
void FolderWizardRemotePath::slotTypedPathError(QNetworkReply *reply)
|
|
|
|
{
|
|
|
|
// Ignore 404s, otherwise users will get annoyed by error popups
|
|
|
|
// when not typing fast enough. It's still clear that a given path
|
|
|
|
// was not found, because the 'Next' button is disabled and no entry
|
|
|
|
// is selected in the tree view.
|
|
|
|
int httpCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
|
|
if (httpCode == 404) {
|
|
|
|
showWarn(""); // hides the warning pane
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
slotHandleLsColNetworkError(reply);
|
|
|
|
}
|
|
|
|
|
2015-08-21 12:46:38 +03:00
|
|
|
LsColJob *FolderWizardRemotePath::runLsColJob(const QString &path)
|
|
|
|
{
|
2020-05-18 21:54:23 +03:00
|
|
|
auto *job = new LsColJob(_account, path, this);
|
2015-08-21 12:46:38 +03:00
|
|
|
job->setProperties(QList<QByteArray>() << "resourcetype");
|
2017-09-20 11:14:48 +03:00
|
|
|
connect(job, &LsColJob::directoryListingSubfolders,
|
|
|
|
this, &FolderWizardRemotePath::slotUpdateDirectories);
|
|
|
|
connect(job, &LsColJob::finishedWithError,
|
|
|
|
this, &FolderWizardRemotePath::slotHandleLsColNetworkError);
|
2015-08-21 12:46:38 +03:00
|
|
|
job->start();
|
|
|
|
|
|
|
|
return job;
|
|
|
|
}
|
|
|
|
|
2020-05-25 22:33:24 +03:00
|
|
|
FolderWizardRemotePath::~FolderWizardRemotePath() = default;
|
2011-04-05 20:31:14 +04:00
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
bool FolderWizardRemotePath::isComplete() const
|
2011-04-05 20:31:14 +04:00
|
|
|
{
|
2013-08-06 23:50:06 +04:00
|
|
|
if (!_ui.folderTreeWidget->currentItem())
|
2013-07-22 20:07:44 +04:00
|
|
|
return false;
|
|
|
|
|
2013-11-26 05:02:56 +04:00
|
|
|
QStringList warnStrings;
|
2013-08-06 23:50:06 +04:00
|
|
|
QString dir = _ui.folderTreeWidget->currentItem()->data(0, Qt::UserRole).toString();
|
2013-11-26 05:02:56 +04:00
|
|
|
if (!dir.startsWith(QLatin1Char('/'))) {
|
|
|
|
dir.prepend(QLatin1Char('/'));
|
|
|
|
}
|
2013-07-23 01:14:41 +04:00
|
|
|
wizard()->setProperty("targetPath", dir);
|
|
|
|
|
2014-06-13 01:17:13 +04:00
|
|
|
Folder::Map map = FolderMan::instance()->map();
|
2013-09-11 01:37:52 +04:00
|
|
|
Folder::Map::const_iterator i = map.constBegin();
|
|
|
|
for (i = map.constBegin(); i != map.constEnd(); i++) {
|
2020-05-18 21:54:23 +03:00
|
|
|
auto *f = static_cast<Folder *>(i.value());
|
2015-04-28 12:29:35 +03:00
|
|
|
if (f->accountState()->account() != _account) {
|
|
|
|
continue;
|
|
|
|
}
|
2013-10-21 23:42:52 +04:00
|
|
|
QString curDir = f->remotePath();
|
2013-11-26 05:02:56 +04:00
|
|
|
if (!curDir.startsWith(QLatin1Char('/'))) {
|
|
|
|
curDir.prepend(QLatin1Char('/'));
|
|
|
|
}
|
|
|
|
if (QDir::cleanPath(dir) == QDir::cleanPath(curDir)) {
|
|
|
|
warnStrings.append(tr("This folder is already being synced."));
|
2013-10-31 14:41:56 +04:00
|
|
|
} else if (dir.startsWith(curDir + QLatin1Char('/'))) {
|
2017-02-23 16:54:17 +03:00
|
|
|
warnStrings.append(tr("You are already syncing <i>%1</i>, which is a parent folder of <i>%2</i>.").arg(Utility::escape(curDir), Utility::escape(dir)));
|
2013-09-11 01:37:52 +04:00
|
|
|
}
|
2011-04-05 20:31:14 +04:00
|
|
|
}
|
2013-11-26 05:02:56 +04:00
|
|
|
|
|
|
|
showWarn(formatWarnings(warnStrings));
|
2017-09-14 16:09:21 +03:00
|
|
|
return true;
|
2011-04-05 20:31:14 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::cleanupPage()
|
2011-10-26 15:59:06 +04:00
|
|
|
{
|
2012-03-16 17:43:37 +04:00
|
|
|
showWarn();
|
2011-10-26 15:59:06 +04:00
|
|
|
}
|
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::initializePage()
|
2011-04-05 20:31:14 +04:00
|
|
|
{
|
2012-03-16 17:43:37 +04:00
|
|
|
showWarn();
|
2013-10-23 16:48:44 +04:00
|
|
|
slotRefreshFolders();
|
2011-10-06 12:54:54 +04:00
|
|
|
}
|
2011-10-05 19:49:03 +04:00
|
|
|
|
2014-01-14 20:40:42 +04:00
|
|
|
void FolderWizardRemotePath::showWarn(const QString &msg) const
|
2011-10-06 12:54:54 +04:00
|
|
|
{
|
2011-10-19 13:53:12 +04:00
|
|
|
if (msg.isEmpty()) {
|
2011-10-26 15:59:06 +04:00
|
|
|
_ui.warnFrame->hide();
|
2012-03-16 17:43:37 +04:00
|
|
|
|
2011-10-19 13:53:12 +04:00
|
|
|
} else {
|
2011-10-26 15:59:06 +04:00
|
|
|
_ui.warnFrame->show();
|
2011-10-19 13:53:12 +04:00
|
|
|
_ui.warnLabel->setText(msg);
|
|
|
|
}
|
2011-10-12 17:14:39 +04:00
|
|
|
}
|
|
|
|
|
2011-10-19 13:53:12 +04:00
|
|
|
// ====================================================================================
|
|
|
|
|
2016-11-29 12:39:20 +03:00
|
|
|
FolderWizardSelectiveSync::FolderWizardSelectiveSync(const AccountPtr &account)
|
2014-08-15 18:26:38 +04:00
|
|
|
{
|
2020-05-18 21:54:23 +03:00
|
|
|
auto *layout = new QVBoxLayout(this);
|
2017-01-03 17:33:06 +03:00
|
|
|
_selectiveSync = new SelectiveSyncWidget(account, this);
|
|
|
|
layout->addWidget(_selectiveSync);
|
2018-04-05 14:35:25 +03:00
|
|
|
|
|
|
|
if (ConfigFile().showExperimentalOptions()) {
|
|
|
|
_placeholderCheckBox = new QCheckBox(tr("Create placeholders instead of downloading files (experimental)"));
|
|
|
|
connect(_placeholderCheckBox, &QCheckBox::clicked, this, &FolderWizardSelectiveSync::placeholderCheckboxClicked);
|
|
|
|
layout->addWidget(_placeholderCheckBox);
|
|
|
|
}
|
2014-08-15 18:26:38 +04:00
|
|
|
}
|
|
|
|
|
2020-05-25 22:33:24 +03:00
|
|
|
FolderWizardSelectiveSync::~FolderWizardSelectiveSync() = default;
|
2014-08-15 18:26:38 +04:00
|
|
|
|
|
|
|
|
|
|
|
void FolderWizardSelectiveSync::initializePage()
|
|
|
|
{
|
|
|
|
QString targetPath = wizard()->property("targetPath").toString();
|
|
|
|
if (targetPath.startsWith('/')) {
|
|
|
|
targetPath = targetPath.mid(1);
|
|
|
|
}
|
2016-05-17 11:49:57 +03:00
|
|
|
QString alias = QFileInfo(targetPath).fileName();
|
|
|
|
if (alias.isEmpty())
|
|
|
|
alias = Theme::instance()->appName();
|
2017-01-04 16:28:11 +03:00
|
|
|
QStringList initialBlacklist;
|
|
|
|
if (Theme::instance()->wizardSelectiveSyncDefaultNothing()) {
|
|
|
|
initialBlacklist = QStringList("/");
|
|
|
|
}
|
|
|
|
_selectiveSync->setFolderInfo(targetPath, alias, initialBlacklist);
|
2014-08-15 18:26:38 +04:00
|
|
|
QWizardPage::initializePage();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FolderWizardSelectiveSync::validatePage()
|
|
|
|
{
|
2017-01-03 17:33:06 +03:00
|
|
|
wizard()->setProperty("selectiveSyncBlackList", QVariant(_selectiveSync->createBlackList()));
|
2018-01-15 19:30:33 +03:00
|
|
|
wizard()->setProperty("usePlaceholders", QVariant(_placeholderCheckBox->isChecked()));
|
2014-08-15 18:26:38 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderWizardSelectiveSync::cleanupPage()
|
|
|
|
{
|
|
|
|
QString targetPath = wizard()->property("targetPath").toString();
|
2016-05-17 11:49:57 +03:00
|
|
|
QString alias = QFileInfo(targetPath).fileName();
|
|
|
|
if (alias.isEmpty())
|
|
|
|
alias = Theme::instance()->appName();
|
2017-01-03 17:33:06 +03:00
|
|
|
_selectiveSync->setFolderInfo(targetPath, alias);
|
2014-08-15 18:26:38 +04:00
|
|
|
QWizardPage::cleanupPage();
|
|
|
|
}
|
|
|
|
|
2018-04-03 18:30:17 +03:00
|
|
|
void FolderWizardSelectiveSync::placeholderCheckboxClicked()
|
|
|
|
{
|
|
|
|
// The click has already had an effect on the box, so if it's
|
|
|
|
// checked it was newly activated.
|
|
|
|
if (_placeholderCheckBox->isChecked()) {
|
|
|
|
OwncloudWizard::askExperimentalPlaceholderFeature([this](bool enable) {
|
|
|
|
if (!enable)
|
|
|
|
_placeholderCheckBox->setChecked(false);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-15 18:26:38 +04:00
|
|
|
|
|
|
|
// ====================================================================================
|
|
|
|
|
|
|
|
|
2011-04-05 20:31:14 +04:00
|
|
|
/**
|
|
|
|
* Folder wizard itself
|
|
|
|
*/
|
|
|
|
|
2015-01-28 12:38:54 +03:00
|
|
|
FolderWizard::FolderWizard(AccountPtr account, QWidget *parent)
|
2011-10-11 16:23:32 +04:00
|
|
|
: QWizard(parent)
|
2016-09-30 15:08:00 +03:00
|
|
|
, _folderWizardSourcePage(new FolderWizardLocalPath(account))
|
2018-11-11 12:56:22 +03:00
|
|
|
, _folderWizardTargetPage(nullptr)
|
2015-01-28 12:38:54 +03:00
|
|
|
, _folderWizardSelectiveSyncPage(new FolderWizardSelectiveSync(account))
|
2011-04-05 13:10:44 +04:00
|
|
|
{
|
2013-11-13 23:12:56 +04:00
|
|
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
2013-07-04 21:59:40 +04:00
|
|
|
setPage(Page_Source, _folderWizardSourcePage);
|
2017-11-21 18:13:06 +03:00
|
|
|
_folderWizardSourcePage->installEventFilter(this);
|
2013-04-08 16:50:26 +04:00
|
|
|
if (!Theme::instance()->singleSyncFolder()) {
|
2015-01-28 12:38:54 +03:00
|
|
|
_folderWizardTargetPage = new FolderWizardRemotePath(account);
|
2013-04-08 16:50:26 +04:00
|
|
|
setPage(Page_Target, _folderWizardTargetPage);
|
2017-11-21 18:13:06 +03:00
|
|
|
_folderWizardTargetPage->installEventFilter(this);
|
2013-04-08 16:50:26 +04:00
|
|
|
}
|
2014-08-15 18:26:38 +04:00
|
|
|
setPage(Page_SelectiveSync, _folderWizardSelectiveSyncPage);
|
2013-04-08 16:50:26 +04:00
|
|
|
|
2015-10-27 14:12:21 +03:00
|
|
|
setWindowTitle(tr("Add Folder Sync Connection"));
|
2013-08-09 02:27:06 +04:00
|
|
|
setOptions(QWizard::CancelButtonOnLeft);
|
2015-10-27 14:12:21 +03:00
|
|
|
setButtonText(QWizard::FinishButton, tr("Add Sync Connection"));
|
2011-04-05 13:10:44 +04:00
|
|
|
}
|
|
|
|
|
2020-05-25 22:33:24 +03:00
|
|
|
FolderWizard::~FolderWizard() = default;
|
2013-04-08 16:50:26 +04:00
|
|
|
|
2017-11-21 18:13:06 +03:00
|
|
|
bool FolderWizard::eventFilter(QObject *watched, QEvent *event)
|
|
|
|
{
|
|
|
|
if (event->type() == QEvent::LayoutRequest) {
|
|
|
|
// Workaround QTBUG-3396: forces QWizardPrivate::updateLayout()
|
|
|
|
QTimer::singleShot(0, this, [this] { setTitleFormat(titleFormat()); });
|
|
|
|
}
|
|
|
|
return QWizard::eventFilter(watched, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderWizard::resizeEvent(QResizeEvent *event)
|
|
|
|
{
|
|
|
|
QWizard::resizeEvent(event);
|
|
|
|
|
|
|
|
// workaround for QTBUG-22819: when the error label word wrap, the minimum height is not adjusted
|
2018-01-09 13:41:39 +03:00
|
|
|
if (auto page = currentPage()) {
|
|
|
|
int hfw = page->heightForWidth(page->width());
|
|
|
|
if (page->height() < hfw) {
|
|
|
|
page->setMinimumSize(page->minimumSizeHint().width(), hfw);
|
|
|
|
setTitleFormat(titleFormat()); // And another workaround for QTBUG-3396
|
|
|
|
}
|
2017-11-21 18:13:06 +03:00
|
|
|
}
|
|
|
|
}
|
2011-10-11 16:23:32 +04:00
|
|
|
|
2011-09-26 15:12:00 +04:00
|
|
|
} // end namespace
|