diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aaf70a86aa..650737e199 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -215,6 +215,7 @@ set(mirall_SRCS mirall/accountsettings.cpp mirall/ignorelisteditor.cpp mirall/itemprogressdialog.cpp + mirall/owncloudgui.cpp ) set(mirall_HEADERS @@ -239,6 +240,7 @@ set(mirall_HEADERS mirall/accountsettings.h mirall/ignorelisteditor.h mirall/itemprogressdialog.h + mirall/owncloudgui.h ) if( UNIX AND NOT APPLE) diff --git a/src/mirall/application.cpp b/src/mirall/application.cpp index 6b58133af2..a7db2695d4 100644 --- a/src/mirall/application.cpp +++ b/src/mirall/application.cpp @@ -97,11 +97,9 @@ QString applicationTrPath() Application::Application(int &argc, char **argv) : SharedTools::QtSingleApplication(argc, argv), - _tray(0), + _gui(0), _networkMgr(new QNetworkConfigurationManager(this)), _sslErrorDialog(0), - _contextMenu(0), - _recentActionsMenu(0), _theme(Theme::instance()), _logBrowser(0), _logExpire(0), @@ -116,22 +114,18 @@ Application::Application(int &argc, char **argv) : //no need to waste time; if ( _helpOnly ) return; + _gui = new ownCloudGui(this); + setupLogBrowser(); setupTranslations(); connect( this, SIGNAL(messageReceived(QString)), SLOT(slotParseOptions(QString))); connect( Logger::instance(), SIGNAL(guiLog(QString,QString)), - this, SLOT(slotShowTrayMessage(QString,QString))); + _gui, SLOT(slotShowTrayMessage(QString,QString))); connect( Logger::instance(), SIGNAL(optionalGuiLog(QString,QString)), - this, SLOT(slotShowOptionalTrayMessage(QString,QString))); + _gui, SLOT(slotShowOptionalTrayMessage(QString,QString))); connect( Logger::instance(), SIGNAL(guiMessage(QString,QString)), - this, SLOT(slotShowGuiMessage(QString,QString))); - - ProgressDispatcher *pd = ProgressDispatcher::instance(); - connect( pd, SIGNAL(progressInfo(QString,Progress::Info)), this, - SLOT(slotUpdateProgress(QString,Progress::Info)) ); - connect( pd, SIGNAL(progressSyncProblem(QString,Progress::SyncProblem)), - SLOT(slotProgressSyncProblem(QString,Progress::SyncProblem))); + _gui, SLOT(slotShowGuiMessage(QString,QString))); // create folder manager for sync folder management FolderMan *folderMan = FolderMan::instance(); @@ -139,11 +133,6 @@ Application::Application(int &argc, char **argv) : this,SLOT(slotSyncStateChange(QString))); folderMan->setSyncEnabled(false); - /* use a signal mapper to map the open requests to the alias names */ - _folderOpenActionMapper = new QSignalMapper(this); - connect(_folderOpenActionMapper, SIGNAL(mapped(const QString &)), - this, SLOT(slotFolderOpenAction(const QString &))); - setQuitOnLastWindowClosed(false); qRegisterMetaType("Progress::Kind"); @@ -159,8 +148,6 @@ Application::Application(int &argc, char **argv) : _theme->setSystrayUseMonoIcons(cfg.monoIcons()); connect (_theme, SIGNAL(systrayUseMonoIconsChanged(bool)), SLOT(slotUseMonoIconsChanged(bool))); - setupActions(); - setupSystemTray(); slotSetupProxy(); folderMan->setupFolders(); @@ -175,9 +162,6 @@ Application::Application(int &argc, char **argv) : connect( ownCloudInfo::instance(), SIGNAL(sslFailed(QNetworkReply*, QList)), this,SLOT(slotSSLFailed(QNetworkReply*, QList))); - connect( ownCloudInfo::instance(), SIGNAL(quotaUpdated(qint64,qint64)), - SLOT(slotRefreshQuotaDisplay(qint64, qint64))); - connect (this, SIGNAL(aboutToQuit()), SLOT(slotCleanup())); qDebug() << "Network Location: " << NetworkLocation::currentLocation().encoded(); @@ -188,6 +172,16 @@ Application::~Application() qDebug() << "* Mirall shutdown"; } +void Application::slotCleanup() +{ + // explicitly close windows. This is somewhat of a hack to ensure + // that saving the geometries happens ASAP during a OS shutdown + _gui->shutdown(); + _gui->deleteLater(); + + if (!_logBrowser.isNull()) _logBrowser->deleteLater(); +} + void Application::slotStartUpdateDetector() { UpdateDetector *updateDetector = new UpdateDetector(this); @@ -196,7 +190,7 @@ void Application::slotStartUpdateDetector() void Application::slotCheckConnection() { - if( checkConfigExists(false) ) { + if( _gui->checkConfigExists(false) ) { MirallConfigFile cfg; AbstractCredentials* credentials(cfg.getCredentials()); @@ -223,20 +217,6 @@ void Application::slotCredentialsFetched() runValidator(); } -void Application::slotCleanup() -{ - // explicitly close windows. This is somewhat of a hack to ensure - // that saving the geometries happens ASAP during a OS shutdown - - // those do delete on close - if (!_settingsDialog.isNull()) _settingsDialog->close(); - if (!_progressDialog.isNull()) _progressDialog->close(); - - // those need an extra invitation - if (!_tray.isNull()) _tray->deleteLater(); - if (!_logBrowser.isNull()) _logBrowser->deleteLater(); -} - void Application::runValidator() { _startupFail.clear(); @@ -251,17 +231,13 @@ void Application::slotConnectionValidatorResult(ConnectionValidator::Status stat { qDebug() << "Connection Validator Result: " << _conValidator->statusString(status); + _gui->startupConnected(status); + if( status == ConnectionValidator::Connected ) { + FolderMan *folderMan = FolderMan::instance(); qDebug() << "######## Connection and Credentials are ok!"; folderMan->setSyncEnabled(true); - _tray->setIcon( _theme->syncStateIcon( SyncResult::NotYetStarted, true ) ); - _tray->show(); - - int cnt = folderMan->map().size(); - slotShowOptionalTrayMessage(tr("%1 Sync Started").arg(_theme->appNameGUI()), - tr("Sync started for %n configured sync folder(s).","", cnt)); - // queue up the sync for all folders. folderMan->slotScheduleAllFolders(); @@ -271,8 +247,7 @@ void Application::slotConnectionValidatorResult(ConnectionValidator::Status stat _startupFail = _conValidator->errors(); } - computeOverallSyncStatus(); - setupContextMenu(); + _gui->computeOverallSyncStatus(_startupFail); _conValidator->deleteLater(); } @@ -331,108 +306,6 @@ void Application::slotownCloudWizardDone( int res ) } -void Application::setupActions() -{ - _actionOpenoC = new QAction(tr("Open %1 in browser").arg(_theme->appNameGUI()), this); - QObject::connect(_actionOpenoC, SIGNAL(triggered(bool)), SLOT(slotOpenOwnCloud())); - _actionQuota = new QAction(tr("Calculating quota..."), this); - _actionQuota->setEnabled( false ); - _actionStatus = new QAction(tr("Unknown status"), this); - _actionStatus->setEnabled( false ); - _actionSettings = new QAction(tr("Settings..."), this); - _actionRecent = new QAction(tr("Details..."), this); - _actionRecent->setEnabled( true ); - - 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())); - _actionQuit = new QAction(tr("Quit %1").arg(_theme->appNameGUI()), this); - QObject::connect(_actionQuit, SIGNAL(triggered(bool)), SLOT(quit())); -} - -void Application::setupSystemTray() -{ - // Setting a parent heres will crash on X11 since by the time qapp runs - // its childrens dtors, the X11->screen variable queried for is gone -> crash - _tray = new Systray(); - _tray->setIcon( _theme->syncStateIcon( SyncResult::NotYetStarted, true ) ); - - connect(_tray.data(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason))); - - setupContextMenu(); - - _tray->show(); -} - -void Application::setupContextMenu() -{ - bool isConfigured = ownCloudInfo::instance()->isConfigured(); - FolderMan *folderMan = FolderMan::instance(); - - _actionOpenoC->setEnabled(isConfigured); - - if( _contextMenu ) { - _contextMenu->clear(); - _recentActionsMenu->clear(); - _recentActionsMenu->addAction(tr("None.")); - _recentActionsMenu->addAction(_actionRecent); - } else { - _contextMenu = new QMenu(); - _recentActionsMenu = _contextMenu->addMenu(tr("Recent Changes")); - // this must be called only once after creating the context menu, or - // it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04). - _tray->setContextMenu(_contextMenu); - } - _contextMenu->setTitle(_theme->appNameGUI() ); - _contextMenu->addAction(_actionOpenoC); - - int folderCnt = folderMan->map().size(); - // add open actions for all sync folders to the tray menu - if( _theme->singleSyncFolder() ) { - // there should be exactly one folder. No sync-folder add action will be shown. - QStringList li = folderMan->map().keys(); - if( li.size() == 1 ) { - Folder *folder = folderMan->map().value(li.first()); - if( folder ) { - // if there is singleFolder mode, a generic open action is displayed. - QAction *action = new QAction( tr("Open %1 folder").arg(_theme->appNameGUI()), this); - connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map())); - _folderOpenActionMapper->setMapping( action, folder->alias() ); - - _contextMenu->addAction(action); - } - } - } else { - // show a grouping with more than one folder. - if ( folderCnt > 1) { - _contextMenu->addAction(tr("Managed Folders:"))->setDisabled(true); - } - foreach (Folder *folder, folderMan->map() ) { - QAction *action = new QAction( tr("Open folder '%1'").arg(folder->alias()), this ); - connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map())); - _folderOpenActionMapper->setMapping( action, folder->alias() ); - - _contextMenu->addAction(action); - } - } - - _contextMenu->addSeparator(); - _contextMenu->addAction(_actionQuota); - _contextMenu->addSeparator(); - _contextMenu->addAction(_actionStatus); - _contextMenu->addMenu(_recentActionsMenu); - _contextMenu->addSeparator(); - _contextMenu->addAction(_actionSettings); - if (!_theme->helpUrl().isEmpty()) { - _contextMenu->addAction(_actionHelp); - } - _contextMenu->addSeparator(); - - _contextMenu->addAction(_actionQuit); -} - void Application::setupLogBrowser() { // might be called from second instance @@ -535,154 +408,9 @@ void Application::slotSetupProxy() FolderMan::instance()->slotScheduleAllFolders(); } -void Application::slotRefreshQuotaDisplay( qint64 total, qint64 used ) -{ - if (total == 0) { - _actionQuota->setText(tr("Quota n/a")); - return; - } - - double percent = used/(double)total*100; - QString percentFormatted = Utility::compactFormatDouble(percent, 1); - QString totalFormatted = Utility::octetsToString(total); - _actionQuota->setText(tr("%1% of %2 in use").arg(percentFormatted).arg(totalFormatted)); -} - void Application::slotUseMonoIconsChanged(bool) { - computeOverallSyncStatus(); -} - -void Application::slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem& problem) -{ - Q_UNUSED(folder); - Q_UNUSED(problem); - - // display a warn icon if warnings happend. - QIcon warnIcon(":/mirall/resources/warning-16"); - _actionRecent->setIcon(warnIcon); - - rebuildRecentMenus(); -} - -void Application::rebuildRecentMenus() -{ - _recentActionsMenu->clear(); - const QList& progressInfoList = ProgressDispatcher::instance()->recentChangedItems(5); - - if( progressInfoList.size() == 0 ) { - _recentActionsMenu->addAction(tr("No items synced recently")); - } else { - QListIterator i(progressInfoList); - - while(i.hasNext()) { - Progress::Info info = i.next(); - QString kindStr = Progress::asResultString(info.kind); - QString timeStr = info.timestamp.toString("hh:mm"); - - QString actionText = tr("%1 (%2, %3)").arg(info.current_file).arg(kindStr).arg(timeStr); - _recentActionsMenu->addAction( actionText ); - } - } - // add a more... entry. - _recentActionsMenu->addAction(_actionRecent); -} - -void Application::slotUpdateProgress(const QString &folder, const Progress::Info& progress) -{ - Q_UNUSED(folder); - - // shows an entry in the context menu. - QString curAmount = Utility::octetsToString(progress.overall_current_bytes); - QString totalAmount = Utility::octetsToString(progress.overall_transmission_size); - _actionStatus->setText(tr("Syncing %1 of %2 (%3 of %4) ").arg(progress.current_file_no) - .arg(progress.overall_file_count).arg(curAmount, totalAmount)); - - // wipe the problem list at start of sync. - if( progress.kind == Progress::StartSync ) { - _actionRecent->setIcon( QIcon() ); // Fixme: Set a "in-progress"-item eventually. - } - - // If there was a change in the file list, redo the progress menu. - if( progress.kind == Progress::EndDownload || progress.kind == Progress::EndUpload || - progress.kind == Progress::EndDelete ) { - rebuildRecentMenus(); - } - - if (progress.kind == Progress::EndSync) { - rebuildRecentMenus(); // show errors. - QTimer::singleShot(2000, this, SLOT(slotDisplayIdle())); - } -} - -void Application::slotDisplayIdle() -{ - _actionStatus->setText(tr("Up to date")); -} - -void Application::slotHelp() -{ - QDesktopServices::openUrl(QUrl(_theme->helpUrl())); -} - -/* - * open the folder with the given Alais - */ -void Application::slotFolderOpenAction( const QString& alias ) -{ - Folder *f = FolderMan::instance()->folder(alias); - qDebug() << "opening local url " << f->path(); - if( f ) { - QUrl url(f->path(), QUrl::TolerantMode); - url.setScheme( QLatin1String("file") ); - -#ifdef Q_OS_WIN32 - // work around a bug in QDesktopServices on Win32, see i-net - QString filePath = f->path(); - - if (filePath.startsWith(QLatin1String("\\\\")) || filePath.startsWith(QLatin1String("//"))) - url.setUrl(QDir::toNativeSeparators(filePath)); - else - url = QUrl::fromLocalFile(filePath); -#endif - QDesktopServices::openUrl(url); - } -} - -void Application::slotOpenOwnCloud() -{ - MirallConfigFile cfgFile; - - QString url = cfgFile.ownCloudUrl(); - QDesktopServices::openUrl( url ); -} - -void Application::slotTrayClicked( QSystemTrayIcon::ActivationReason reason ) -{ - // A click on the tray icon should only open the status window on Win and - // Linux, not on Mac. They want a menu entry. -#if !defined Q_OS_MAC - if( reason == QSystemTrayIcon::Trigger ) { - checkConfigExists(true); // start settings if config is existing. - } -#endif -} - -bool Application::checkConfigExists(bool openSettings) -{ - // if no config file is there, start the configuration wizard. - MirallConfigFile cfgFile; - - if( cfgFile.exists() && !cfgFile.ownCloudUrl().isEmpty() ) { - if( openSettings ) { - slotSettings(); - } - return true; - } else { - qDebug() << "No configured folders yet, starting setup wizard"; - OwncloudSetupWizard::runWizard(this, SLOT(slotownCloudWizardDone(int))); - return false; - } + _gui->computeOverallSyncStatus(_startupFail); } void Application::slotOpenLogBrowser() @@ -691,36 +419,6 @@ void Application::slotOpenLogBrowser() _logBrowser->raise(); } -// slot hit when a folder gets changed in the settings dialog. -void Application::slotFoldersChanged() -{ - computeOverallSyncStatus(); - setupContextMenu(); -} - -void Application::slotSettings() -{ - if (_settingsDialog.isNull()) { - _settingsDialog = new SettingsDialog(this); - _settingsDialog->setAttribute( Qt::WA_DeleteOnClose, true ); - _settingsDialog->show(); - } - - _settingsDialog->setGeneralErrors( _startupFail ); - Utility::raiseDialog(_settingsDialog.data()); -} - -void Application::slotItemProgressDialog() -{ - if (_progressDialog.isNull()) { - _progressDialog = new ItemProgressDialog(this); - _progressDialog->setAttribute( Qt::WA_DeleteOnClose, true ); - _progressDialog->setupList(); - _progressDialog->show(); - } - Utility::raiseDialog(_progressDialog.data()); -} - void Application::slotParseOptions(const QString &opts) { QStringList options = opts.split(QLatin1Char('|')); @@ -728,47 +426,17 @@ void Application::slotParseOptions(const QString &opts) setupLogBrowser(); } -void Application::slotShowTrayMessage(const QString &title, const QString &msg) -{ - if( _tray ) - _tray->showMessage(title, msg); - else - qDebug() << "Tray not ready: " << msg; -} - -void Application::slotShowOptionalTrayMessage(const QString &title, const QString &msg) -{ - MirallConfigFile cfg; - if (cfg.optionalDesktopNotifications()) - slotShowTrayMessage(title, msg); -} - -void Application::slotShowGuiMessage(const QString &title, const QString &message) -{ - QMessageBox *msgBox = new QMessageBox; - msgBox->setAttribute(Qt::WA_DeleteOnClose); - msgBox->setText(message); - msgBox->setWindowTitle(title); - msgBox->setIcon(QMessageBox::Information); - msgBox->open(); -} - +// only used to start a new logfile void Application::slotSyncStateChange( const QString& alias ) { FolderMan *folderMan = FolderMan::instance(); const SyncResult& result = folderMan->syncResult( alias ); - emit folderStateChanged( folderMan->folder(alias) ); - - computeOverallSyncStatus(); qDebug() << "Sync state changed for folder " << alias << ": " << result.statusString(); if (result.status() == SyncResult::Success || result.status() == SyncResult::Error) { enterNextLogFile(); } - if( _progressDialog ) { - _progressDialog->setSyncResult(result); - } } void Application::parseOptions(const QStringList &options) @@ -820,43 +488,6 @@ void Application::parseOptions(const QStringList &options) } } -void Application::computeOverallSyncStatus() -{ - - // display the info of the least successful sync (eg. not just display the result of the latest sync - QString trayMessage; - FolderMan *folderMan = FolderMan::instance(); - Folder::Map map = folderMan->map(); - SyncResult overallResult = FolderMan::accountStatus(map.values()); - - // if there have been startup problems, show an error message. - if( !_startupFail.isEmpty() ) { - trayMessage = _startupFail.join(QLatin1String("\n")); - QIcon statusIcon = _theme->syncStateIcon( SyncResult::Error, true ); - _tray->setIcon( statusIcon ); - _tray->setToolTip(trayMessage); - } else { - // create the tray blob message, check if we have an defined state - if( overallResult.status() != SyncResult::Undefined ) { - QStringList allStatusStrings; - foreach(Folder* folder, map.values()) { - qDebug() << "Folder in overallStatus Message: " << folder << " with name " << folder->alias(); - QString folderMessage = folderMan->statusToString(folder->syncResult().status(), folder->syncEnabled()); - allStatusStrings += tr("Folder %1: %2").arg(folder->alias(), folderMessage); - } - - if( ! allStatusStrings.isEmpty() ) - trayMessage = allStatusStrings.join(QLatin1String("\n")); - else - trayMessage = tr("No sync folders configured."); - - QIcon statusIcon = _theme->syncStateIcon( overallResult.status(), true); - _tray->setIcon( statusIcon ); - _tray->setToolTip(trayMessage); - } - } -} - // Helpers for displaying messages. Note that there is no console on Windows. #ifdef Q_OS_WIN // Format as
 HTML
diff --git a/src/mirall/application.h b/src/mirall/application.h
index f05a433855..bd1590d8b0 100644
--- a/src/mirall/application.h
+++ b/src/mirall/application.h
@@ -25,7 +25,7 @@
 
 #include "mirall/syncresult.h"
 #include "mirall/logbrowser.h"
-#include "mirall/systray.h"
+#include "mirall/owncloudgui.h"
 #include "mirall/connectionvalidator.h"
 #include "mirall/progressdispatcher.h"
 
@@ -62,16 +62,11 @@ public slots:
 protected:
     void parseOptions(const QStringList& );
     void setupTranslations();
-    void setupActions();
-    void setupSystemTray();
     void setupContextMenu();
     void setupLogBrowser();
     void enterNextLogFile();
     bool checkConfigExists(bool openSettings);
 
-    //folders have to be disabled while making config changes
-    void computeOverallSyncStatus();
-
     // reimplemented
 #if defined(Q_WS_WIN)
     bool winEventFilter( MSG * message, long * result );
@@ -82,29 +77,15 @@ signals:
     void folderStateChanged(Folder*);
 
 protected slots:
-    void slotFoldersChanged();
-    void slotSettings();
-    void slotItemProgressDialog();
     void slotParseOptions( const QString& );
-    void slotShowTrayMessage(const QString&, const QString&);
-    void slotShowOptionalTrayMessage(const QString&, const QString&);
-    void slotShowGuiMessage(const QString& title, const QString& message);
     void slotCheckConnection();
     void slotConnectionValidatorResult(ConnectionValidator::Status);
     void slotSyncStateChange( const QString& );
-    void slotTrayClicked( QSystemTrayIcon::ActivationReason );
-    void slotFolderOpenAction(const QString & );
-    void slotOpenOwnCloud();
     void slotOpenLogBrowser();
     void slotSSLFailed( QNetworkReply *reply, QList errors );
     void slotStartUpdateDetector();
     void slotSetupProxy();
-    void slotRefreshQuotaDisplay( qint64 total, qint64 used );
     void slotUseMonoIconsChanged( bool );
-    void slotUpdateProgress(const QString&, const Progress::Info&);
-    void slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem &problem);
-    void slotDisplayIdle();
-    void slotHelp();
     void slotCredentialsFetched();
     void slotCleanup();
 private:
