[Pkg-owncloud-commits] [owncloud-client] 06/115: Selective sync: Add UI to select paths
Sandro Knauß
hefee-guest at moszumanska.debian.org
Fri Aug 29 22:03:53 UTC 2014
This is an automated email from the git hooks/post-receive script.
hefee-guest pushed a commit to branch master
in repository owncloud-client.
commit aa85e875bd2aa3d80c61e371f7a52e2c915420fe
Author: Olivier Goffart <ogoffart at woboq.com>
Date: Mon Aug 11 15:09:17 2014 +0200
Selective sync: Add UI to select paths
---
src/CMakeLists.txt | 1 +
src/mirall/accountsettings.cpp | 18 +++
src/mirall/accountsettings.h | 1 +
src/mirall/accountsettings.ui | 7 +
src/mirall/folder.h | 5 +
src/mirall/folderman.cpp | 10 +-
src/mirall/folderman.h | 7 +-
src/mirall/logger.cpp | 2 +-
src/mirall/selectivesyncdialog.cpp | 256 +++++++++++++++++++++++++++++++++++++
src/mirall/selectivesyncdialog.h | 47 +++++++
10 files changed, 346 insertions(+), 8 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ec15a25..9d4e66b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -267,6 +267,7 @@ set(mirall_SRCS
mirall/socketapi.cpp
mirall/sslbutton.cpp
mirall/syncrunfilelog.cpp
+ mirall/selectivesyncdialog.cpp
)
diff --git a/src/mirall/accountsettings.cpp b/src/mirall/accountsettings.cpp
index 6259d44..4db0c28 100644
--- a/src/mirall/accountsettings.cpp
+++ b/src/mirall/accountsettings.cpp
@@ -26,6 +26,7 @@
#include "mirall/ignorelisteditor.h"
#include "mirall/account.h"
#include "mirall/quotainfo.h"
+#include "selectivesyncdialog.h"
#include "creds/abstractcredentials.h"
#include <math.h>
@@ -77,6 +78,7 @@ AccountSettings::AccountSettings(QWidget *parent) :
ui->_buttonRemove->setEnabled(false);
ui->_buttonEnable->setEnabled(false);
+ ui->_buttonSelectiveSync->setEnabled(false);
ui->_buttonAdd->setEnabled(true);
QAction *resetFolderAction = new QAction(this);
@@ -92,6 +94,7 @@ AccountSettings::AccountSettings(QWidget *parent) :
connect(ui->_buttonRemove, SIGNAL(clicked()), this, SLOT(slotRemoveCurrentFolder()));
connect(ui->_buttonEnable, SIGNAL(clicked()), this, SLOT(slotEnableCurrentFolder()));
connect(ui->_buttonAdd, SIGNAL(clicked()), this, SLOT(slotAddFolder()));
+ connect(ui->_buttonSelectiveSync, SIGNAL(clicked()), this, SLOT(slotSelectiveSync()));
connect(ui->modifyAccountButton, SIGNAL(clicked()), SLOT(slotOpenAccountWizard()));
connect(ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));;
@@ -152,6 +155,7 @@ void AccountSettings::slotFolderActivated( const QModelIndex& indx )
}
ui->_buttonAdd->setEnabled(_account && _account->state() == Account::Connected);
ui->_buttonEnable->setEnabled( isValid );
+ ui->_buttonSelectiveSync->setEnabled( isValid );
if ( isValid ) {
bool folderEnabled = _model->data( indx, FolderStatusDelegate::FolderSyncEnabled).toBool();
@@ -369,6 +373,20 @@ void AccountSettings::slotResetCurrentFolder()
}
}
+void AccountSettings::slotSelectiveSync()
+{
+ QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
+ if( selected.isValid() ) {
+ QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
+ FolderMan *folderMan = FolderMan::instance();
+ Folder *f = folderMan->folder(alias);
+ if (f) {
+ (new SelectiveSyncDialog(f, this))->show();
+ }
+ }
+
+}
+
void AccountSettings::slotDoubleClicked( const QModelIndex& indx )
{
if( ! indx.isValid() ) return;
diff --git a/src/mirall/accountsettings.h b/src/mirall/accountsettings.h
index 4e64ea2..53c6ad8 100644
--- a/src/mirall/accountsettings.h
+++ b/src/mirall/accountsettings.h
@@ -81,6 +81,7 @@ protected slots:
void slotFolderWizardRejected();
void slotOpenAccountWizard();
void slotHideProgress();
+ void slotSelectiveSync();
private:
QString shortenFilename( const QString& folder, const QString& file ) const;
diff --git a/src/mirall/accountsettings.ui b/src/mirall/accountsettings.ui
index 133dfaa..e62916d 100644
--- a/src/mirall/accountsettings.ui
+++ b/src/mirall/accountsettings.ui
@@ -71,6 +71,13 @@
</widget>
</item>
<item>
+ <widget class="QPushButton" name="_buttonSelectiveSync">
+ <property name="text">
+ <string>Selective Sync...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/mirall/folder.h b/src/mirall/folder.h
index 8a9d554..52304c8 100644
--- a/src/mirall/folder.h
+++ b/src/mirall/folder.h
@@ -121,6 +121,10 @@ public:
SyncJournalDb *journalDb() { return &_journal; }
CSYNC *csyncContext() { return _csync_ctx; }
+ QStringList selectiveSyncList() { return _selectiveSyncWhiteList; }
+ void setSelectiveSyncList(const QStringList &whiteList)
+ { _selectiveSyncWhiteList = whiteList; }
+
signals:
void syncStateChange();
@@ -188,6 +192,7 @@ private:
SyncResult _syncResult;
QScopedPointer<SyncEngine> _engine;
QStringList _errors;
+ QStringList _selectiveSyncWhiteList;
bool _csyncError;
bool _csyncUnavail;
bool _wipeDb;
diff --git a/src/mirall/folderman.cpp b/src/mirall/folderman.cpp
index 5729c4d..554ea34 100644
--- a/src/mirall/folderman.cpp
+++ b/src/mirall/folderman.cpp
@@ -234,7 +234,7 @@ void FolderMan::terminateCurrentSync()
#define PAR_O_TAG QLatin1String("__PAR_OPEN__")
#define PAR_C_TAG QLatin1String("__PAR_CLOSE__")
-QString FolderMan::escapeAlias( const QString& alias ) const
+QString FolderMan::escapeAlias( const QString& alias )
{
QString a(alias);
@@ -312,6 +312,7 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
QString backend = settings.value(QLatin1String("backend")).toString();
QString targetPath = settings.value( QLatin1String("targetPath")).toString();
bool paused = settings.value( QLatin1String("paused"), false).toBool();
+ QStringList whiteList = settings.value( QLatin1String("whiteList")).toStringList();
// QString connection = settings.value( QLatin1String("connection") ).toString();
QString alias = unescapeAlias( escapedAlias );
@@ -326,7 +327,8 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
}
folder = new Folder( alias, path, targetPath, this );
- folder->setConfigFile(file);
+ folder->setConfigFile(cfgFile.absoluteFilePath());
+ folder->setSelectiveSyncList(whiteList);
qDebug() << "Adding folder to Folder Map " << folder;
_folderMap[alias] = folder;
if (paused) {
@@ -359,7 +361,7 @@ void FolderMan::slotEnableFolder( const QString& alias, bool enable )
slotScheduleSync(alias);
// FIXME: Use MirallConfigFile
- QSettings settings(_folderConfigPath + QLatin1Char('/') + f->configFile(), QSettings::IniFormat);
+ QSettings settings(f->configFile(), QSettings::IniFormat);
settings.beginGroup(escapeAlias(f->alias()));
if (enable) {
settings.remove("paused");
@@ -588,7 +590,7 @@ void FolderMan::removeFolder( const QString& alias )
f->setSyncEnabled(false);
// remove the folder configuration
- QFile file( _folderConfigPath + QLatin1Char('/') + f->configFile() );
+ QFile file(f->configFile() );
if( file.exists() ) {
qDebug() << "Remove folder config file " << file.fileName();
file.remove();
diff --git a/src/mirall/folderman.h b/src/mirall/folderman.h
index c3a8d00..abfaf12 100644
--- a/src/mirall/folderman.h
+++ b/src/mirall/folderman.h
@@ -84,6 +84,10 @@ public:
void removeMonitorPath( const QString& alias, const QString& path );
void addMonitorPath( const QString& alias, const QString& path );
+ // Escaping of the alias which is used in QSettings AND the file
+ // system, thus need to be escaped.
+ static QString escapeAlias( const QString& );
+
signals:
/**
* signal to indicate a folder named by alias has changed its sync state.
@@ -131,9 +135,6 @@ private:
QString getBackupName( const QString& ) const;
void registerFolderMonitor( Folder *folder );
- // Escaping of the alias which is used in QSettings AND the file
- // system, thus need to be escaped.
- QString escapeAlias( const QString& ) const;
QString unescapeAlias( const QString& ) const;
void removeFolder( const QString& );
diff --git a/src/mirall/logger.cpp b/src/mirall/logger.cpp
index 0bc8d1c..4ab9232 100644
--- a/src/mirall/logger.cpp
+++ b/src/mirall/logger.cpp
@@ -50,7 +50,7 @@ Logger *Logger::instance()
Logger::Logger( QObject* parent) : QObject(parent),
_showTime(true), _doLogging(false), _doFileFlush(false), _logExpire(0)
{
- qInstallMessageHandler(mirallLogCatcher);
+// qInstallMessageHandler(mirallLogCatcher);
}
Logger::~Logger() {
diff --git a/src/mirall/selectivesyncdialog.cpp b/src/mirall/selectivesyncdialog.cpp
new file mode 100644
index 0000000..56d3999
--- /dev/null
+++ b/src/mirall/selectivesyncdialog.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) by Olivier Goffart <ogoffart at woboq.com>
+ *
+ * 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.
+ */
+#include "selectivesyncdialog.h"
+#include "folder.h"
+#include "account.h"
+#include "networkjobs.h"
+#include "theme.h"
+#include "folderman.h"
+#include <QDialogButtonBox>
+#include <QVBoxLayout>
+#include <QTreeWidget>
+#include <qpushbutton.h>
+#include <QFileIconProvider>
+#include <QDebug>
+#include <QSettings>
+#include <QScopedValueRollback>
+
+namespace Mirall {
+
+SelectiveSyncDialog::SelectiveSyncDialog(Folder* folder, QWidget* parent, Qt::WindowFlags f)
+ : QDialog(parent, f), _folder(folder)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ _treeView = new QTreeWidget;
+ connect(_treeView, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(slotItemExpanded(QTreeWidgetItem*)));
+ connect(_treeView, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(slotItemChanged(QTreeWidgetItem*,int)));
+ layout->addWidget(_treeView);
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal);
+ QPushButton *button;
+ button = buttonBox->addButton(QDialogButtonBox::Ok);
+ connect(button, SIGNAL(clicked()), this, SLOT(accept()));
+ button = buttonBox->addButton(QDialogButtonBox::Cancel);
+ connect(button, SIGNAL(clicked()), this, SLOT(reject()));
+ layout->addWidget(buttonBox);
+
+ // Make sure we don't get crashes if the folder is destroyed while we are still open
+ connect(_folder, SIGNAL(destroyed(QObject*)), this, SLOT(deleteLater()));
+
+ refreshFolders();
+}
+
+void SelectiveSyncDialog::refreshFolders()
+{
+ LsColJob *job = new LsColJob(AccountManager::instance()->account(), _folder->remotePath(), this);
+ connect(job, SIGNAL(directoryListing(QStringList)),
+ this, SLOT(slotUpdateDirectories(QStringList)));
+ job->start();
+ _treeView->clear();
+
+}
+
+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;
+ }
+ }
+ return 0;
+}
+
+void SelectiveSyncDialog::recursiveInsert(QTreeWidgetItem* parent, QStringList pathTrail,
+ QString path)
+{
+ QFileIconProvider prov;
+ QIcon folderIcon = prov.icon(QFileIconProvider::Folder);
+ if (pathTrail.size() == 0) {
+ if (path.endsWith('/')) {
+ path.chop(1);
+ }
+ parent->setToolTip(0, path);
+ parent->setData(0, Qt::UserRole, path);
+ } else {
+ QTreeWidgetItem *item = findFirstChild(parent, pathTrail.first());
+ if (!item) {
+ item = new QTreeWidgetItem(parent);
+ if (parent->checkState(0) == Qt::Checked) {
+ item->setCheckState(0, Qt::Checked);
+ } else if (parent->checkState(0) == Qt::Unchecked) {
+ item->setCheckState(0, Qt::Unchecked);
+ } else {
+ item->setCheckState(0, Qt::Unchecked);
+ foreach(const QString &str , _folder->selectiveSyncList()) {
+ if (str + "/" == path) {
+ item->setCheckState(0, Qt::Checked);
+ break;
+ } else if (str.startsWith(path)) {
+ item->setCheckState(0, Qt::PartiallyChecked);
+ }
+ }
+ }
+ item->setIcon(0, folderIcon);
+ item->setText(0, pathTrail.first());
+// item->setData(0, Qt::UserRole, pathTrail.first());
+ item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
+ }
+
+ pathTrail.removeFirst();
+ recursiveInsert(item, pathTrail, path);
+ }
+}
+
+void SelectiveSyncDialog::slotUpdateDirectories(const QStringList &list)
+{
+ QScopedValueRollback<bool> isInserting(_inserting);
+ _inserting = true;
+
+ QTreeWidgetItem *root = _treeView->topLevelItem(0);
+ if (!root) {
+ root = new QTreeWidgetItem(_treeView);
+ root->setText(0, _folder->alias());
+ root->setIcon(0, Theme::instance()->applicationIcon());
+ root->setData(0, Qt::UserRole, _folder->remotePath());
+ if (_folder->selectiveSyncList().isEmpty() || _folder->selectiveSyncList().contains(QString())) {
+ root->setCheckState(0, Qt::Checked);
+ } else {
+ root->setCheckState(0, Qt::PartiallyChecked);
+ }
+ }
+ const QString folderPath = _folder->remoteUrl().path();
+ foreach (QString path, list) {
+ path.remove(folderPath);
+ QStringList paths = path.split('/');
+ if (paths.last().isEmpty()) paths.removeLast();
+ recursiveInsert(root, paths, path);
+ }
+ root->setExpanded(true);
+}
+
+void SelectiveSyncDialog::slotItemExpanded(QTreeWidgetItem *item)
+{
+ QString dir = item->data(0, Qt::UserRole).toString();
+ LsColJob *job = new LsColJob(AccountManager::instance()->account(), dir, this);
+ connect(job, SIGNAL(directoryListing(QStringList)),
+ SLOT(slotUpdateDirectories(QStringList)));
+ job->start();
+}
+
+void SelectiveSyncDialog::slotItemChanged(QTreeWidgetItem *item, int col)
+{
+ if (col != 0 || _inserting)
+ return;
+
+ if (item->checkState(0) == Qt::Checked) {
+ // If we are checked, check that we may need to check the parent as well if
+ // all the sibilings are also checked
+ QTreeWidgetItem *parent = item->parent();
+ if (parent && parent->checkState(0) != Qt::Checked) {
+ bool hasUnchecked = false;
+ for (int i = 0; i < parent->childCount(); ++i) {
+ if (parent->child(i)->checkState(0) != Qt::Checked) {
+ hasUnchecked = true;
+ break;
+ }
+ }
+ if (!hasUnchecked) {
+ parent->setCheckState(0, Qt::Checked);
+ } else if (parent->checkState(0) == Qt::Unchecked) {
+ parent->setCheckState(0, Qt::PartiallyChecked);
+ }
+ }
+ // also check all the childs
+ for (int i = 0; i < item->childCount(); ++i) {
+ if (item->child(i)->checkState(0) != Qt::Checked) {
+ item->child(i)->setCheckState(0, Qt::Checked);
+ }
+ }
+ }
+
+ if (item->checkState(0) == Qt::Unchecked) {
+ QTreeWidgetItem *parent = item->parent();
+ if (parent && parent->checkState(0) != Qt::Unchecked) {
+ bool hasChecked = false;
+ for (int i = 0; i < parent->childCount(); ++i) {
+ if (parent->child(i)->checkState(0) != Qt::Unchecked) {
+ hasChecked = true;
+ break;
+ }
+ }
+ if (!hasChecked) {
+ parent->setCheckState(0, Qt::Unchecked);
+ } else if (parent->checkState(0) == Qt::Checked) {
+ parent->setCheckState(0, Qt::PartiallyChecked);
+ }
+ }
+
+ // Uncheck all the childs
+ for (int i = 0; i < item->childCount(); ++i) {
+ if (item->child(i)->checkState(0) != Qt::Unchecked) {
+ item->child(i)->setCheckState(0, Qt::Unchecked);
+ }
+ }
+ }
+
+ if (item->checkState(0) == Qt::PartiallyChecked) {
+ QTreeWidgetItem *parent = item->parent();
+ if (parent && parent->checkState(0) != Qt::PartiallyChecked) {
+ parent->setCheckState(0, Qt::PartiallyChecked);
+ }
+ }
+}
+
+QStringList SelectiveSyncDialog::createWhiteList(QTreeWidgetItem* root) const
+{
+ if (!root) {
+ root = _treeView->topLevelItem(0);
+ }
+ if (!root) return {};
+
+ switch(root->checkState(0)) {
+ case Qt::Checked:
+ return { root->data(0, Qt::UserRole).toString() };
+ case Qt::Unchecked:
+ return {};
+ case Qt::PartiallyChecked:
+ break;
+ }
+
+ QStringList result;
+ for (int i = 0; i < root->childCount(); ++i) {
+ result += createWhiteList(root->child(i));
+ }
+ return result;
+}
+
+void SelectiveSyncDialog::accept()
+{
+ QStringList whiteList = createWhiteList();
+ _folder->setSelectiveSyncList(whiteList);
+
+ // FIXME: Use MirallConfigFile
+ QSettings settings(_folder->configFile(), QSettings::IniFormat);
+ settings.beginGroup(FolderMan::escapeAlias(_folder->alias()));
+ settings.setValue("whiteList", whiteList);
+
+ QDialog::accept();
+}
+
+
+
+}
+
+
+
diff --git a/src/mirall/selectivesyncdialog.h b/src/mirall/selectivesyncdialog.h
new file mode 100644
index 0000000..a74a7aa
--- /dev/null
+++ b/src/mirall/selectivesyncdialog.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) by Olivier Goffart <ogoffart at woboq.com>
+ *
+ * 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.
+ */
+
+#pragma once
+#include <QDialog>
+
+class QTreeWidgetItem;
+class QTreeWidget;
+namespace Mirall {
+
+class Folder;
+
+class SelectiveSyncDialog : public QDialog {
+ Q_OBJECT
+public:
+ explicit SelectiveSyncDialog(Folder *folder, QWidget* parent = 0, Qt::WindowFlags f = 0);
+
+ virtual void accept() Q_DECL_OVERRIDE;
+ QStringList createWhiteList(QTreeWidgetItem* root = 0) const;
+
+private slots:
+ void refreshFolders();
+ void slotUpdateDirectories(const QStringList &);
+ void slotItemExpanded(QTreeWidgetItem *);
+ void slotItemChanged(QTreeWidgetItem*,int);
+
+private:
+ void recursiveInsert(QTreeWidgetItem* parent, QStringList pathTrail, QString path);
+
+ Folder *_folder;
+ QTreeWidget *_treeView;
+ bool _inserting = false; // set to true when we are inserting new items on the list
+};
+
+
+}
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git
More information about the Pkg-owncloud-commits
mailing list