2011-04-06 13:48:02 +04:00
/*
* Copyright ( C ) by Duncan Mac - Vicar P . < duncan @ kde . org >
2013-07-22 22:27:42 +04:00
* Copyright ( C ) by Daniel Molkentin < danimo @ owncloud . com >
* Copyright ( C ) by Klaas Freitag < freitag @ owncloud . com >
2011-04-06 13:48:02 +04:00
*
* 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 .
*/
2013-02-25 12:54:19 +04:00
# include "config.h"
2012-07-20 19:13:23 +04:00
2011-02-17 02:21:45 +03:00
# include "mirall/folder.h"
# include "mirall/folderwatcher.h"
2012-03-28 14:23:34 +04:00
# include "mirall/mirallconfigfile.h"
2012-03-31 14:44:22 +04:00
# include "mirall/syncresult.h"
2013-07-22 22:27:42 +04:00
# include "mirall/logger.h"
# include "mirall/owncloudinfo.h"
2013-08-05 22:14:22 +04:00
# include "mirall/utility.h"
2013-07-30 13:19:22 +04:00
# include "creds/abstractcredentials.h"
2011-02-17 02:21:45 +03:00
2012-05-21 18:48:49 +04:00
# include <QDebug>
# include <QTimer>
# include <QUrl>
2012-06-25 17:31:13 +04:00
# include <QFileSystemWatcher>
# include <QDir>
2013-07-22 22:27:42 +04:00
# include <QMessageBox>
# include <QPushButton>
2012-05-21 18:48:49 +04:00
2011-02-17 02:21:45 +03:00
namespace Mirall {
2013-07-30 16:37:46 +04:00
void csyncLogCatcher ( CSYNC */ * ctx */ ,
int /*verbosity*/ ,
const char */ * function */ ,
2013-07-22 22:27:42 +04:00
const char * buffer ,
2013-07-30 16:37:46 +04:00
void */ * userdata */ )
2013-07-22 22:27:42 +04:00
{
Logger : : instance ( ) - > csyncLog ( QString : : fromUtf8 ( buffer ) ) ;
}
2012-03-26 15:20:15 +04:00
Folder : : Folder ( const QString & alias , const QString & path , const QString & secondPath , QObject * parent )
2013-07-22 22:27:42 +04:00
: QObject ( parent )
, _path ( path )
, _secondPath ( secondPath )
, _alias ( alias )
, _enabled ( true )
, _thread ( 0 )
, _csync ( 0 )
, _csyncError ( false )
, _csyncUnavail ( false )
, _csync_ctx ( 0 )
2011-02-17 02:21:45 +03:00
{
2012-03-13 18:42:29 +04:00
qsrand ( QTime : : currentTime ( ) . msec ( ) ) ;
2013-08-08 16:30:45 +04:00
_timeSinceLastSync . start ( ) ;
2012-03-08 14:39:31 +04:00
2013-08-05 15:34:36 +04:00
_watcher = new FolderWatcher ( path , this ) ;
2012-03-28 14:23:34 +04:00
MirallConfigFile cfg ;
2013-07-05 18:54:11 +04:00
_watcher - > addIgnoreListFile ( cfg . excludeFile ( MirallConfigFile : : SystemScope ) ) ;
_watcher - > addIgnoreListFile ( cfg . excludeFile ( MirallConfigFile : : UserScope ) ) ;
2012-03-28 14:23:34 +04:00
2011-03-23 01:03:43 +03:00
QObject : : connect ( _watcher , SIGNAL ( folderChanged ( const QStringList & ) ) ,
SLOT ( slotChanged ( const QStringList & ) ) ) ;
2011-03-28 01:29:45 +04:00
2012-04-20 16:31:06 +04:00
_syncResult . setStatus ( SyncResult : : NotYetStarted ) ;
2012-02-20 19:45:27 +04:00
2013-07-22 22:27:42 +04:00
ServerActionNotifier * notifier = new ServerActionNotifier ( this ) ;
2013-08-05 16:35:01 +04:00
connect ( this , SIGNAL ( syncFinished ( SyncResult ) ) , this , SLOT ( slotSyncFinished ( SyncResult ) ) ) ;
2013-07-22 22:27:42 +04:00
connect ( this , SIGNAL ( syncFinished ( SyncResult ) ) , notifier , SLOT ( slotSyncFinished ( SyncResult ) ) ) ;
2012-10-30 15:42:17 +04:00
// check if the local path exists
checkLocalPath ( ) ;
2013-08-05 19:01:08 +04:00
int polltime = cfg . remotePollInterval ( ) ;
qDebug ( ) < < " setting remote poll timer interval to " < < polltime < < " msec " ;
_pollTimer . setInterval ( polltime ) ;
QObject : : connect ( & _pollTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( slotPollTimerTimeout ( ) ) ) ;
_pollTimer . start ( ) ;
2013-08-06 20:04:42 +04:00
_syncResult . setFolder ( alias ) ;
2011-02-17 02:21:45 +03:00
}
2013-07-22 22:27:42 +04:00
bool Folder : : init ( )
{
2013-08-05 21:45:16 +04:00
QString url = Utility : : toCSyncScheme ( ownCloudInfo : : instance ( ) - > webdavUrl ( ) + secondPath ( ) ) ;
2013-07-22 22:27:42 +04:00
QString localpath = path ( ) ;
if ( csync_create ( & _csync_ctx , localpath . toUtf8 ( ) . data ( ) , url . toUtf8 ( ) . data ( ) ) < 0 ) {
qDebug ( ) < < " Unable to create csync-context! " ;
slotCSyncError ( tr ( " Unable to create csync-context " ) ) ;
_csync_ctx = 0 ;
} else {
csync_set_log_callback ( _csync_ctx , csyncLogCatcher ) ;
csync_set_log_verbosity ( _csync_ctx , 11 ) ;
MirallConfigFile cfgFile ;
csync_set_config_dir ( _csync_ctx , cfgFile . configPath ( ) . toUtf8 ( ) ) ;
csync_enable_conflictcopys ( _csync_ctx ) ;
setIgnoredFiles ( ) ;
2013-07-29 16:44:54 +04:00
cfgFile . getCredentials ( ) - > syncContextPreInit ( _csync_ctx ) ;
2013-07-22 22:27:42 +04:00
if ( csync_init ( _csync_ctx ) < 0 ) {
qDebug ( ) < < " Could not initialize csync! " < < csync_get_error ( _csync_ctx ) < < csync_get_error_string ( _csync_ctx ) ;
slotCSyncError ( CSyncThread : : csyncErrorToString ( csync_get_error ( _csync_ctx ) , csync_get_error_string ( _csync_ctx ) ) ) ;
csync_destroy ( _csync_ctx ) ;
_csync_ctx = 0 ;
}
}
return _csync_ctx ;
}
2011-02-17 02:21:45 +03:00
Folder : : ~ Folder ( )
{
2013-07-22 22:27:42 +04:00
if ( _thread ) {
_thread - > quit ( ) ;
csync_request_abort ( _csync_ctx ) ;
_thread - > wait ( ) ;
}
delete _csync ;
// Destroy csync here.
csync_destroy ( _csync_ctx ) ;
2011-02-17 02:21:45 +03:00
}
2012-10-30 15:42:17 +04:00
void Folder : : checkLocalPath ( )
{
QFileInfo fi ( _path ) ;
if ( fi . isDir ( ) & & fi . isReadable ( ) ) {
qDebug ( ) < < " Checked local path ok " ;
} else {
if ( ! fi . exists ( ) ) {
2012-10-30 17:37:15 +04:00
// try to create the local dir
QDir d ( _path ) ;
if ( d . mkpath ( _path ) ) {
qDebug ( ) < < " Successfully created the local dir " < < _path ;
2012-10-30 15:42:17 +04:00
}
}
2012-10-30 17:37:15 +04:00
// Check directory again
if ( ! fi . exists ( ) ) {
_syncResult . setErrorString ( tr ( " Local folder %1 does not exist. " ) . arg ( _path ) ) ;
_syncResult . setStatus ( SyncResult : : SetupError ) ;
} else if ( ! fi . isDir ( ) ) {
_syncResult . setErrorString ( tr ( " %1 should be a directory but is not. " ) . arg ( _path ) ) ;
_syncResult . setStatus ( SyncResult : : SetupError ) ;
} else if ( ! fi . isReadable ( ) ) {
_syncResult . setErrorString ( tr ( " %1 is not readable. " ) . arg ( _path ) ) ;
_syncResult . setStatus ( SyncResult : : SetupError ) ;
}
2012-10-30 15:42:17 +04:00
}
// if all is fine, connect a FileSystemWatcher
if ( _syncResult . status ( ) ! = SyncResult : : SetupError ) {
_pathWatcher = new QFileSystemWatcher ( this ) ;
_pathWatcher - > addPath ( _path ) ;
connect ( _pathWatcher , SIGNAL ( directoryChanged ( QString ) ) ,
SLOT ( slotLocalPathChanged ( QString ) ) ) ;
}
}
2011-04-06 11:52:02 +04:00
QString Folder : : alias ( ) const
{
return _alias ;
}
2011-02-17 17:10:06 +03:00
QString Folder : : path ( ) const
{
2012-10-29 14:22:02 +04:00
QString p ( _path ) ;
if ( ! p . endsWith ( QLatin1Char ( ' / ' ) ) ) {
p . append ( QLatin1Char ( ' / ' ) ) ;
}
return p ;
2011-02-17 17:10:06 +03:00
}
2013-07-22 22:27:42 +04:00
bool Folder : : isBusy ( ) const
{
return ( _thread & & _thread - > isRunning ( ) ) ;
}
2012-03-26 15:20:15 +04:00
QString Folder : : secondPath ( ) const
{
return _secondPath ;
}
2012-08-15 19:16:44 +04:00
QString Folder : : nativePath ( ) const
{
return QDir : : toNativeSeparators ( _path ) ;
}
2011-10-13 18:41:24 +04:00
bool Folder : : syncEnabled ( ) const
{
return _enabled ;
}
void Folder : : setSyncEnabled ( bool doit )
{
_enabled = doit ;
2011-11-04 14:41:49 +04:00
_watcher - > setEventsEnabled ( doit ) ;
2012-03-26 15:20:15 +04:00
2012-03-31 14:44:22 +04:00
qDebug ( ) < < " setSyncEnabled - ############################ " < < doit ;
2012-03-26 15:20:15 +04:00
if ( doit ) {
// undefined until next sync
2012-03-31 14:44:22 +04:00
_syncResult . setStatus ( SyncResult : : NotYetStarted ) ;
2012-04-17 15:16:48 +04:00
_syncResult . clearErrors ( ) ;
2012-03-26 15:20:15 +04:00
evaluateSync ( QStringList ( ) ) ;
} else {
2012-04-30 10:56:56 +04:00
// disable folder. Done through the _enabled-flag set above
2012-03-26 15:20:15 +04:00
}
2011-10-13 18:41:24 +04:00
}
2013-02-18 17:56:21 +04:00
void Folder : : setSyncState ( SyncResult : : Status state )
{
_syncResult . setStatus ( state ) ;
}
2012-02-20 19:45:27 +04:00
SyncResult Folder : : syncResult ( ) const
2011-10-13 18:41:24 +04:00
{
2012-02-20 19:45:27 +04:00
return _syncResult ;
2011-10-13 18:41:24 +04:00
}
2013-07-30 16:37:46 +04:00
void Folder : : evaluateSync ( const QStringList & /*pathList*/ )
2011-04-06 17:57:18 +04:00
{
2011-10-13 18:41:24 +04:00
if ( ! _enabled ) {
qDebug ( ) < < " * " < < alias ( ) < < " sync skipped, disabled! " ;
return ;
}
2012-02-28 19:49:13 +04:00
2012-03-31 14:44:22 +04:00
_syncResult . setStatus ( SyncResult : : NotYetStarted ) ;
2012-03-29 12:13:19 +04:00
emit scheduleToSync ( alias ( ) ) ;
2012-03-31 14:44:22 +04:00
}
2011-04-05 14:16:24 +04:00
void Folder : : slotPollTimerTimeout ( )
{
2013-08-08 16:30:45 +04:00
qDebug ( ) < < " * Polling " < < alias ( ) < < " for changes. Ignoring all pending events until now (time since next sync: " < < ( _timeSinceLastSync . elapsed ( ) / 1000 ) < < " s) " ;
2011-04-05 14:16:24 +04:00
_watcher - > clearPendingEvents ( ) ;
2013-08-05 21:53:58 +04:00
2013-08-08 16:30:45 +04:00
if ( _timeSinceLastSync . elapsed ( ) > MirallConfigFile ( ) . forceSyncInterval ( ) ) {
qDebug ( ) < < " * Force Sync now " ;
evaluateSync ( QStringList ( ) ) ;
} else {
// check if the etag is different
QObject : : connect ( new RequestEtagJob ( secondPath ( ) , this ) , SIGNAL ( etagRetreived ( QString ) ) ,
this , SLOT ( etagRetreived ( QString ) ) ) ;
}
2013-08-05 21:53:58 +04:00
}
void Folder : : etagRetreived ( const QString & etag )
{
qDebug ( ) < < " * Compare etag " < < etag < < " with previous etag " < < _lastEtag ;
if ( _lastEtag ! = etag ) {
_lastEtag = etag ;
evaluateSync ( QStringList ( ) ) ;
}
2011-04-06 17:57:18 +04:00
}
2013-08-05 21:53:58 +04:00
2011-03-23 01:03:43 +03:00
void Folder : : slotChanged ( const QStringList & pathList )
2011-02-17 02:21:45 +03:00
{
2012-02-16 01:36:52 +04:00
qDebug ( ) < < " ** Changed was notified on " < < pathList ;
2011-04-06 17:57:18 +04:00
evaluateSync ( pathList ) ;
2011-02-17 02:21:45 +03:00
}
2011-04-08 13:36:53 +04:00
void Folder : : slotSyncFinished ( const SyncResult & result )
2011-02-17 17:10:06 +03:00
{
2012-12-06 21:38:45 +04:00
_watcher - > setEventsEnabledDelayed ( 2000 ) ;
2013-08-05 19:01:08 +04:00
_pollTimer . start ( ) ;
2013-08-08 16:30:45 +04:00
_timeSinceLastSync . restart ( ) ;
2011-12-12 20:47:30 +04:00
2013-05-04 17:16:53 +04:00
qDebug ( ) < < " OO folder slotSyncFinished: result: " < < int ( result . status ( ) ) ;
2012-02-29 18:25:16 +04:00
emit syncStateChange ( ) ;
2011-02-17 17:10:06 +03:00
}
2011-02-17 02:21:45 +03:00
2012-06-25 17:31:13 +04:00
void Folder : : slotLocalPathChanged ( const QString & dir )
{
QDir notifiedDir ( dir ) ;
2013-07-22 22:27:42 +04:00
QDir localPath ( path ( ) ) ;
2012-06-25 17:31:13 +04:00
2013-07-22 22:27:42 +04:00
if ( notifiedDir . absolutePath ( ) = = localPath . absolutePath ( ) ) {
2012-06-25 17:31:13 +04:00
if ( ! localPath . exists ( ) ) {
2013-07-22 22:27:42 +04:00
qDebug ( ) < < " XXXXXXX The sync folder root was removed!! " ;
if ( _thread & & _thread - > isRunning ( ) ) {
qDebug ( ) < < " CSync currently running, set wipe flag!! " ;
} else {
qDebug ( ) < < " CSync not running, wipe it now!! " ;
wipe ( ) ;
}
2012-06-25 17:31:13 +04:00
qDebug ( ) < < " ALARM: The local path was DELETED! " ;
}
}
}
2012-11-22 15:29:50 +04:00
void Folder : : setConfigFile ( const QString & file )
{
_configFile = file ;
}
QString Folder : : configFile ( )
{
return _configFile ;
}
2013-07-22 22:27:42 +04:00
void Folder : : slotThreadTreeWalkResult ( const SyncFileItemVector & items )
2011-10-18 12:22:24 +04:00
{
2013-07-22 22:27:42 +04:00
_syncResult . setSyncFileItemVector ( items ) ;
2011-10-18 12:22:24 +04:00
}
2013-08-07 16:59:41 +04:00
void Folder : : slotCatchWatcherError ( const QString & error )
{
Logger : : instance ( ) - > postGuiLog ( tr ( " Error " ) , error ) ;
}
2013-07-22 22:27:42 +04:00
void Folder : : slotTerminateSync ( )
2011-10-18 12:22:24 +04:00
{
2013-07-22 22:27:42 +04:00
qDebug ( ) < < " folder " < < alias ( ) < < " Terminating! " ;
MirallConfigFile cfg ;
QString configDir = cfg . configPath ( ) ;
qDebug ( ) < < " csync's Config Dir: " < < configDir ;
if ( _thread & & _csync ) {
csync_request_abort ( _csync_ctx ) ;
_thread - > quit ( ) ;
_thread - > wait ( ) ;
_csync - > deleteLater ( ) ;
delete _thread ;
_csync = 0 ;
_thread = 0 ;
csync_resume ( _csync_ctx ) ;
}
if ( ! configDir . isEmpty ( ) ) {
QFile file ( configDir + QLatin1String ( " /lock " ) ) ;
if ( file . exists ( ) ) {
qDebug ( ) < < " After termination, lock file exists and gets removed. " ;
file . remove ( ) ;
}
}
_errors . append ( tr ( " The CSync thread terminated. " ) ) ;
_csyncError = true ;
qDebug ( ) < < " -> CSync Terminated! " ;
slotCSyncFinished ( ) ;
2011-10-18 12:22:24 +04:00
}
2013-07-22 22:27:42 +04:00
// This removes the csync File database if the sync folder definition is removed
// permanentely. This is needed to provide a clean startup again in case another
// local folder is synced to the same ownCloud.
// See http://bugs.owncloud.org/thebuggenie/owncloud/issues/oc-788
2012-06-11 12:10:07 +04:00
void Folder : : wipe ( )
{
2013-07-22 22:27:42 +04:00
QString stateDbFile = path ( ) + QLatin1String ( " .csync_journal.db " ) ;
QFile file ( stateDbFile ) ;
if ( file . exists ( ) ) {
if ( ! file . remove ( ) ) {
qDebug ( ) < < " WRN: Failed to remove existing csync StateDB " < < stateDbFile ;
} else {
qDebug ( ) < < " wipe: Removed csync StateDB " < < stateDbFile ;
}
} else {
qDebug ( ) < < " WRN: statedb is empty, can not remove. " ;
}
// Check if the tmp database file also exists
QString ctmpName = path ( ) + QLatin1String ( " .csync_journal.db.ctmp " ) ;
QFile ctmpFile ( ctmpName ) ;
if ( ctmpFile . exists ( ) ) {
ctmpFile . remove ( ) ;
}
}
void Folder : : setIgnoredFiles ( )
{
MirallConfigFile cfgFile ;
csync_clear_exclude_list ( _csync_ctx ) ;
QString excludeList = cfgFile . excludeFile ( MirallConfigFile : : SystemScope ) ;
if ( ! excludeList . isEmpty ( ) ) {
qDebug ( ) < < " ==== added system ignore list to csync: " < < excludeList . toUtf8 ( ) ;
csync_add_exclude_list ( _csync_ctx , excludeList . toUtf8 ( ) ) ;
}
excludeList = cfgFile . excludeFile ( MirallConfigFile : : UserScope ) ;
if ( ! excludeList . isEmpty ( ) ) {
qDebug ( ) < < " ==== added user defined ignore list to csync: " < < excludeList . toUtf8 ( ) ;
csync_add_exclude_list ( _csync_ctx , excludeList . toUtf8 ( ) ) ;
}
}
void Folder : : setProxy ( )
{
if ( _csync_ctx ) {
/* Store proxy */
QUrl proxyUrl ( ownCloudInfo : : instance ( ) - > webdavUrl ( ) ) ;
QList < QNetworkProxy > proxies = QNetworkProxyFactory : : proxyForQuery ( proxyUrl ) ;
// We set at least one in Application
Q_ASSERT ( proxies . count ( ) > 0 ) ;
QNetworkProxy proxy = proxies . first ( ) ;
if ( proxy . type ( ) = = QNetworkProxy : : NoProxy ) {
qDebug ( ) < < " Passing NO proxy to csync for " < < proxyUrl ;
} else {
qDebug ( ) < < " Passing " < < proxy . hostName ( ) < < " of proxy type " < < proxy . type ( )
< < " to csync for " < < proxyUrl ;
}
int proxyPort = proxy . port ( ) ;
csync_set_module_property ( _csync_ctx , " proxy_type " , ( char * ) proxyTypeToCStr ( proxy . type ( ) ) ) ;
csync_set_module_property ( _csync_ctx , " proxy_host " , proxy . hostName ( ) . toUtf8 ( ) . data ( ) ) ;
csync_set_module_property ( _csync_ctx , " proxy_port " , & proxyPort ) ;
csync_set_module_property ( _csync_ctx , " proxy_user " , proxy . user ( ) . toUtf8 ( ) . data ( ) ) ;
csync_set_module_property ( _csync_ctx , " proxy_pwd " , proxy . password ( ) . toUtf8 ( ) . data ( ) ) ;
}
}
const char * Folder : : proxyTypeToCStr ( QNetworkProxy : : ProxyType type )
{
switch ( type ) {
case QNetworkProxy : : NoProxy :
return " NoProxy " ;
case QNetworkProxy : : DefaultProxy :
return " DefaultProxy " ;
case QNetworkProxy : : Socks5Proxy :
return " Socks5Proxy " ;
case QNetworkProxy : : HttpProxy :
return " HttpProxy " ;
case QNetworkProxy : : HttpCachingProxy :
return " HttpCachingProxy " ;
case QNetworkProxy : : FtpCachingProxy :
return " FtpCachingProxy " ;
default :
return " NoProxy " ;
}
}
void Folder : : startSync ( const QStringList & pathList )
{
Q_UNUSED ( pathList )
if ( ! _csync_ctx ) {
// no _csync_ctx yet, initialize it.
init ( ) ;
2013-08-08 02:46:23 +04:00
setProxy ( ) ;
2013-07-22 22:27:42 +04:00
if ( ! _csync_ctx ) {
qDebug ( ) < < Q_FUNC_INFO < < " init failed. " ;
// the error should already be set
QMetaObject : : invokeMethod ( this , " slotCSyncFinished " , Qt : : QueuedConnection ) ;
return ;
}
}
if ( _thread & & _thread - > isRunning ( ) ) {
qCritical ( ) < < " * ERROR csync is still running and new sync requested. " ;
return ;
}
if ( _thread )
_thread - > quit ( ) ;
delete _csync ;
delete _thread ;
_errors . clear ( ) ;
_csyncError = false ;
_csyncUnavail = false ;
_syncResult . clearErrors ( ) ;
_syncResult . setStatus ( SyncResult : : SyncPrepare ) ;
emit syncStateChange ( ) ;
qDebug ( ) < < " *** Start syncing " ;
_thread = new QThread ( this ) ;
_thread - > setPriority ( QThread : : LowPriority ) ;
setIgnoredFiles ( ) ;
_csync = new CSyncThread ( _csync_ctx ) ;
_csync - > moveToThread ( _thread ) ;
2012-06-11 12:10:07 +04:00
2013-07-22 22:27:42 +04:00
qRegisterMetaType < SyncFileItemVector > ( " SyncFileItemVector " ) ;
qRegisterMetaType < SyncFileItem : : Direction > ( " SyncFileItem::Direction " ) ;
connect ( _csync , SIGNAL ( treeWalkResult ( const SyncFileItemVector & ) ) ,
this , SLOT ( slotThreadTreeWalkResult ( const SyncFileItemVector & ) ) , Qt : : QueuedConnection ) ;
connect ( _csync , SIGNAL ( started ( ) ) , SLOT ( slotCSyncStarted ( ) ) , Qt : : QueuedConnection ) ;
connect ( _csync , SIGNAL ( finished ( ) ) , SLOT ( slotCSyncFinished ( ) ) , Qt : : QueuedConnection ) ;
connect ( _csync , SIGNAL ( csyncError ( QString ) ) , SLOT ( slotCSyncError ( QString ) ) , Qt : : QueuedConnection ) ;
connect ( _csync , SIGNAL ( csyncUnavailable ( ) ) , SLOT ( slotCsyncUnavailable ( ) ) , Qt : : QueuedConnection ) ;
//blocking connection so the message box happens in this thread, but block the csync thread.
connect ( _csync , SIGNAL ( aboutToRemoveAllFiles ( SyncFileItem : : Direction , bool * ) ) ,
SLOT ( slotAboutToRemoveAllFiles ( SyncFileItem : : Direction , bool * ) ) , Qt : : BlockingQueuedConnection ) ;
2013-07-26 15:44:38 +04:00
connect ( _csync , SIGNAL ( transmissionProgress ( Progress : : Info ) ) , this , SLOT ( slotTransmissionProgress ( Progress : : Info ) ) ) ;
2013-07-22 22:27:42 +04:00
_thread - > start ( ) ;
QMetaObject : : invokeMethod ( _csync , " startSync " , Qt : : QueuedConnection ) ;
2013-08-05 16:35:01 +04:00
// disable events until syncing is done
_watcher - > setEventsEnabled ( false ) ;
2013-08-05 19:01:08 +04:00
_pollTimer . stop ( ) ;
2013-07-22 22:27:42 +04:00
emit syncStarted ( ) ;
2012-06-11 12:10:07 +04:00
}
2013-07-22 22:27:42 +04:00
void Folder : : slotCSyncError ( const QString & err )
{
_errors . append ( err ) ;
_csyncError = true ;
}
void Folder : : slotCSyncStarted ( )
{
qDebug ( ) < < " * csync thread started " ;
_syncResult . setStatus ( SyncResult : : SyncRunning ) ;
emit syncStateChange ( ) ;
}
void Folder : : slotCsyncUnavailable ( )
{
_csyncUnavail = true ;
}
void Folder : : slotCSyncFinished ( )
{
qDebug ( ) < < " -> CSync Finished slot with error " < < _csyncError ;
if ( _csyncError ) {
_syncResult . setStatus ( SyncResult : : Error ) ;
qDebug ( ) < < " ** error Strings: " < < _errors ;
_syncResult . setErrorStrings ( _errors ) ;
qDebug ( ) < < " * owncloud csync thread finished with error " ;
} else if ( _csyncUnavail ) {
_syncResult . setStatus ( SyncResult : : Unavailable ) ;
2013-08-02 16:22:01 +04:00
} else if ( _syncResult . warnCount ( ) > 0 ) {
// there have been warnings on the way.
_syncResult . setStatus ( SyncResult : : Problem ) ;
2013-07-22 22:27:42 +04:00
} else {
_syncResult . setStatus ( SyncResult : : Success ) ;
}
if ( _thread & & _thread - > isRunning ( ) ) {
_thread - > quit ( ) ;
}
ownCloudInfo : : instance ( ) - > getQuotaRequest ( " / " ) ;
emit syncFinished ( _syncResult ) ;
}
2013-07-31 00:22:04 +04:00
void Folder : : slotTransmissionProgress ( const Progress : : Info & progress )
2013-07-22 22:27:42 +04:00
{
2013-07-31 00:22:43 +04:00
Progress : : Info newInfo = progress ;
newInfo . folder = alias ( ) ;
if ( newInfo . current_file . startsWith ( QLatin1String ( " ownclouds:// " ) ) | |
newInfo . current_file . startsWith ( QLatin1String ( " owncloud:// " ) ) ) {
// rip off the whole ownCloud URL.
2013-08-05 21:45:16 +04:00
QString remotePathUrl = ownCloudInfo : : instance ( ) - > webdavUrl ( ) + secondPath ( ) ;
newInfo . current_file . remove ( Utility : : toCSyncScheme ( remotePathUrl ) ) ;
2013-07-31 00:22:43 +04:00
}
2013-08-02 14:16:21 +04:00
QString localPath = path ( ) ;
if ( newInfo . current_file . startsWith ( localPath ) ) {
// remove the local dir.
newInfo . current_file = newInfo . current_file . right ( newInfo . current_file . length ( ) - localPath . length ( ) ) ;
}
2013-07-31 00:22:43 +04:00
2013-08-02 16:22:01 +04:00
// remember problems happening to set the correct Sync status in slot slotCSyncFinished.
if ( newInfo . kind = = Progress : : StartSync ) {
_syncResult . setWarnCount ( 0 ) ;
}
if ( newInfo . kind = = Progress : : Error ) {
_syncResult . setWarnCount ( _syncResult . warnCount ( ) + 1 ) ;
}
2013-07-31 00:22:43 +04:00
ProgressDispatcher : : instance ( ) - > setProgressInfo ( alias ( ) , newInfo ) ;
2013-07-22 22:27:42 +04:00
}
ServerActionNotifier : : ServerActionNotifier ( QObject * parent )
: QObject ( parent )
{
}
void ServerActionNotifier : : slotSyncFinished ( const SyncResult & result )
{
SyncFileItemVector items = result . syncFileItemVector ( ) ;
if ( items . count ( ) = = 0 )
return ;
int newItems = 0 ;
int removedItems = 0 ;
int updatedItems = 0 ;
SyncFileItem firstItemNew ;
SyncFileItem firstItemDeleted ;
SyncFileItem firstItemUpdated ;
foreach ( const SyncFileItem & item , items ) {
if ( item . _dir = = SyncFileItem : : Down ) {
switch ( item . _instruction ) {
case CSYNC_INSTRUCTION_NEW :
newItems + + ;
if ( firstItemNew . isEmpty ( ) )
firstItemNew = item ;
break ;
case CSYNC_INSTRUCTION_REMOVE :
removedItems + + ;
if ( firstItemDeleted . isEmpty ( ) )
firstItemDeleted = item ;
break ;
case CSYNC_INSTRUCTION_UPDATED :
updatedItems + + ;
if ( firstItemUpdated . isEmpty ( ) )
firstItemUpdated = item ;
2013-07-31 00:22:43 +04:00
break ;
case CSYNC_INSTRUCTION_ERROR :
qDebug ( ) < < " Got Instruction ERROR. " < < result . errorString ( ) ;
break ;
2013-07-22 22:27:42 +04:00
default :
// nothing.
break ;
}
}
}
2013-08-07 16:58:56 +04:00
Logger * logger = Logger : : instance ( ) ;
2013-07-22 22:27:42 +04:00
if ( newItems > 0 ) {
QString file = QDir : : toNativeSeparators ( firstItemNew . _file ) ;
if ( newItems = = 1 )
2013-08-07 16:58:56 +04:00
logger - > postGuiLog ( tr ( " New file available " ) , tr ( " '%1' has been synced to this machine. " ) . arg ( file ) ) ;
2013-07-22 22:27:42 +04:00
else
2013-08-07 16:58:56 +04:00
logger - > postGuiLog ( tr ( " New files available " ) , tr ( " '%1' and %n other file(s) have been synced to this machine. " ,
" " , newItems - 1 ) . arg ( file ) ) ;
2013-07-22 22:27:42 +04:00
}
if ( removedItems > 0 ) {
QString file = QDir : : toNativeSeparators ( firstItemDeleted . _file ) ;
if ( removedItems = = 1 )
2013-08-07 16:58:56 +04:00
logger - > postGuiLog ( tr ( " File removed " ) , tr ( " '%1' has been removed. " ) . arg ( file ) ) ;
2013-07-22 22:27:42 +04:00
else
2013-08-07 16:58:56 +04:00
logger - > postGuiLog ( tr ( " Files removed " ) , tr ( " '%1' and %n other file(s) have been removed. " ,
" " , removedItems - 1 ) . arg ( file ) ) ;
2013-07-22 22:27:42 +04:00
}
if ( updatedItems > 0 ) {
QString file = QDir : : toNativeSeparators ( firstItemUpdated . _file ) ;
if ( updatedItems = = 1 )
2013-08-07 16:58:56 +04:00
logger - > postGuiLog ( tr ( " File updated " ) , tr ( " '%1' has been updated. " ) . arg ( file ) ) ;
2013-07-22 22:27:42 +04:00
else
2013-08-07 16:58:56 +04:00
logger - > postGuiLog ( tr ( " Files updated " ) , tr ( " '%1' and %n other file(s) have been updated. " ,
" " , updatedItems - 1 ) . arg ( file ) ) ;
2013-07-22 22:27:42 +04:00
}
}
void Folder : : slotAboutToRemoveAllFiles ( SyncFileItem : : Direction direction , bool * cancel )
{
QString msg = direction = = SyncFileItem : : Down ?
tr ( " This sync would remove all the files in the local sync folder '%1'. \n "
" If you or your administrator have reset your account on the server, choose "
" \" Keep files \" . If you want your data to be removed, choose \" Remove all files \" . " ) :
tr ( " This sync would remove all the files in the sync folder '%1'. \n "
" This might be because the folder was silently reconfigured, or that all "
" the file were manually removed. \n "
" Are you sure you want to perform this operation? " ) ;
QMessageBox msgBox ( QMessageBox : : Warning , tr ( " Remove All Files? " ) ,
msg . arg ( alias ( ) ) ) ;
msgBox . addButton ( tr ( " Remove all files " ) , QMessageBox : : DestructiveRole ) ;
QPushButton * keepBtn = msgBox . addButton ( tr ( " Keep files " ) , QMessageBox : : ActionRole ) ;
if ( msgBox . exec ( ) = = - 1 ) {
* cancel = true ;
return ;
}
* cancel = msgBox . clickedButton ( ) = = keepBtn ;
if ( * cancel ) {
wipe ( ) ;
}
}
2011-02-17 02:21:45 +03:00
} // namespace Mirall