@@ -113,29 +94,14 @@ private:
     void rebuildRecentMenus();
     void runValidator();
 
-    QPointer _tray;
-    QAction *_actionOpenoC;
-    QAction *_actionSettings;
-    QAction *_actionQuota;
-    QAction *_actionStatus;
-    QAction *_actionRecent;
-    QAction *_actionHelp;
-    QAction *_actionQuit;
-
+    QPointer _gui;
     QNetworkConfigurationManager *_networkMgr;
 
     SslErrorDialog *_sslErrorDialog;
     ConnectionValidator *_conValidator;
 
-    // tray's menu
-    QMenu *_contextMenu;
-    QMenu *_recentActionsMenu;
-
     Theme *_theme;
-    QSignalMapper *_folderOpenActionMapper;
     QPointer_logBrowser;
-    QPointer _settingsDialog;
-    QPointer _progressDialog;
 
     QString _logFile;
     QString _logDirectory;
diff --git a/src/mirall/owncloudgui.cpp b/src/mirall/owncloudgui.cpp
new file mode 100644
index 0000000000..ac99c909ab
--- /dev/null
+++ b/src/mirall/owncloudgui.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) by Klaas Freitag 
+ *
+ * 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 "mirall/application.h"
+#include "mirall/owncloudgui.h"
+#include "mirall/theme.h"
+#include "mirall/folderman.h"
+#include "mirall/owncloudinfo.h"
+#include "mirall/mirallconfigfile.h"
+#include "mirall/utility.h"
+#include "mirall/progressdispatcher.h"
+#include "mirall/itemprogressdialog.h"
+#include "mirall/owncloudsetupwizard.h"
+#include "mirall/settingsdialog.h"
+
+#include 
+#include 
+
+namespace Mirall {
+
+ownCloudGui::ownCloudGui(Application *parent) :
+    QObject(parent),
+    _contextMenu(0),
+    _recentActionsMenu(0),
+    _app(parent)
+{
+    _tray = new Systray();
+    _tray->setIcon( Theme::instance()->syncStateIcon( SyncResult::NotYetStarted, true ) );
+
+    connect(_tray.data(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+            SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
+
+    setupActions();
+    setupContextMenu();
+
+    _tray->show();
+
+    /* use a signal mapper to map the open requests to the alias names */
+    _folderOpenActionMapper = new QSignalMapper(this);
+    connect(_folderOpenActionMapper, SIGNAL(mapped(const QString &)),
+            this, SLOT(slotFolderOpenAction(const QString &)));
+
+    ProgressDispatcher *pd = ProgressDispatcher::instance();
+    connect( pd, SIGNAL(progressInfo(QString,Progress::Info)), this,
+             SLOT(slotUpdateProgress(QString,Progress::Info)) );
+    connect( pd, SIGNAL(progressSyncProblem(QString,Progress::SyncProblem)),
+             SLOT(slotProgressSyncProblem(QString,Progress::SyncProblem)));
+
+    FolderMan *folderMan = FolderMan::instance();
+    connect( folderMan, SIGNAL(folderSyncStateChange(QString)),
+             this,SLOT(slotSyncStateChange(QString)));
+
+}
+
+// REFACTOR: This should rather be in application.... or rather in MirallConfigFile?
+bool ownCloudGui::checkConfigExists(bool openSettings)
+{
+    // if no config file is there, start the configuration wizard.
+    MirallConfigFile cfgFile;
+
+    if( cfgFile.exists() && !cfgFile.ownCloudUrl().isEmpty() ) {
+        if( openSettings ) {
+            this->slotSettings();
+        }
+        return true;
+    } else {
+        qDebug() << "No configured folders yet, starting setup wizard";
+        OwncloudSetupWizard::runWizard(this, SLOT(slotownCloudWizardDone(int)));
+        return false;
+    }
+}
+
+void ownCloudGui::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
+{
+    // A click on the tray icon should only open the status window on Win and
+    // Linux, not on Mac. They want a menu entry.
+#if !defined Q_OS_MAC
+    if( reason == QSystemTrayIcon::Trigger ) {
+        checkConfigExists(true); // start settings if config is existing.
+    }
+#endif
+}
+
+void ownCloudGui::slotSyncStateChange( const QString& alias )
+{
+    FolderMan *folderMan = FolderMan::instance();
+    const SyncResult& result = folderMan->syncResult( alias );
+
+    computeOverallSyncStatus(_startupFail);
+
+    qDebug() << "Sync state changed for folder " << alias << ": "  << result.statusString();
+
+    if( _progressDialog ) {
+        _progressDialog->setSyncResult(result);
+    }
+}
+
+// c
+void ownCloudGui::slotFoldersChanged()
+{
+    computeOverallSyncStatus(_startupFail);
+    setupContextMenu();
+}
+
+void ownCloudGui::slotOpenLogBrowser()
+{
+    // REFACTOR: do somehting useful.
+}
+
+void ownCloudGui::startupConnected( ConnectionValidator::Status /* status */ )
+{
+    FolderMan *folderMan = FolderMan::instance();
+    qDebug() << "######## Connection and Credentials are ok!";
+    folderMan->setSyncEnabled(true);
+    _tray->setIcon( Theme::instance()->syncStateIcon( SyncResult::NotYetStarted, true ) );
+    _tray->show();
+
+    int cnt = folderMan->map().size();
+    slotShowOptionalTrayMessage(tr("%1 Sync Started").arg(Theme::instance()->appNameGUI()),
+                        tr("Sync started for %n configured sync folder(s).","", cnt));
+
+
+}
+
+void ownCloudGui::computeOverallSyncStatus( const QStringList& startupFails )
+{
+
+    // display the info of the least successful sync (eg. not just display the result of the latest sync
+    QString trayMessage;
+    FolderMan *folderMan = FolderMan::instance();
+    Folder::Map map = folderMan->map();
+    SyncResult overallResult = FolderMan::accountStatus(map.values());
+
+    // if there have been startup problems, show an error message.
+    if( !startupFails.isEmpty() ) {
+        trayMessage = startupFails.join(QLatin1String("\n"));
+        QIcon statusIcon = Theme::instance()->syncStateIcon( SyncResult::Error, true );
+        _tray->setIcon( statusIcon );
+        _tray->setToolTip(trayMessage);
+    } else {
+        // create the tray blob message, check if we have an defined state
+        if( overallResult.status() != SyncResult::Undefined ) {
+            QStringList allStatusStrings;
+            foreach(Folder* folder, map.values()) {
+                qDebug() << "Folder in overallStatus Message: " << folder << " with name " << folder->alias();
+                QString folderMessage = folderMan->statusToString(folder->syncResult().status(), folder->syncEnabled());
+                allStatusStrings += tr("Folder %1: %2").arg(folder->alias(), folderMessage);
+            }
+
+            if( ! allStatusStrings.isEmpty() )
+                trayMessage = allStatusStrings.join(QLatin1String("\n"));
+            else
+                trayMessage = tr("No sync folders configured.");
+
+            QIcon statusIcon = Theme::instance()->syncStateIcon( overallResult.status(), true);
+            _tray->setIcon( statusIcon );
+            _tray->setToolTip(trayMessage);
+        }
+    }
+}
+
+void ownCloudGui::setupContextMenu()
+{
+    bool isConfigured = ownCloudInfo::instance()->isConfigured();
+    FolderMan *folderMan = FolderMan::instance();
+
+    _actionOpenoC->setEnabled(isConfigured);
+
+    if( _contextMenu ) {
+        _contextMenu->clear();
+        _recentActionsMenu->clear();
+        _recentActionsMenu->addAction(tr("None."));
+        _recentActionsMenu->addAction(_actionRecent);
+    } else {
+        _contextMenu = new QMenu();
+        _recentActionsMenu = _contextMenu->addMenu(tr("Recent Changes"));
+        // this must be called only once after creating the context menu, or
+        // it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
+        _tray->setContextMenu(_contextMenu);
+    }
+    _contextMenu->setTitle(Theme::instance()->appNameGUI() );
+    _contextMenu->addAction(_actionOpenoC);
+
+    int folderCnt = folderMan->map().size();
+    // add open actions for all sync folders to the tray menu
+    if( Theme::instance()->singleSyncFolder() ) {
+        // there should be exactly one folder. No sync-folder add action will be shown.
+        QStringList li = folderMan->map().keys();
+        if( li.size() == 1 ) {
+            Folder *folder = folderMan->map().value(li.first());
+            if( folder ) {
+                // if there is singleFolder mode, a generic open action is displayed.
+                QAction *action = new QAction( tr("Open %1 folder").arg(Theme::instance()->appNameGUI()), this);
+                connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map()));
+                _folderOpenActionMapper->setMapping( action, folder->alias() );
+
+                _contextMenu->addAction(action);
+            }
+        }
+    } else {
+        // show a grouping with more than one folder.
+        if ( folderCnt > 1) {
+            _contextMenu->addAction(tr("Managed Folders:"))->setDisabled(true);
+        }
+        foreach (Folder *folder, folderMan->map() ) {
+            QAction *action = new QAction( tr("Open folder '%1'").arg(folder->alias()), this );
+            connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map()));
+            _folderOpenActionMapper->setMapping( action, folder->alias() );
+
+            _contextMenu->addAction(action);
+        }
+    }
+
+    _contextMenu->addSeparator();
+    _contextMenu->addAction(_actionQuota);
+    _contextMenu->addSeparator();
+    _contextMenu->addAction(_actionStatus);
+    _contextMenu->addMenu(_recentActionsMenu);
+    _contextMenu->addSeparator();
+    _contextMenu->addAction(_actionSettings);
+    if (!Theme::instance()->helpUrl().isEmpty()) {
+        _contextMenu->addAction(_actionHelp);
+    }
+    _contextMenu->addSeparator();
+
+    _contextMenu->addAction(_actionQuit);
+}
+
+
+void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg)
+{
+    if( _tray )
+        _tray->showMessage(title, msg);
+    else
+        qDebug() << "Tray not ready: " << msg;
+}
+
+void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg)
+{
+    MirallConfigFile cfg;
+    if (cfg.optionalDesktopNotifications())
+        slotShowTrayMessage(title, msg);
+}
+
+
+/*
+ * open the folder with the given Alais
+ */
+void ownCloudGui::slotFolderOpenAction( const QString& alias )
+{
+    Folder *f = FolderMan::instance()->folder(alias);
+    qDebug() << "opening local url " << f->path();
+    if( f ) {
+        QUrl url(f->path(), QUrl::TolerantMode);
+        url.setScheme( QLatin1String("file") );
+
+#ifdef Q_OS_WIN32
+        // work around a bug in QDesktopServices on Win32, see i-net
+        QString filePath = f->path();
+
+        if (filePath.startsWith(QLatin1String("\\\\")) || filePath.startsWith(QLatin1String("//")))
+            url.setUrl(QDir::toNativeSeparators(filePath));
+        else
+            url = QUrl::fromLocalFile(filePath);
+#endif
+        QDesktopServices::openUrl(url);
+    }
+}
+
+void ownCloudGui::setupActions()
+{
+    _actionOpenoC = new QAction(tr("Open %1 in browser").arg(Theme::instance()->appNameGUI()), this);
+    QObject::connect(_actionOpenoC, SIGNAL(triggered(bool)), SLOT(slotOpenOwnCloud()));
+    _actionQuota = new QAction(tr("Calculating quota..."), this);
+    _actionQuota->setEnabled( false );
+    _actionStatus = new QAction(tr("Unknown status"), this);
+    _actionStatus->setEnabled( false );
+    _actionSettings = new QAction(tr("Settings..."), this);
+    _actionRecent = new QAction(tr("Details..."), this);
+    _actionRecent->setEnabled( true );
+
+    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()));
+    _actionQuit = new QAction(tr("Quit %1").arg(Theme::instance()->appNameGUI()), this);
+    QObject::connect(_actionQuit, SIGNAL(triggered(bool)), _app, SLOT(quit()));
+
+    connect( ownCloudInfo::instance(), SIGNAL(quotaUpdated(qint64,qint64)),
+             SLOT(slotRefreshQuotaDisplay(qint64, qint64)));
+}
+
+void ownCloudGui::slotRefreshQuotaDisplay( qint64 total, qint64 used )
+{
+    if (total == 0) {
+        _actionQuota->setText(tr("Quota n/a"));
+        return;
+    }
+
+    double percent = used/(double)total*100;
+    QString percentFormatted = Utility::compactFormatDouble(percent, 1);
+    QString totalFormatted = Utility::octetsToString(total);
+    _actionQuota->setText(tr("%1% of %2 in use").arg(percentFormatted).arg(totalFormatted));
+}
+
+void ownCloudGui::slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem& problem)
+{
+    Q_UNUSED(folder);
+    Q_UNUSED(problem);
+
+    // display a warn icon if warnings happend.
+    QIcon warnIcon(":/mirall/resources/warning-16");
+    _actionRecent->setIcon(warnIcon);
+
+    rebuildRecentMenus();
+}
+
+void ownCloudGui::rebuildRecentMenus()
+{
+    _recentActionsMenu->clear();
+    const QList& progressInfoList = ProgressDispatcher::instance()->recentChangedItems(5);
+
+    if( progressInfoList.size() == 0 ) {
+        _recentActionsMenu->addAction(tr("No items synced recently"));
+    } else {
+        QListIterator i(progressInfoList);
+
+        while(i.hasNext()) {
+            Progress::Info info = i.next();
+            QString kindStr = Progress::asResultString(info.kind);
+            QString timeStr = info.timestamp.toString("hh:mm");
+
+            QString actionText = tr("%1 (%2, %3)").arg(info.current_file).arg(kindStr).arg(timeStr);
+            _recentActionsMenu->addAction( actionText );
+        }
+    }
+    // add a more... entry.
+    _recentActionsMenu->addAction(_actionRecent);
+}
+
+
+void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info& progress)
+{
+    Q_UNUSED(folder);
+
+    // shows an entry in the context menu.
+    QString curAmount = Utility::octetsToString(progress.overall_current_bytes);
+    QString totalAmount = Utility::octetsToString(progress.overall_transmission_size);
+    _actionStatus->setText(tr("Syncing %1 of %2 (%3 of %4) ").arg(progress.current_file_no)
+                           .arg(progress.overall_file_count).arg(curAmount, totalAmount));
+
+    // wipe the problem list at start of sync.
+    if( progress.kind == Progress::StartSync ) {
+        _actionRecent->setIcon( QIcon() ); // Fixme: Set a "in-progress"-item eventually.
+    }
+
+    // If there was a change in the file list, redo the progress menu.
+    if( progress.kind == Progress::EndDownload || progress.kind == Progress::EndUpload ||
+            progress.kind == Progress::EndDelete ) {
+        rebuildRecentMenus();
+    }
+
+    if (progress.kind == Progress::EndSync) {
+        rebuildRecentMenus();  // show errors.
+        QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
+    }
+}
+
+void ownCloudGui::slotDisplayIdle()
+{
+    _actionStatus->setText(tr("Up to date"));
+}
+
+void ownCloudGui::slotShowGuiMessage(const QString &title, const QString &message)
+{
+    QMessageBox *msgBox = new QMessageBox;
+    msgBox->setAttribute(Qt::WA_DeleteOnClose);
+    msgBox->setText(message);
+    msgBox->setWindowTitle(title);
+    msgBox->setIcon(QMessageBox::Information);
+    msgBox->open();
+}
+
+void ownCloudGui::slotSettings()
+{
+    if (_settingsDialog.isNull()) {
+        _settingsDialog = new SettingsDialog(this);
+        _settingsDialog->setAttribute( Qt::WA_DeleteOnClose, true );
+        _settingsDialog->show();
+    }
+
+    _settingsDialog->setGeneralErrors( _startupFail );
+    Utility::raiseDialog(_settingsDialog.data());
+}
+
+void ownCloudGui::slotItemProgressDialog()
+{
+    if (_progressDialog.isNull()) {
+        _progressDialog = new ItemProgressDialog(_app);
+        _progressDialog->setAttribute( Qt::WA_DeleteOnClose, true );
+        _progressDialog->setupList();
+        _progressDialog->show();
+    }
+    Utility::raiseDialog(_progressDialog.data());
+}
+
+void ownCloudGui::shutdown()
+{
+    // those do delete on close
+    if (!_settingsDialog.isNull()) _settingsDialog->close();
+    if (!_progressDialog.isNull()) _progressDialog->close();
+}
+
+} // end namespace
diff --git a/src/mirall/owncloudgui.h b/src/mirall/owncloudgui.h
new file mode 100644
index 0000000000..1f7a49dec9
--- /dev/null
+++ b/src/mirall/owncloudgui.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) by Klaas Freitag 
+ *
+ * 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 OWNCLOUDGUI_H
+#define OWNCLOUDGUI_H
+
+#include "mirall/systray.h"
+#include "mirall/connectionvalidator.h"
+#include "mirall/progressdispatcher.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+namespace Mirall {
+
+class SettingsDialog;
+class ItemProgressDialog;
+class Application;
+
+class ownCloudGui : public QObject
+{
+    Q_OBJECT
+public:
+    explicit ownCloudGui(Application *parent = 0);
+
+    void setupContextMenu();
+    void startupConnected( ConnectionValidator::Status status );
+
+    bool checkConfigExists(bool openSettings);
+
+signals:
+
+public slots:
+    void computeOverallSyncStatus( const QStringList& startupFails );
+    void slotShowTrayMessage(const QString &title, const QString &msg);
+    void slotShowOptionalTrayMessage(const QString &title, const QString &msg);
+    void slotFolderOpenAction( const QString& alias );
+    void slotRefreshQuotaDisplay( qint64 total, qint64 used );
+    void rebuildRecentMenus();
+    void slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem& problem);
+    void slotUpdateProgress(const QString &folder, const Progress::Info& progress);
+    void slotShowGuiMessage(const QString &title, const QString &message);
+    void slotFoldersChanged();
+    void slotItemProgressDialog();
+    void slotSettings();
+    void shutdown();
+    void slotSyncStateChange( const QString& alias );
+    void slotTrayClicked( QSystemTrayIcon::ActivationReason reason );
+    void slotOpenLogBrowser();
+
+private slots:
+    void slotDisplayIdle();
+
+private:
+    void setupActions();
+
+    QPointer _tray;
+    QPointer _settingsDialog;
+    QPointer _progressDialog;
+
+    // tray's menu
+    QMenu *_contextMenu;
+    QMenu *_recentActionsMenu;
+
+    QAction *_actionOpenoC;
+    QAction *_actionSettings;
+    QAction *_actionQuota;
+    QAction *_actionStatus;
+    QAction *_actionRecent;
+    QAction *_actionHelp;
+    QAction *_actionQuit;
+
+    Application *_app;
+
+    QSignalMapper *_folderOpenActionMapper;
+
+    QStringList _startupFail;
+};
+
+} // namespace Mirall
+
+#endif // OWNCLOUDGUI_H
diff --git a/src/mirall/settingsdialog.cpp b/src/mirall/settingsdialog.cpp
index bf5c5e0ee4..092c83adac 100644
--- a/src/mirall/settingsdialog.cpp
+++ b/src/mirall/settingsdialog.cpp
@@ -19,9 +19,9 @@
 #include "mirall/generalsettings.h"
 #include "mirall/networksettings.h"
 #include "mirall/accountsettings.h"
