nextcloud-desktop/src/mirall/application.cpp

462 lines
14 KiB
C++
Raw Normal View History

2011-04-06 13:48:02 +04:00
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
2011-10-13 15:55:52 +04:00
#include <QtCore>
#include <QtGui>
#include <QHash>
#include <QHashIterator>
#include <QUrl>
#include <QDesktopServices>
2012-02-23 14:44:44 +04:00
#include <QSplashScreen>
2011-02-17 02:21:45 +03:00
#include "mirall/application.h"
#include "mirall/folder.h"
#include "mirall/folderwatcher.h"
#include "mirall/folderwizard.h"
#include "mirall/networklocation.h"
#include "mirall/unisonfolder.h"
#include "mirall/owncloudfolder.h"
2011-09-26 17:00:12 +04:00
#include "mirall/statusdialog.h"
#include "mirall/owncloudsetupwizard.h"
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/miralltheme.h"
#include "mirall/owncloudtheme.h"
#ifdef WITH_CSYNC
#include "mirall/csyncfolder.h"
#endif
#include "mirall/inotify.h"
2011-02-17 02:21:45 +03:00
namespace Mirall {
Application::Application(int argc, char **argv) :
QApplication(argc, argv),
2011-04-04 14:23:30 +04:00
_networkMgr(new QNetworkConfigurationManager(this)),
2011-04-06 12:56:20 +04:00
_contextMenu(0)
2011-02-17 02:21:45 +03:00
{
#ifdef OWNCLOUD_CLIENT
_theme = new ownCloudTheme();
#else
_theme = new mirallTheme();
#endif
setApplicationName( _theme->appName() );
2012-02-23 14:44:44 +04:00
_splash = new QSplashScreen( _theme->splashScreen() );
_splash->show();
processEvents();
// Internationalization support.
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
installTranslator(&qtTranslator);
QTranslator myappTranslator;
myappTranslator.load("mirall_" + QLocale::system().name());
installTranslator(&myappTranslator);
_folderMan = new FolderMan();
connect( _folderMan, SIGNAL(folderSyncStateChange(QString)),
this,SLOT(slotSyncStateChange(QString)));
/* 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);
_folderWizard = new FolderWizard();
_owncloudSetupWizard = new OwncloudSetupWizard( _folderMan );
_statusDialog = new StatusDialog( _theme );
connect( _statusDialog, SIGNAL(addASync()), this, SLOT(slotAddFolder()) );
2011-10-13 15:55:52 +04:00
connect( _statusDialog, SIGNAL(removeFolderAlias( const QString&)),
SLOT(slotRemoveFolder(const QString&)));
#if 0
2011-10-18 12:22:24 +04:00
connect( _statusDialog, SIGNAL(fetchFolderAlias(const QString&)),
SLOT(slotFetchFolder( const QString&)));
connect( _statusDialog, SIGNAL(pushFolderAlias(const QString&)),
SLOT(slotPushFolder( const QString&)));
#endif
connect( _statusDialog, SIGNAL(enableFolderAlias(QString,bool)),
SLOT(slotEnableFolder(QString,bool)));
connect( _statusDialog, SIGNAL(infoFolderAlias(const QString&)),
SLOT(slotInfoFolder( const QString&)));
connect( _statusDialog, SIGNAL(openFolderAlias(const QString&)),
SLOT(slotFolderOpenAction(QString)));
qDebug() << "* Network is" << (_networkMgr->isOnline() ? "online" : "offline");
foreach (QNetworkConfiguration netCfg, _networkMgr->allConfigurations(QNetworkConfiguration::Active)) {
//qDebug() << "Network:" << netCfg.identifier();
}
/* setup the folder list */
int cnt = _folderMan->setupFolders();
setupActions();
setupSystemTray();
if( cnt ) {
_tray->setIcon(_theme->folderIcon("owncloud", 24));
}
2012-02-23 14:44:44 +04:00
QTimer::singleShot( 5000, this, SLOT(slotHideSplash()) );
2011-11-04 14:41:49 +04:00
qDebug() << "Network Location: " << NetworkLocation::currentLocation().encoded();
2011-02-17 02:21:45 +03:00
}
Application::~Application()
{
qDebug() << "* Mirall shutdown";
delete _networkMgr;
delete _folderMan;
delete _tray;
}
2012-02-23 14:44:44 +04:00
void Application::slotHideSplash()
{
delete _splash;
}
2011-02-17 02:21:45 +03:00
void Application::setupActions()
{
2011-10-14 18:39:53 +04:00
_actionAddFolder = new QAction(tr("Add folder..."), this);
2011-02-17 02:21:45 +03:00
QObject::connect(_actionAddFolder, SIGNAL(triggered(bool)), SLOT(slotAddFolder()));
2011-10-14 18:39:53 +04:00
_actionConfigure = new QAction(tr("Configure..."), this);
QObject::connect(_actionConfigure, SIGNAL(triggered(bool)), SLOT(slotConfigure()));
2011-02-17 02:21:45 +03:00
_actionQuit = new QAction(tr("Quit"), this);
QObject::connect(_actionQuit, SIGNAL(triggered(bool)), SLOT(quit()));
}
void Application::setupSystemTray()
{
_tray = new QSystemTrayIcon(this);
_tray->setIcon( _theme->folderIcon("none", 22) ); // load the grey icon
2011-09-26 17:00:12 +04:00
connect(_tray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
setupContextMenu();
2011-02-17 02:21:45 +03:00
_tray->show();
}
void Application::setupContextMenu()
{
delete _contextMenu;
_contextMenu = new QMenu();
_contextMenu->setTitle(_theme->appName() );
_contextMenu->addAction(_actionConfigure);
_contextMenu->addAction(_actionAddFolder);
_contextMenu->addSeparator();
// here all folders should be added
foreach (Folder *folder, _folderMan->map() ) {
QAction *action = new QAction( tr("open %1").arg( folder->alias()), this );
action->setIcon( _theme->folderIcon( folder->backend(), 22) );
connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map()));
_folderOpenActionMapper->setMapping( action, folder->alias() );
_contextMenu->addAction(action);
}
_contextMenu->addSeparator();
_contextMenu->addAction(_actionQuit);
_tray->setContextMenu(_contextMenu);
}
/*
* open the folder with the given Alais
*/
void Application::slotFolderOpenAction( const QString& alias )
{
Folder *f = _folderMan->folder(alias);
if( f ) {
QDesktopServices::openUrl(QUrl( f->path() ));
}
}
2011-09-26 17:00:12 +04:00
void Application::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
{
if( reason == QSystemTrayIcon::Trigger ) {
_folderMan->disableFoldersWithRestore();
// check if there is a mirall.cfg already.
if( _owncloudSetupWizard->wizard()->isVisible() ) {
_owncloudSetupWizard->wizard()->show();
2011-10-14 18:39:53 +04:00
}
// if no config file is there, start the configuration wizard.
MirallConfigFile cfgFile;
if( !cfgFile.exists() ) {
2011-09-27 21:10:01 +04:00
qDebug() << "No configured folders yet, start the Owncloud integration dialog.";
_owncloudSetupWizard->startWizard();
2011-09-27 21:10:01 +04:00
} else {
_statusDialog->setFolderList( _folderMan->map() );
2011-10-20 12:26:40 +04:00
_statusDialog->show();
2011-09-27 21:10:01 +04:00
}
_folderMan->restoreEnabledFolders();
2011-09-26 17:00:12 +04:00
}
}
2011-02-17 02:21:45 +03:00
void Application::slotAddFolder()
{
_folderMan->disableFoldersWithRestore();
Folder::Map folderMap = _folderMan->map();
_folderWizard->setFolderMap( &folderMap );
_folderWizard->restart();
if (_folderWizard->exec() == QDialog::Accepted) {
qDebug() << "* Folder wizard completed";
bool goodData = true;
QString alias = _folderWizard->field("alias").toString();
QString sourceFolder = _folderWizard->field("sourceFolder").toString();
QString backend = QString::fromLocal8Bit("csync");
QString targetPath;
bool onlyThisLAN = false;
bool onlyOnline = false;
if (_folderWizard->field("local?").toBool()) {
// setup a local csync folder
targetPath = _folderWizard->field("targetLocalFolder").toString();
} else if (_folderWizard->field("remote?").toBool()) {
// setup a remote csync folder
targetPath = _folderWizard->field("targetURLFolder").toString();
onlyOnline = _folderWizard->field("onlyOnline?").toBool();
onlyThisLAN = _folderWizard->field("onlyThisLAN?").toBool();
} else if( _folderWizard->field("OC?").toBool()) {
// setup a ownCloud folder
backend = QString::fromLocal8Bit("owncloud");
targetPath = _folderWizard->field("targetOCFolder").toString();
} else {
qWarning() << "* Folder not local and note remote?";
goodData = false;
}
if( goodData ) {
_folderMan->addFolderDefinition( backend, alias, sourceFolder, targetPath, onlyThisLAN );
2012-03-13 18:39:04 +04:00
_statusDialog->slotAddFolder( _folderMan->folder( alias ) );
}
} else {
qDebug() << "* Folder wizard cancelled";
}
_folderMan->restoreEnabledFolders();
2011-02-17 02:21:45 +03:00
}
/*
* the folder is to be removed. The slot is called from a signal emitted by
* the status dialog, which removes the folder from its list by itself.
*/
2011-10-13 15:55:52 +04:00
void Application::slotRemoveFolder( const QString& alias )
{
int ret = QMessageBox::question( 0, tr("Confirm Folder Remove"), tr("Do you really want to remove upload folder <i>%1</i>?").arg(alias),
QMessageBox::Yes|QMessageBox::No );
2011-10-13 15:55:52 +04:00
if( ret == QMessageBox::No ) {
return;
}
2011-10-13 15:55:52 +04:00
_folderMan->slotRemoveFolder( alias );
2011-10-13 15:55:52 +04:00
}
#ifdef HAVE_FETCH_AND_PUSH
2011-10-18 12:22:24 +04:00
void Application::slotFetchFolder( const QString& alias )
{
qDebug() << "start to fetch folder with alias " << alias;
if( ! _folderMap.contains( alias ) ) {
qDebug() << "!! Can not fetch alias " << alias << ", can not be found in folderMap.";
return;
}
Folder *f = _folderMap[alias];
}
void Application::slotPushFolder( const QString& alias )
{
qDebug() << "start to push folder with alias " << alias;
if( ! _folderMap.contains( alias ) ) {
qDebug() << "!! Can not push alias " << alias << ", can not be found in folderMap.";
return;
}
Folder *f = _folderMap[alias];
}
#endif
void Application::slotInfoFolder( const QString& alias )
{
qDebug() << "details of folder with alias " << alias;
SyncResult folderResult = _folderMan->syncResult( alias );
QString folderMessage = tr( "Last sync was succesful" );
SyncResult::Status syncStatus = folderResult.status();
if ( syncStatus == SyncResult::Error ) {
folderMessage = tr( "<b>Syncing Error</b><br/>" );
} else if ( syncStatus == SyncResult::SetupError ) {
folderMessage = tr( "<b>Setup Error</b><br/>" );
} else if ( syncStatus == SyncResult::Disabled ) {
folderMessage = tr( "<b>Disabled Folder</b><br/>" ).arg( folderResult.errorString() );
} else if ( syncStatus == SyncResult::Undefined ) {
folderMessage = tr( "<b>Undefined state</b><br/>" );
}
QMessageBox infoBox( QMessageBox::Information, tr( "Folder information" ), alias, QMessageBox::Ok );
QStringList li = folderResult.errorStrings();
foreach( const QString l, li ) {
folderMessage += "<p>" + l +"</p>";
}
infoBox.setText( folderMessage );
// qDebug() << "informative text: " << infoBox.informativeText();
if ( !folderResult.syncChanges().isEmpty() ) {
QString details;
QHash < QString, QStringList > changes = folderResult.syncChanges();
QHash< QString, QStringList >::const_iterator change_it = changes.constBegin();
for(; change_it != changes.constEnd(); ++change_it ) {
QString changeType = tr( "Unknown" );
if ( change_it.key() == "changed" ) {
changeType = tr( "Changed files:\n" );
} else if ( change_it.key() == "added" ) {
changeType = tr( "Added files:\n" );
} else if ( change_it.key() == "deleted" ) {
changeType = tr( "New files in the server, or files deleted locally:\n");
}
QStringList files = change_it.value();
QString fileList;
foreach( QString file, files) {
fileList += file + "\n";
}
details += changeType + fileList;
}
infoBox.setDetailedText(details);
qDebug() << "detailed text: " << infoBox.detailedText();
}
infoBox.exec();
}
void Application::slotEnableFolder(const QString& alias, const bool enable)
{
qDebug() << "Application: enable folder with alias " << alias;
_folderMan->slotEnableFolder( alias, enable );
slotSyncStateChange( alias );
}
2011-10-14 18:39:53 +04:00
void Application::slotConfigure()
{
_folderMan->disableFoldersWithRestore();
_owncloudSetupWizard->startWizard();
_folderMan->restoreEnabledFolders();
2011-04-04 14:23:30 +04:00
}
void Application::slotSyncStateChange( const QString& alias )
2011-04-04 14:23:30 +04:00
{
SyncResult result = _folderMan->syncResult( alias );
2011-04-04 14:23:30 +04:00
2012-03-13 18:39:04 +04:00
_statusDialog->slotUpdateFolderState( _folderMan->folder(alias) );
computeOverallSyncStatus();
qDebug() << "Sync state changed for folder " << alias << ": " << result.errorString();
}
void Application::computeOverallSyncStatus()
{
// display the info of the least succesful sync (eg. not just display the result of the latest sync
SyncResult overallResult = SyncResult::Success;
QString trayMessage;
Folder::Map map = _folderMan->map();
foreach ( Folder *syncedFolder, map ) {
QString folderMessage;
SyncResult folderResult = syncedFolder->syncResult();
SyncResult::Status syncStatus = folderResult.status();
if ( syncStatus == SyncResult::Success ) {
folderMessage = tr( "Folder %1: Ok." ).arg( syncedFolder->alias() );
} else if ( syncStatus == SyncResult::Error ) {
overallResult = SyncResult::Error;
folderMessage = tr( "Folder %1: %2" ).arg( syncedFolder->alias(), folderResult.errorString() );
} else if ( syncStatus == SyncResult::SetupError ) {
if ( overallResult.status() != SyncResult::Error ) {
overallResult = SyncResult::SetupError;
}
folderMessage = tr( "Folder %1: setup error" ).arg( syncedFolder->alias() );
} else if ( syncStatus == SyncResult::Disabled ) {
if ( overallResult.status() != SyncResult::SetupError
&& overallResult.status() != SyncResult::Error ) {
overallResult = SyncResult::Disabled;
}
folderMessage = tr( "Folder %1: %2" ).arg( syncedFolder->alias(), folderResult.errorString() );
} else if ( syncStatus == SyncResult::Undefined ) {
if ( overallResult.status() == SyncResult::Success ) {
overallResult = SyncResult::Undefined;
}
folderMessage = tr( "Folder %1: undefined state" ).arg( syncedFolder->alias() );
}
if ( !trayMessage.isEmpty() ) {
trayMessage += "\n";
2011-10-13 18:41:24 +04:00
}
trayMessage += folderMessage;
if( _statusDialog->isVisible() ) {
_statusDialog->slotUpdateFolderState( syncedFolder );
}
}
// QIcon statusIcon = _theme->syncStateIcon( overallResult.status(), 22 );
// if( overallResult.status() == SyncResult::Success ) {
// Rather display the mirall icon instead of the ok icon.
#ifdef _WIN32
QIcon statusIcon = _theme->applicationIcon( 16 );
#else
QIcon statusIcon = _theme->applicationIcon( 22 );
#endif
// }
_tray->setIcon( statusIcon );
_tray->setToolTip(trayMessage);
}
2011-02-17 02:21:45 +03:00
} // namespace Mirall