Folders: Store inside account config.

This commit is contained in:
Christian Kamm 2015-04-24 10:18:33 +02:00
parent a13a974e2d
commit 27159104a9
12 changed files with 262 additions and 144 deletions

View file

@ -27,6 +27,8 @@ static const char authTypeC[] = "authType";
static const char userC[] = "user";
static const char httpUserC[] = "http_user";
static const char caCertsKeyC[] = "CaCertificates";
static const char accountsC[] = "Accounts";
static const char foldersC[] = "Folders";
}
@ -40,7 +42,7 @@ AccountManager *AccountManager::instance()
bool AccountManager::restore()
{
QScopedPointer<QSettings> settings(Account::settingsWithGroup("Accounts"));
QScopedPointer<QSettings> settings(Account::settingsWithGroup(QLatin1String(accountsC)));
// If there are no accounts, check the old format.
if (settings->childGroups().isEmpty()) {
@ -49,7 +51,7 @@ bool AccountManager::restore()
foreach (const auto& accountId, settings->childGroups()) {
settings->beginGroup(accountId);
if (auto acc = load(settings)) {
if (auto acc = load(*settings)) {
acc->_id = accountId;
addAccount(acc);
}
@ -106,7 +108,7 @@ bool AccountManager::restoreFromLegacySettings()
// Try to load the single account.
if (!settings->childKeys().isEmpty()) {
if (auto acc = load(settings)) {
if (auto acc = load(*settings)) {
if (migratedCreds) {
acc->setMigrated(true);
}
@ -119,41 +121,41 @@ bool AccountManager::restoreFromLegacySettings()
void AccountManager::save()
{
QScopedPointer<QSettings> settings(Account::settingsWithGroup("Accounts"));
QScopedPointer<QSettings> settings(Account::settingsWithGroup(QLatin1String(accountsC)));
foreach (const auto &acc, _accounts) {
settings->beginGroup(acc->account()->id());
save(acc->account(), settings);
save(acc->account(), *settings);
settings->endGroup();
}
}
void AccountManager::save(const AccountPtr& acc, QScopedPointer<QSettings>& settings)
void AccountManager::save(const AccountPtr& acc, QSettings& settings)
{
settings->setValue(QLatin1String(urlC), acc->_url.toString());
settings.setValue(QLatin1String(urlC), acc->_url.toString());
if (acc->_credentials) {
acc->_credentials->persist();
Q_FOREACH(QString key, acc->_settingsMap.keys()) {
settings->setValue(key, acc->_settingsMap.value(key));
settings.setValue(key, acc->_settingsMap.value(key));
}
settings->setValue(QLatin1String(authTypeC), acc->_credentials->authType());
settings.setValue(QLatin1String(authTypeC), acc->_credentials->authType());
// HACK: Save http_user also as user
if (acc->_settingsMap.contains(httpUserC))
settings->setValue(userC, acc->_settingsMap.value(httpUserC));
settings.setValue(userC, acc->_settingsMap.value(httpUserC));
}
settings->sync();
settings.sync();
// Save accepted certificates.
settings->beginGroup(QLatin1String("General"));
settings.beginGroup(QLatin1String("General"));
qDebug() << "Saving " << acc->approvedCerts().count() << " unknown certs.";
QByteArray certs;
Q_FOREACH( const QSslCertificate& cert, acc->approvedCerts() ) {
certs += cert.toPem() + '\n';
}
if (!certs.isEmpty()) {
settings->setValue( QLatin1String(caCertsKeyC), certs );
settings.setValue( QLatin1String(caCertsKeyC), certs );
}
settings->endGroup();
settings.endGroup();
// Save cookies.
if (acc->_am) {
@ -165,28 +167,29 @@ void AccountManager::save(const AccountPtr& acc, QScopedPointer<QSettings>& sett
}
}
AccountPtr AccountManager::load(const QScopedPointer<QSettings>& settings)
AccountPtr AccountManager::load(QSettings& settings)
{
auto acc = Account::create();
acc->setUrl(settings->value(QLatin1String(urlC)).toUrl());
acc->setUrl(settings.value(QLatin1String(urlC)).toUrl());
// We want to only restore settings for that auth type and the user value
acc->_settingsMap.insert(QLatin1String(userC), settings->value(userC));
QString authTypePrefix = settings->value(authTypeC).toString() + "_";
Q_FOREACH(QString key, settings->childKeys()) {
acc->_settingsMap.insert(QLatin1String(userC), settings.value(userC));
QString authTypePrefix = settings.value(authTypeC).toString() + "_";
Q_FOREACH(QString key, settings.childKeys()) {
if (!key.startsWith(authTypePrefix))
continue;
acc->_settingsMap.insert(key, settings->value(key));
acc->_settingsMap.insert(key, settings.value(key));
}
acc->setCredentials(CredentialsFactory::create(settings->value(QLatin1String(authTypeC)).toString()));
acc->setCredentials(CredentialsFactory::create(settings.value(QLatin1String(authTypeC)).toString()));
// now the cert, it is in the general group
settings->beginGroup(QLatin1String("General"));
acc->setApprovedCerts(QSslCertificate::fromData(settings->value(caCertsKeyC).toByteArray()));
settings.beginGroup(QLatin1String("General"));
acc->setApprovedCerts(QSslCertificate::fromData(settings.value(caCertsKeyC).toByteArray()));
acc->setSslErrorHandler(new SslDialogErrorHandler);
settings->endGroup();
settings.endGroup();
return acc;
}

View file

@ -51,8 +51,8 @@ public:
QList<AccountStatePtr> accounts() { return _accounts; }
private:
void save(const AccountPtr& account, QScopedPointer<QSettings>& settings);
AccountPtr load(const QScopedPointer<QSettings>& settings);
void save(const AccountPtr& account, QSettings& settings);
AccountPtr load(QSettings& settings);
bool restoreFromLegacySettings();
bool isAccountIdAvailable(const QString& id) const;

View file

@ -184,16 +184,13 @@ void AccountSettings::slotFolderWizardAccepted()
qDebug() << "* Folder wizard completed";
QString alias = folderWizard->field(QLatin1String("alias")).toString();
QString sourceFolder = folderWizard->field(QLatin1String("sourceFolder")).toString();
QString targetPath = folderWizard->property("targetPath").toString();
QStringList selectiveSyncBlackList
= folderWizard->property("selectiveSyncBlackList").toStringList();
FolderDefinition definition;
definition.alias = folderWizard->field(QLatin1String("alias")).toString();
definition.localPath = folderWizard->field(QLatin1String("sourceFolder")).toString();
definition.targetPath = folderWizard->property("targetPath").toString();
definition.selectiveSyncBlackList = folderWizard->property("selectiveSyncBlackList").toStringList();
if (!folderMan->addFolderDefinition(alias, sourceFolder, targetPath, selectiveSyncBlackList))
return;
Folder *f = folderMan->setupFolderFromConfigFile( alias );
Folder *f = folderMan->addFolder(_accountState, definition);
folderMan->setSyncEnabled(true);
if( f ) {
folderMan->slotScheduleAllFolders();

View file

@ -38,6 +38,7 @@
#include <QTimer>
#include <QUrl>
#include <QDir>
#include <QSettings>
#include <QMessageBox>
#include <QPushButton>
@ -54,16 +55,16 @@ static void csyncLogCatcher(int /*verbosity*/,
Folder::Folder(AccountState* accountState,
const QString& alias,
const QString& path,
const QString& secondPath,
const FolderDefinition& definition,
QObject* parent)
: QObject(parent)
, _accountState(accountState)
, _path(path)
, _remotePath(secondPath)
, _alias(alias)
, _paused(false)
, _definition(definition)
, _alias(_definition.alias)
, _path(_definition.localPath)
, _remotePath(_definition.targetPath)
, _paused(_definition.paused)
, _selectiveSyncBlackList(_definition.selectiveSyncBlackList)
, _csyncError(false)
, _csyncUnavail(false)
, _wipeDb(false)
@ -72,7 +73,7 @@ Folder::Folder(AccountState* accountState,
, _forceSyncOnPollTimeout(false)
, _consecutiveFailingSyncs(0)
, _consecutiveFollowUpSyncs(0)
, _journal(path)
, _journal(_path)
, _csync_ctx(0)
{
qsrand(QTime::currentTime().msec());
@ -84,7 +85,7 @@ Folder::Folder(AccountState* accountState,
// check if the local path exists
checkLocalPath();
_syncResult.setFolder(alias);
_syncResult.setFolder(_alias);
}
bool Folder::init()
@ -220,8 +221,13 @@ bool Folder::syncPaused() const
void Folder::setSyncPaused( bool paused )
{
const bool oldPaused = _paused;
_paused = paused;
if (_paused != oldPaused) {
saveToSettings();
}
if( !paused ) {
// qDebug() << "Syncing enabled on folder " << name();
} else {
@ -567,16 +573,6 @@ void Folder::slotWatchedPathChanged(const QString& path)
}
}
void Folder::setConfigFile( const QString& file )
{
_configFile = file;
}
QString Folder::configFile()
{
return _configFile;
}
static void addErroredSyncItemPathsToList(const SyncFileItemVector& items, QSet<QString>* set) {
Q_FOREACH(const SyncFileItem &item, items) {
if (item.hasErrorStatus()) {
@ -640,6 +636,20 @@ bool Folder::estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s)
return false;
}
void Folder::saveToSettings() const
{
QScopedPointer<QSettings> settings(_accountState->account()->settings());
settings->beginGroup(QLatin1String("Folders"));
FolderDefinition::save(*settings, _definition);
}
void Folder::removeFromSettings() const
{
QScopedPointer<QSettings> settings(_accountState->account()->settings());
settings->beginGroup(QLatin1String("Folders"));
settings->remove(_definition.alias);
}
void Folder::watcherSlot(QString fn)
{
// FIXME: On OS X we could not do this "if" since on OS X the file watcher ignores events for ourselves
@ -847,6 +857,7 @@ void Folder::setSelectiveSyncBlackList(const QStringList& blackList)
_selectiveSyncBlackList[i].append(QLatin1Char('/'));
}
}
saveToSettings();
}
@ -1020,5 +1031,31 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool *cancel)
QTimer::singleShot(50, this, SLOT(slotRunEtagJob()));
}
}
void FolderDefinition::save(QSettings& settings, const FolderDefinition& folder)
{
settings.beginGroup(folder.alias);
settings.setValue(QLatin1String("localPath"), folder.localPath);
settings.setValue(QLatin1String("targetPath"), folder.targetPath);
settings.setValue(QLatin1String("blackList"), folder.selectiveSyncBlackList);
settings.setValue(QLatin1String("paused"), folder.paused);
settings.endGroup();
}
bool FolderDefinition::load(QSettings& settings, const QString& alias,
FolderDefinition* folder)
{
settings.beginGroup(alias);
folder->alias = alias;
folder->localPath = settings.value(QLatin1String("localPath")).toString();
folder->targetPath = settings.value(QLatin1String("targetPath")).toString();
folder->selectiveSyncBlackList = settings.value(QLatin1String("blackList")).toStringList();
folder->paused = settings.value(QLatin1String("paused")).toBool();
settings.endGroup();
return true;
}
} // namespace OCC

View file

@ -37,19 +37,46 @@
#include <qelapsedtimer.h>
class QThread;
class QSettings;
namespace OCC {
class SyncEngine;
class AccountState;
class FolderDefinition
{
public:
FolderDefinition()
: paused(false)
{}
/// The name of the folder in the ui and internally
QString alias;
/// path on local machine
QString localPath;
/// path on remote
QString targetPath;
/// Which folders not to sync
QStringList selectiveSyncBlackList;
/// whether the folder is paused
bool paused;
/// Saves the folder definition, creating a new settings group.
static void save(QSettings& settings, const FolderDefinition& folder);
/// Reads a folder definition from a settings group with the name 'alias'.
static bool load(QSettings& settings, const QString& alias,
FolderDefinition* folder);
};
class Folder : public QObject
{
Q_OBJECT
public:
Folder(AccountState* accountState,
const QString&, const QString&, const QString& , QObject*parent = 0L);
Folder(AccountState* accountState, const FolderDefinition& definition,
QObject* parent = 0L);
~Folder();
@ -136,6 +163,11 @@ public:
qint64 msecLastSyncDuration() const { return _lastSyncDuration; }
int consecutiveFollowUpSyncs() const { return _consecutiveFollowUpSyncs; }
/// Saves the folder data in the account's settings.
void saveToSettings() const;
/// Removes the folder from the account's settings.
void removeFromSettings() const;
signals:
void syncStateChange();
void syncStarted();
@ -209,15 +241,17 @@ private:
const QString& renameTarget = QString::null );
AccountState* _accountState;
QString _path;
QString _remotePath;
QString _alias;
QString _configFile;
bool _paused;
FolderDefinition _definition;
// TODO: Remove these.
QString& _path;
QString& _remotePath;
QString& _alias;
bool& _paused;
QStringList& _selectiveSyncBlackList;
SyncResult _syncResult;
QScopedPointer<SyncEngine> _engine;
QStringList _errors;
QStringList _selectiveSyncBlackList;
bool _csyncError;
bool _csyncUnavail;
bool _wipeDb;

View file

@ -187,15 +187,51 @@ void FolderMan::removeMonitorPath( const QString& alias, const QString& path )
int FolderMan::setupFolders()
{
qDebug() << "* Setup folders from " << _folderConfigPath;
unloadAndDeleteAllFolders();
QScopedPointer<QSettings> settings(Account::settingsWithGroup(QLatin1String("Accounts")));
const auto accountsWithSettings = settings->childGroups();
if (accountsWithSettings.isEmpty()) {
return setupFoldersMigration();
}
qDebug() << "* Setup folders from settings file";
foreach (const auto& account, AccountManager::instance()->accounts()) {
const auto id = account->account()->id();
if (!accountsWithSettings.contains(id)) {
continue;
}
settings->beginGroup(id);
settings->beginGroup(QLatin1String("Folders"));
foreach (const auto& folderAlias, settings->childGroups()) {
FolderDefinition folderDefinition;
if (FolderDefinition::load(*settings, folderAlias, &folderDefinition)) {
Folder* f = addFolderInternal(account.data(), folderDefinition);
if (f) {
slotScheduleSync(f->alias());
emit folderSyncStateChange(f->alias());
}
}
}
settings->endGroup(); // Folders
settings->endGroup(); // <account>
}
emit folderListLoaded(_folderMap);
return _folderMap.size();
}
int FolderMan::setupFoldersMigration()
{
ConfigFile cfg;
QDir storageDir(cfg.configPath());
storageDir.mkpath(QLatin1String("folders"));
_folderConfigPath = cfg.configPath() + QLatin1String("folders");
qDebug() << "* Setup folders from " << _folderConfigPath << "(migration)";
QDir dir( _folderConfigPath );
//We need to include hidden files just in case the alias starts with '.'
dir.setFilter(QDir::Files | QDir::Hidden);
@ -352,9 +388,12 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
return 0;
}
folder = new Folder( accountState, alias, path, targetPath, this );
folder->setConfigFile(cfgFile.absoluteFilePath());
folder->setSelectiveSyncBlackList(blackList);
FolderDefinition folderDefinition;
folderDefinition.alias = alias;
folderDefinition.localPath = path;
folderDefinition.targetPath = targetPath;
folderDefinition.selectiveSyncBlackList = blackList;
folder = new Folder( accountState, folderDefinition, this );
qDebug() << "Adding folder to Folder Map " << folder;
_folderMap[alias] = folder;
if (paused) {
@ -384,16 +423,12 @@ void FolderMan::slotSetFolderPaused( const QString& alias, bool paused )
slotScheduleSync(alias);
// FIXME: Use ConfigFile
QSettings settings(f->configFile(), QSettings::IniFormat);
settings.beginGroup(escapeAlias(f->alias()));
if (!paused) {
settings.remove("paused");
_disabledFolders.remove(f);
} else {
settings.setValue("paused", true);
_disabledFolders.insert(f);
}
f->setSyncPaused(paused);
emit folderSyncStateChange(alias);
}
@ -703,25 +738,37 @@ void FolderMan::slotFolderSyncFinished( const SyncResult& )
startScheduledSyncSoon();
}
bool FolderMan::addFolderDefinition(const QString& alias, const QString& sourceFolder,
const QString& targetPath, const QStringList& selectiveSyncBlackList)
Folder* FolderMan::addFolder(AccountState* accountState, const FolderDefinition& folderDefinition)
{
if (! ensureJournalGone(sourceFolder))
return false;
if (!ensureJournalGone(folderDefinition.localPath)) {
return 0;
}
QString escapedAlias = escapeAlias(alias);
// Create a settings file named after the alias
QSettings settings( _folderConfigPath + QLatin1Char('/') + escapedAlias, QSettings::IniFormat);
settings.beginGroup(escapedAlias);
settings.setValue(QLatin1String("localPath"), sourceFolder );
settings.setValue(QLatin1String("targetPath"), targetPath );
// for compat reasons
settings.setValue(QLatin1String("backend"), "owncloud" );
settings.setValue(QLatin1String("connection"), Theme::instance()->appName());
settings.setValue(QLatin1String("blackList"), selectiveSyncBlackList);
settings.sync();
auto folder = addFolderInternal(accountState, folderDefinition);
folder->saveToSettings();
}
return true;
Folder* FolderMan::addFolderInternal(AccountState* accountState, const FolderDefinition& folderDefinition)
{
auto folder = new Folder( accountState, folderDefinition, this );
qDebug() << "Adding folder to Folder Map " << folder;
_folderMap[folder->alias()] = folder;
if (folderDefinition.paused) {
folder->setSyncPaused(true);
_disabledFolders.insert(folder);
}
/* Use a signal mapper to connect the signals to the alias */
connect(folder, SIGNAL(scheduleToSync(const QString&)), SLOT(slotScheduleSync(const QString&)));
connect(folder, SIGNAL(syncStateChange()), _folderChangeSignalMapper, SLOT(map()));
connect(folder, SIGNAL(syncStarted()), SLOT(slotFolderSyncStarted()));
connect(folder, SIGNAL(syncFinished(SyncResult)), SLOT(slotFolderSyncFinished(SyncResult)));
_folderChangeSignalMapper->setMapping( folder, folder->alias() );
registerFolderMonitor(folder);
return folder;
}
Folder *FolderMan::folderForPath(const QString &path)
@ -776,11 +823,7 @@ void FolderMan::slotRemoveFolder( const QString& alias )
f->setSyncPaused(true);
// remove the folder configuration
QFile file(f->configFile() );
if( file.exists() ) {
qDebug() << "Remove folder config file " << file.fileName();
file.remove();
}
f->removeFromSettings();
unloadFolder( alias );
if( !currentlyRunning ) {

View file

@ -41,22 +41,13 @@ public:
static FolderMan* instance();
int setupFolders();
int setupFoldersMigration();
OCC::Folder::Map map();
/**
* Add a folder definition to the config
* Params:
* QString alias
* QString sourceFolder on local machine
* QString targetPath on remote
*
* Ensures any existing journal in the sourceFolder is deleted.
* Returns true on success.
/** Adds a folder for an account, ensures the journal is gone and saves it in the settings.
*/
bool addFolderDefinition(const QString& alias, const QString& sourceFolder,
const QString& targetPath,
const QStringList& selectiveSyncBlacklist = QStringList());
Folder* addFolder(AccountState* accountState, const FolderDefinition& folderDefinition);
/** Returns the folder which the file or directory stored in path is in */
Folder* folderForPath(const QString& path);
@ -145,9 +136,14 @@ private slots:
// slot to take the next folder from queue and start syncing.
void slotStartScheduledFolderSync();
void slotEtagPollTimerTimeout();
void slotRemoveFoldersForAccount(AccountState* accountState);
private:
/** Adds a folder for an account, does not add it to the account settings.
*/
Folder* addFolderInternal(AccountState* accountState, const FolderDefinition& folderDefinition);
/* unloads a folder object, does not delete it */
void unloadFolder( const QString& alias );

View file

@ -475,10 +475,6 @@ void FolderStatusModel::slotApplySelectiveSync()
QStringList blackList = createBlackList(&_folders[i], oldBlackList);
folder->setSelectiveSyncBlackList(blackList);
// FIXME: Use ConfigFile
QSettings settings(folder->configFile(), QSettings::IniFormat);
settings.beginGroup(FolderMan::escapeAlias(folder->alias()));
settings.setValue("blackList", blackList);
FolderMan *folderMan = FolderMan::instance();
auto blackListSet = blackList.toSet();
auto oldBlackListSet = oldBlackList.toSet();

View file

@ -480,8 +480,14 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
bool startFromScratch = _ocWizard->field("OCSyncFromScratch").toBool();
if (!startFromScratch || ensureStartFromScratch(localFolder)) {
qDebug() << "Adding folder definition for" << localFolder << _remoteFolder;
folderMan->addFolderDefinition(Theme::instance()->appName(),
localFolder, _remoteFolder, _ocWizard->selectiveSyncBlacklist() );
FolderDefinition folderDefinition;
folderDefinition.alias = Theme::instance()->appName();
folderDefinition.localPath = localFolder;
folderDefinition.targetPath = _remoteFolder;
folderDefinition.selectiveSyncBlackList = _ocWizard->selectiveSyncBlacklist();
#warning fixme: which account? save the one from addAccount below?
AccountState* account = AccountManager::instance()->accounts().value(0).data();
folderMan->addFolder(account, folderDefinition);
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
}
}

View file

@ -400,10 +400,6 @@ void SelectiveSyncDialog::accept()
QStringList blackList = _treeView->createBlackList();
_folder->setSelectiveSyncBlackList(blackList);
// FIXME: Use ConfigFile
QSettings settings(_folder->configFile(), QSettings::IniFormat);
settings.beginGroup(FolderMan::escapeAlias(_folder->alias()));
settings.setValue("blackList", blackList);
FolderMan *folderMan = FolderMan::instance();
if (_folder->isBusy()) {
_folder->slotTerminateSync();

View file

@ -318,6 +318,13 @@ QSettings *Account::settingsWithGroup(const QString& group, QObject *parent)
return settings;
}
QSettings* Account::settings()
{
auto s = settingsWithGroup(QLatin1String("Accounts"));
s->beginGroup(id());
return s;
}
QVariant Account::credentialSetting(const QString &key) const
{
if (_credentials) {

View file

@ -121,6 +121,9 @@ public:
with the given parent. If no parents is specified, the caller must destroy the settings */
static QSettings* settingsWithGroup(const QString &group, QObject *parent = 0);
/** Returns a new settings object for this account, already in the right groups. */
QSettings* settings();
// to be called by credentials only
QVariant credentialSetting(const QString& key) const;
void setCredentialSetting(const QString& key, const QVariant &value);