-#include "mirall/application.h"
 #include "mirall/mirallconfigfile.h"
 #include "mirall/progressdispatcher.h"
+#include "mirall/owncloudgui.h"
 
 #include 
 #include 
@@ -39,7 +39,7 @@ QIcon createDummy() {
     return icon;
 }
 
-SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
+SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
     QDialog(parent),
     _ui(new Ui::SettingsDialog)
 {
@@ -50,7 +50,7 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
 
     _accountSettings = new AccountSettings(this);
     addAccount(tr("Account"), _accountSettings);
-    slotUpdateAccountState();
+    // slotUpdateAccountState(); REFACTOR: Do we still need this? Now in slotSyncStateChange
 
     QIcon generalIcon(QLatin1String(":/mirall/resources/settings.png"));
     QListWidgetItem *general = new QListWidgetItem(generalIcon, tr("General"), _ui->labelWidget);
@@ -65,17 +65,17 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
     _ui->labelWidget->addItem(network);
     NetworkSettings *networkSettings = new NetworkSettings;
     _ui->stack->addWidget(networkSettings);
-    connect(networkSettings, SIGNAL(proxySettingsChanged()), app, SLOT(slotSetupProxy()));
+    // REFACTOR check: connect(networkSettings, SIGNAL(proxySettingsChanged()), app, SLOT(slotSetupProxy()));
 
     //connect(generalSettings, SIGNAL(resizeToSizeHint()), SLOT(resizeToSizeHint()));
+    FolderMan *folderMan = FolderMan::instance();
+    connect( folderMan, SIGNAL(folderSyncStateChange(QString)),
+             this, SLOT(slotSyncStateChange(QString)));
 
-    connect( app, SIGNAL(folderStateChanged(Folder*)), _accountSettings, SLOT(slotUpdateFolderState(Folder*)));
-    connect( app, SIGNAL(folderStateChanged(Folder*)), SLOT(slotUpdateAccountState()));
-
-    connect( _accountSettings, SIGNAL(folderChanged()), app, SLOT(slotFoldersChanged()));
+    connect( _accountSettings, SIGNAL(folderChanged()), gui, SLOT(slotFoldersChanged()));
     connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)),
