2012-02-17 12:48:31 +04:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Klaas Freitag <freitag@owncloud.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.
|
|
|
|
*/
|
2012-07-20 19:13:23 +04:00
|
|
|
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "folderman.h"
|
2014-11-10 01:25:57 +03:00
|
|
|
#include "configfile.h"
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "folder.h"
|
|
|
|
#include "syncresult.h"
|
|
|
|
#include "theme.h"
|
2014-07-17 13:31:45 +04:00
|
|
|
#include "socketapi.h"
|
2014-08-29 22:40:33 +04:00
|
|
|
#include "account.h"
|
2014-12-18 14:09:48 +03:00
|
|
|
#include "accountstate.h"
|
2015-04-09 17:19:17 +03:00
|
|
|
#include "accountmanager.h"
|
2015-03-11 12:51:36 +03:00
|
|
|
#include "filesystem.h"
|
2012-02-17 12:48:31 +04:00
|
|
|
|
2012-10-20 20:47:33 +04:00
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
#include <CoreServices/CoreServices.h>
|
|
|
|
#endif
|
2012-12-07 22:53:36 +04:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
#include <shlobj.h>
|
|
|
|
#endif
|
2012-10-20 20:47:33 +04:00
|
|
|
|
2013-06-06 19:59:50 +04:00
|
|
|
#include <QMessageBox>
|
2014-07-14 17:31:38 +04:00
|
|
|
#include <QPointer>
|
2012-05-21 18:48:49 +04:00
|
|
|
#include <QtCore>
|
2014-12-03 00:32:54 +03:00
|
|
|
#include <QMutableSetIterator>
|
|
|
|
#include <QSet>
|
2012-05-21 18:48:49 +04:00
|
|
|
|
2014-11-10 00:34:07 +03:00
|
|
|
namespace OCC {
|
2012-02-17 12:48:31 +04:00
|
|
|
|
2013-07-22 15:59:52 +04:00
|
|
|
FolderMan* FolderMan::_instance = 0;
|
|
|
|
|
2014-09-17 15:35:54 +04:00
|
|
|
/**
|
|
|
|
* The minimum time between a sync being requested and it
|
|
|
|
* being executed in milliseconds.
|
|
|
|
*
|
2015-02-26 13:00:06 +03:00
|
|
|
* This delay must be large enough to ensure fileIsStillChanging()
|
|
|
|
* in the upload propagator doesn't decide to skip the file because
|
|
|
|
* the modification was too recent.
|
2014-09-17 15:35:54 +04:00
|
|
|
*/
|
2015-01-16 14:23:15 +03:00
|
|
|
static qint64 msBetweenRequestAndSync = 2000;
|
2014-09-17 15:35:54 +04:00
|
|
|
|
2012-02-17 12:48:31 +04:00
|
|
|
FolderMan::FolderMan(QObject *parent) :
|
2013-02-09 17:04:04 +04:00
|
|
|
QObject(parent),
|
2015-06-16 10:30:29 +03:00
|
|
|
_currentSyncFolder(0),
|
2015-07-17 13:12:00 +03:00
|
|
|
_syncEnabled( true ),
|
|
|
|
_appRestartRequired(false)
|
2012-02-17 12:48:31 +04:00
|
|
|
{
|
2014-05-26 16:34:08 +04:00
|
|
|
Q_ASSERT(!_instance);
|
|
|
|
_instance = this;
|
2014-07-15 15:34:32 +04:00
|
|
|
|
2014-07-17 17:00:21 +04:00
|
|
|
_socketApi = new SocketApi(this);
|
2014-12-03 00:32:54 +03:00
|
|
|
|
2014-12-10 15:01:36 +03:00
|
|
|
ConfigFile cfg;
|
2014-12-03 00:32:54 +03:00
|
|
|
int polltime = cfg.remotePollInterval();
|
|
|
|
qDebug() << "setting remote poll timer interval to" << polltime << "msec";
|
|
|
|
_etagPollTimer.setInterval( polltime );
|
|
|
|
QObject::connect(&_etagPollTimer, SIGNAL(timeout()), this, SLOT(slotEtagPollTimerTimeout()));
|
|
|
|
_etagPollTimer.start();
|
2014-12-18 14:09:48 +03:00
|
|
|
|
2015-01-16 14:23:15 +03:00
|
|
|
_startScheduledSyncTimer.setSingleShot(true);
|
|
|
|
connect(&_startScheduledSyncTimer, SIGNAL(timeout()),
|
|
|
|
SLOT(slotStartScheduledFolderSync()));
|
|
|
|
|
2015-04-17 18:56:17 +03:00
|
|
|
connect(AccountManager::instance(), SIGNAL(accountRemoved(AccountState*)),
|
2014-12-18 14:09:48 +03:00
|
|
|
SLOT(slotRemoveFoldersForAccount(AccountState*)));
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2013-07-22 15:59:52 +04:00
|
|
|
FolderMan *FolderMan::instance()
|
|
|
|
{
|
|
|
|
return _instance;
|
|
|
|
}
|
|
|
|
|
2012-02-17 12:48:31 +04:00
|
|
|
FolderMan::~FolderMan()
|
|
|
|
{
|
2013-06-29 00:27:53 +04:00
|
|
|
qDeleteAll(_folderMap);
|
2014-05-26 16:34:08 +04:00
|
|
|
_instance = 0;
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2014-11-10 00:34:07 +03:00
|
|
|
OCC::Folder::Map FolderMan::map()
|
2012-02-17 12:48:31 +04:00
|
|
|
{
|
|
|
|
return _folderMap;
|
|
|
|
}
|
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
void FolderMan::unloadFolder( Folder *f )
|
2014-07-15 18:06:06 +04:00
|
|
|
{
|
2015-02-27 12:42:59 +03:00
|
|
|
if( !f ) {
|
|
|
|
return;
|
|
|
|
}
|
2014-07-25 14:20:38 +04:00
|
|
|
|
2015-02-27 12:42:59 +03:00
|
|
|
if( _socketApi ) {
|
2015-04-28 16:13:39 +03:00
|
|
|
_socketApi->slotUnregisterPath(f->alias());
|
2015-02-27 12:42:59 +03:00
|
|
|
}
|
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
if( _folderWatchers.contains(f->alias())) {
|
|
|
|
_folderWatchers.remove(f->alias());
|
2014-07-15 18:06:06 +04:00
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
_folderMap.remove( f->alias() );
|
2015-06-17 16:55:48 +03:00
|
|
|
|
|
|
|
disconnect(f, SIGNAL(scheduleToSync(Folder*)),
|
|
|
|
this, SLOT(slotScheduleSync(Folder*)));
|
|
|
|
disconnect(f, SIGNAL(syncStarted()),
|
|
|
|
this, SLOT(slotFolderSyncStarted()));
|
|
|
|
disconnect(f, SIGNAL(syncFinished(SyncResult)),
|
|
|
|
this, SLOT(slotFolderSyncFinished(SyncResult)));
|
|
|
|
disconnect(f, SIGNAL(syncStateChange()),
|
|
|
|
this, SLOT(slotForwardFolderSyncStateChange()));
|
2014-07-15 18:06:06 +04:00
|
|
|
}
|
|
|
|
|
2015-02-27 12:42:59 +03:00
|
|
|
int FolderMan::unloadAndDeleteAllFolders()
|
2013-06-03 19:26:48 +04:00
|
|
|
{
|
|
|
|
int cnt = 0;
|
|
|
|
|
|
|
|
// clear the list of existing folders.
|
|
|
|
Folder::MapIterator i(_folderMap);
|
|
|
|
while (i.hasNext()) {
|
|
|
|
i.next();
|
2015-02-27 12:42:59 +03:00
|
|
|
Folder* f = i.value();
|
2015-04-28 16:13:39 +03:00
|
|
|
unloadFolder(f);
|
2015-02-27 12:42:59 +03:00
|
|
|
delete f;
|
2013-06-03 19:26:48 +04:00
|
|
|
cnt++;
|
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
_lastSyncFolder = 0;
|
|
|
|
_currentSyncFolder = 0;
|
2014-01-20 18:44:58 +04:00
|
|
|
_scheduleQueue.clear();
|
2015-09-04 11:33:48 +03:00
|
|
|
emit scheduleQueueChanged();
|
2014-07-15 18:06:06 +04:00
|
|
|
|
|
|
|
Q_ASSERT(_folderMap.count() == 0);
|
2013-06-03 19:26:48 +04:00
|
|
|
return cnt;
|
|
|
|
}
|
2012-02-17 12:48:31 +04:00
|
|
|
|
2014-01-11 23:35:16 +04:00
|
|
|
// add a monitor to the local file system. If there is a change in the
|
|
|
|
// file system, the method slotFolderMonitorFired is triggered through
|
|
|
|
// the SignalMapper
|
|
|
|
void FolderMan::registerFolderMonitor( Folder *folder )
|
|
|
|
{
|
|
|
|
if( !folder ) return;
|
|
|
|
|
|
|
|
if( !_folderWatchers.contains(folder->alias() ) ) {
|
2014-11-07 13:41:21 +03:00
|
|
|
FolderWatcher *fw = new FolderWatcher(folder->path(), folder);
|
2014-01-11 23:35:16 +04:00
|
|
|
|
2014-11-07 12:53:41 +03:00
|
|
|
// Connect the pathChanged signal, which comes with the changed path,
|
2014-01-11 23:35:16 +04:00
|
|
|
// to the signal mapper which maps to the folder alias. The changed path
|
|
|
|
// is lost this way, but we do not need it for the current implementation.
|
2014-11-07 13:41:21 +03:00
|
|
|
connect(fw, SIGNAL(pathChanged(QString)), folder, SLOT(slotWatchedPathChanged(QString)));
|
2014-01-11 23:35:16 +04:00
|
|
|
_folderWatchers.insert(folder->alias(), fw);
|
2014-10-13 19:23:42 +04:00
|
|
|
|
|
|
|
// This is at the moment only for the behaviour of the SocketApi.
|
2014-11-07 12:53:41 +03:00
|
|
|
connect(fw, SIGNAL(pathChanged(QString)), folder, SLOT(watcherSlot(QString)));
|
2014-01-11 23:35:16 +04:00
|
|
|
}
|
2014-07-25 14:20:38 +04:00
|
|
|
|
|
|
|
// register the folder with the socket API
|
|
|
|
if( _socketApi ) {
|
|
|
|
_socketApi->slotRegisterPath(folder->alias());
|
|
|
|
}
|
2014-01-11 23:35:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FolderMan::addMonitorPath( const QString& alias, const QString& path )
|
|
|
|
{
|
|
|
|
if( !alias.isEmpty() && _folderWatchers.contains(alias) ) {
|
|
|
|
FolderWatcher *fw = _folderWatchers[alias];
|
|
|
|
|
|
|
|
if( fw ) {
|
|
|
|
fw->addPath(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderMan::removeMonitorPath( const QString& alias, const QString& path )
|
|
|
|
{
|
|
|
|
if( !alias.isEmpty() && _folderWatchers.contains(alias) ) {
|
|
|
|
FolderWatcher *fw = _folderWatchers[alias];
|
|
|
|
|
|
|
|
if( fw ) {
|
|
|
|
fw->removePath(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-18 12:35:18 +04:00
|
|
|
int FolderMan::setupFolders()
|
2012-02-17 12:48:31 +04:00
|
|
|
{
|
2015-04-24 11:18:33 +03:00
|
|
|
unloadAndDeleteAllFolders();
|
2012-02-17 12:48:31 +04:00
|
|
|
|
2015-06-15 16:04:39 +03:00
|
|
|
auto settings = Account::settingsWithGroup(QLatin1String("Accounts"));
|
2015-04-24 11:18:33 +03:00
|
|
|
const auto accountsWithSettings = settings->childGroups();
|
|
|
|
if (accountsWithSettings.isEmpty()) {
|
2015-07-31 19:31:54 +03:00
|
|
|
int r = setupFoldersMigration();
|
|
|
|
if (r > 0) {
|
2015-08-06 13:49:18 +03:00
|
|
|
AccountManager::instance()->save(false); // don't save credentials, they had not been loaded from keychain
|
2015-07-31 19:31:54 +03:00
|
|
|
}
|
|
|
|
return r;
|
2015-04-24 11:18:33 +03:00
|
|
|
}
|
2013-02-10 14:00:22 +04:00
|
|
|
|
2015-04-24 11:18:33 +03:00
|
|
|
qDebug() << "* Setup folders from settings file";
|
2014-05-26 16:34:08 +04:00
|
|
|
|
2015-04-24 11:18:33 +03:00
|
|
|
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)) {
|
2015-06-17 15:53:58 +03:00
|
|
|
Folder* f = addFolderInternal(folderDefinition);
|
2015-04-24 11:18:33 +03:00
|
|
|
if (f) {
|
2015-06-17 15:53:58 +03:00
|
|
|
f->setAccountState( account.data() );
|
2015-04-28 16:13:39 +03:00
|
|
|
slotScheduleSync(f);
|
|
|
|
emit folderSyncStateChange(f);
|
2015-04-24 11:18:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
settings->endGroup(); // Folders
|
|
|
|
settings->endGroup(); // <account>
|
|
|
|
}
|
2012-02-17 14:11:18 +04:00
|
|
|
|
2015-04-24 11:18:33 +03:00
|
|
|
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);
|
|
|
|
QStringList list = dir.entryList();
|
|
|
|
|
2015-10-05 07:21:19 +03:00
|
|
|
// Normally there should be only one account when migrating.
|
2015-05-12 17:48:19 +03:00
|
|
|
AccountState* accountState = AccountManager::instance()->accounts().value(0).data();
|
2015-04-24 11:18:33 +03:00
|
|
|
foreach ( const QString& alias, list ) {
|
2015-05-12 17:48:19 +03:00
|
|
|
Folder *f = setupFolderFromOldConfigFile( alias, accountState );
|
2015-04-24 11:18:33 +03:00
|
|
|
if( f ) {
|
2015-04-28 16:13:39 +03:00
|
|
|
slotScheduleSync(f);
|
2015-09-04 11:33:48 +03:00
|
|
|
emit folderSyncStateChange(f);
|
2015-04-24 11:18:33 +03:00
|
|
|
}
|
2012-07-25 17:00:18 +04:00
|
|
|
}
|
2014-03-26 22:30:13 +04:00
|
|
|
|
2015-04-24 11:18:33 +03:00
|
|
|
emit folderListLoaded(_folderMap);
|
2014-03-26 22:30:13 +04:00
|
|
|
|
2015-04-24 11:18:33 +03:00
|
|
|
// return the number of valid folders.
|
|
|
|
return _folderMap.size();
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
2014-01-20 18:12:26 +04:00
|
|
|
|
2013-06-06 19:59:50 +04:00
|
|
|
bool FolderMan::ensureJournalGone(const QString &localPath)
|
|
|
|
{
|
2014-04-06 21:34:56 +04:00
|
|
|
// FIXME move this to UI, not libowncloudsync
|
2013-06-06 19:59:50 +04:00
|
|
|
// remove old .csync_journal file
|
2013-06-06 23:43:05 +04:00
|
|
|
QString stateDbFile = localPath+QLatin1String("/.csync_journal.db");
|
|
|
|
while (QFile::exists(stateDbFile) && !QFile::remove(stateDbFile)) {
|
2014-12-11 14:28:01 +03:00
|
|
|
qDebug() << "Could not remove old db file at" << stateDbFile;
|
2013-06-06 19:59:50 +04:00
|
|
|
int ret = QMessageBox::warning(0, tr("Could not reset folder state"),
|
|
|
|
tr("An old sync journal '%1' was found, "
|
|
|
|
"but could not be removed. Please make sure "
|
|
|
|
"that no application is currently using it.")
|
2013-06-06 23:43:05 +04:00
|
|
|
.arg(QDir::fromNativeSeparators(QDir::cleanPath(stateDbFile))),
|
2013-06-06 19:59:50 +04:00
|
|
|
QMessageBox::Retry|QMessageBox::Abort);
|
|
|
|
if (ret == QMessageBox::Abort) {
|
2013-06-06 23:43:05 +04:00
|
|
|
return false;
|
2013-06-06 19:59:50 +04:00
|
|
|
}
|
|
|
|
}
|
2013-06-06 23:43:05 +04:00
|
|
|
return true;
|
2013-06-06 19:59:50 +04:00
|
|
|
}
|
|
|
|
|
2012-10-17 17:13:55 +04:00
|
|
|
#define SLASH_TAG QLatin1String("__SLASH__")
|
|
|
|
#define BSLASH_TAG QLatin1String("__BSLASH__")
|
|
|
|
#define QMARK_TAG QLatin1String("__QMARK__")
|
|
|
|
#define PERCENT_TAG QLatin1String("__PERCENT__")
|
|
|
|
#define STAR_TAG QLatin1String("__STAR__")
|
|
|
|
#define COLON_TAG QLatin1String("__COLON__")
|
|
|
|
#define PIPE_TAG QLatin1String("__PIPE__")
|
|
|
|
#define QUOTE_TAG QLatin1String("__QUOTE__")
|
|
|
|
#define LT_TAG QLatin1String("__LESS_THAN__")
|
|
|
|
#define GT_TAG QLatin1String("__GREATER_THAN__")
|
2012-11-22 15:31:02 +04:00
|
|
|
#define PAR_O_TAG QLatin1String("__PAR_OPEN__")
|
|
|
|
#define PAR_C_TAG QLatin1String("__PAR_CLOSE__")
|
2012-10-17 17:13:55 +04:00
|
|
|
|
2014-08-11 17:09:17 +04:00
|
|
|
QString FolderMan::escapeAlias( const QString& alias )
|
2012-10-17 17:13:55 +04:00
|
|
|
{
|
|
|
|
QString a(alias);
|
|
|
|
|
|
|
|
a.replace( QLatin1Char('/'), SLASH_TAG );
|
|
|
|
a.replace( QLatin1Char('\\'), BSLASH_TAG );
|
|
|
|
a.replace( QLatin1Char('?'), QMARK_TAG );
|
|
|
|
a.replace( QLatin1Char('%'), PERCENT_TAG );
|
|
|
|
a.replace( QLatin1Char('*'), STAR_TAG );
|
|
|
|
a.replace( QLatin1Char(':'), COLON_TAG );
|
|
|
|
a.replace( QLatin1Char('|'), PIPE_TAG );
|
|
|
|
a.replace( QLatin1Char('"'), QUOTE_TAG );
|
|
|
|
a.replace( QLatin1Char('<'), LT_TAG );
|
|
|
|
a.replace( QLatin1Char('>'), GT_TAG );
|
2012-11-22 15:31:02 +04:00
|
|
|
a.replace( QLatin1Char('['), PAR_O_TAG );
|
|
|
|
a.replace( QLatin1Char(']'), PAR_C_TAG );
|
2012-10-17 17:13:55 +04:00
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2014-09-03 18:12:21 +04:00
|
|
|
SocketApi *FolderMan::socketApi()
|
|
|
|
{
|
|
|
|
return this->_socketApi;
|
|
|
|
}
|
|
|
|
|
2015-09-02 17:05:58 +03:00
|
|
|
QString FolderMan::unescapeAlias( const QString& alias )
|
2012-10-17 17:13:55 +04:00
|
|
|
{
|
|
|
|
QString a(alias);
|
|
|
|
|
|
|
|
a.replace( SLASH_TAG, QLatin1String("/") );
|
|
|
|
a.replace( BSLASH_TAG, QLatin1String("\\") );
|
|
|
|
a.replace( QMARK_TAG, QLatin1String("?") );
|
|
|
|
a.replace( PERCENT_TAG, QLatin1String("%") );
|
|
|
|
a.replace( STAR_TAG, QLatin1String("*") );
|
|
|
|
a.replace( COLON_TAG, QLatin1String(":") );
|
|
|
|
a.replace( PIPE_TAG, QLatin1String("|") );
|
|
|
|
a.replace( QUOTE_TAG, QLatin1String("\"") );
|
|
|
|
a.replace( LT_TAG, QLatin1String("<") );
|
|
|
|
a.replace( GT_TAG, QLatin1String(">") );
|
2012-11-22 15:31:02 +04:00
|
|
|
a.replace( PAR_O_TAG, QLatin1String("[") );
|
|
|
|
a.replace( PAR_C_TAG, QLatin1String("]") );
|
2012-10-17 17:13:55 +04:00
|
|
|
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2012-02-17 12:48:31 +04:00
|
|
|
// filename is the name of the file only, it does not include
|
|
|
|
// the configuration directory path
|
2015-05-12 17:48:19 +03:00
|
|
|
Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountState *accountState )
|
|
|
|
{
|
2012-10-17 17:13:55 +04:00
|
|
|
Folder *folder = 0;
|
2012-02-17 12:48:31 +04:00
|
|
|
|
|
|
|
qDebug() << " ` -> setting up:" << file;
|
2012-10-17 17:13:55 +04:00
|
|
|
QString escapedAlias(file);
|
2015-10-05 07:21:19 +03:00
|
|
|
// check the unescaped variant (for the case when the filename comes out
|
|
|
|
// of the directory listing). If the file does not exist, escape the
|
2012-10-17 17:13:55 +04:00
|
|
|
// file and try again.
|
|
|
|
QFileInfo cfgFile( _folderConfigPath, file);
|
|
|
|
|
|
|
|
if( !cfgFile.exists() ) {
|
|
|
|
// try the escaped variant.
|
|
|
|
escapedAlias = escapeAlias(file);
|
|
|
|
cfgFile.setFile( _folderConfigPath, escapedAlias );
|
|
|
|
}
|
|
|
|
if( !cfgFile.isReadable() ) {
|
2015-10-05 07:21:19 +03:00
|
|
|
qDebug() << "Cannot read folder definition for alias " << cfgFile.filePath();
|
2012-10-17 17:13:55 +04:00
|
|
|
return folder;
|
|
|
|
}
|
|
|
|
|
2013-11-13 21:58:06 +04:00
|
|
|
QSettings settings( _folderConfigPath + QLatin1Char('/') + escapedAlias, QSettings::IniFormat);
|
2012-08-17 19:13:17 +04:00
|
|
|
qDebug() << " -> file path: " << settings.fileName();
|
2012-02-17 12:48:31 +04:00
|
|
|
|
2012-11-22 15:31:29 +04:00
|
|
|
// Check if the filename is equal to the group setting. If not, use the group
|
|
|
|
// name as an alias.
|
|
|
|
QStringList groups = settings.childGroups();
|
|
|
|
|
|
|
|
if( ! groups.contains(escapedAlias) && groups.count() > 0 ) {
|
|
|
|
escapedAlias = groups.first();
|
|
|
|
}
|
|
|
|
|
2012-10-17 17:13:55 +04:00
|
|
|
settings.beginGroup( escapedAlias ); // read the group with the same name as the file which is the folder alias
|
2012-02-17 12:48:31 +04:00
|
|
|
|
2013-09-09 16:00:13 +04:00
|
|
|
QString path = settings.value(QLatin1String("localPath")).toString();
|
2012-08-17 19:13:17 +04:00
|
|
|
QString backend = settings.value(QLatin1String("backend")).toString();
|
2013-11-13 21:58:06 +04:00
|
|
|
QString targetPath = settings.value( QLatin1String("targetPath")).toString();
|
|
|
|
bool paused = settings.value( QLatin1String("paused"), false).toBool();
|
2012-10-17 17:13:55 +04:00
|
|
|
// QString connection = settings.value( QLatin1String("connection") ).toString();
|
2012-11-22 15:31:29 +04:00
|
|
|
QString alias = unescapeAlias( escapedAlias );
|
2012-02-17 14:11:18 +04:00
|
|
|
|
2013-07-22 22:27:42 +04:00
|
|
|
if (backend.isEmpty() || backend != QLatin1String("owncloud")) {
|
|
|
|
qWarning() << "obsolete configuration of type" << backend;
|
|
|
|
return 0;
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2013-07-22 22:27:42 +04:00
|
|
|
// cut off the leading slash, oCUrl always has a trailing.
|
|
|
|
if( targetPath.startsWith(QLatin1Char('/')) ) {
|
|
|
|
targetPath.remove(0,1);
|
|
|
|
}
|
2013-02-10 17:57:57 +04:00
|
|
|
|
2014-12-18 14:09:48 +03:00
|
|
|
if (!accountState) {
|
|
|
|
qWarning() << "can't create folder without an account";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-24 11:18:33 +03:00
|
|
|
FolderDefinition folderDefinition;
|
|
|
|
folderDefinition.alias = alias;
|
|
|
|
folderDefinition.localPath = path;
|
|
|
|
folderDefinition.targetPath = targetPath;
|
2015-06-17 16:55:48 +03:00
|
|
|
folderDefinition.paused = paused;
|
2015-08-10 12:03:57 +03:00
|
|
|
folderDefinition.ignoreHiddenFiles = ignoreHiddenFiles();
|
2015-06-17 15:53:58 +03:00
|
|
|
|
2015-06-17 16:55:48 +03:00
|
|
|
folder = addFolderInternal(folderDefinition);
|
|
|
|
if (folder) {
|
|
|
|
folder->setAccountState(accountState);
|
2012-02-17 12:48:31 +04:00
|
|
|
|
2015-06-17 15:53:58 +03:00
|
|
|
QStringList blackList = settings.value( QLatin1String("blackList")).toStringList();
|
|
|
|
if (!blackList.empty()) {
|
|
|
|
//migrate settings
|
|
|
|
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
|
|
|
|
settings.remove(QLatin1String("blackList"));
|
|
|
|
}
|
|
|
|
|
|
|
|
folder->saveToSettings();
|
2015-05-21 13:22:50 +03:00
|
|
|
}
|
2015-07-31 19:31:54 +03:00
|
|
|
qDebug() << "Migrated!" << folder;
|
2015-07-31 18:09:56 +03:00
|
|
|
settings.sync();
|
2012-02-17 12:48:31 +04:00
|
|
|
return folder;
|
|
|
|
}
|
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
void FolderMan::slotSetFolderPaused( Folder *f, bool paused )
|
2012-02-17 12:48:31 +04:00
|
|
|
{
|
2015-01-16 14:23:15 +03:00
|
|
|
if( !f ) {
|
2015-04-28 16:13:39 +03:00
|
|
|
qWarning() << "!! slotSetFolderPaused called with empty folder";
|
2015-01-16 14:23:15 +03:00
|
|
|
return;
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2015-11-11 12:56:19 +03:00
|
|
|
f->setSyncPaused(paused);
|
2015-01-16 14:23:15 +03:00
|
|
|
if (!paused) {
|
|
|
|
_disabledFolders.remove(f);
|
2015-11-11 12:56:19 +03:00
|
|
|
slotScheduleSync(f);
|
2015-01-16 14:23:15 +03:00
|
|
|
} else {
|
|
|
|
_disabledFolders.insert(f);
|
2012-04-30 10:56:56 +04:00
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
emit folderSyncStateChange(f);
|
2012-04-30 10:56:56 +04:00
|
|
|
}
|
|
|
|
|
2014-11-21 14:58:38 +03:00
|
|
|
// this really terminates the current sync process
|
|
|
|
// ie. no questions, no prisoners
|
2012-04-30 10:56:56 +04:00
|
|
|
// csync still remains in a stable state, regardless of that.
|
2014-11-21 14:58:38 +03:00
|
|
|
void FolderMan::terminateSyncProcess()
|
2012-04-30 10:56:56 +04:00
|
|
|
{
|
2015-04-28 16:13:39 +03:00
|
|
|
Folder *f = _currentSyncFolder;
|
2015-01-16 14:23:15 +03:00
|
|
|
if( f ) {
|
|
|
|
// This will, indirectly and eventually, call slotFolderSyncFinished
|
|
|
|
// and thereby clear _currentSyncFolder.
|
|
|
|
f->slotTerminateSync();
|
2012-04-30 10:56:56 +04:00
|
|
|
}
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2012-02-21 14:50:19 +04:00
|
|
|
Folder *FolderMan::folder( const QString& alias )
|
|
|
|
{
|
|
|
|
if( !alias.isEmpty() ) {
|
|
|
|
if( _folderMap.contains( alias )) {
|
|
|
|
return _folderMap[alias];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-02-19 20:24:10 +04:00
|
|
|
void FolderMan::slotScheduleAllFolders()
|
|
|
|
{
|
|
|
|
foreach( Folder *f, _folderMap.values() ) {
|
2015-07-01 12:39:57 +03:00
|
|
|
if (f && f->canSync()) {
|
2015-04-28 16:13:39 +03:00
|
|
|
slotScheduleSync( f );
|
2013-08-05 15:34:36 +04:00
|
|
|
}
|
2013-02-19 20:24:10 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-17 13:12:00 +03:00
|
|
|
void FolderMan::slotScheduleAppRestart()
|
|
|
|
{
|
|
|
|
_appRestartRequired = true;
|
|
|
|
qDebug() << "## Application restart requested!";
|
|
|
|
}
|
|
|
|
|
2012-03-22 19:22:08 +04:00
|
|
|
/*
|
|
|
|
* if a folder wants to be synced, it calls this slot and is added
|
|
|
|
* to the queue. The slot to actually start a sync is called afterwards.
|
|
|
|
*/
|
2015-04-28 16:13:39 +03:00
|
|
|
void FolderMan::slotScheduleSync( Folder *f )
|
2012-03-22 19:22:08 +04:00
|
|
|
{
|
2015-01-16 14:23:15 +03:00
|
|
|
if( !f ) {
|
2015-04-28 16:13:39 +03:00
|
|
|
qWarning() << "slotScheduleSync called with null folder";
|
2014-05-15 21:29:40 +04:00
|
|
|
return;
|
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
auto alias = f->alias();
|
2014-09-17 15:02:11 +04:00
|
|
|
|
2014-10-13 19:23:42 +04:00
|
|
|
if( _socketApi ) {
|
|
|
|
// We want the SocketAPI to already now update so that it can show the EVAL icon
|
|
|
|
// for files/folders. Only do this when not syncing, else we might get a lot
|
|
|
|
// of those notifications.
|
2015-05-12 16:50:38 +03:00
|
|
|
_socketApi->slotUpdateFolderView(f);
|
2014-05-15 21:29:40 +04:00
|
|
|
}
|
2014-09-17 15:02:11 +04:00
|
|
|
|
2014-01-11 23:35:16 +04:00
|
|
|
qDebug() << "Schedule folder " << alias << " to sync!";
|
2012-03-22 19:22:08 +04:00
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
if( ! _scheduleQueue.contains(f) ) {
|
2015-09-04 11:33:48 +03:00
|
|
|
if( !f->canSync() ) {
|
2015-07-01 12:39:57 +03:00
|
|
|
qDebug() << "Folder is not ready to sync, not scheduled!";
|
2014-09-30 14:33:51 +04:00
|
|
|
if( _socketApi ) {
|
2015-05-12 16:50:38 +03:00
|
|
|
_socketApi->slotUpdateFolderView(f);
|
2014-09-30 14:33:51 +04:00
|
|
|
}
|
2014-09-17 15:02:11 +04:00
|
|
|
return;
|
2014-01-11 23:35:16 +04:00
|
|
|
}
|
2015-09-04 11:33:48 +03:00
|
|
|
f->prepareToSync();
|
|
|
|
emit folderSyncStateChange(f);
|
2015-04-28 16:13:39 +03:00
|
|
|
_scheduleQueue.enqueue(f);
|
2015-09-04 11:33:48 +03:00
|
|
|
emit scheduleQueueChanged();
|
2012-03-29 12:13:19 +04:00
|
|
|
} else {
|
2013-02-20 19:06:46 +04:00
|
|
|
qDebug() << " II> Sync for folder " << alias << " already scheduled, do not enqueue!";
|
2012-03-29 12:13:19 +04:00
|
|
|
}
|
2014-09-17 15:02:11 +04:00
|
|
|
|
2015-01-16 14:23:15 +03:00
|
|
|
startScheduledSyncSoon();
|
2012-03-22 19:22:08 +04:00
|
|
|
}
|
|
|
|
|
2014-12-03 16:56:46 +03:00
|
|
|
void FolderMan::slotScheduleETagJob(const QString &/*alias*/, RequestEtagJob *job)
|
2014-12-03 00:32:54 +03:00
|
|
|
{
|
|
|
|
QObject::connect(job, SIGNAL(destroyed(QObject*)), this, SLOT(slotEtagJobDestroyed(QObject*)));
|
|
|
|
QMetaObject::invokeMethod(this, "slotRunOneEtagJob", Qt::QueuedConnection);
|
2014-12-03 16:56:46 +03:00
|
|
|
// maybe: add to queue
|
2014-12-03 00:32:54 +03:00
|
|
|
}
|
|
|
|
|
2014-12-03 16:56:46 +03:00
|
|
|
void FolderMan::slotEtagJobDestroyed(QObject* /*o*/)
|
2014-12-03 00:32:54 +03:00
|
|
|
{
|
2014-12-03 16:56:46 +03:00
|
|
|
// _currentEtagJob is automatically cleared
|
|
|
|
// maybe: remove from queue
|
2014-12-03 00:32:54 +03:00
|
|
|
QMetaObject::invokeMethod(this, "slotRunOneEtagJob", Qt::QueuedConnection);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderMan::slotRunOneEtagJob()
|
|
|
|
{
|
|
|
|
if (_currentEtagJob.isNull()) {
|
|
|
|
QString alias;
|
|
|
|
foreach(Folder *f, _folderMap) {
|
|
|
|
if (f->etagJob()) {
|
|
|
|
// Caveat: always grabs the first folder with a job, but we think this is Ok for now and avoids us having a seperate queue.
|
|
|
|
_currentEtagJob = f->etagJob();
|
|
|
|
alias = f->alias();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (_currentEtagJob.isNull()) {
|
2014-12-03 16:56:46 +03:00
|
|
|
qDebug() << "No more remote ETag check jobs to schedule.";
|
2015-07-17 13:12:00 +03:00
|
|
|
|
|
|
|
/* now it might be a good time to check for restarting... */
|
|
|
|
if( _currentSyncFolder == NULL && _appRestartRequired ) {
|
|
|
|
restartApplication();
|
|
|
|
}
|
2014-12-03 00:32:54 +03:00
|
|
|
} else {
|
2014-12-03 16:56:46 +03:00
|
|
|
qDebug() << "Scheduling" << alias << "to check remote ETag";
|
2014-12-03 00:32:54 +03:00
|
|
|
_currentEtagJob->start(); // on destroy/end it will continue the queue via slotEtagJobDestroyed
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-01 12:39:57 +03:00
|
|
|
void FolderMan::slotAccountStateChanged()
|
|
|
|
{
|
|
|
|
AccountState * accountState = qobject_cast<AccountState*>(sender());
|
|
|
|
if (! accountState) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QString accountName = accountState->account()->displayName();
|
|
|
|
|
|
|
|
if (accountState->isConnected()) {
|
|
|
|
qDebug() << "Account" << accountName << "connected, scheduling its folders";
|
|
|
|
|
|
|
|
foreach (Folder *f, _folderMap.values()) {
|
|
|
|
if (f
|
|
|
|
&& f->canSync()
|
|
|
|
&& f->accountState() == accountState) {
|
|
|
|
slotScheduleSync(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
qDebug() << "Account" << accountName << "disconnected, "
|
|
|
|
"terminating or descheduling sync folders";
|
|
|
|
|
|
|
|
if (_currentSyncFolder
|
|
|
|
&& _currentSyncFolder->accountState() == accountState) {
|
|
|
|
_currentSyncFolder->slotTerminateSync();
|
|
|
|
}
|
|
|
|
|
|
|
|
QMutableListIterator<Folder*> it(_scheduleQueue);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
Folder* f = it.next();
|
|
|
|
if (f->accountState() == accountState) {
|
|
|
|
it.remove();
|
|
|
|
}
|
|
|
|
}
|
2015-09-04 11:33:48 +03:00
|
|
|
emit scheduleQueueChanged();
|
2015-07-01 12:39:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-05 07:21:19 +03:00
|
|
|
// only enable or disable foldermans will schedule and do syncs.
|
2014-08-19 16:03:41 +04:00
|
|
|
// this is not the same as Pause and Resume of folders.
|
2013-02-10 14:00:22 +04:00
|
|
|
void FolderMan::setSyncEnabled( bool enabled )
|
|
|
|
{
|
2013-08-14 14:59:56 +04:00
|
|
|
if (!_syncEnabled && enabled && !_scheduleQueue.isEmpty()) {
|
2015-10-05 07:21:19 +03:00
|
|
|
// We have things in our queue that were waiting for the connection to come back on.
|
2015-01-16 14:23:15 +03:00
|
|
|
startScheduledSyncSoon();
|
2013-08-14 14:59:56 +04:00
|
|
|
}
|
2013-02-10 14:00:22 +04:00
|
|
|
_syncEnabled = enabled;
|
2014-08-19 16:03:41 +04:00
|
|
|
// force a redraw in case the network connect status changed
|
2015-04-28 16:13:39 +03:00
|
|
|
emit( folderSyncStateChange(0) );
|
2013-02-10 14:00:22 +04:00
|
|
|
}
|
|
|
|
|
2015-01-16 14:23:15 +03:00
|
|
|
void FolderMan::startScheduledSyncSoon(qint64 msMinimumDelay)
|
|
|
|
{
|
|
|
|
if (_startScheduledSyncTimer.isActive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (_scheduleQueue.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
if (_currentSyncFolder) {
|
2015-01-16 14:23:15 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
qint64 msDelay = msMinimumDelay;
|
|
|
|
qint64 msSinceLastSync = 0;
|
|
|
|
|
|
|
|
// Require a pause based on the duration of the last sync run.
|
2015-04-28 16:13:39 +03:00
|
|
|
if (Folder* lastFolder = _lastSyncFolder) {
|
2015-01-16 14:23:15 +03:00
|
|
|
msSinceLastSync = lastFolder->msecSinceLastSync();
|
|
|
|
|
|
|
|
// 1s -> 1.5s pause
|
|
|
|
// 10s -> 5s pause
|
|
|
|
// 1min -> 12s pause
|
|
|
|
// 1h -> 90s pause
|
|
|
|
qint64 pause = qSqrt(lastFolder->msecLastSyncDuration()) / 20.0 * 1000.0;
|
|
|
|
msDelay = qMax(msDelay, pause);
|
|
|
|
}
|
|
|
|
|
2015-01-16 14:45:12 +03:00
|
|
|
// Punish consecutive follow-up syncs with longer delays.
|
2015-04-28 16:13:39 +03:00
|
|
|
if (Folder* nextFolder = _scheduleQueue.head()) {
|
2015-01-16 14:45:12 +03:00
|
|
|
int followUps = nextFolder->consecutiveFollowUpSyncs();
|
|
|
|
if (followUps >= 2) {
|
|
|
|
// This is okay due to the 1min maximum delay limit below.
|
|
|
|
msDelay *= qPow(followUps, 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delays beyond one minute seem too big, particularly since there
|
|
|
|
// could be things later in the queue that shouldn't be punished by a
|
|
|
|
// long delay!
|
2015-01-16 14:23:15 +03:00
|
|
|
msDelay = qMin(msDelay, 60*1000ll);
|
|
|
|
|
2015-01-28 13:23:20 +03:00
|
|
|
// Time since the last sync run counts against the delay
|
2015-01-16 14:23:15 +03:00
|
|
|
msDelay = qMax(1ll, msDelay - msSinceLastSync);
|
2015-01-28 13:23:20 +03:00
|
|
|
|
|
|
|
// A minimum of delay here is essential as the sync will not upload
|
|
|
|
// files that were changed too recently.
|
|
|
|
msDelay = qMax(msBetweenRequestAndSync, msDelay);
|
|
|
|
|
2015-01-16 14:23:15 +03:00
|
|
|
qDebug() << "Scheduling a sync in" << (msDelay/1000) << "seconds";
|
|
|
|
_startScheduledSyncTimer.start(msDelay);
|
|
|
|
}
|
|
|
|
|
2012-03-22 19:22:08 +04:00
|
|
|
/*
|
|
|
|
* slot to start folder syncs.
|
|
|
|
* It is either called from the slot where folders enqueue themselves for
|
|
|
|
* syncing or after a folder sync was finished.
|
|
|
|
*/
|
2014-09-17 15:02:11 +04:00
|
|
|
void FolderMan::slotStartScheduledFolderSync()
|
2012-03-22 19:22:08 +04:00
|
|
|
{
|
2015-04-28 16:13:39 +03:00
|
|
|
if( _currentSyncFolder ) {
|
|
|
|
qDebug() << "Currently folder " << _currentSyncFolder->alias() << " is running, wait for finish!";
|
2012-03-22 19:22:08 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-10 14:00:22 +04:00
|
|
|
if( ! _syncEnabled ) {
|
|
|
|
qDebug() << "FolderMan: Syncing is disabled, no scheduling.";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-30 10:56:56 +04:00
|
|
|
qDebug() << "XX slotScheduleFolderSync: folderQueue size: " << _scheduleQueue.count();
|
2015-01-16 14:23:15 +03:00
|
|
|
if( _scheduleQueue.isEmpty() ) {
|
|
|
|
return;
|
|
|
|
}
|
2014-01-11 23:35:16 +04:00
|
|
|
|
2015-11-11 12:56:19 +03:00
|
|
|
// Find the first folder in the queue that can be synced.
|
|
|
|
Folder* f = nullptr;
|
|
|
|
while( !_scheduleQueue.isEmpty() ) {
|
|
|
|
f = _scheduleQueue.dequeue();
|
|
|
|
Q_ASSERT(f);
|
|
|
|
|
|
|
|
if( f->canSync() ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 11:33:48 +03:00
|
|
|
emit scheduleQueueChanged();
|
2014-01-11 23:35:16 +04:00
|
|
|
|
2015-01-16 14:23:15 +03:00
|
|
|
// Start syncing this folder!
|
2015-11-11 12:56:19 +03:00
|
|
|
if( f ) {
|
2015-04-28 16:13:39 +03:00
|
|
|
_currentSyncFolder = f;
|
2015-01-16 14:23:15 +03:00
|
|
|
f->startSync( QStringList() );
|
2012-03-22 19:22:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-03 00:32:54 +03:00
|
|
|
void FolderMan::slotEtagPollTimerTimeout()
|
|
|
|
{
|
|
|
|
//qDebug() << Q_FUNC_INFO << "Checking if we need to make any folders check the remote ETag";
|
2014-12-10 15:01:36 +03:00
|
|
|
ConfigFile cfg;
|
2014-12-03 00:32:54 +03:00
|
|
|
int polltime = cfg.remotePollInterval();
|
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
foreach (Folder *f, _folderMap) {
|
2015-07-01 12:39:57 +03:00
|
|
|
if (!f) {
|
|
|
|
continue;
|
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
if (_currentSyncFolder == f) {
|
2014-12-03 00:32:54 +03:00
|
|
|
continue;
|
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
if (_scheduleQueue.contains(f)) {
|
2014-12-03 00:32:54 +03:00
|
|
|
continue;
|
|
|
|
}
|
2015-07-01 12:39:57 +03:00
|
|
|
if (_disabledFolders.contains(f)) {
|
2014-12-03 00:32:54 +03:00
|
|
|
continue;
|
|
|
|
}
|
2015-07-01 12:39:57 +03:00
|
|
|
if (f->etagJob() || f->isBusy() || !f->canSync()) {
|
2014-12-03 00:32:54 +03:00
|
|
|
continue;
|
|
|
|
}
|
2015-07-01 12:39:57 +03:00
|
|
|
if (f->msecSinceLastSync() < polltime) {
|
2014-12-03 00:32:54 +03:00
|
|
|
continue;
|
|
|
|
}
|
2015-04-28 16:13:39 +03:00
|
|
|
QMetaObject::invokeMethod(f, "slotRunEtagJob", Qt::QueuedConnection);
|
2014-12-03 00:32:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-18 14:09:48 +03:00
|
|
|
void FolderMan::slotRemoveFoldersForAccount(AccountState* accountState)
|
|
|
|
{
|
2015-04-28 16:13:39 +03:00
|
|
|
QVarLengthArray<Folder *, 16> foldersToRemove;
|
2014-12-18 14:09:48 +03:00
|
|
|
Folder::MapIterator i(_folderMap);
|
|
|
|
while (i.hasNext()) {
|
|
|
|
i.next();
|
|
|
|
Folder* folder = i.value();
|
|
|
|
if (folder->accountState() == accountState) {
|
2015-04-28 16:13:39 +03:00
|
|
|
foldersToRemove.append(folder);
|
2014-12-18 14:09:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
foreach (const auto &f, foldersToRemove) {
|
|
|
|
slotRemoveFolder(f);
|
2014-12-18 14:09:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-17 16:55:48 +03:00
|
|
|
void FolderMan::slotForwardFolderSyncStateChange()
|
|
|
|
{
|
|
|
|
if (Folder* f = qobject_cast<Folder*>(sender())) {
|
|
|
|
emit folderSyncStateChange(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-17 12:48:31 +04:00
|
|
|
void FolderMan::slotFolderSyncStarted( )
|
|
|
|
{
|
2015-04-28 16:13:39 +03:00
|
|
|
qDebug() << ">===================================== sync started for " << _currentSyncFolder->alias();
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2012-03-22 19:22:08 +04:00
|
|
|
/*
|
|
|
|
* a folder indicates that its syncing is finished.
|
|
|
|
* Start the next sync after the system had some milliseconds to breath.
|
2014-10-09 17:50:29 +04:00
|
|
|
* This delay is particularly useful to avoid late file change notifications
|
|
|
|
* (that we caused ourselves by syncing) from triggering another spurious sync.
|
2012-03-22 19:22:08 +04:00
|
|
|
*/
|
2012-02-17 12:48:31 +04:00
|
|
|
void FolderMan::slotFolderSyncFinished( const SyncResult& )
|
|
|
|
{
|
2015-04-28 16:13:39 +03:00
|
|
|
qDebug() << "<===================================== sync finished for " << _currentSyncFolder->alias();
|
2012-03-29 12:13:19 +04:00
|
|
|
|
2015-01-16 14:23:15 +03:00
|
|
|
_lastSyncFolder = _currentSyncFolder;
|
2015-04-28 16:13:39 +03:00
|
|
|
_currentSyncFolder = 0;
|
2014-01-11 23:35:16 +04:00
|
|
|
|
2015-01-16 14:23:15 +03:00
|
|
|
startScheduledSyncSoon();
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2015-04-24 11:18:33 +03:00
|
|
|
Folder* FolderMan::addFolder(AccountState* accountState, const FolderDefinition& folderDefinition)
|
2012-02-17 12:48:31 +04:00
|
|
|
{
|
2015-04-24 11:18:33 +03:00
|
|
|
if (!ensureJournalGone(folderDefinition.localPath)) {
|
|
|
|
return 0;
|
|
|
|
}
|
2014-12-11 14:28:01 +03:00
|
|
|
|
2015-06-17 15:53:58 +03:00
|
|
|
auto folder = addFolderInternal(folderDefinition);
|
2015-07-13 15:35:19 +03:00
|
|
|
if(folder && accountState) {
|
2015-06-17 15:53:58 +03:00
|
|
|
folder->setAccountState(accountState);
|
2015-06-17 15:54:39 +03:00
|
|
|
folder->saveToSettings();
|
2015-06-17 15:53:58 +03:00
|
|
|
}
|
2015-04-27 15:34:39 +03:00
|
|
|
return folder;
|
2015-04-24 11:18:33 +03:00
|
|
|
}
|
2014-12-11 14:28:01 +03:00
|
|
|
|
2015-06-17 15:53:58 +03:00
|
|
|
Folder* FolderMan::addFolderInternal(const FolderDefinition& folderDefinition)
|
2015-04-24 11:18:33 +03:00
|
|
|
{
|
2015-06-17 15:53:58 +03:00
|
|
|
auto folder = new Folder(folderDefinition, this );
|
2015-04-24 11:18:33 +03:00
|
|
|
|
|
|
|
qDebug() << "Adding folder to Folder Map " << folder;
|
|
|
|
_folderMap[folder->alias()] = folder;
|
2015-06-17 16:55:48 +03:00
|
|
|
if (folder->syncPaused()) {
|
2015-04-24 11:18:33 +03:00
|
|
|
_disabledFolders.insert(folder);
|
|
|
|
}
|
|
|
|
|
2015-06-17 16:55:48 +03:00
|
|
|
// See matching disconnects in unloadFolder().
|
2015-04-28 16:13:39 +03:00
|
|
|
connect(folder, SIGNAL(scheduleToSync(Folder*)), SLOT(slotScheduleSync(Folder*)));
|
2015-04-24 11:18:33 +03:00
|
|
|
connect(folder, SIGNAL(syncStarted()), SLOT(slotFolderSyncStarted()));
|
|
|
|
connect(folder, SIGNAL(syncFinished(SyncResult)), SLOT(slotFolderSyncFinished(SyncResult)));
|
2015-06-17 16:55:48 +03:00
|
|
|
connect(folder, SIGNAL(syncStateChange()), SLOT(slotForwardFolderSyncStateChange()));
|
2015-04-24 11:18:33 +03:00
|
|
|
|
|
|
|
registerFolderMonitor(folder);
|
|
|
|
return folder;
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2014-07-01 18:24:14 +04:00
|
|
|
Folder *FolderMan::folderForPath(const QString &path)
|
2013-10-03 19:04:55 +04:00
|
|
|
{
|
2014-07-14 17:13:28 +04:00
|
|
|
QString absolutePath = QDir::cleanPath(path)+QLatin1Char('/');
|
2013-10-03 19:04:55 +04:00
|
|
|
|
2014-07-14 17:13:28 +04:00
|
|
|
foreach(Folder* folder, this->map().values()) {
|
2015-05-05 18:34:01 +03:00
|
|
|
const QString folderPath = folder->cleanPath()+QLatin1Char('/');
|
2014-07-14 17:13:28 +04:00
|
|
|
|
|
|
|
if(absolutePath.startsWith(folderPath)) {
|
2014-10-13 19:23:42 +04:00
|
|
|
//qDebug() << "found folder: " << folder->path() << " for " << absolutePath;
|
2013-10-03 19:04:55 +04:00
|
|
|
return folder;
|
|
|
|
}
|
|
|
|
}
|
2015-01-15 19:51:08 +03:00
|
|
|
|
2013-10-03 19:04:55 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-11-16 17:04:59 +03:00
|
|
|
QStringList FolderMan::findFileInLocalFolders( const QString& relPath )
|
|
|
|
{
|
|
|
|
QStringList re;
|
|
|
|
|
|
|
|
foreach(Folder* folder, this->map().values()) {
|
|
|
|
QString path = folder->cleanPath();
|
|
|
|
QString remRelPath;
|
2015-11-16 17:38:08 +03:00
|
|
|
// cut off the remote path from the server path.
|
2015-11-16 17:04:59 +03:00
|
|
|
remRelPath = relPath.mid(folder->remotePath().length());
|
|
|
|
path += remRelPath;
|
|
|
|
|
|
|
|
if( QFile::exists(path) ) {
|
|
|
|
re.append( path );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return re;
|
|
|
|
}
|
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
void FolderMan::slotRemoveFolder( Folder *f )
|
2012-02-17 12:48:31 +04:00
|
|
|
{
|
2015-02-27 12:42:59 +03:00
|
|
|
if( !f ) {
|
2015-04-28 16:13:39 +03:00
|
|
|
qWarning() << "!! Can not remove null folder";
|
2015-02-27 12:42:59 +03:00
|
|
|
return;
|
2012-03-29 12:13:19 +04:00
|
|
|
}
|
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
qDebug() << "Removing " << f->alias();
|
2013-06-12 14:41:32 +04:00
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
const bool currentlyRunning = (_currentSyncFolder == f);
|
2015-02-27 12:42:59 +03:00
|
|
|
if( currentlyRunning ) {
|
|
|
|
// abort the sync now
|
|
|
|
terminateSyncProcess();
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
|
2015-09-04 11:33:48 +03:00
|
|
|
if (_scheduleQueue.removeAll(f) > 0) {
|
|
|
|
emit scheduleQueueChanged();
|
|
|
|
}
|
2014-03-10 15:22:06 +04:00
|
|
|
|
2015-02-27 12:42:59 +03:00
|
|
|
f->wipe();
|
|
|
|
f->setSyncPaused(true);
|
2014-07-15 18:06:06 +04:00
|
|
|
|
2015-02-27 12:42:59 +03:00
|
|
|
// remove the folder configuration
|
2015-04-24 11:18:33 +03:00
|
|
|
f->removeFromSettings();
|
2014-07-15 18:06:06 +04:00
|
|
|
|
2015-04-28 16:13:39 +03:00
|
|
|
unloadFolder( f);
|
2015-09-18 15:34:01 +03:00
|
|
|
if( currentlyRunning ) {
|
|
|
|
// We want to schedule the next folder once this is done
|
|
|
|
connect(f, SIGNAL(syncFinished(SyncResult)),
|
|
|
|
SLOT(slotFolderSyncFinished(SyncResult)));
|
|
|
|
// Let the folder delete itself when done.
|
|
|
|
connect(f, SIGNAL(syncFinished(SyncResult)), f, SLOT(deleteLater()));
|
|
|
|
} else {
|
2015-02-27 12:42:59 +03:00
|
|
|
delete f;
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-15 15:49:13 +04:00
|
|
|
QString FolderMan::getBackupName( QString fullPathName ) const
|
2013-05-26 15:56:51 +04:00
|
|
|
{
|
2014-09-15 15:49:13 +04:00
|
|
|
if (fullPathName.endsWith("/"))
|
|
|
|
fullPathName.chop(1);
|
|
|
|
|
2013-05-26 15:56:51 +04:00
|
|
|
if( fullPathName.isEmpty() ) return QString::null;
|
|
|
|
|
2015-07-29 13:23:33 +03:00
|
|
|
QString newName = fullPathName + tr(" (backup)");
|
2013-05-26 15:56:51 +04:00
|
|
|
QFileInfo fi( newName );
|
2015-08-03 10:17:45 +03:00
|
|
|
int cnt = 2;
|
2013-05-26 15:56:51 +04:00
|
|
|
do {
|
|
|
|
if( fi.exists() ) {
|
2015-07-29 13:23:33 +03:00
|
|
|
newName = fullPathName + tr(" (backup %1)").arg(cnt++);
|
2013-05-26 15:56:51 +04:00
|
|
|
fi.setFile(newName);
|
|
|
|
}
|
|
|
|
} while( fi.exists() );
|
|
|
|
|
|
|
|
return newName;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FolderMan::startFromScratch( const QString& localFolder )
|
|
|
|
{
|
2014-09-05 12:13:00 +04:00
|
|
|
if( localFolder.isEmpty() ) {
|
|
|
|
return false;
|
|
|
|
}
|
2013-05-26 15:56:51 +04:00
|
|
|
|
|
|
|
QFileInfo fi( localFolder );
|
2014-09-05 12:13:00 +04:00
|
|
|
QDir parentDir( fi.dir() );
|
|
|
|
QString folderName = fi.fileName();
|
|
|
|
|
|
|
|
// Adjust for case where localFolder ends with a /
|
|
|
|
if ( fi.isDir() ) {
|
|
|
|
folderName = parentDir.dirName();
|
|
|
|
parentDir.cdUp();
|
|
|
|
}
|
2013-06-03 17:47:07 +04:00
|
|
|
|
2014-09-05 12:13:00 +04:00
|
|
|
if( fi.exists() ) {
|
|
|
|
// It exists, but is empty -> just reuse it.
|
|
|
|
if( fi.isDir() && fi.dir().count() == 0 ) {
|
2013-06-03 17:47:07 +04:00
|
|
|
qDebug() << "startFromScratch: Directory is empty!";
|
|
|
|
return true;
|
|
|
|
}
|
2014-10-24 13:12:02 +04:00
|
|
|
// Disconnect the socket api from the database to avoid that locking of the
|
|
|
|
// db file does not allow to move this dir.
|
|
|
|
if( _socketApi ) {
|
2014-10-24 17:07:33 +04:00
|
|
|
Folder *f = folderForPath(localFolder);
|
|
|
|
if(f) {
|
|
|
|
if( localFolder.startsWith(f->path()) ) {
|
|
|
|
_socketApi->slotUnregisterPath(f->alias());
|
2014-10-24 13:36:01 +04:00
|
|
|
}
|
2014-12-02 12:21:27 +03:00
|
|
|
f->journalDb()->close();
|
2015-10-05 07:21:19 +03:00
|
|
|
f->slotTerminateSync(); // Normally it should not be running, but viel hilft viel
|
2014-10-24 13:36:01 +04:00
|
|
|
}
|
2014-10-24 13:12:02 +04:00
|
|
|
}
|
|
|
|
|
2014-09-05 12:13:00 +04:00
|
|
|
// Make a backup of the folder/file.
|
|
|
|
QString newName = getBackupName( parentDir.absoluteFilePath( folderName ) );
|
2015-03-11 12:51:36 +03:00
|
|
|
QString renameError;
|
|
|
|
if( !FileSystem::rename( fi.absoluteFilePath(), newName, &renameError ) ) {
|
2014-09-05 12:13:00 +04:00
|
|
|
qDebug() << "startFromScratch: Could not rename" << fi.absoluteFilePath()
|
2015-03-11 12:51:36 +03:00
|
|
|
<< "to" << newName << "error:" << renameError;
|
2014-09-05 12:13:00 +04:00
|
|
|
return false;
|
2013-05-26 15:56:51 +04:00
|
|
|
}
|
|
|
|
}
|
2014-09-05 12:13:00 +04:00
|
|
|
|
|
|
|
if( !parentDir.mkdir( fi.absoluteFilePath() ) ) {
|
|
|
|
qDebug() << "startFromScratch: Could not mkdir" << fi.absoluteFilePath();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2013-05-26 15:56:51 +04:00
|
|
|
}
|
|
|
|
|
2013-10-14 18:11:15 +04:00
|
|
|
void FolderMan::setDirtyProxy(bool value)
|
|
|
|
{
|
|
|
|
foreach( Folder *f, _folderMap.values() ) {
|
2014-01-20 18:12:26 +04:00
|
|
|
if(f) {
|
|
|
|
f->setProxyDirty(value);
|
2015-03-25 14:25:18 +03:00
|
|
|
|
|
|
|
if (f->accountState() && f->accountState()->account()
|
|
|
|
&& f->accountState()->account()->networkAccessManager()) {
|
2015-10-05 07:21:19 +03:00
|
|
|
// Need to do this so we do not use the old determined system proxy
|
2015-03-25 14:25:18 +03:00
|
|
|
f->accountState()->account()->networkAccessManager()->setProxy(
|
|
|
|
QNetworkProxy(QNetworkProxy::DefaultProxy));
|
|
|
|
}
|
2014-01-20 18:12:26 +04:00
|
|
|
}
|
2013-10-14 18:11:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-31 20:29:50 +04:00
|
|
|
void FolderMan::setDirtyNetworkLimits()
|
|
|
|
{
|
|
|
|
foreach( Folder *f, _folderMap.values() ) {
|
|
|
|
// set only in busy folders. Otherwise they read the config anyway.
|
|
|
|
if(f && f->isBusy()) {
|
|
|
|
f->setDirtyNetworkLimits();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2013-10-14 18:11:15 +04:00
|
|
|
|
2013-07-22 14:10:13 +04:00
|
|
|
SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
|
|
|
|
{
|
|
|
|
SyncResult overallResult(SyncResult::Undefined);
|
|
|
|
|
2013-12-20 18:13:33 +04:00
|
|
|
int cnt = folders.count();
|
|
|
|
|
|
|
|
// if one folder: show the state of the one folder.
|
2015-10-05 07:21:19 +03:00
|
|
|
// if more folders:
|
2013-12-20 18:13:33 +04:00
|
|
|
// if one of them has an error -> show error
|
|
|
|
// if one is paused, but others ok, show ok
|
|
|
|
// do not show "problem" in the tray
|
|
|
|
//
|
|
|
|
if( cnt == 1 ) {
|
|
|
|
Folder *folder = folders.at(0);
|
|
|
|
if( folder ) {
|
2014-08-19 15:58:20 +04:00
|
|
|
if( folder->syncPaused() ) {
|
|
|
|
overallResult.setStatus(SyncResult::Paused);
|
|
|
|
} else {
|
|
|
|
SyncResult::Status syncStatus = folder->syncResult().status();
|
|
|
|
|
|
|
|
|
|
|
|
switch( syncStatus ) {
|
|
|
|
case SyncResult::Undefined:
|
|
|
|
overallResult.setStatus(SyncResult::Error);
|
|
|
|
break;
|
|
|
|
case SyncResult::NotYetStarted:
|
|
|
|
overallResult.setStatus( SyncResult::NotYetStarted );
|
|
|
|
break;
|
|
|
|
case SyncResult::SyncPrepare:
|
|
|
|
overallResult.setStatus( SyncResult::SyncPrepare );
|
|
|
|
break;
|
|
|
|
case SyncResult::SyncRunning:
|
|
|
|
overallResult.setStatus( SyncResult::SyncRunning );
|
|
|
|
break;
|
|
|
|
case SyncResult::Problem: // don't show the problem icon in tray.
|
|
|
|
case SyncResult::Success:
|
|
|
|
if( overallResult.status() == SyncResult::Undefined )
|
|
|
|
overallResult.setStatus( SyncResult::Success );
|
|
|
|
break;
|
|
|
|
case SyncResult::Error:
|
|
|
|
overallResult.setStatus( SyncResult::Error );
|
|
|
|
break;
|
|
|
|
case SyncResult::SetupError:
|
|
|
|
if ( overallResult.status() != SyncResult::Error )
|
|
|
|
overallResult.setStatus( SyncResult::SetupError );
|
|
|
|
break;
|
|
|
|
case SyncResult::SyncAbortRequested:
|
|
|
|
overallResult.setStatus( SyncResult::SyncAbortRequested);
|
|
|
|
break;
|
|
|
|
case SyncResult::Paused:
|
|
|
|
overallResult.setStatus( SyncResult::Paused);
|
|
|
|
break;
|
|
|
|
}
|
2013-12-20 18:13:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int errorsSeen = 0;
|
|
|
|
int goodSeen = 0;
|
2015-07-01 12:39:57 +03:00
|
|
|
int abortOrPausedSeen = 0;
|
2013-12-20 18:13:33 +04:00
|
|
|
int runSeen = 0;
|
|
|
|
int various = 0;
|
|
|
|
|
|
|
|
foreach ( Folder *folder, folders ) {
|
2014-08-19 15:58:20 +04:00
|
|
|
if( folder->syncPaused() ) {
|
2015-07-01 12:39:57 +03:00
|
|
|
abortOrPausedSeen++;
|
2014-08-19 15:58:20 +04:00
|
|
|
} else {
|
|
|
|
SyncResult folderResult = folder->syncResult();
|
|
|
|
SyncResult::Status syncStatus = folderResult.status();
|
|
|
|
|
|
|
|
switch( syncStatus ) {
|
|
|
|
case SyncResult::Undefined:
|
|
|
|
case SyncResult::NotYetStarted:
|
|
|
|
various++;
|
|
|
|
break;
|
2015-07-01 13:30:18 +03:00
|
|
|
case SyncResult::SyncPrepare:
|
2014-08-19 15:58:20 +04:00
|
|
|
case SyncResult::SyncRunning:
|
|
|
|
runSeen++;
|
|
|
|
break;
|
|
|
|
case SyncResult::Problem: // don't show the problem icon in tray.
|
|
|
|
case SyncResult::Success:
|
|
|
|
goodSeen++;
|
|
|
|
break;
|
|
|
|
case SyncResult::Error:
|
|
|
|
case SyncResult::SetupError:
|
|
|
|
errorsSeen++;
|
|
|
|
break;
|
|
|
|
case SyncResult::SyncAbortRequested:
|
|
|
|
case SyncResult::Paused:
|
2015-07-01 12:39:57 +03:00
|
|
|
abortOrPausedSeen++;
|
2014-08-19 15:58:20 +04:00
|
|
|
// no default case on purpose, check compiler warnings
|
|
|
|
}
|
2013-12-20 18:13:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
bool set = false;
|
|
|
|
if( errorsSeen > 0 ) {
|
|
|
|
overallResult.setStatus(SyncResult::Error);
|
|
|
|
set = true;
|
|
|
|
}
|
2015-07-01 12:39:57 +03:00
|
|
|
if( !set && abortOrPausedSeen > 0 && abortOrPausedSeen == cnt ) {
|
2013-12-20 18:13:33 +04:00
|
|
|
// only if all folders are paused
|
|
|
|
overallResult.setStatus(SyncResult::Paused);
|
|
|
|
set = true;
|
|
|
|
}
|
|
|
|
if( !set && runSeen > 0 ) {
|
|
|
|
overallResult.setStatus(SyncResult::SyncRunning);
|
|
|
|
set = true;
|
|
|
|
}
|
|
|
|
if( !set && goodSeen > 0 ) {
|
|
|
|
overallResult.setStatus(SyncResult::Success);
|
|
|
|
set = true;
|
2013-07-22 14:10:13 +04:00
|
|
|
}
|
|
|
|
}
|
2013-12-20 18:13:33 +04:00
|
|
|
|
2013-07-22 14:10:13 +04:00
|
|
|
return overallResult;
|
|
|
|
}
|
|
|
|
|
2014-08-19 15:58:20 +04:00
|
|
|
QString FolderMan::statusToString( SyncResult syncStatus, bool paused ) const
|
2013-07-22 14:10:13 +04:00
|
|
|
{
|
|
|
|
QString folderMessage;
|
|
|
|
switch( syncStatus.status() ) {
|
|
|
|
case SyncResult::Undefined:
|
|
|
|
folderMessage = tr( "Undefined State." );
|
|
|
|
break;
|
|
|
|
case SyncResult::NotYetStarted:
|
2015-10-05 07:21:19 +03:00
|
|
|
folderMessage = tr( "Waiting to start syncing." );
|
2013-07-22 14:10:13 +04:00
|
|
|
break;
|
|
|
|
case SyncResult::SyncPrepare:
|
|
|
|
folderMessage = tr( "Preparing for sync." );
|
|
|
|
break;
|
|
|
|
case SyncResult::SyncRunning:
|
|
|
|
folderMessage = tr( "Sync is running." );
|
|
|
|
break;
|
|
|
|
case SyncResult::Success:
|
|
|
|
folderMessage = tr( "Last Sync was successful." );
|
|
|
|
break;
|
|
|
|
case SyncResult::Error:
|
|
|
|
break;
|
2013-08-07 16:46:47 +04:00
|
|
|
case SyncResult::Problem:
|
2013-08-08 13:16:18 +04:00
|
|
|
folderMessage = tr( "Last Sync was successful, but with warnings on individual files.");
|
2013-08-07 16:46:47 +04:00
|
|
|
break;
|
2013-07-22 14:10:13 +04:00
|
|
|
case SyncResult::SetupError:
|
|
|
|
folderMessage = tr( "Setup Error." );
|
|
|
|
break;
|
2013-10-03 18:21:54 +04:00
|
|
|
case SyncResult::SyncAbortRequested:
|
|
|
|
folderMessage = tr( "User Abort." );
|
|
|
|
break;
|
2013-12-20 18:13:33 +04:00
|
|
|
case SyncResult::Paused:
|
|
|
|
folderMessage = tr("Sync is paused.");
|
|
|
|
break;
|
2013-07-22 14:10:13 +04:00
|
|
|
// no default case on purpose, check compiler warnings
|
|
|
|
}
|
2014-08-19 15:58:20 +04:00
|
|
|
if( paused ) {
|
2013-08-05 15:34:36 +04:00
|
|
|
// sync is disabled.
|
|
|
|
folderMessage = tr( "%1 (Sync is paused)" ).arg(folderMessage);
|
|
|
|
}
|
2013-07-22 14:10:13 +04:00
|
|
|
return folderMessage;
|
2012-02-17 12:48:31 +04:00
|
|
|
}
|
2013-07-22 14:10:13 +04:00
|
|
|
|
2015-07-28 13:14:52 +03:00
|
|
|
QString FolderMan::checkPathValidityForNewFolder(const QString& path, bool forNewDirectory)
|
2015-07-13 15:35:19 +03:00
|
|
|
{
|
2015-07-28 13:14:52 +03:00
|
|
|
if (path.isEmpty()) {
|
|
|
|
return tr("No valid folder selected!");
|
|
|
|
}
|
|
|
|
|
2015-07-13 15:35:19 +03:00
|
|
|
QFileInfo selFile( path );
|
|
|
|
QString userInput = selFile.canonicalFilePath();
|
|
|
|
|
2015-07-28 13:14:52 +03:00
|
|
|
if (!selFile.exists()) {
|
|
|
|
return checkPathValidityForNewFolder(selFile.dir().path(), true);
|
|
|
|
}
|
2015-07-13 15:35:19 +03:00
|
|
|
|
|
|
|
if( !selFile.isDir() ) {
|
2015-09-07 09:51:22 +03:00
|
|
|
return tr("The selected path is not a folder!");
|
2015-07-13 15:35:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( !selFile.isWritable() ) {
|
|
|
|
return tr("You have no permission to write to the selected folder!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if the local directory isn't used yet in another ownCloud sync
|
|
|
|
|
|
|
|
for (auto i = _folderMap.constBegin(); i != _folderMap.constEnd(); ++i ) {
|
|
|
|
Folder *f = static_cast<Folder*>(i.value());
|
|
|
|
QString folderDir = QDir( f->path() ).canonicalPath();
|
|
|
|
if( folderDir.isEmpty() ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if( ! folderDir.endsWith(QLatin1Char('/')) ) folderDir.append(QLatin1Char('/'));
|
|
|
|
|
|
|
|
if (QDir::cleanPath(f->path()) == QDir::cleanPath(userInput)
|
|
|
|
&& QDir::cleanPath(QDir(f->path()).canonicalPath()) == QDir(userInput).canonicalPath()) {
|
2015-09-08 14:37:57 +03:00
|
|
|
return tr("The local folder %1 is already used in a folder sync connection. "
|
|
|
|
"Please pick another one!")
|
2015-07-13 15:35:19 +03:00
|
|
|
.arg(QDir::toNativeSeparators(userInput));
|
|
|
|
}
|
2015-07-28 13:14:52 +03:00
|
|
|
if (!forNewDirectory && QDir::cleanPath(folderDir).startsWith(QDir::cleanPath(userInput)+'/')) {
|
2015-09-08 14:37:57 +03:00
|
|
|
return tr("The local folder %1 already contains a folder used in a folder sync connection. "
|
|
|
|
"Please pick another one!")
|
|
|
|
.arg(QDir::toNativeSeparators(userInput));
|
2015-07-13 15:35:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
QString absCleanUserFolder = QDir::cleanPath(QDir(userInput).canonicalPath())+'/';
|
2015-07-28 13:14:52 +03:00
|
|
|
if (!forNewDirectory && QDir::cleanPath(folderDir).startsWith(absCleanUserFolder) ) {
|
2015-09-08 14:37:57 +03:00
|
|
|
return tr("The local folder %1 is a symbolic link. "
|
|
|
|
"The link target already contains a folder used in a folder sync connection. "
|
|
|
|
"Please pick another one!")
|
|
|
|
.arg(QDir::toNativeSeparators(userInput));
|
2015-07-13 15:35:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (QDir::cleanPath(QString(userInput)).startsWith( QDir::cleanPath(folderDir)+'/')) {
|
2015-09-08 14:37:57 +03:00
|
|
|
return tr("The local folder %1 is already contained in a folder used in a folder sync connection. "
|
|
|
|
"Please pick another one!")
|
|
|
|
.arg(QDir::toNativeSeparators(userInput));
|
2015-07-13 15:35:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (absCleanUserFolder.startsWith( QDir::cleanPath(folderDir)+'/')) {
|
2015-09-08 14:37:57 +03:00
|
|
|
return tr("The local folder %1 is a symbolic link. "
|
|
|
|
"The link target is already contained in a folder used in a folder sync connection. "
|
|
|
|
"Please pick another one!")
|
|
|
|
.arg(QDir::toNativeSeparators(userInput));
|
2015-07-13 15:35:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-08-10 12:03:57 +03:00
|
|
|
bool FolderMan::ignoreHiddenFiles() const
|
|
|
|
{
|
|
|
|
if (_folderMap.empty()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return _folderMap.begin().value()->ignoreHiddenFiles();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderMan::setIgnoreHiddenFiles(bool ignore)
|
|
|
|
{
|
|
|
|
// Note that the setting will revert to 'true' if all folders
|
|
|
|
// are deleted...
|
|
|
|
foreach (Folder* folder, _folderMap) {
|
|
|
|
folder->setIgnoreHiddenFiles(ignore);
|
|
|
|
folder->saveToSettings();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 11:33:48 +03:00
|
|
|
QQueue<Folder*> FolderMan::scheduleQueue() const
|
|
|
|
{
|
|
|
|
return _scheduleQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Folder *FolderMan::currentSyncFolder() const
|
|
|
|
{
|
|
|
|
return _currentSyncFolder;
|
|
|
|
}
|
|
|
|
|
2015-07-17 13:12:00 +03:00
|
|
|
void FolderMan::restartApplication()
|
|
|
|
{
|
|
|
|
if( Utility::isLinux() ) {
|
|
|
|
// restart:
|
|
|
|
qDebug() << "### Restarting application NOW, PID" << qApp->applicationPid() << "is ending.";
|
|
|
|
qApp->quit();
|
|
|
|
QStringList args = qApp->arguments();
|
|
|
|
QString prg = args.takeFirst();
|
|
|
|
|
|
|
|
QProcess::startDetached(prg, args);
|
|
|
|
} else {
|
|
|
|
qDebug() << "On this platform we do not restart.";
|
|
|
|
}
|
|
|
|
}
|
2015-07-13 15:35:19 +03:00
|
|
|
|
2014-11-10 00:34:07 +03:00
|
|
|
} // namespace OCC
|