diff options
Diffstat (limited to 'src')
29 files changed, 704 insertions, 189 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3b13aa416..0ad1f6c70 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,7 @@ mirall/networksettings.ui mirall/accountsettings.ui mirall/ignorelisteditor.ui mirall/fileitemdialog.ui +mirall/itemprogressdialog.ui wizard/owncloudsetupnocredspage.ui wizard/owncloudhttpcredspage.ui wizard/owncloudwizardresultpage.ui @@ -195,6 +196,7 @@ set(mirall_SRCS mirall/networksettings.cpp mirall/accountsettings.cpp mirall/ignorelisteditor.cpp + mirall/itemprogressdialog.cpp ) set(mirall_HEADERS @@ -219,6 +221,7 @@ set(mirall_HEADERS mirall/networksettings.h mirall/accountsettings.h mirall/ignorelisteditor.h + mirall/itemprogressdialog.h ) if( UNIX AND NOT APPLE) diff --git a/src/mirall/accountsettings.cpp b/src/mirall/accountsettings.cpp index e774b4c89..495d92300 100644 --- a/src/mirall/accountsettings.cpp +++ b/src/mirall/accountsettings.cpp @@ -26,6 +26,7 @@ #include "mirall/owncloudsetupwizard.h" #include "mirall/mirallconfigfile.h" #include "mirall/ignorelisteditor.h" +#include "mirall/itemprogressdialog.h" #include <math.h> @@ -44,6 +45,7 @@ AccountSettings::AccountSettings(QWidget *parent) : ui->setupUi(this); _model = new FolderStatusModel; + _model->setParent(this); FolderStatusDelegate *delegate = new FolderStatusDelegate; ui->_folderList->setItemDelegate( delegate ); @@ -212,10 +214,18 @@ void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f ) if( f->syncEnabled() ) { item->setData( theme->syncStateIcon( status ), FolderStatusDelegate::FolderStatusIconRole ); } else { - item->setData( theme->folderDisabledIcon( ), FolderStatusDelegate::FolderStatusIconRole ); // size 48 before + item->setData( theme->folderDisabledIcon( ), FolderStatusDelegate::FolderStatusIconRole ); // size 48 before } item->setData( theme->statusHeaderText( status ), FolderStatusDelegate::FolderStatus ); - item->setData( errors, FolderStatusDelegate::FolderErrorMsg ); + item->setData( errors, FolderStatusDelegate::FolderErrorMsg ); + + bool ongoing = false; + item->setData( QVariant(res.warnCount()), FolderStatusDelegate::WarningCount ); + if( status == SyncResult::SyncRunning ) { + ongoing = true; + } + item->setData( ongoing, FolderStatusDelegate::SyncRunning); + } void AccountSettings::slotRemoveCurrentFolder() @@ -385,11 +395,11 @@ void AccountSettings::slotUpdateFolderState( Folder *folder ) item = _model->item( ++row ); } - +#if 0 if( !_fileItemDialog.isNull() && _fileItemDialog->isVisible() ) { _fileItemDialog->setSyncResult( FolderMan::instance()->syncResult(folder) ); } - +#endif if( item ) { folderToModelItem( item, folder ); } else { @@ -481,15 +491,26 @@ QString AccountSettings::shortenFilename( const QString& folder, const QString& // rip off the whole ownCloud URL. Folder *f = FolderMan::instance()->folder(folder); if( f ) { - QString regexp = QString("^owncloud[s]*://.*/remote.php/webdav/%1/").arg(f->secondPath()); - QRegExp re( regexp ); - re.setMinimal(true); - shortFile.remove(re); + QString remotePathUrl = ownCloudInfo::instance()->webdavUrl() + QLatin1Char('/') + f->secondPath(); + shortFile.remove(Utility::toCSyncScheme(remotePathUrl)); + } } return shortFile; } +void AccountSettings::slotProgressProblem(const QString& folder, const Progress::SyncProblem& problem) +{ + Q_UNUSED(problem); + + QStandardItem *item = itemForFolder( folder ); + if( !item ) return; + + int warnCount = qvariant_cast<int>( item->data(FolderStatusDelegate::WarningCount) ); + warnCount++; + item->setData( QVariant(warnCount), FolderStatusDelegate::WarningCount ); +} + void AccountSettings::slotSetProgress(const QString& folder, const Progress::Info &progress ) { // qDebug() << "================================> Progress for folder " << folder << " file " << file << ": "<< p1; @@ -507,7 +528,6 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf return; } - QString itemFileName = shortenFilename(folder, progress.current_file); QString syncFileProgressString; @@ -519,9 +539,11 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf switch( progress.kind ) { case Progress::StartSync: + item->setData( QVariant(0), FolderStatusDelegate::WarningCount ); break; case Progress::StartDownload: case Progress::StartUpload: + case Progress::StartDelete: syncFileProgressString = tr("Start"); if( _hideProgressTimers.contains(item) ) { // The timer is still running. @@ -636,24 +658,7 @@ void AccountSettings::slotIgnoreFilesEditor() void AccountSettings::slotInfoAboutCurrentFolder() { - QModelIndex selected = ui->_folderList->selectionModel()->currentIndex(); - if( selected.isValid() ) { - QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString(); - qDebug() << "Info Folder alias " << alias; - if( !alias.isEmpty() ) { - - qDebug() << "details of folder with alias " << alias; - - if( _fileItemDialog.isNull() ) { - _fileItemDialog = new FileItemDialog(this); - _fileItemDialog->open(); - } else { - Utility::raiseDialog( _fileItemDialog ); - } - - _fileItemDialog->setSyncResult( FolderMan::instance()->syncResult( alias ) ); - } - } + emit(openProgressDialog()); } AccountSettings::~AccountSettings() diff --git a/src/mirall/accountsettings.h b/src/mirall/accountsettings.h index b3d2fb6bf..b9b1c0031 100644 --- a/src/mirall/accountsettings.h +++ b/src/mirall/accountsettings.h @@ -23,6 +23,7 @@ #include "mirall/folder.h" #include "mirall/progressdispatcher.h" +#include "mirall/itemprogressdialog.h" class QStandardItemModel; class QModelIndex; @@ -37,7 +38,7 @@ class AccountSettings; } class FolderMan; -class FileItemDialog; +class ItemProgressDialog; class IgnoreListEditor; class AccountSettings : public QWidget @@ -54,6 +55,7 @@ public: signals: void folderChanged(); + void openProgressDialog(); void openFolderAlias( const QString& ); void infoFolderAlias( const QString& ); @@ -67,6 +69,7 @@ public slots: void slotDoubleClicked( const QModelIndex& ); void slotFolderOpenAction( const QString& ); void slotSetProgress(const QString&, const Progress::Info& progress); + void slotProgressProblem(const QString& folder, const Progress::SyncProblem& problem); void slotUpdateQuota( qint64,qint64 ); void slotIgnoreFilesEditor(); @@ -89,7 +92,7 @@ private: QStandardItem* itemForFolder(const QString& ); Ui::AccountSettings *ui; - QPointer<FileItemDialog> _fileItemDialog; + QPointer<ItemProgressDialog> _fileItemDialog; QPointer<IgnoreListEditor> _ignoreEditor; QStandardItemModel *_model; QListWidgetItem *_item; diff --git a/src/mirall/application.cpp b/src/mirall/application.cpp index 20648bdb8..77896e398 100644 --- a/src/mirall/application.cpp +++ b/src/mirall/application.cpp @@ -32,6 +32,7 @@ #include "mirall/updatedetector.h" #include "mirall/logger.h" #include "mirall/settingsdialog.h" +#include "mirall/itemprogressdialog.h" #include "mirall/utility.h" #include "mirall/inotify.h" #include "mirall/connectionvalidator.h" @@ -320,10 +321,10 @@ void Application::setupActions() _actionStatus = new QAction(tr("Unknown status"), this); _actionStatus->setEnabled( false ); _actionSettings = new QAction(tr("Settings..."), this); - _actionRecent = new QAction(tr("more..."), this); + _actionRecent = new QAction(tr("Details..."), this); _actionRecent->setEnabled( true ); - QObject::connect(_actionRecent, SIGNAL(triggered(bool)), SLOT(slotShowRecentChanges())); + QObject::connect(_actionRecent, SIGNAL(triggered(bool)), SLOT(slotItemProgressDialog())); QObject::connect(_actionSettings, SIGNAL(triggered(bool)), SLOT(slotSettings())); _actionHelp = new QAction(tr("Help"), this); QObject::connect(_actionHelp, SIGNAL(triggered(bool)), SLOT(slotHelp())); @@ -357,6 +358,7 @@ void Application::setupContextMenu() _contextMenu->clear(); _recentActionsMenu->clear(); _recentActionsMenu->addAction(tr("None.")); + _recentActionsMenu->addAction(_actionRecent); } else { _contextMenu = new QMenu(); _recentActionsMenu = _contextMenu->addMenu(tr("Recent Changes...")); @@ -672,11 +674,6 @@ void Application::slotFoldersChanged() setupContextMenu(); } -void Application::slotShowRecentChanges() -{ - // not yet here. -} - void Application::slotSettings() { if (_settingsDialog.isNull()) { @@ -687,6 +684,17 @@ void Application::slotSettings() Utility::raiseDialog(_settingsDialog); } +void Application::slotItemProgressDialog() +{ + if (_progressDialog.isNull()) { + _progressDialog = new ItemProgressDialog(this); + _progressDialog->setAttribute( Qt::WA_DeleteOnClose, true ); + _progressDialog->setupList(); + _progressDialog->open(); + } + Utility::raiseDialog(_progressDialog); +} + void Application::slotParseOptions(const QString &opts) { QStringList options = opts.split(QLatin1Char('|')); @@ -787,7 +795,7 @@ void Application::computeOverallSyncStatus() QStringList allStatusStrings; foreach(Folder* folder, map.values()) { qDebug() << "Folder in overallStatus Message: " << folder << " with name " << folder->alias(); - QString folderMessage = folderMan->statusToString(folder->syncResult().status()); + QString folderMessage = folderMan->statusToString(folder->syncResult().status(), folder->syncEnabled()); allStatusStrings += tr("Folder %1: %2").arg(folder->alias(), folderMessage); } diff --git a/src/mirall/application.h b/src/mirall/application.h index 0e964ab8b..65557a58e 100644 --- a/src/mirall/application.h +++ b/src/mirall/application.h @@ -44,6 +44,7 @@ class FolderWizard; class ownCloudInfo; class SslErrorDialog; class SettingsDialog; +class ItemProgressDialog; class Application : public SharedTools::QtSingleApplication { @@ -84,6 +85,7 @@ signals: protected slots: void slotFoldersChanged(); void slotSettings(); + void slotItemProgressDialog(); void slotParseOptions( const QString& ); void slotShowTrayMessage(const QString&, const QString&); void slotShowOptionalTrayMessage(const QString&, const QString&); @@ -134,6 +136,8 @@ private: QSignalMapper *_folderOpenActionMapper; LogBrowser *_logBrowser; QPointer<SettingsDialog> _settingsDialog; + QPointer<ItemProgressDialog> _progressDialog; + QString _logFile; QString _logDirectory; diff --git a/src/mirall/csyncthread.cpp b/src/mirall/csyncthread.cpp index ca9cc9045..245152102 100644 --- a/src/mirall/csyncthread.cpp +++ b/src/mirall/csyncthread.cpp @@ -442,6 +442,14 @@ Progress::Kind CSyncThread::csyncToProgressKind( enum csync_notify_type_e kind ) case CSYNC_NOTIFY_FINISHED_SYNC_SEQUENCE: pKind = Progress::EndSync; break; +#if 0 + case CSYNC_NOTIFY_START_DELETE: + pKind = Progress::StartDelete; + break; + case CSYNC_NOTIFY_END_DELETE: + pKind = Progress::EndDelete; + break; +#endif case CSYNC_NOTIFY_ERROR: pKind = Progress::Error; break; diff --git a/src/mirall/folder.cpp b/src/mirall/folder.cpp index 1e395e192..6eb3312ae 100644 --- a/src/mirall/folder.cpp +++ b/src/mirall/folder.cpp @@ -42,19 +42,6 @@ void csyncLogCatcher(CSYNC */*ctx*/, Logger::instance()->csyncLog( QString::fromUtf8(buffer) ); } -static QString replaceScheme(const QString &urlStr) -{ - - QUrl url( urlStr ); - if( url.scheme() == QLatin1String("http") ) { - url.setScheme( QLatin1String("owncloud") ); - } else { - // connect SSL! - url.setScheme( QLatin1String("ownclouds") ); - } - return url.toString(); -} - Folder::Folder(const QString &alias, const QString &path, const QString& secondPath, QObject *parent) : QObject(parent) , _pollTimer(new QTimer(this)) @@ -69,17 +56,8 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP , _csync_ctx(0) { qsrand(QTime::currentTime().msec()); - MirallConfigFile cfgFile; - - _pollTimer->setSingleShot(true); - int polltime = cfgFile.remotePollInterval()- 2000 + (int)( 4000.0*qrand()/(RAND_MAX+1.0)); - qDebug() << "setting remote poll timer interval to" << polltime << "msec for folder " << alias; - _pollTimer->setInterval( polltime ); - QObject::connect(_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout())); - _pollTimer->start(); - - _watcher = new Mirall::FolderWatcher(path, this); + _watcher = new FolderWatcher(path, this); MirallConfigFile cfg; _watcher->addIgnoreListFile( cfg.excludeFile(MirallConfigFile::SystemScope) ); @@ -87,15 +65,12 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP QObject::connect(_watcher, SIGNAL(folderChanged(const QStringList &)), SLOT(slotChanged(const QStringList &))); - QObject::connect(this, SIGNAL(syncStarted()), - SLOT(slotSyncStarted())); - QObject::connect(this, SIGNAL(syncFinished(const SyncResult &)), - SLOT(slotSyncFinished(const SyncResult &))); _syncResult.setStatus( SyncResult::NotYetStarted ); ServerActionNotifier *notifier = new ServerActionNotifier(this); connect(notifier, SIGNAL(guiLog(QString,QString)), Logger::instance(), SIGNAL(optionalGuiLog(QString,QString))); + connect(this, SIGNAL(syncFinished(SyncResult)), this, SLOT(slotSyncFinished(SyncResult))); connect(this, SIGNAL(syncFinished(SyncResult)), notifier, SLOT(slotSyncFinished(SyncResult))); // check if the local path exists @@ -104,7 +79,7 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP bool Folder::init() { - QString url = replaceScheme(ownCloudInfo::instance()->webdavUrl() + secondPath()); + QString url = Utility::toCSyncScheme(ownCloudInfo::instance()->webdavUrl() + secondPath()); QString localpath = path(); if( csync_create( &_csync_ctx, localpath.toUtf8().data(), url.toUtf8().data() ) < 0 ) { @@ -217,9 +192,6 @@ void Folder::setSyncEnabled( bool doit ) { _enabled = doit; _watcher->setEventsEnabled( doit ); - if( doit && ! _pollTimer->isActive() ) { - _pollTimer->start(); - } qDebug() << "setSyncEnabled - ############################ " << doit; if( doit ) { @@ -232,21 +204,11 @@ void Folder::setSyncEnabled( bool doit ) } } -int Folder::pollInterval() const -{ - return _pollTimer->interval(); -} - void Folder::setSyncState(SyncResult::Status state) { _syncResult.setStatus(state); } -void Folder::setPollInterval(int milliseconds) -{ - _pollTimer->setInterval( milliseconds ); -} - SyncResult Folder::syncResult() const { return _syncResult; @@ -259,11 +221,6 @@ void Folder::evaluateSync(const QStringList &/*pathList*/) return; } - // stop the poll timer here. Its started again in the slot of - // sync finished. - qDebug() << "* " << alias() << "Poll timer disabled"; - _pollTimer->stop(); - _syncResult.setStatus( SyncResult::NotYetStarted ); emit scheduleToSync( alias() ); @@ -282,27 +239,12 @@ void Folder::slotChanged(const QStringList &pathList) evaluateSync(pathList); } -void Folder::slotSyncStarted() -{ - // disable events until syncing is done - _watcher->setEventsEnabled(false); -} - void Folder::slotSyncFinished(const SyncResult &result) { _watcher->setEventsEnabledDelayed(2000); qDebug() << "OO folder slotSyncFinished: result: " << int(result.status()); emit syncStateChange(); - - // reenable the poll timer if folder is sync enabled - if( syncEnabled() ) { - qDebug() << "* " << alias() << "Poll timer enabled with " << _pollTimer->interval() << "milliseconds"; - _pollTimer->start(); - } else { - qDebug() << "* Not enabling poll timer for " << alias(); - _pollTimer->stop(); - } } void Folder::slotLocalPathChanged( const QString& dir ) @@ -518,6 +460,9 @@ void Folder::startSync(const QStringList &pathList) _thread->start(); QMetaObject::invokeMethod(_csync, "startSync", Qt::QueuedConnection); + + // disable events until syncing is done + _watcher->setEventsEnabled(false); emit syncStarted(); } @@ -551,6 +496,9 @@ void Folder::slotCSyncFinished() qDebug() << " * owncloud csync thread finished with error"; } else if (_csyncUnavail) { _syncResult.setStatus(SyncResult::Unavailable); + } else if( _syncResult.warnCount() > 0 ) { + // there have been warnings on the way. + _syncResult.setStatus(SyncResult::Problem); } else { _syncResult.setStatus(SyncResult::Success); } @@ -570,10 +518,21 @@ void Folder::slotTransmissionProgress(const Progress::Info& progress) if(newInfo.current_file.startsWith(QLatin1String("ownclouds://")) || newInfo.current_file.startsWith(QLatin1String("owncloud://")) ) { // rip off the whole ownCloud URL. - QString regexp = QString("^owncloud[s]*://.*/remote.php/webdav/%1/").arg(secondPath()); - QRegExp re( regexp ); - re.setMinimal(true); - newInfo.current_file.remove(re); + QString remotePathUrl = ownCloudInfo::instance()->webdavUrl() + secondPath(); + newInfo.current_file.remove(Utility::toCSyncScheme(remotePathUrl)); + } + 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()); + } + + // 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 ); } ProgressDispatcher::instance()->setProgressInfo(alias(), newInfo); diff --git a/src/mirall/folder.h b/src/mirall/folder.h index 3f8dfdcb4..966711c70 100644 --- a/src/mirall/folder.h +++ b/src/mirall/folder.h @@ -25,15 +25,13 @@ #include <QHash> #include <QNetworkAccessManager> #include <QNetworkProxy> -#include <QNetworkProxyFactory> #include <QObject> #include <QStringList> -#include <QThread> -#include <QTimer> #include <QDebug> class QFileSystemWatcher; +class QThread; namespace Mirall { @@ -135,8 +133,6 @@ public: */ virtual void wipe(); - QTimer *_pollTimer; - signals: void syncStateChange(); void syncStarted(); @@ -156,12 +152,6 @@ public slots: */ void slotTerminateSync(); - /** - * Sets minimum amounts of milliseconds that will separate - * poll intervals - */ - void setPollInterval( int ); - void slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool*); @@ -182,11 +172,6 @@ private slots: void slotPollTimerTimeout(); - - /** called when the watcher detect a list of changed paths */ - - void slotSyncStarted(); - /** * Triggered by a file system watcher on the local sync dir */ @@ -196,11 +181,6 @@ private slots: protected: bool init(); - /** - * The minimum amounts of seconds to wait before - * doing a full sync to see if the remote changed - */ - int pollInterval() const; void setSyncState(SyncResult::Status state); void setIgnoredFiles(); diff --git a/src/mirall/folderman.cpp b/src/mirall/folderman.cpp index e945f58e8..d12237fc4 100644 --- a/src/mirall/folderman.cpp +++ b/src/mirall/folderman.cpp @@ -37,7 +37,8 @@ FolderMan* FolderMan::_instance = 0; FolderMan::FolderMan(QObject *parent) : QObject(parent), - _syncEnabled( true ) + _syncEnabled( true ), + _pollTimer(new QTimer(this)) { // if QDir::mkpath would not be so stupid, I would not need to have this // duplication of folderConfigPath() here @@ -49,6 +50,14 @@ FolderMan::FolderMan(QObject *parent) : _folderChangeSignalMapper = new QSignalMapper(this); connect(_folderChangeSignalMapper, SIGNAL(mapped(const QString &)), this, SIGNAL(folderSyncStateChange(const QString &))); + + _pollTimer->setSingleShot(true); + int polltime = cfg.remotePollInterval(); + qDebug() << "setting remote poll timer interval to" << polltime << "msec"; + _pollTimer->setInterval( polltime ); + QObject::connect(_pollTimer, SIGNAL(timeout()), this, SLOT(slotScheduleAllFolders())); + _pollTimer->setSingleShot(true); + _pollTimer->start(); } FolderMan *FolderMan::instance() @@ -296,7 +305,7 @@ void FolderMan::terminateSyncProcess( const QString& alias ) f->slotTerminateSync(); if(_currentSyncFolder == folderAlias ) - _currentSyncFolder = QString::null; + _currentSyncFolder.clear(); } } } @@ -325,7 +334,9 @@ SyncResult FolderMan::syncResult( Folder *f ) void FolderMan::slotScheduleAllFolders() { foreach( Folder *f, _folderMap.values() ) { - slotScheduleSync( f->alias() ); + if (f->syncEnabled()) { + slotScheduleSync( f->alias() ); + } } } @@ -344,13 +355,11 @@ void FolderMan::slotScheduleSync( const QString& alias ) } if( ! _scheduleQueue.contains(alias )) { - _scheduleQueue.append(alias); + _scheduleQueue.enqueue(alias); } else { qDebug() << " II> Sync for folder " << alias << " already scheduled, do not enqueue!"; } - slotScheduleFolderSync(); - } void FolderMan::setSyncEnabled( bool enabled ) @@ -377,12 +386,15 @@ void FolderMan::slotScheduleFolderSync() qDebug() << "XX slotScheduleFolderSync: folderQueue size: " << _scheduleQueue.count(); if( ! _scheduleQueue.isEmpty() ) { - const QString alias = _scheduleQueue.takeFirst(); + const QString alias = _scheduleQueue.dequeue(); if( _folderMap.contains( alias ) ) { ownCloudInfo::instance()->getQuotaRequest("/"); Folder *f = _folderMap[alias]; _currentSyncFolder = alias; - f->startSync( QStringList() ); + if (f->syncEnabled()) { + f->startSync( QStringList() ); + _pollTimer->stop(); + } } } } @@ -402,6 +414,7 @@ void FolderMan::slotFolderSyncFinished( const SyncResult& ) _currentSyncFolder.clear(); QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync())); + _pollTimer->start(); } void FolderMan::addFolderDefinition(const QString& alias, const QString& sourceFolder, const QString& targetPath ) @@ -548,7 +561,7 @@ SyncResult FolderMan::accountStatus(const QList<Folder*> &folders) return overallResult; } -QString FolderMan::statusToString( SyncResult syncStatus ) const +QString FolderMan::statusToString( SyncResult syncStatus, bool enabled ) const { QString folderMessage; switch( syncStatus.status() ) { @@ -578,11 +591,10 @@ QString FolderMan::statusToString( SyncResult syncStatus ) const break; // no default case on purpose, check compiler warnings } -// FIXME! -// if( !folder->syncEnabled() ) { -// // sync is disabled. -// folderMessage = tr( "%1 (Sync is paused)" ).arg(folderMessage); -// } + if( !enabled ) { + // sync is disabled. + folderMessage = tr( "%1 (Sync is paused)" ).arg(folderMessage); + } return folderMessage; } diff --git a/src/mirall/folderman.h b/src/mirall/folderman.h index 22d63e9b7..48331aecd 100644 --- a/src/mirall/folderman.h +++ b/src/mirall/folderman.h @@ -25,6 +25,7 @@ #include "mirall/syncfileitem.h" class QSignalMapper; +class QTimer; class SyncResult; @@ -78,7 +79,7 @@ public: /** Creates a new and empty local directory. */ bool startFromScratch( const QString& ); - QString statusToString( SyncResult ) const; + QString statusToString( SyncResult, bool enabled ) const; static SyncResult accountStatus( const QList<Folder*> &folders ); @@ -131,11 +132,12 @@ private: void removeFolder( const QString& ); Folder::Map _folderMap; + QTimer *_pollTimer; QString _folderConfigPath; QSignalMapper *_folderChangeSignalMapper; QString _currentSyncFolder; - QStringList _scheduleQueue; bool _syncEnabled; + QQueue<QString> _scheduleQueue; explicit FolderMan(QObject *parent = 0); static FolderMan *_instance; diff --git a/src/mirall/folderstatusmodel.cpp b/src/mirall/folderstatusmodel.cpp index 1b75489e1..bc2403c96 100644 --- a/src/mirall/folderstatusmodel.cpp +++ b/src/mirall/folderstatusmodel.cpp @@ -118,16 +118,17 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & int aliasMargin = aliasFm.height()/2; int margin = subFm.height()/4; - QIcon statusIcon = qvariant_cast<QIcon>(index.data(FolderStatusIconRole)); - QString aliasText = qvariant_cast<QString>(index.data(FolderAliasRole)); - QString pathText = qvariant_cast<QString>(index.data(FolderPathRole)); - QString remotePath = qvariant_cast<QString>(index.data(FolderSecondPathRole)); - QString errorText = qvariant_cast<QString>(index.data(FolderErrorMsg)); + QIcon statusIcon = qvariant_cast<QIcon>(index.data(FolderStatusIconRole)); + QString aliasText = qvariant_cast<QString>(index.data(FolderAliasRole)); + QString pathText = qvariant_cast<QString>(index.data(FolderPathRole)); + QString remotePath = qvariant_cast<QString>(index.data(FolderSecondPathRole)); + QString errorText = qvariant_cast<QString>(index.data(FolderErrorMsg)); int overallPercent = qvariant_cast<int>(index.data(SyncProgressOverallPercent)); QString overallString = qvariant_cast<QString>(index.data(SyncProgressOverallString)); QString itemString = qvariant_cast<QString>(index.data(SyncProgressItemString)); - + int warningCount = qvariant_cast<int>(index.data(WarningCount)); + bool syncOngoing = qvariant_cast<bool>(index.data(SyncRunning)); // QString statusText = qvariant_cast<QString>(index.data(FolderStatus)); bool syncEnabled = index.data(FolderSyncEnabled).toBool(); // QString syncStatus = syncEnabled? tr( "Enabled" ) : tr( "Disabled" ); @@ -166,6 +167,20 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & QPixmap pm = statusIcon.pixmap(iconSize, iconSize, syncEnabled ? QIcon::Normal : QIcon::Disabled ); painter->drawPixmap(QPoint(iconRect.left(), iconRect.top()), pm); + // only show the warning icon if the sync is running. Otherwise its + // encoded in the status icon. + if( warningCount > 0 && syncOngoing) { + QRect warnRect; + warnRect.setLeft(iconRect.left()); + warnRect.setTop(iconRect.bottom()-17); + warnRect.setWidth(16); + warnRect.setHeight(16); + + QIcon warnIcon(":/mirall/resources/warning-16"); + QPixmap pm = warnIcon.pixmap(16,16, syncEnabled ? QIcon::Normal : QIcon::Disabled ); + painter->drawPixmap(QPoint(warnRect.left(), warnRect.top()),pm ); + } + if ((option.state & QStyle::State_Selected) && (option.state & QStyle::State_Active) // Hack: Windows Vista's light blue is not contrasting enough for white diff --git a/src/mirall/folderstatusmodel.h b/src/mirall/folderstatusmodel.h index ec8537db2..7db24f698 100644 --- a/src/mirall/folderstatusmodel.h +++ b/src/mirall/folderstatusmodel.h @@ -48,7 +48,9 @@ class FolderStatusDelegate : public QStyledItemDelegate SyncProgressOverallPercent, SyncProgressOverallString, SyncProgressItemString, - AddProgressSpace + AddProgressSpace, + WarningCount, + SyncRunning }; void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const; QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const; diff --git a/src/mirall/folderwizard.cpp b/src/mirall/folderwizard.cpp index 74e8eaaf5..d3604747a 100644 --- a/src/mirall/folderwizard.cpp +++ b/src/mirall/folderwizard.cpp @@ -22,6 +22,7 @@ #include <QDir> #include <QFileDialog> #include <QFileInfo> +#include <QFileIconProvider> #include <QInputDialog> #include <QUrl> #include <QValidator> @@ -178,6 +179,8 @@ FolderWizardTargetPage::FolderWizardTargetPage() void FolderWizardTargetPage::slotAddRemoteFolder() { QInputDialog *dlg = new QInputDialog(this); + dlg->setWindowTitle(tr("Add Remote Folder")); + dlg->setLabelText(tr("Enter the name of the new folder:")); dlg->open(this, SLOT(slotCreateRemoteFolder(QString))); dlg->setAttribute(Qt::WA_DeleteOnClose); } @@ -205,9 +208,13 @@ void FolderWizardTargetPage::slotCreateRemoteFolderFinished( QNetworkReply::Netw void FolderWizardTargetPage::slotUpdateDirectories(QStringList list) { _ui.folderListWidget->clear(); - foreach (QString item, list) { - item.remove(QLatin1String("/remote.php/webdav")); - _ui.folderListWidget->addItem(item); + QFileIconProvider prov; + QIcon folderIcon = prov.icon(QFileIconProvider::Folder); + QString webdavFolder = QUrl(ownCloudInfo::instance()->webdavUrl()).path(); + foreach (QString path, list) { + path.remove(webdavFolder); + if (!path.startsWith("/")) path.prepend('/'); + new QListWidgetItem(folderIcon, path, _ui.folderListWidget); } } diff --git a/src/mirall/ignorelisteditor.cpp b/src/mirall/ignorelisteditor.cpp index e1e831d04..5d413f63a 100644 --- a/src/mirall/ignorelisteditor.cpp +++ b/src/mirall/ignorelisteditor.cpp @@ -32,7 +32,9 @@ IgnoreListEditor::IgnoreListEditor(QWidget *parent) : { ui->setupUi(this); - ui->descriptionLabel->setText(tr("Files matching the following patterns will not be synchronized:")); + ui->descriptionLabel->setText(tr("Files or directories matching a pattern will not be synchronized.\n\n" + "Checked items will also be deleted if they prevent a directory from " + "being removed. This is useful for meta data.")); MirallConfigFile cfgFile; readIgnoreFile(cfgFile.excludeFile(MirallConfigFile::SystemScope), true); @@ -49,7 +51,8 @@ IgnoreListEditor::IgnoreListEditor(QWidget *parent) : static void setupItemFlags(QListWidgetItem* item) { - item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable); + item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable); + item->setCheckState(Qt::Unchecked); } IgnoreListEditor::~IgnoreListEditor() @@ -83,7 +86,11 @@ void IgnoreListEditor::slotUpdateLocalIgnoreList() for(int i = 0; i < ui->listWidget->count(); ++i) { QListWidgetItem *item = ui->listWidget->item(i); if (item->flags() & Qt::ItemIsEnabled) { - ignores.write(item->text().toUtf8()+'\n'); + QByteArray prepend; + if (item->checkState() == Qt::Checked) { + prepend = "]"; + } + ignores.write(prepend+item->text().toUtf8()+'\n'); } } } else { @@ -95,8 +102,13 @@ void IgnoreListEditor::slotUpdateLocalIgnoreList() void IgnoreListEditor::slotAddPattern() { QString pattern = QInputDialog::getText(this, tr("Add Ignore Pattern"), tr("Add a new ignore pattern:")); - QListWidgetItem *item = new QListWidgetItem(pattern); + QListWidgetItem *item = new QListWidgetItem; setupItemFlags(item); + if (pattern.startsWith("]")) { + pattern = pattern.mid(1); + item->setCheckState(Qt::Checked); + } + item->setText(pattern); ui->listWidget->addItem(item); ui->listWidget->scrollToItem(item); } @@ -128,9 +140,14 @@ void IgnoreListEditor::readIgnoreFile(const QString &file, bool readOnly) QString line = QString::fromUtf8(ignores.readLine()); line.chop(1); if (!line.isEmpty() && !line.startsWith("#")) { - QListWidgetItem *item = new QListWidgetItem(line); + QListWidgetItem *item = new QListWidgetItem; + setupItemFlags(item); + if (line.startsWith("]")) { + line = line.mid(1); + item->setCheckState(Qt::Checked); + } + item->setText(line); if (readOnly) { - setupItemFlags(item); item->setFlags(item->flags() ^ Qt::ItemIsEnabled); item->setToolTip(disabledTip); } diff --git a/src/mirall/ignorelisteditor.ui b/src/mirall/ignorelisteditor.ui index 7d5f98356..f65d3cb0f 100644 --- a/src/mirall/ignorelisteditor.ui +++ b/src/mirall/ignorelisteditor.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>400</width> + <width>471</width> <height>359</height> </rect> </property> @@ -14,15 +14,28 @@ <string>Ignored Files Editor</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="descriptionLabel"> + <item row="5" column="0" colspan="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <spacer name="verticalSpacer"> <property name="enabled"> <bool>true</bool> </property> - <property name="text"> - <string/> + <property name="orientation"> + <enum>Qt::Vertical</enum> </property> - </widget> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>213</height> + </size> + </property> + </spacer> </item> <item row="1" column="0" rowspan="3"> <widget class="QListWidget" name="listWidget"> @@ -51,26 +64,16 @@ </property> </widget> </item> - <item row="3" column="1"> - <spacer name="verticalSpacer"> + <item row="4" column="0" colspan="2"> + <widget class="QLabel" name="descriptionLabel"> <property name="enabled"> <bool>true</bool> </property> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>213</height> - </size> + <property name="text"> + <string/> </property> - </spacer> - </item> - <item row="4" column="0" colspan="2"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + <property name="wordWrap"> + <bool>true</bool> </property> </widget> </item> diff --git a/src/mirall/itemprogressdialog.cpp b/src/mirall/itemprogressdialog.cpp new file mode 100644 index 000000000..5205c8710 --- /dev/null +++ b/src/mirall/itemprogressdialog.cpp @@ -0,0 +1,258 @@ +/* + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <QtGui> + +#include "mirall/itemprogressdialog.h" +#include "mirall/syncresult.h" +#include "mirall/logger.h" +#include "mirall/utility.h" +#include "mirall/theme.h" +#include "mirall/folderman.h" + +#include "ui_itemprogressdialog.h" + +#define TYPE_SUCCESS 1 +#define TYPE_CONFLICT 2 +#define TYPE_NEW 3 +#define TYPE_DELETED 4 +#define TYPE_ERROR 5 +#define TYPE_RENAME 6 +#define TYPE_IGNORE 7 + +#define FILE_TYPE 100 + +namespace Mirall { + +ItemProgressDialog::ItemProgressDialog(Application*, QWidget *parent) : + QDialog(parent), + _ui(new Ui::ItemProgressDialog), + ErrorIndicatorRole( Qt::UserRole +1 ) +{ + _ui->setupUi(this); + connect(_ui->_dialogButtonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), + this, SLOT(accept())); + + connect(ProgressDispatcher::instance(), SIGNAL(progressInfo(QString,Progress::Info)), + this, SLOT(slotProgressInfo(QString,Progress::Info))); + connect(ProgressDispatcher::instance(), SIGNAL(progressSyncProblem(const QString&,const Progress::SyncProblem&)), + this, SLOT(slotProgressErrors(const QString&, const Progress::SyncProblem&))); + + QStringList header; + header << tr("Folder/Time"); + header << tr("File"); + header << tr("Action"); + header << tr("Size"); + + _ui->_treeWidget->setHeaderLabels( header ); + + _ui->_treeWidget->setColumnWidth(1, 180); + + connect(this, SIGNAL(guiLog(QString,QString)), Logger::instance(), SIGNAL(guiLog(QString,QString))); + + QPushButton *copyBtn = _ui->_dialogButtonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole); + connect(copyBtn, SIGNAL(clicked()), SLOT(copyToClipboard())); + + setWindowTitle(tr("Sync Protocol")); + +} + +void ItemProgressDialog::setupList() +{ + // get the folders to set up the top level list. + Folder::Map map = FolderMan::instance()->map(); + foreach( Folder *f, map.values() ) { + findFolderItem(f->alias()); + } + + QList<Progress::Info> progressList = ProgressDispatcher::instance()->recentChangedItems(0); // All. + + QHash <QString, int> folderHash; + + foreach( Progress::Info info, progressList ) { + slotProgressInfo( info.folder, info ); + folderHash[info.folder] = 1; + } + + QList<Progress::SyncProblem> problemList = ProgressDispatcher::instance()->recentProblems(0); + foreach( Progress::SyncProblem prob, problemList ) { + slotProgressErrors(prob.folder, prob); + folderHash[prob.folder] = 1; + } + + foreach( const QString& folder, folderHash.keys() ) { + decorateFolderItem(folder); + } + +} + +ItemProgressDialog::~ItemProgressDialog() +{ + delete _ui; +} + +void ItemProgressDialog::copyToClipboard() +{ + QString text; + QTextStream ts(&text); + + int topLevelItems = _ui->_treeWidget->topLevelItemCount(); + for (int i = 0; i < topLevelItems; i++) { + QTreeWidgetItem *item = _ui->_treeWidget->topLevelItem(i); + ts << left << qSetFieldWidth(50) + << item->data(0, Qt::DisplayRole).toString() + << right << qSetFieldWidth(6) + << item->data(1, Qt::DisplayRole).toString() + << endl; + int childItems = item->childCount(); + for (int j = 0; j < childItems; j++) { + QTreeWidgetItem *child =item->child(j); + ts << left << qSetFieldWidth(0) << QLatin1String(" ") + << child->data(0,Qt::DisplayRole).toString() + << QString::fromLatin1(" (%1)").arg( + child->data(1, Qt::DisplayRole).toString() + ) + << endl; + } + } + + QApplication::clipboard()->setText(text); + emit guiLog(tr("Copied to clipboard"), tr("The sync protocol has been copied to the clipboard.")); +} + +void ItemProgressDialog::accept() +{ + QDialog::accept(); +} + +void ItemProgressDialog::decorateFolderItem( const QString& folder ) +{ + QTreeWidgetItem *folderItem = findFolderItem(folder); + if( ! folderItem ) return; + int errorCnt = 0; + + int childCnt = folderItem->childCount(); + for( int cnt = 0; cnt < childCnt; cnt++ ) { + bool isErrorItem = folderItem->child(cnt)->data(0, ErrorIndicatorRole).toBool(); + if( isErrorItem ) { + errorCnt++; + } + } + + if( errorCnt == 0 ) { + folderItem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Success)); + } else { + // FIXME: Set a soft error icon here. + folderItem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Error)); + } +} + +QTreeWidgetItem *ItemProgressDialog::createFolderItem(const QString& folder) +{ + QStringList strings; + strings.append(folder); + QTreeWidgetItem *item = new QTreeWidgetItem( _ui->_treeWidget, strings ); + item->setFirstColumnSpanned(true); + return item; +} + +QTreeWidgetItem *ItemProgressDialog::findFolderItem( const QString& folder ) +{ + QTreeWidgetItem *folderItem; + + if( folder.isEmpty() ) return NULL; + + if( !_folderItems.contains(folder)) { + _folderItems[folder] = createFolderItem(folder); + _ui->_treeWidget->addTopLevelItem(_folderItems[folder]); + } + folderItem = _folderItems[folder]; + + return folderItem; +} + +void ItemProgressDialog::cleanErrors( const QString& folder ) +{ + _problemCounter = 0; + QList<QTreeWidgetItem*> wipeList; + + QTreeWidgetItem *folderItem = findFolderItem(folder); + if( ! folderItem ) return; + + int childCnt = folderItem->childCount(); + for( int cnt = 0; cnt < childCnt; cnt++ ) { + bool isErrorItem = folderItem->child(cnt)->data(0, ErrorIndicatorRole).toBool(); + if( isErrorItem ) { + wipeList.append(folderItem->child(cnt)); + } + } + qDeleteAll(wipeList.begin(), wipeList.end()); +} + +void ItemProgressDialog::slotProgressErrors( const QString& folder, const Progress::SyncProblem& problem ) +{ + QTreeWidgetItem *folderItem; + + folderItem = findFolderItem(folder); + if( !folderItem ) return; + + QStringList columns; + QString timeStr = problem.timestamp.toString("hh:mm"); + + columns << timeStr; + columns << problem.current_file; + QString errMsg = tr("Problem: %1").arg(problem.error_message); + columns << errMsg; + // FIXME: Show the error code if available. + + QTreeWidgetItem *item = new QTreeWidgetItem(folderItem, columns); + item->setData(0, ErrorIndicatorRole, QVariant(true) ); + item->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Problem, true)); + + Q_UNUSED(item); +} + +void ItemProgressDialog::slotProgressInfo( const QString& folder, const Progress::Info& progress ) +{ + QTreeWidgetItem *folderItem; + folderItem = findFolderItem(folder); + if( !folderItem ) return; + + if( progress.kind == Progress::StartSync ) { + cleanErrors( folder ); + folderItem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::SyncRunning)); + } + + if( progress.kind == Progress::EndSync ) { + decorateFolderItem( folder ); + } + + // Ingore other events than finishing an individual up- or download. + if( !(progress.kind == Progress::EndDownload || progress.kind == Progress::EndUpload || progress.kind == Progress::EndDelete)) { + return; + } + + QStringList columns; + QString timeStr = progress.timestamp.toString("hh:mm"); + + columns << timeStr; + columns << progress.current_file; + columns << Progress::asString(progress.kind); + columns << Utility::octetsToString( progress.file_size ); + + QTreeWidgetItem *item = new QTreeWidgetItem(folderItem, columns); + Q_UNUSED(item); +} + + +} diff --git a/src/mirall/itemprogressdialog.h b/src/mirall/itemprogressdialog.h new file mode 100644 index 000000000..493621ee2 --- /dev/null +++ b/src/mirall/itemprogressdialog.h @@ -0,0 +1,67 @@ +/* + * 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; version 2 of the License. + * + * 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. + */ + +#ifndef FILEITEMDIALOG_H +#define FILEITEMDIALOG_H + +#include <QDialog> +#include <QDateTime> + +#include "mirall/progressdispatcher.h" + +#include "ui_fileitemdialog.h" + +namespace Mirall { +class SyncResult; + +namespace Ui { + class ItemProgressDialog; +} +class Application; + +class ItemProgressDialog : public QDialog +{ + Q_OBJECT +public: + explicit ItemProgressDialog(Application *app, QWidget *parent = 0); + ~ItemProgressDialog(); + + void setupList(); + +signals: + +public slots: + void accept(); + void slotProgressInfo( const QString& folder, const Progress::Info& progress ); + void slotProgressErrors( const QString& folder, const Progress::SyncProblem& problem ); + +protected slots: + void copyToClipboard(); + +signals: + void guiLog(const QString&, const QString&); + +private: + QTreeWidgetItem *createFolderItem(const QString& folder); + QTreeWidgetItem *findFolderItem( const QString& folder ); + void cleanErrors( const QString& folder ); + void decorateFolderItem( const QString& folder ); + + QHash<QString, QTreeWidgetItem*> _folderItems; + const int ErrorIndicatorRole; + Ui::ItemProgressDialog *_ui; + int _problemCounter; +}; + +} +#endif // FILEITEMDIALOG_H diff --git a/src/mirall/itemprogressdialog.ui b/src/mirall/itemprogressdialog.ui new file mode 100644 index 000000000..6bde5f207 --- /dev/null +++ b/src/mirall/itemprogressdialog.ui @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Mirall::ItemProgressDialog</class> + <widget class="QWidget" name="Mirall::ItemProgressDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>612</width> + <height>543</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="font"> + <font> + <pointsize>14</pointsize> + </font> + </property> + <property name="text"> + <string>Detailed Sync Protocol</string> + </property> + </widget> + </item> + <item> + <widget class="QTreeWidget" name="_treeWidget"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="rootIsDecorated"> + <bool>true</bool> + </property> + <property name="uniformRowHeights"> + <bool>true</bool> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <property name="columnCount"> + <number>4</number> + </property> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + <column> + <property name="text"> + <string notr="true">2</string> + </property> + </column> + <column> + <property name="text"> + <string>3</string> + </property> + </column> + <column> + <property name="text"> + <string>4</string> + </property> + </column> + </widget> + </item> + <item> + <widget class="QLabel" name="_timelabel"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="_errorLabel"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="_dialogButtonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/mirall/owncloudinfo.cpp b/src/mirall/owncloudinfo.cpp index b9016e37a..296598e83 100644 --- a/src/mirall/owncloudinfo.cpp +++ b/src/mirall/owncloudinfo.cpp @@ -166,6 +166,7 @@ QNetworkReply* ownCloudInfo::getQuotaRequest( const QString& dir ) " <d:prop>\n" " <d:quota-available-bytes/>\n" " <d:quota-used-bytes/>\n" + " <d:getetag/>" " </d:prop>\n" "</d:propfind>\n"); QBuffer *buf = new QBuffer; @@ -241,6 +242,7 @@ void ownCloudInfo::slotGetQuotaFinished() qint64 quotaUsedBytes = 0; qint64 quotaAvailableBytes = 0; + QString etag; while (!reader.atEnd()) { QXmlStreamReader::TokenType type = reader.readNext(); @@ -253,6 +255,8 @@ void ownCloudInfo::slotGetQuotaFinished() } else if (name == QLatin1String("quota-available-bytes")) { quotaAvailableBytes = reader.readElementText().toLongLong(&ok); if (!ok) quotaAvailableBytes = 0; + } else if (name == QLatin1String("getetag")) { + etag = reader.readElementText(); } } } @@ -262,6 +266,7 @@ void ownCloudInfo::slotGetQuotaFinished() _lastQuotaTotalBytes = total; _lastQuotaUsedBytes = quotaUsedBytes; emit quotaUpdated(total, quotaUsedBytes); + _lastEtag = etag; } else { _lastQuotaTotalBytes = 0; _lastQuotaUsedBytes = 0; @@ -544,6 +549,7 @@ QString ownCloudInfo::webdavUrl(const QString &connection) url = cfgFile.ownCloudUrl( connection ); } url.append( QLatin1String( WEBDAV_PATH ) ); + if (!url.endsWith('/')) url.append('/'); return url; } diff --git a/src/mirall/owncloudinfo.h b/src/mirall/owncloudinfo.h index 6fde51042..be11e7177 100644 --- a/src/mirall/owncloudinfo.h +++ b/src/mirall/owncloudinfo.h @@ -98,11 +98,13 @@ public: /** * returns the owncloud webdav url. * It may be different from the one in the config if there was a HTTP redirection + * The returned URL is guaranteed to end in a forward slash ('/') */ QString webdavUrl(const QString& connection = QString()); qint64 lastQuotaUsedBytes() const { return _lastQuotaUsedBytes; } qint64 lastQuotaTotalBytes() const { return _lastQuotaTotalBytes; } + QString lastEtag() const { return _lastEtag; } QList<QNetworkCookie> getLastAuthCookies(); @@ -154,6 +156,7 @@ private: int _redirectCount; qint64 _lastQuotaUsedBytes; qint64 _lastQuotaTotalBytes; + QString _lastEtag; }; } // ns Mirall diff --git a/src/mirall/progressdispatcher.cpp b/src/mirall/progressdispatcher.cpp index c4ec1b22a..57c74b967 100644 --- a/src/mirall/progressdispatcher.cpp +++ b/src/mirall/progressdispatcher.cpp @@ -57,6 +57,12 @@ QString Progress::asString( Kind kind ) case EndSync: re = QObject::tr("finished"); break; + case StartDelete: + re = QObject::tr("start delete"); + break; + case EndDelete: + re = QObject::tr("deleted"); + break; default: Q_ASSERT(false); } @@ -84,12 +90,18 @@ ProgressDispatcher::~ProgressDispatcher() QList<Progress::Info> ProgressDispatcher::recentChangedItems(int count) { - return _recentChanges.mid(0, count); + if( count > 0 ) { + return _recentChanges.mid(0, count); + } + return _recentChanges; } QList<Progress::SyncProblem> ProgressDispatcher::recentProblems(int count) { - return _recentProblems.mid(0, count); + if( count > 0 ) { + return _recentProblems.mid(0, count); + } + return _recentProblems; } void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress::Info& progress) @@ -105,6 +117,7 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress:: err.current_file = newProgress.current_file; err.error_message = QString::fromLocal8Bit( (const char*)newProgress.file_size ); err.error_code = newProgress.file_size; + err.timestamp = QTime::currentTime(); _recentProblems.enqueue( err ); if( _recentProblems.size() > _problemQueueSize ) { @@ -112,6 +125,9 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress:: } emit progressSyncProblem( folder, err ); } else { + if( newProgress.kind == Progress::StartSync ) { + _recentProblems.clear(); + } if( newProgress.kind == Progress::EndSync ) { newProgress.overall_current_bytes = newProgress.overall_transmission_size; newProgress.current_file_no = newProgress.overall_file_count; diff --git a/src/mirall/progressdispatcher.h b/src/mirall/progressdispatcher.h index 91c7954bc..94cb34d2c 100644 --- a/src/mirall/progressdispatcher.h +++ b/src/mirall/progressdispatcher.h @@ -40,6 +40,8 @@ public: EndDownload, EndUpload, EndSync, + StartDelete, + EndDelete, Error } Kind; @@ -64,6 +66,7 @@ public: QString current_file; QString error_message; int error_code; + QTime timestamp; } SyncProblem; static QString asString( Kind ); diff --git a/src/mirall/settingsdialog.cpp b/src/mirall/settingsdialog.cpp index 333c74cb9..47229bd1c 100644 --- a/src/mirall/settingsdialog.cpp +++ b/src/mirall/settingsdialog.cpp @@ -77,9 +77,12 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) : connect( _accountSettings, SIGNAL(folderChanged()), app, SLOT(slotFoldersChanged())); connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)), app, SLOT(slotFolderOpenAction(QString))); + connect( _accountSettings, SIGNAL(openProgressDialog()), app, SLOT(slotItemProgressDialog())); connect( ProgressDispatcher::instance(), SIGNAL(progressInfo(QString, Progress::Info)), _accountSettings, SLOT(slotSetProgress(QString, Progress::Info)) ); + connect( ProgressDispatcher::instance(), SIGNAL(progressSyncProblem(QString,Progress::SyncProblem)), + _accountSettings, SLOT(slotProgressProblem(QString,Progress::SyncProblem)) ); _ui->labelWidget->setCurrentRow(_ui->labelWidget->row(general)); diff --git a/src/mirall/syncresult.cpp b/src/mirall/syncresult.cpp index 2a7a71726..6884e05c9 100644 --- a/src/mirall/syncresult.cpp +++ b/src/mirall/syncresult.cpp @@ -18,12 +18,14 @@ namespace Mirall { SyncResult::SyncResult() -: _status( Undefined ) + : _status( Undefined ), + _warnCount(0) { } SyncResult::SyncResult(SyncResult::Status status ) - : _status(status) + : _status(status), + _warnCount(0) { } @@ -87,6 +89,16 @@ QDateTime SyncResult::syncTime() const return _syncTime; } +void SyncResult::setWarnCount(int wc) +{ + _warnCount = wc; +} + +int SyncResult::warnCount() const +{ + return _warnCount; +} + void SyncResult::setErrorStrings( const QStringList& list ) { _errors = list; diff --git a/src/mirall/syncresult.h b/src/mirall/syncresult.h index ac0cc6eb2..439f1cfc9 100644 --- a/src/mirall/syncresult.h +++ b/src/mirall/syncresult.h @@ -34,6 +34,7 @@ public: SyncPrepare, SyncRunning, Success, + Problem, Error, SetupError, Unavailable @@ -46,6 +47,8 @@ public: void setErrorStrings( const QStringList& ); QString errorString() const; QStringList errorStrings() const; + int warnCount() const; + void setWarnCount(int wc); void clearErrors(); // handle a list of changed items. @@ -65,6 +68,7 @@ private: * when the sync tool support this... */ QStringList _errors; + int _warnCount; }; } diff --git a/src/mirall/theme.cpp b/src/mirall/theme.cpp index caf7401af..2e8d13004 100644 --- a/src/mirall/theme.cpp +++ b/src/mirall/theme.cpp @@ -56,6 +56,9 @@ QString Theme::statusHeaderText( SyncResult::Status status ) const case SyncResult::Success: resultStr = QObject::tr("Sync Success"); break; + case SyncResult::Problem: + resultStr = QObject::tr("Sync Success, problems with individual files."); + break; case SyncResult::Error: resultStr = QObject::tr("Sync Error - Click info button for details."); break; @@ -223,6 +226,8 @@ QIcon Theme::syncStateIcon( SyncResult::Status status, bool sysTray ) const case SyncResult::Success: statusIcon = QLatin1String("state-ok"); break; + case SyncResult::Problem: + statusIcon = QLatin1String("state-error"); // FIXME: Use state-problem once we have an icon. case SyncResult::Error: case SyncResult::SetupError: default: diff --git a/src/mirall/theme.h b/src/mirall/theme.h index efe39a9ef..85376dfa0 100644 --- a/src/mirall/theme.h +++ b/src/mirall/theme.h @@ -82,7 +82,6 @@ public: virtual QIcon syncStateIcon( SyncResult::Status, bool sysTray = false ) const; virtual QIcon folderDisabledIcon() const = 0; - virtual QIcon applicationIcon() const = 0; virtual QString statusHeaderText( SyncResult::Status ) const; diff --git a/src/mirall/utility.cpp b/src/mirall/utility.cpp index e88fd25be..cee8c3998 100644 --- a/src/mirall/utility.cpp +++ b/src/mirall/utility.cpp @@ -109,21 +109,21 @@ QString Utility::octetsToString( qint64 octets ) if (octets >= tb) { if (octets < 10*tb) { - return compactFormatDouble(double(octets)/double(tb), 1, QLatin1String("TB")); + return compactFormatDouble(qreal(octets)/qreal(tb), 1, QLatin1String("TB")); } - return QString::number(octets/tb) + QLatin1String(" TB"); + return QString::number(qRound64(qreal(octets)/qreal(tb))) + QLatin1String(" TB"); } else if (octets >= gb) { if (octets < 10*gb) { - return compactFormatDouble(double(octets)/double(gb), 1, QLatin1String("GB")); + return compactFormatDouble(qreal(octets)/qreal(gb), 1, QLatin1String("GB")); } - return QString::number(octets/gb) + QLatin1String(" GB"); + return QString::number(qRound64(qreal(octets)/qreal(gb))) + QLatin1String(" GB"); } else if (octets >= mb) { if (octets < 10*mb) { - return compactFormatDouble(double(octets)/double(mb), 1, QLatin1String("MB")); + return compactFormatDouble(qreal(octets)/qreal(mb), 1, QLatin1String("MB")); } - return QString::number(octets/mb) + QLatin1String(" MB"); + return QString::number(qRound64(qreal(octets)/qreal(mb))) + QLatin1String(" MB"); } else if (octets >= kb) { - return QString::number(octets/kb) + QLatin1String(" KB"); + return QString::number(qRound64(qreal(octets)/qreal(kb))) + QLatin1String(" KB"); } else { return QString::number(octets) + QLatin1String(" bytes"); } @@ -345,4 +345,17 @@ QString Utility::compactFormatDouble(double value, int prec, const QString& unit return str; } +QString Utility::toCSyncScheme(const QString &urlStr) +{ + + QUrl url( urlStr ); + if( url.scheme() == QLatin1String("http") ) { + url.setScheme( QLatin1String("owncloud") ); + } else { + // connect SSL! + url.setScheme( QLatin1String("ownclouds") ); + } + return url.toString(); +} + } // namespace Mirall diff --git a/src/mirall/utility.h b/src/mirall/utility.h index 4bed2f15c..46022c725 100644 --- a/src/mirall/utility.h +++ b/src/mirall/utility.h @@ -32,6 +32,7 @@ namespace Utility bool hasLaunchOnStartup(const QString &appName); void setLaunchOnStartup(const QString &appName, const QString& guiName, bool launch); qint64 freeDiskSpace(const QString &path, bool *ok = 0); + QString toCSyncScheme(const QString &urlStr); /** Like QLocale::toString(double, 'f', prec), but drops trailing zeros after the decimal point */ /** |