-             app, SLOT(slotFolderOpenAction(QString)));
-    connect( _accountSettings, SIGNAL(openProgressDialog()), app, SLOT(slotItemProgressDialog()));
+             gui, SLOT(slotFolderOpenAction(QString)));
+    connect( _accountSettings, SIGNAL(openProgressDialog()), gui, SLOT(slotItemProgressDialog()));
 
     connect( ProgressDispatcher::instance(), SIGNAL(progressInfo(QString, Progress::Info)),
              _accountSettings, SLOT(slotSetProgress(QString, Progress::Info)) );
@@ -92,7 +92,7 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
 
     QAction *showLogWindow = new QAction(this);
     showLogWindow->setShortcut(QKeySequence("F12"));
-    connect(showLogWindow, SIGNAL(triggered()), app, SLOT(slotOpenLogBrowser()));
+    connect(showLogWindow, SIGNAL(triggered()), gui, SLOT(slotOpenLogBrowser()));
     addAction(showLogWindow);
 
     int iconSize = 32;
@@ -130,11 +130,16 @@ void SettingsDialog::addAccount(const QString &title, QWidget *widget)
 
 }
 
-void SettingsDialog::slotUpdateAccountState()
+void SettingsDialog::slotSyncStateChange(const QString& alias)
 {
     FolderMan *folderMan = FolderMan::instance();
     SyncResult state = folderMan->accountStatus(folderMan->map().values());
     _accountItem->setIcon(Theme::instance()->syncStateIcon(state.status()));
+
+    Folder *folder = folderMan->folder(alias);
+    if( folder ) {
+        _accountSettings->slotUpdateFolderState(folder);
+    }
 }
 
 void SettingsDialog::setGeneralErrors(const QStringList &errors)
diff --git a/src/mirall/settingsdialog.h b/src/mirall/settingsdialog.h
index a86835e431..1496e27d5d 100644
--- a/src/mirall/settingsdialog.h
+++ b/src/mirall/settingsdialog.h
@@ -30,25 +30,26 @@ class SettingsDialog;
 class AccountSettings;
 class Application;
 class FolderMan;
+class ownCloudGui;
 
 class SettingsDialog : public QDialog
 {
     Q_OBJECT
 
 public:
-    explicit SettingsDialog(Application *app, QWidget *parent = 0);
+    explicit SettingsDialog(ownCloudGui *gui, QWidget *parent = 0);
     ~SettingsDialog();
 
     void addAccount(const QString &title, QWidget *widget);
     void setGeneralErrors( const QStringList& errors );
 
+public slots:
+    void slotSyncStateChange(const QString& alias);
+
 protected:
     void reject();
     void accept();
 
-protected slots:
-    void slotUpdateAccountState();
-
 private:
     Ui::SettingsDialog *_ui;
     AccountSettings *_accountSettings;