1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-16 06:44:07 +02:00

Compare commits

...

78 Commits

Author SHA1 Message Date
Daniel Molkentin
82d79b1188 Remove folder from the scheduling queue
Not really needed, but cleaner
2013-06-12 12:42:02 +02:00
Olivier Goffart
e33601becd Fix leak 2013-06-12 12:23:12 +02:00
Olivier Goffart
334443adbb Fix crash when removing a folder
The problem is that the module_property of csync are not really tight to
a context, but are global to all the contextes.
Which means csync_owncloud may still have a pointer to the destroyed
context of the destroyed folder.
By always resetting the context pointer, we make sure there is no stale
pointers there
2013-06-12 12:23:12 +02:00
Daniel Molkentin
99579e8a2a 1.3.0beta3 2013-06-12 11:10:08 +02:00
Daniel Molkentin
89438f7ace Make SyncDisabler local to slotAddFolder
This also allows us to update the folder state as
soon as the wizard is being closed.
2013-06-12 09:27:20 +02:00
Daniel Molkentin
d323ec5dd9 FileItemDialog: more clarity in the label
- finished %n sec ago -> last finished %n sec ago
- switch to minutes after 60 seconds
2013-06-11 22:34:37 +02:00
Daniel Molkentin
bb5cf37330 Fix issues found after review
- use safer formatting
- remove unnecessary condition
2013-06-11 22:33:11 +02:00
Daniel Molkentin
4b0bdd648c Do not repeat old strings
Fixes #678, fixes #494
2013-06-11 22:14:32 +02:00
Olivier Goffart
5588fbe695 Fix clicking on the systray when the setup is not finished
We should raise the wizard
2013-06-11 21:32:44 +02:00
Olivier Goffart
12ea381205 Do not re-use the configuration wizard.
Create it on demand.
This allow yo alays keep a cleen state.
Mirall issue #668
2013-06-11 21:15:37 +02:00
Daniel Molkentin
99fbf25fb2 Keep the member variable, avoids double instanciation 2013-06-11 18:41:35 +02:00
Daniel Molkentin
b37645e14d Revert "Put FolderWizard on the stack"
This reverts commit 1ec5a1aaa2.
2013-06-11 18:33:39 +02:00
Daniel Molkentin
1ec5a1aaa2 Put FolderWizard on the stack 2013-06-11 18:19:09 +02:00
Daniel Molkentin
3eb7acde25 Folder wizard: use native separators in path lineedit 2013-06-11 18:18:38 +02:00
Daniel Molkentin
e53e39cfad Remove obsolete members from enum 2013-06-11 18:17:34 +02:00
Daniel Molkentin
1a17f40233 Remove debug 2013-06-11 18:17:22 +02:00
Daniel Molkentin
10094a997a Proxy Dialog: default to port 8080 2013-06-11 17:46:00 +02:00
Daniel Molkentin
2af38b093f Fix status delegate
- remove magic values
- remove backend icon, put status icon in the front
- elide text when > list view width
- use list view font
2013-06-11 14:46:12 +02:00
Daniel Molkentin
b03c168175 Status dialog> Do not adjust pen when using Vista Style
Light blue and white are not contrasting enough
2013-06-10 21:29:45 +02:00
Daniel Molkentin
1c6bc84d2d Wizard: Always initialize all labels 2013-06-10 21:29:45 +02:00
Olivier Goffart
541239c17b Make the message box more explicit when all files have been removed
Also clean the db if the user wish to keep the files
2013-06-10 15:58:02 +02:00
Daniel Molkentin
74b4ade15a Add missing return statement 2013-06-10 15:37:52 +02:00
Daniel Molkentin
205502fd3b Fix incorrect license attribution
Fixes #672
2013-06-10 07:42:35 +02:00
Daniel Molkentin
54e4217216 Add Missing LGPL_EXCEPTION.txt
Fixes #671
2013-06-10 07:38:35 +02:00
Olivier Goffart
d2579a7754 Warn if we detect that all fles are about to be removed. 2013-06-08 15:41:53 +02:00
Daniel Molkentin
76580840dd Fix misleading confirmation message
Fixes #459
2013-06-07 22:01:26 +02:00
Olivier Goffart
779e59156c Added --logexpire to remove the log after some hours 2013-06-07 18:58:16 +02:00
Daniel Molkentin
b0f0d0b1cd qDebug() ises local8bit, not utf-8.
Fixes #651
2013-06-07 17:28:04 +02:00
Daniel Molkentin
858dcb53bd Status dialog delegate: Use font from option 2013-06-06 22:12:18 +02:00
Daniel Molkentin
9d7db88fcb status dialog: Use contrast color for highlights
Fixes #440.
2013-06-06 22:11:36 +02:00
Daniel Molkentin
2099b7c6a0 ensureJournalGone: fix logic 2013-06-06 21:43:05 +02:00
Daniel Molkentin
4442564ad2 Clean up slotAddFolder
Ensure folder sync scheduling is off in the meanwhile.
2013-06-06 21:27:15 +02:00
Daniel Molkentin
12148b5c9b remove journal when adding a new sync on an existing folder 2013-06-06 17:59:50 +02:00
Daniel Molkentin
d7d77a49fc Show help on Windows
We have no console, so show a message box.
2013-06-06 16:00:51 +02:00
Daniel Molkentin
b70c2f5c20 torture scripts: fix description 2013-06-06 11:05:21 +02:00
Daniel Molkentin
033249423f Add torture scripts + standard layout files 2013-06-05 21:36:55 +02:00
Daniel Molkentin
0c959e8661 Windows: Log change of power state 2013-06-05 16:14:20 +02:00
Daniel Molkentin
79785241ea Docs: --logdir replaces --logfile 2013-06-05 14:57:32 +02:00
Daniel Molkentin
0090862313 wizard: show native separators on folder chooser button 2013-06-04 00:46:34 +02:00
Daniel Molkentin
a4a68c6622 Wizard: Better wording when renaming failes 2013-06-03 23:34:28 +02:00
Klaas Freitag
49b4c341ae Really unload folders before reconfiguring. 2013-06-03 17:27:06 +02:00
Olivier Goffart
7c1f91abdd Add the --logdir commandline option
To log to a different file for every sync.

This also changed a QueuedConnection to AutoConnection, that way we
directly save the log from the main thread in the file without waiting
for the event loop (so if it crashes before, the log has been writen)
2013-06-03 16:25:41 +02:00
Klaas Freitag
1f2ba7e254 Handle rename fails for backup reasons correctly. 2013-06-03 15:47:39 +02:00
Klaas Freitag
8014bcb7c4 Check for emptiness before backuping the entire dir. 2013-06-03 15:47:07 +02:00
Klaas Freitag
b1c8bf5954 Fix backup name generation. 2013-06-03 15:46:41 +02:00
Klaas Freitag
0eb6740bac Added default argument to terminateSyncProcess 2013-06-03 15:46:11 +02:00
Klaas Freitag
96531b548a Minor Cleanups. 2013-06-03 15:45:28 +02:00
Klaas Freitag
f3371360ed Check the CredentialStore state before fetching creds again. 2013-06-03 15:44:58 +02:00
Daniel Molkentin
c1b92f9fed beta2 2013-05-31 16:25:57 +02:00
Daniel Molkentin
b028ca0738 Merge pull request #650 from manolopm/master
Fixes for windows client when setup server url customization
2013-05-31 07:25:09 -07:00
Daniel Molkentin
a9aab30d55 Display proxy errors 2013-05-31 16:16:56 +02:00
Daniel Molkentin
efbad3a3c8 Propagate proxy changes to csync at run time 2013-05-31 16:16:41 +02:00
Manuel Padron Martinez
b6ed959f98 Removes server url label if a custom url is defined
Signed-off-by: Manuel Padron Martinez <manolopm@gmail.com>
2013-05-31 04:46:26 +01:00
Manuel Padron Martinez
477953f965 Put wizard url customization before connect signals
Signed-off-by: Manuel Padron Martinez <manolopm@gmail.com>
2013-05-31 04:45:48 +01:00
Daniel Molkentin
aaf59cece5 Wizard: Normalize directory separators 2013-05-29 17:24:59 +02:00
Daniel Molkentin
e88b7e8ec2 Centralize User Agent string and use in UpdateDetector 2013-05-29 16:13:38 +02:00
Daniel Molkentin
078b09b5f4 Remove obsolete include 2013-05-29 16:12:42 +02:00
Daniel Molkentin
0d06fe764a Status dialog: Use correct font metrics
This avoids cutting charcters such as 'y'.
2013-05-29 14:46:02 +02:00
Daniel Molkentin
94f8c39a9e Proxy settings: Also keep proxy user/pwd
make sure not to use it when the user
has asked us not to.

Simplify setupProxy()
2013-05-29 12:56:23 +02:00
Daniel Molkentin
7d1bd9da86 Properly deal with SOCKS proxies
Fixes #10
2013-05-29 02:14:40 +02:00
Daniel Molkentin
ed8cdf6910 Remember proxy settings even after switching type
Fixes #649
2013-05-29 01:41:04 +02:00
Daniel Molkentin
7ee83847c8 Do not try to reset the wizard when visible 2013-05-29 01:30:00 +02:00
Daniel Molkentin
52eca1362f Delete QWizard on destruction 2013-05-29 01:29:56 +02:00
Daniel Molkentin
eec1af09c4 Wizard: Fix rich text label layouting 2013-05-29 01:17:12 +02:00
Daniel Molkentin
c651c8cbf9 Wizard: Improve wording. 2013-05-29 01:16:52 +02:00
Daniel Molkentin
da6a398624 Wizard: Warn on re-setup with multiple folders 2013-05-28 20:25:31 +02:00
Daniel Molkentin
1418512a9f More cheating on proxies: Add OS to User-Agent 2013-05-28 19:35:30 +02:00
Daniel Molkentin
dd2859880b Set User-Agent to contain Mozilla/5.0 string
A blatant lie for a blatant abuse of Firewall filters.
2013-05-28 15:44:41 +02:00
Daniel Molkentin
f38d8ba2e4 Improve wizard in edit mode 2013-05-28 14:51:49 +02:00
Daniel Molkentin
fdd52a2520 Kill non-boxed mode for now 2013-05-28 14:51:48 +02:00
Daniel Molkentin
e2c0792043 take local folder path from property
This gets set by slotSelectFolder() and from the wizards caller.
2013-05-28 14:51:41 +02:00
Daniel Molkentin
e8889530b0 Fix owncloud theme icon 2013-05-28 14:42:41 +02:00
Klaas Freitag
23f67d950a Handle password change correct, add "sync from scratch".
The setup wizard now destinguishes if there was already a configuration
or not. If yes, it's going to password-change mode. Also added a checkbox
that allows to start a sync from a cleared local directory.
2013-05-26 14:04:11 +02:00
Klaas Freitag
0bd1f507ab Added a checkbox "start sync from scratch". 2013-05-26 13:57:28 +02:00
Klaas Freitag
2bcfc143f6 Let the folderman create a new sync directory.
If a sync directory exists its moved to a backup path and created new.
That allows to start a sync "from scratch".
2013-05-26 13:56:51 +02:00
Klaas Freitag
9dc21bf8a3 Let the keychain return new creds during async save.
The credentials are asynchronously saved. The credentialstore now returns
the creds even if the saving has not yet finished but is running, for that
the new state AsyncWriting was added. That makes the start of the sync
after the password was changed more reliable.
2013-05-26 13:55:23 +02:00
Klaas Freitag
70f627ba06 Fix the folder setup wizard. 2013-05-24 09:54:48 +02:00
Daniel Molkentin
0683c26d41 Make setting custom folders work again
Also, ensure that opening the local directory from the wizard
will work on Windows.
2013-05-23 01:51:05 +02:00
46 changed files with 8254 additions and 694 deletions

View File

@@ -1,6 +1,6 @@
set( VERSION_MAJOR 1 ) set( VERSION_MAJOR 1 )
set( VERSION_MINOR 3 ) set( VERSION_MINOR 3 )
set( VERSION_PATCH 0 ) set( VERSION_PATCH 0 )
set( VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${VERSION_SUFFIX}beta1) set( VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${VERSION_SUFFIX}beta3)
set( SOVERSION 0 ) set( SOVERSION 0 )

View File

@@ -19,7 +19,7 @@ Mac OS X
Installing the ownCloud client on your Mac follows the normal app installation Installing the ownCloud client on your Mac follows the normal app installation
pattern: pattern:
1. Download the installation file Click ownCloud-1.1.1.dmg, a window with the 1. Download the installation file Click ownCloud-x.y.z.dmg, a window with the
2. ownCloud icon opens In that window, drag the ownCloud application into the 2. ownCloud icon opens In that window, drag the ownCloud application into the
3. Applications folder on the right hand side From Applications, choose 3. Applications folder on the right hand side From Applications, choose
ownCloud ownCloud

View File

@@ -3,8 +3,8 @@ ownCloud Client supports the following command line switches:
``--logwindow`` ``--logwindow``
open a window to show log output at startup. open a window to show log output at startup.
``--logfile`` `<filename>` ``--logdir`` `<dir>`
write log output to file. write log output to dir, one for each sync run.
``--flushlog`` ``--flushlog``
flush the log file after every write. flush the log file after every write.

View File

@@ -9,7 +9,7 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
=========== ===========
owncloud is a file synchronisation desktop utility it is based on mirall. ownCloud is a file synchronisation desktop utility it is based on mirall.
It synchronizes files on your local machine with an ownCloud Server. If you It synchronizes files on your local machine with an ownCloud Server. If you
make a change to the files on one computer, it will flow across the others make a change to the files on one computer, it will flow across the others
using this desktop sync clients. using this desktop sync clients.

View File

@@ -4,9 +4,12 @@ Doc Build Convenience Scripts
* ``htmlhelp.sh``: A script to install Microsoft HTML Workshop on Linux or Mac OS using Wine, along with some dependencies. * ``htmlhelp.sh``: A script to install Microsoft HTML Workshop on Linux or Mac OS using Wine, along with some dependencies.
* ``htmlhelp.reg``: Registry file to override some DLLs with their native version and set the right Windows version. * ``htmlhelp.reg``: Registry file to override some DLLs with their native version and set the right Windows version.
Those files have been taken from the HTML Help Project (http://code.google.com/p/htmlhelp/wiki/HHW4Wine). Those files have been taken from the `HTML Help Project`_.
License License
------- -------
The HTML Help Project has licensed its software under LGPLv3 terms. The HTML Help Project has licensed_ its software under LGPLv2.1 terms
.. _HTML Help Project: http://code.google.com/p/htmlhelp/wiki/HHW4Wine
.. _licensed: https://code.google.com/p/htmlhelp/source/browse/trunk/pyhtmlhelp/COPYING

View File

@@ -41,7 +41,7 @@ Here are a couple of useful steps to isolate the problem.
Logfiles Logfiles
======== ========
Doing effective debugging requires to provide as much as relevant logfiles as Doing effective debugging requires to provide as much as relevant logs as
possible. The log output can help you with tracking down problem, and if you possible. The log output can help you with tracking down problem, and if you
report a bug, you're advised to include the output. report a bug, you're advised to include the output.
@@ -57,11 +57,12 @@ starting the client again with this parameter. Syntax:
* Mac OS X: ``/Applications/owncloud.app/Contents/MacOS/owncloud --logwindow`` * Mac OS X: ``/Applications/owncloud.app/Contents/MacOS/owncloud --logwindow``
* Linux: ``owncloud --logwindow`` * Linux: ``owncloud --logwindow``
It is also possible to directly log into a file, which is an useful option It is also possible to directly log to a directory, which is an useful option
in case the problem only happens ocassionally. In that case it is better to in case the problem only happens ocassionally. In that case it is better to
create a huge logfile than piping the whole log through the log window. create a huge amount of data, as the log window has a limited buffer.
To create a log file, start the client with ``--logfile <filename>``. To write logs to disk, start the client with ``--logdir <dir>``, where ``<dir>``
is an existing directory. Each sync run will create a new file.
:ownCloud server Logfile: :ownCloud server Logfile:
The ownCloud server maintains an ownCloud specific logfile as well. It can and The ownCloud server maintains an ownCloud specific logfile as well. It can and

View File

@@ -9,6 +9,7 @@
<file>resources/folder-grey.png</file> <file>resources/folder-grey.png</file>
<file>resources/task-ongoing.png</file> <file>resources/task-ongoing.png</file>
<file>resources/view-refresh.png</file> <file>resources/view-refresh.png</file>
<file>resources/warning-16.png</file>
<file>resources/owncloud_logo_blue.png</file> <file>resources/owncloud_logo_blue.png</file>
</qresource> </qresource>
</RCC> </RCC>

BIN
resources/warning-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

22
src/3rdparty/LGPL_EXCEPTION.txt vendored Normal file
View File

@@ -0,0 +1,22 @@
Digia Qt LGPL Exception version 1.1
As an additional permission to the GNU Lesser General Public License version
2.1, the object code form of a "work that uses the Library" may incorporate
material from a header file that is part of the Library. You may distribute
such object code under terms of your choice, provided that:
(i) the header files of the Library have not been modified; and
(ii) the incorporated material is limited to numerical parameters, data
structure layouts, accessors, macros, inline functions and
templates; and
(iii) you comply with the terms of Section 6 of the GNU Lesser General
Public License version 2.1.
Moreover, you may apply this exception to a modified version of the Library,
provided that such modification does not involve copying material from the
Library into the modified Library's header files unless such material is
limited to (i) numerical parameters; (ii) data structure layouts;
(iii) accessors; and (iv) small macros, templates and inline functions of
five lines or less in length.
Furthermore, you are not required to apply this additional permission to a
modified version of the Library.

View File

@@ -29,12 +29,15 @@
#include "mirall/mirallconfigfile.h" #include "mirall/mirallconfigfile.h"
#include "mirall/updatedetector.h" #include "mirall/updatedetector.h"
#include "mirall/proxydialog.h" #include "mirall/proxydialog.h"
#include "mirall/version.h"
#include "mirall/credentialstore.h" #include "mirall/credentialstore.h"
#include "mirall/logger.h" #include "mirall/logger.h"
#include "mirall/inotify.h" #include "mirall/inotify.h"
#if defined(Q_OS_WIN)
#include <windows.h>
#endif
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
#include <QHash> #include <QHash>
@@ -51,10 +54,26 @@ namespace Mirall {
void mirallLogCatcher(QtMsgType type, const char *msg) void mirallLogCatcher(QtMsgType type, const char *msg)
{ {
Q_UNUSED(type) Q_UNUSED(type)
Logger::instance()->mirallLog( QString::fromUtf8(msg) ); // qDebug() exports to local8Bit, which is not always UTF-8
Logger::instance()->mirallLog( QString::fromLocal8Bit(msg) );
} }
namespace { namespace {
static const char optionsC[] =
"Options:\n"
" -h --help : show this help screen.\n"
" --logwindow : open a window to show log output.\n"
" --logfile <filename> : write log output to file <filename>.\n"
" --logdir <name> : write each sync log output in a new file\n"
" in directory <name>.\n"
" --logexpire <hours> : removes logs older than <hours> hours.\n"
" (to be used with --logdir)\n"
" --logflush : flush the log file after every write.\n"
" --monoicons : Use black/white pictograms for systray.\n"
" --confdir <dirname> : Use the given configuration directory.\n"
;
QString applicationTrPath() QString applicationTrPath()
{ {
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
@@ -83,11 +102,13 @@ Application::Application(int &argc, char **argv) :
_theme(Theme::instance()), _theme(Theme::instance()),
_updateDetector(0), _updateDetector(0),
_logBrowser(0), _logBrowser(0),
_logExpire(0),
_showLogWindow(false), _showLogWindow(false),
_logFlush(false), _logFlush(false),
_helpOnly(false), _helpOnly(false),
_fileItemDialog(0), _fileItemDialog(0),
_statusDialog(0) _statusDialog(0),
_folderWizard(0)
{ {
setApplicationName( _theme->appNameGUI() ); setApplicationName( _theme->appNameGUI() );
setWindowIcon( _theme->applicationIcon() ); setWindowIcon( _theme->applicationIcon() );
@@ -114,12 +135,6 @@ Application::Application(int &argc, char **argv) :
setQuitOnLastWindowClosed(false); setQuitOnLastWindowClosed(false);
_folderWizard = new FolderWizard;
_owncloudSetupWizard = new OwncloudSetupWizard( _folderMan, _theme, this );
connect( _owncloudSetupWizard, SIGNAL(ownCloudWizardDone(int)),
this, SLOT(slotownCloudWizardDone(int)));
_statusDialog = new StatusDialog( _theme ); _statusDialog = new StatusDialog( _theme );
connect( _statusDialog, SIGNAL(addASync()), this, SLOT(slotAddFolder()) ); connect( _statusDialog, SIGNAL(addASync()), this, SLOT(slotAddFolder()) );
@@ -191,7 +206,7 @@ void Application::slotStartFolderSetup( int result )
ownCloudInfo::instance()->checkInstallation(); ownCloudInfo::instance()->checkInstallation();
} else { } else {
_owncloudSetupWizard->startWizard(); slotConfigure();
} }
} else { } else {
qDebug() << "Setup Wizard was canceled. No reparsing of config."; qDebug() << "Setup Wizard was canceled. No reparsing of config.";
@@ -247,23 +262,28 @@ void Application::slotFetchCredentials()
{ {
QString trayMessage; QString trayMessage;
if( CredentialStore::instance()->canTryAgain() ) { if( CredentialStore::instance()->state() == CredentialStore::Ok ) {
connect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)), // the credentials are still valid and ok.
this, SLOT(slotCredentialsFetched(bool)) ); slotCredentialsFetched( true );
CredentialStore::instance()->fetchCredentials();
if( CredentialStore::instance()->state() == CredentialStore::TooManyAttempts ) {
trayMessage = tr("Too many incorrect password attempts.");
}
} else { } else {
qDebug() << "Can not try again to fetch Credentials."; if( CredentialStore::instance()->canTryAgain() ) {
trayMessage = tr("%1 user credentials are wrong. Please check configuration.") connect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)),
.arg(Theme::instance()->appNameGUI()); this, SLOT(slotCredentialsFetched(bool)) );
} CredentialStore::instance()->fetchCredentials();
if( CredentialStore::instance()->state() == CredentialStore::TooManyAttempts ) {
trayMessage = tr("Too many incorrect password attempts.");
}
} else {
qDebug() << "Can not try again to fetch Credentials.";
trayMessage = tr("%1 user credentials are wrong. Please check configuration.")
.arg(Theme::instance()->appNameGUI());
}
if( !trayMessage.isEmpty() ) { if( !trayMessage.isEmpty() ) {
_tray->showMessage(tr("Credentials"), trayMessage); _tray->showMessage(tr("Credentials"), trayMessage);
_actionOpenStatus->setEnabled( false ); _actionOpenStatus->setEnabled( false );
_actionAddFolder->setEnabled( false ); _actionAddFolder->setEnabled( false );
}
} }
} }
@@ -403,6 +423,7 @@ void Application::slotownCloudWizardDone( int res )
} }
_folderMan->setSyncEnabled( true ); _folderMan->setSyncEnabled( true );
slotStartFolderSetup( res ); slotStartFolderSetup( res );
_owncloudSetupWizard.reset(0);
} }
void Application::setupActions() void Application::setupActions()
@@ -522,7 +543,9 @@ void Application::setupLogBrowser()
_logBrowser = new LogBrowser; _logBrowser = new LogBrowser;
qInstallMsgHandler( mirallLogCatcher ); qInstallMsgHandler( mirallLogCatcher );
// ## TODO: allow new log name maybe? // ## TODO: allow new log name maybe?
if (!_logFile.isEmpty()) { if (!_logDirectory.isEmpty()) {
enterNextLogFile();
} else if (!_logFile.isEmpty()) {
qDebug() << "Logging into logfile: " << _logFile << " with flush " << _logFlush; qDebug() << "Logging into logfile: " << _logFile << " with flush " << _logFlush;
_logBrowser->setLogFile( _logFile, _logFlush ); _logBrowser->setLogFile( _logFile, _logFlush );
} }
@@ -538,38 +561,74 @@ void Application::setupLogBrowser()
} }
void Application::setupProxy() void Application::enterNextLogFile()
{ {
// if (_logBrowser && !_logDirectory.isEmpty()) {
Mirall::MirallConfigFile cfg; QDir dir(_logDirectory);
int proxy = cfg.proxyType(); if (!dir.exists()) {
dir.mkpath(".");
}
switch(proxy) { // Find out what is the file with the highest nymber if any
case QNetworkProxy::NoProxy: { QStringList files = dir.entryList(QStringList("owncloud.log.*"),
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); QDir::Files);
break; QRegExp rx("owncloud.log.(\\d+)");
} uint maxNumber = 0;
case QNetworkProxy::DefaultProxy: { QDateTime now = QDateTime::currentDateTime();
QNetworkProxyFactory::setUseSystemConfiguration(true); foreach(const QString &s, files) {
break; if (rx.exactMatch(s)) {
} maxNumber = qMax(maxNumber, rx.cap(1).toUInt());
if (_logExpire > 0) {
QFileInfo fileInfo = dir.absoluteFilePath(s);
if (fileInfo.lastModified().addSecs(60*60 * _logExpire) < now) {
dir.remove(s);
}
}
}
}
case QNetworkProxy::Socks5Proxy: { QString filename = _logDirectory + "/owncloud.log." + QString::number(maxNumber+1);
proxy = QNetworkProxy::HttpProxy; _logBrowser->setLogFile(filename , _logFlush);
cfg.setProxyType(proxy);
// fall through
} }
case QNetworkProxy::HttpProxy:{ }
QNetworkProxy proxy;
proxy.setType(QNetworkProxy::HttpProxy); QNetworkProxy proxyFromConfig(const MirallConfigFile& cfg)
proxy.setHostName(cfg.proxyHostName()); {
proxy.setPort(cfg.proxyPort()); QNetworkProxy proxy;
proxy.setHostName(cfg.proxyHostName());
proxy.setPort(cfg.proxyPort());
if (cfg.proxyNeedsAuth()) {
proxy.setUser(cfg.proxyUser()); proxy.setUser(cfg.proxyUser());
proxy.setPassword(cfg.proxyPassword()); proxy.setPassword(cfg.proxyPassword());
}
return proxy;
}
void Application::setupProxy()
{
Mirall::MirallConfigFile cfg;
int proxyType = cfg.proxyType();
QNetworkProxy proxy = proxyFromConfig(cfg);
switch(proxyType) {
case QNetworkProxy::NoProxy:
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
break;
case QNetworkProxy::DefaultProxy:
QNetworkProxyFactory::setUseSystemConfiguration(true);
break;
case QNetworkProxy::Socks5Proxy:
proxy.setType(QNetworkProxy::Socks5Proxy);
QNetworkProxy::setApplicationProxy(proxy); QNetworkProxy::setApplicationProxy(proxy);
break; break;
case QNetworkProxy::HttpProxy:
proxy.setType(QNetworkProxy::HttpProxy);
QNetworkProxy::setApplicationProxy(proxy);
break;
default:
break;
} }
} _folderMan->setProxy();
} }
/* /*
@@ -614,7 +673,7 @@ void Application::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
slotFetchCredentials(); slotFetchCredentials();
} }
#if defined Q_WS_WIN || defined Q_WS_X11 #if defined Q_WS_WIN || defined Q_WS_X11
if( reason == QSystemTrayIcon::Trigger && _actionOpenStatus->isEnabled() ) { if( reason == QSystemTrayIcon::Trigger ) {
slotOpenStatus(); slotOpenStatus();
} }
#endif #endif
@@ -622,63 +681,58 @@ void Application::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
void Application::slotAddFolder() void Application::slotAddFolder()
{ {
_folderMan->setSyncEnabled(false); // do not start more syncs. /** Helper class to ensure sync is always switched back on */
class SyncDisabler
{
public:
SyncDisabler(Application *app) : _app(app)
{
_app->_folderMan->setSyncEnabled(false);
}
~SyncDisabler() {
_app->_folderMan->setSyncEnabled(true);
_app->computeOverallSyncStatus();
_app->_folderMan->slotScheduleAllFolders();
}
private:
Application *_app;
};
Folder::Map folderMap = _folderMan->map(); if (_folderWizard) {
raiseDialog(_folderWizard);
_folderWizard->setFolderMap( &folderMap ); return;
_folderWizard->restart();
if (_folderWizard->exec() == QDialog::Accepted) {
qDebug() << "* Folder wizard completed";
bool goodData = true;
QString alias = _folderWizard->field(QLatin1String("alias")).toString();
QString sourceFolder = _folderWizard->field(QLatin1String("sourceFolder")).toString();
QString backend = QLatin1String("csync");
QString targetPath;
bool onlyThisLAN = false;
bool onlyOnline = false;
if (_folderWizard->field(QLatin1String("local?")).toBool()) {
// setup a local csync folder
targetPath = _folderWizard->field(QLatin1String("targetLocalFolder")).toString();
} else if (_folderWizard->field(QLatin1String("remote?")).toBool()) {
// setup a remote csync folder
targetPath = _folderWizard->field(QLatin1String("targetURLFolder")).toString();
onlyOnline = _folderWizard->field(QLatin1String("onlyOnline?")).toBool();
onlyThisLAN = _folderWizard->field(QLatin1String("onlyThisLAN?")).toBool();
(void) onlyOnline;
(void) onlyThisLAN;
} else if( _folderWizard->field(QLatin1String("OC?")).toBool() ||
Theme::instance()->singleSyncFolder()) {
// setup a ownCloud folder
backend = QLatin1String("owncloud");
targetPath = _folderWizard->field(QLatin1String("targetOCFolder")).toString(); //empty in single folder mode
} else {
qWarning() << "* Folder not local and note remote?";
goodData = false;
} }
_folderMan->setSyncEnabled(true); // do start sync again. // disables sync queuing while in scope
SyncDisabler disableSync(this);
if( goodData ) { Folder::Map folderMap = _folderMan->map();
_folderMan->addFolderDefinition( backend, alias, sourceFolder, targetPath, onlyThisLAN ); _folderWizard = new FolderWizard;
_folderWizard->setFolderMap( &folderMap );
if (_folderWizard->exec() == QDialog::Accepted) {
qDebug() << "* Folder wizard completed";
QString alias = _folderWizard->field(QLatin1String("alias")).toString();
QString sourceFolder = _folderWizard->field(QLatin1String("sourceFolder")).toString();
QString targetPath = _folderWizard->field(QLatin1String("OCFolderLineEdit")).toString();
QString backend = QLatin1String("owncloud");
if (!FolderMan::ensureJournalGone( sourceFolder ))
return;
_folderMan->addFolderDefinition( backend, alias, sourceFolder, targetPath, false );
Folder *f = _folderMan->setupFolderFromConfigFile( alias ); Folder *f = _folderMan->setupFolderFromConfigFile( alias );
if( f ) { if( f ) {
_statusDialog->slotAddFolder( f ); _statusDialog->slotAddFolder( f );
_statusDialog->buttonsSetEnabled(); _statusDialog->buttonsSetEnabled();
setupContextMenu(); setupContextMenu();
} }
}
} else { } else {
qDebug() << "* Folder wizard cancelled"; qDebug() << "* Folder wizard cancelled";
} }
_folderMan->setSyncEnabled(true); _folderWizard->deleteLater();
_folderMan->slotScheduleAllFolders(); _folderWizard = 0;
} }
void Application::slotOpenStatus() void Application::slotOpenStatus()
@@ -688,7 +742,7 @@ void Application::slotOpenStatus()
QWidget *raiseWidget = 0; QWidget *raiseWidget = 0;
// check if there is a mirall.cfg already. // check if there is a mirall.cfg already.
if( _owncloudSetupWizard->wizard()->isVisible() ) { if( _owncloudSetupWizard && _owncloudSetupWizard->wizard()->isVisible() ) {
raiseWidget = _owncloudSetupWizard->wizard(); raiseWidget = _owncloudSetupWizard->wizard();
} }
@@ -698,8 +752,7 @@ void Application::slotOpenStatus()
if( !cfgFile.exists() ) { if( !cfgFile.exists() ) {
qDebug() << "No configured folders yet, start the Owncloud integration dialog."; qDebug() << "No configured folders yet, start the Owncloud integration dialog.";
_folderMan->setSyncEnabled(false); slotConfigure();
_owncloudSetupWizard->startWizard();
} else { } else {
qDebug() << "#============# Status dialog starting #=============#"; qDebug() << "#============# Status dialog starting #=============#";
raiseWidget = _statusDialog; raiseWidget = _statusDialog;
@@ -746,16 +799,14 @@ void Application::slotAbout()
void Application::slotRemoveFolder( const QString& alias ) void Application::slotRemoveFolder( const QString& alias )
{ {
int ret = QMessageBox::question( 0, tr("Confirm Folder Remove"), int ret = QMessageBox::question( 0, tr("Confirm Folder Remove"),
tr("Do you really want to remove upload folder <i>%1</i>?").arg(alias), tr("<p>Do you really want to stop syncing the upload folder <i>%1</i>?</p>"
"<p><b>Note:</b> This will not remove the files from your client.</p>").arg(alias),
QMessageBox::Yes|QMessageBox::No ); QMessageBox::Yes|QMessageBox::No );
if( ret == QMessageBox::No ) { if( ret == QMessageBox::No ) {
return; return;
} }
Folder *f = _folderMan->folder(alias); Folder *f = _folderMan->folder(alias);
if( f && _overallStatusStrings.contains( f->alias() )) {
_overallStatusStrings.remove( f->alias() );
}
_folderMan->slotRemoveFolder( alias ); _folderMan->slotRemoveFolder( alias );
_statusDialog->slotRemoveSelectedFolder( ); _statusDialog->slotRemoveSelectedFolder( );
@@ -809,6 +860,15 @@ void Application::slotEnableFolder(const QString& alias, const bool enable)
void Application::slotConfigure() void Application::slotConfigure()
{ {
if (_owncloudSetupWizard && !_owncloudSetupWizard->wizard()->isVisible()) {
raiseDialog(_owncloudSetupWizard->wizard());
return;
}
_owncloudSetupWizard.reset(new OwncloudSetupWizard( _folderMan, _theme, this ));;
connect( _owncloudSetupWizard.data(), SIGNAL(ownCloudWizardDone(int)),
this, SLOT(slotownCloudWizardDone(int)));
_folderMan->setSyncEnabled(false); // do not start more syncs. _folderMan->setSyncEnabled(false); // do not start more syncs.
_owncloudSetupWizard->startWizard(); _owncloudSetupWizard->startWizard();
} }
@@ -846,6 +906,10 @@ void Application::slotSyncStateChange( const QString& alias )
computeOverallSyncStatus(); computeOverallSyncStatus();
qDebug() << "Sync state changed for folder " << alias << ": " << result.statusString(); qDebug() << "Sync state changed for folder " << alias << ": " << result.statusString();
if (result.status() == SyncResult::Success || result.status() == SyncResult::Error) {
enterNextLogFile();
}
} }
void Application::parseOptions(const QStringList &options) void Application::parseOptions(const QStringList &options)
@@ -869,6 +933,18 @@ void Application::parseOptions(const QStringList &options)
} else { } else {
setHelp(); setHelp();
} }
} else if (option == QLatin1String("--logdir")) {
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
_logDirectory = it.next();
} else {
setHelp();
}
} else if (option == QLatin1String("--logexpire")) {
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
_logExpire = it.next().toInt();
} else {
setHelp();
}
} else if (option == QLatin1String("--logflush")) { } else if (option == QLatin1String("--logflush")) {
_logFlush = true; _logFlush = true;
} else if (option == QLatin1String("--monoicons")) { } else if (option == QLatin1String("--monoicons")) {
@@ -892,11 +968,12 @@ void Application::computeOverallSyncStatus()
// display the info of the least successful sync (eg. not just display the result of the latest sync // display the info of the least successful sync (eg. not just display the result of the latest sync
SyncResult overallResult(SyncResult::Undefined ); SyncResult overallResult(SyncResult::Undefined );
QMap<QString, QString> overallStatusStrings;
QString trayMessage; QString trayMessage;
Folder::Map map = _folderMan->map(); Folder::Map map = _folderMan->map();
foreach ( Folder *syncedFolder, map.values() ) { foreach ( Folder *syncedFolder, map.values() ) {
QString folderMessage = _overallStatusStrings[syncedFolder->alias()]; QString folderMessage;
SyncResult folderResult = syncedFolder->syncResult(); SyncResult folderResult = syncedFolder->syncResult();
SyncResult::Status syncStatus = folderResult.status(); SyncResult::Status syncStatus = folderResult.status();
@@ -926,9 +1003,9 @@ void Application::computeOverallSyncStatus()
break; break;
case SyncResult::Success: case SyncResult::Success:
if( overallResult.status() == SyncResult::Undefined ) { if( overallResult.status() == SyncResult::Undefined ) {
folderMessage = tr( "Last Sync was successful." );
overallResult.setStatus( SyncResult::Success ); overallResult.setStatus( SyncResult::Success );
} }
folderMessage = tr( "Last Sync was successful." );
break; break;
case SyncResult::Error: case SyncResult::Error:
overallResult.setStatus( SyncResult::Error ); overallResult.setStatus( SyncResult::Error );
@@ -950,15 +1027,13 @@ void Application::computeOverallSyncStatus()
} }
qDebug() << "Folder in overallStatus Message: " << syncedFolder << " with name " << syncedFolder->alias(); qDebug() << "Folder in overallStatus Message: " << syncedFolder << " with name " << syncedFolder->alias();
QString msg = QString::fromLatin1("Folder %1: %2").arg(syncedFolder->alias()).arg(folderMessage); QString msg = tr("Folder %1: %2").arg(syncedFolder->alias(), folderMessage);
if( msg != _overallStatusStrings[syncedFolder->alias()] ) { overallStatusStrings[syncedFolder->alias()] = msg;
_overallStatusStrings[syncedFolder->alias()] = msg;
}
} }
// create the tray blob message, check if we have an defined state // create the tray blob message, check if we have an defined state
if( overallResult.status() != SyncResult::Undefined ) { if( overallResult.status() != SyncResult::Undefined ) {
QStringList allStatusStrings = _overallStatusStrings.values(); QStringList allStatusStrings = overallStatusStrings.values();
if( ! allStatusStrings.isEmpty() ) if( ! allStatusStrings.isEmpty() )
trayMessage = allStatusStrings.join(QLatin1String("\n")); trayMessage = allStatusStrings.join(QLatin1String("\n"));
else else
@@ -971,22 +1046,48 @@ void Application::computeOverallSyncStatus()
} }
} }
// Helpers for displaying messages. Note that there is no console on Windows.
#ifdef Q_OS_WIN
// Format as <pre> HTML
static inline void toHtml(QString &t)
{
t.replace(QLatin1Char('&'), QLatin1String("&amp;"));
t.replace(QLatin1Char('<'), QLatin1String("&lt;"));
t.replace(QLatin1Char('>'), QLatin1String("&gt;"));
t.insert(0, QLatin1String("<html><pre>"));
t.append(QLatin1String("</pre></html>"));
}
static void displayHelpText(QString t) // No console on Windows.
{
toHtml(t);
QMessageBox::information(0, Theme::instance()->appNameGUI(), t);
}
#else
static void displayHelpText(const QString &t)
{
std::cout << qPrintable(t);
}
#endif
void Application::showHelp() void Application::showHelp()
{ {
setHelp(); setHelp();
std::cout << _theme->appName().toLatin1().constData() << " version " << QString helpText;
_theme->version().toLatin1().constData() << std::endl << std::endl; QTextStream stream(&helpText);
std::cout << "File synchronisation desktop utility." << std::endl << std::endl; stream << _theme->appName().toLatin1().constData()
std::cout << "Options:" << std::endl; << QLatin1String(" version ")
std::cout << " -h --help : show this help screen." << std::endl; << _theme->version().toLatin1().constData() << endl;
std::cout << " --logwindow : open a window to show log output." << std::endl;
std::cout << " --logfile <filename> : write log output to file <filename>." << std::endl; stream << QLatin1String("File synchronisation desktop utility.") << endl << endl
std::cout << " --logflush : flush the log file after every write." << std::endl; << QLatin1String(optionsC);
std::cout << " --monoicons : Use black/white pictograms for systray." << std::endl;
std::cout << " --confdir <dirname> : Use the given configuration directory." << std::endl;
std::cout << std::endl;
if (_theme->appName() == QLatin1String("ownCloud")) if (_theme->appName() == QLatin1String("ownCloud"))
std::cout << "For more information, see http://www.owncloud.org" << std::endl; stream << endl << "For more information, see http://www.owncloud.org" << endl;
displayHelpText(helpText);
} }
void Application::setHelp() void Application::setHelp()
@@ -994,6 +1095,30 @@ void Application::setHelp()
_helpOnly = true; _helpOnly = true;
} }
#if defined(Q_OS_WIN)
bool Application::winEventFilter(MSG *pMsg, long *result)
{
if (pMsg->message == WM_POWERBROADCAST) {
switch(pMsg->wParam) {
case PBT_APMPOWERSTATUSCHANGE:
qDebug() << "WM_POWERBROADCAST: Power state changed";
break;
case PBT_APMSUSPEND:
qDebug() << "WM_POWERBROADCAST: Entering low power state";
break;
case PBT_APMRESUMEAUTOMATIC:
qDebug() << "WM_POWERBROADCAST: Resuming from low power state";
break;
default:
break;
}
return true;
}
return SharedTools::QtSingleApplication::winEventFilter(pMsg, result);
}
#endif
QString substLang(const QString &lang) QString substLang(const QString &lang)
{ {
// Map the more apropriate script codes // Map the more apropriate script codes

View File

@@ -79,10 +79,16 @@ protected:
void setupContextMenu(); void setupContextMenu();
void setupLogBrowser(); void setupLogBrowser();
void setupProxy(); void setupProxy();
void enterNextLogFile();
//folders have to be disabled while making config changes //folders have to be disabled while making config changes
void computeOverallSyncStatus(); void computeOverallSyncStatus();
// reimplemented
#if defined(Q_WS_WIN)
bool winEventFilter( MSG * message, long * result );
#endif
protected slots: protected slots:
void slotTrayClicked( QSystemTrayIcon::ActivationReason ); void slotTrayClicked( QSystemTrayIcon::ActivationReason );
void slotFolderOpenAction(const QString & ); void slotFolderOpenAction(const QString & );
@@ -118,7 +124,7 @@ private:
#endif #endif
FolderWizard *_folderWizard; FolderWizard *_folderWizard;
OwncloudSetupWizard *_owncloudSetupWizard; QScopedPointer<OwncloudSetupWizard> _owncloudSetupWizard;
SslErrorDialog *_sslErrorDialog; SslErrorDialog *_sslErrorDialog;
// tray's menu // tray's menu
@@ -130,9 +136,10 @@ private:
Theme *_theme; Theme *_theme;
QSignalMapper *_folderOpenActionMapper; QSignalMapper *_folderOpenActionMapper;
UpdateDetector *_updateDetector; UpdateDetector *_updateDetector;
QMap<QString, QString> _overallStatusStrings;
LogBrowser *_logBrowser; LogBrowser *_logBrowser;
QString _logFile; QString _logFile;
QString _logDirectory;
int _logExpire;
bool _showLogWindow; bool _showLogWindow;
bool _logFlush; bool _logFlush;
bool _helpOnly; bool _helpOnly;

View File

@@ -69,30 +69,18 @@ CredentialStore::CredState CredentialStore::state()
bool CredentialStore::canTryAgain() bool CredentialStore::canTryAgain()
{ {
bool canDoIt = false;
if( _tries > MAX_LOGIN_ATTEMPTS ) { if( _tries > MAX_LOGIN_ATTEMPTS ) {
qDebug() << "canTryAgain: Max attempts reached."; qDebug() << "canTryAgain: Max attempts reached.";
return false; return false;
} }
if( _state == NotFetched ) { /* Since QtKeyChain is required now, it makes sense to only query once. */
if( _state == NotFetched || _state == AsyncWriting ) {
return true; return true;
} else {
return false;
} }
switch( _type ) {
case CredentialStore::User:
canDoIt = true;
break;
case CredentialStore::Settings:
break;
case CredentialStore::KeyChain:
canDoIt = true;
break;
default:
break;
}
return canDoIt;
} }
void CredentialStore::fetchCredentials() void CredentialStore::fetchCredentials()
@@ -147,7 +135,7 @@ void CredentialStore::fetchCredentials()
} }
case CredentialStore::KeyChain: { case CredentialStore::KeyChain: {
// If the credentials are here already, return. // If the credentials are here already, return.
if( _state == Ok ) { if( _state == Ok || _state == AsyncWriting ) {
emit(fetchCredentialsFinished(true)); emit(fetchCredentialsFinished(true));
return; return;
} }
@@ -347,6 +335,7 @@ void CredentialStore::saveCredentials( )
connect( job, SIGNAL(finished(QKeychain::Job*)), this, connect( job, SIGNAL(finished(QKeychain::Job*)), this,
SLOT(slotKeyChainWriteFinished(QKeychain::Job*))); SLOT(slotKeyChainWriteFinished(QKeychain::Job*)));
_state = AsyncWriting;
job->start(); job->start();
#endif #endif
break; break;
@@ -373,15 +362,21 @@ void CredentialStore::slotKeyChainWriteFinished( QKeychain::Job *job )
pwdJob->errorString().contains(QLatin1String("Could not open wallet"))) { pwdJob->errorString().contains(QLatin1String("Could not open wallet"))) {
_type = Settings; _type = Settings;
saveCredentials(); saveCredentials();
_state = NoKeychainBackend;
} else {
_state = Error;
} }
} else { } else {
qDebug() << "Successfully stored password for user " << _user; qDebug() << "Successfully stored password for user " << _user;
// Try to remove password formerly stored in the config file. // Try to remove password formerly stored in the config file.
MirallConfigFile cfgFile; MirallConfigFile cfgFile;
cfgFile.clearPasswordFromConfig(); cfgFile.clearPasswordFromConfig();
_state = NotFetched;
_tries = 0;
} }
} else { } else {
qDebug() << "Error: KeyChain Write Password Job failed!"; qDebug() << "Error: KeyChain Write Password Job failed!";
_state = Error;
} }
#else #else
(void) job; (void) job;

View File

@@ -57,6 +57,7 @@ public:
AccessDenied, AccessDenied,
NoKeychainBackend, NoKeychainBackend,
Error, Error,
AsyncWriting,
TooManyAttempts }; TooManyAttempts };
enum CredentialType { enum CredentialType {

View File

@@ -191,6 +191,11 @@ int CSyncThread::treewalkFile( TREE_WALK_FILE *file, bool remote )
int re = 0; int re = 0;
if (file->instruction != CSYNC_INSTRUCTION_IGNORE
&& file->instruction != CSYNC_INSTRUCTION_REMOVE) {
_hasFiles = true;
}
switch(file->instruction) { switch(file->instruction) {
case CSYNC_INSTRUCTION_NONE: case CSYNC_INSTRUCTION_NONE:
case CSYNC_INSTRUCTION_IGNORE: case CSYNC_INSTRUCTION_IGNORE:
@@ -310,6 +315,7 @@ void CSyncThread::startSync()
// cleans up behind us and emits finished() to ease error handling // cleans up behind us and emits finished() to ease error handling
CSyncRunScopeHelper helper(_csync_ctx, this); CSyncRunScopeHelper helper(_csync_ctx, this);
csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
csync_set_userdata(_csync_ctx, this); csync_set_userdata(_csync_ctx, this);
// csync_set_auth_callback( _csync_ctx, getauth ); // csync_set_auth_callback( _csync_ctx, getauth );
@@ -327,6 +333,7 @@ void CSyncThread::startSync()
return; return;
} }
_hasFiles = false;
bool walkOk = true; bool walkOk = true;
if( csync_walk_local_tree(_csync_ctx, &treewalkLocal, 0) < 0 ) { if( csync_walk_local_tree(_csync_ctx, &treewalkLocal, 0) < 0 ) {
qDebug() << "Error in local treewalk."; qDebug() << "Error in local treewalk.";
@@ -336,6 +343,16 @@ void CSyncThread::startSync()
qDebug() << "Error in remote treewalk."; qDebug() << "Error in remote treewalk.";
} }
if (!_hasFiles && !_syncedItems.isEmpty()) {
qDebug() << Q_FUNC_INFO << "All the files are going to be removed, asking the user";
bool cancel = true;
emit aboutToRemoveAllFiles(_syncedItems.first()._dir, &cancel);
if (cancel) {
qDebug() << Q_FUNC_INFO << "Abort sync";
return;
}
}
if (_needsUpdate) if (_needsUpdate)
emit(started()); emit(started());

View File

@@ -56,6 +56,8 @@ signals:
void finished(); void finished();
void started(); void started();
void aboutToRemoveAllFiles(SyncFileItem::Direction direction, bool *cancel);
private: private:
void handleSyncError(CSYNC *ctx, const char *state); void handleSyncError(CSYNC *ctx, const char *state);
static void progress(const char *remote_url, static void progress(const char *remote_url,
@@ -79,6 +81,8 @@ private:
CSYNC *_csync_ctx; CSYNC *_csync_ctx;
bool _needsUpdate; bool _needsUpdate;
bool _hasFiles; // true if there is at least one file that is not ignored or removed
friend class CSyncRunScopeHelper; friend class CSyncRunScopeHelper;
}; };
} }

View File

@@ -123,7 +123,10 @@ void FileItemDialog::slotSetFolderMessage()
QDateTime now = QDateTime::currentDateTime(); QDateTime now = QDateTime::currentDateTime();
int secs = _lastSyncTime.secsTo(now); int secs = _lastSyncTime.secsTo(now);
_timelabel->setText(tr("%1 (finished %n sec. ago)", "", secs).arg(_folderMessage)); if (secs < 60)
_timelabel->setText(tr("%1 (last finished %n sec. ago)", "", secs).arg(_folderMessage));
else
_timelabel->setText(tr("%1 (last finished %n min. ago)", "", secs/60).arg(_folderMessage));
} }
void FileItemDialog::copyToClipboard() void FileItemDialog::copyToClipboard()

View File

@@ -173,6 +173,11 @@ public slots:
*/ */
void setPollInterval( int ); void setPollInterval( int );
/**
* If folder is network-based, reimplement to react to proxy changes
*/
virtual void setProxy() {}
protected: protected:
/** /**
* The minimum amounts of seconds to wait before * The minimum amounts of seconds to wait before

View File

@@ -27,6 +27,7 @@
#endif #endif
#include <QDesktopServices> #include <QDesktopServices>
#include <QMessageBox>
#include <QtCore> #include <QtCore>
namespace Mirall { namespace Mirall {
@@ -79,20 +80,28 @@ void FolderMan::slotReparseConfiguration()
setupKnownFolders(); setupKnownFolders();
} }
int FolderMan::unloadAllFolders()
{
// first terminate sync jobs.
terminateCurrentSync();
int cnt = 0;
// clear the list of existing folders.
Folder::MapIterator i(_folderMap);
while (i.hasNext()) {
i.next();
delete _folderMap.take( i.key() );
cnt++;
}
return cnt;
}
int FolderMan::setupKnownFolders() int FolderMan::setupKnownFolders()
{ {
qDebug() << "* Setup folders from " << _folderConfigPath; qDebug() << "* Setup folders from " << _folderConfigPath;
// first terminate sync jobs. unloadAllFolders();
terminateCurrentSync();
// clear the list of existing folders.
Folder::MapIterator i(_folderMap);
while (i.hasNext()) {
i.next();
delete _folderMap.take( i.key() );
}
QDir dir( _folderConfigPath ); QDir dir( _folderConfigPath );
dir.setFilter(QDir::Files); dir.setFilter(QDir::Files);
@@ -117,6 +126,25 @@ void FolderMan::wipeAllJournals()
} }
} }
bool FolderMan::ensureJournalGone(const QString &localPath)
{
// remove old .csync_journal file
QString stateDbFile = localPath+QLatin1String("/.csync_journal.db");
while (QFile::exists(stateDbFile) && !QFile::remove(stateDbFile)) {
int ret = QMessageBox::warning(0, tr("Could not reset folder state"),
tr("An old sync journal '%1' was found, "
"but could not be removed. Please make sure "
"that no application is currently using it.")
.arg(QDir::fromNativeSeparators(QDir::cleanPath(stateDbFile))),
QMessageBox::Retry|QMessageBox::Abort);
if (ret == QMessageBox::Abort) {
return false;
}
}
return true;
}
void FolderMan::terminateCurrentSync() void FolderMan::terminateCurrentSync()
{ {
if( !_currentSyncFolder.isEmpty() ) { if( !_currentSyncFolder.isEmpty() ) {
@@ -235,7 +263,7 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
folder->setConfigFile(file); folder->setConfigFile(file);
} else { } else {
qWarning() << "unknown backend" << backend; qWarning() << "unknown backend" << backend;
return NULL; return 0;
} }
} }
@@ -275,12 +303,18 @@ void FolderMan::slotEnableFolder( const QString& alias, bool enable )
// csync still remains in a stable state, regardless of that. // csync still remains in a stable state, regardless of that.
void FolderMan::terminateSyncProcess( const QString& alias ) void FolderMan::terminateSyncProcess( const QString& alias )
{ {
Folder *f = _folderMap[alias]; QString folderAlias = alias;
if( f ) { if( alias.isEmpty() ) {
f->slotTerminateSync(); folderAlias = _currentSyncFolder;
}
if( ! folderAlias.isEmpty() ) {
Folder *f = _folderMap[folderAlias];
if( f ) {
f->slotTerminateSync();
if(_currentSyncFolder == alias ) if(_currentSyncFolder == folderAlias )
_currentSyncFolder = QString::null; _currentSyncFolder = QString::null;
}
} }
} }
@@ -437,6 +471,8 @@ void FolderMan::removeFolder( const QString& alias )
{ {
Folder *f = 0; Folder *f = 0;
_scheduleQueue.removeAll(alias);
if( _folderMap.contains( alias )) { if( _folderMap.contains( alias )) {
qDebug() << "Removing " << alias; qDebug() << "Removing " << alias;
f = _folderMap.take( alias ); f = _folderMap.take( alias );
@@ -455,4 +491,53 @@ void FolderMan::removeFolder( const QString& alias )
} }
} }
QString FolderMan::getBackupName( const QString& fullPathName ) const
{
if( fullPathName.isEmpty() ) return QString::null;
QString newName = fullPathName + QLatin1String(".oC_bak");
QFileInfo fi( newName );
int cnt = 1;
do {
if( fi.exists() ) {
newName = fullPathName + QString( ".oC_bak_%1").arg(cnt++);
fi.setFile(newName);
}
} while( fi.exists() );
return newName;
}
bool FolderMan::startFromScratch( const QString& localFolder )
{
if( localFolder.isEmpty() ) return false;
QFileInfo fi( localFolder );
if( fi.exists() && fi.isDir() ) {
QDir file = fi.dir();
// check if there are files in the directory.
if( file.count() == 0 ) {
// directory is existing, but its empty. Use it.
qDebug() << "startFromScratch: Directory is empty!";
return true;
}
QString newName = getBackupName( fi.absoluteFilePath() );
if( file.rename( fi.absoluteFilePath(), newName )) {
if( file.mkdir( fi.absoluteFilePath() ) ) {
return true;
}
}
}
return false;
}
void FolderMan::setProxy()
{
foreach( Folder *f, _folderMap.values() ) {
f->setProxy();
}
}
} }

View File

@@ -76,6 +76,23 @@ public:
*/ */
void wipeAllJournals(); void wipeAllJournals();
/**
* Ensures that a given directory does not contain a .csync_journal.
*
* @returns false if the journal could not be removed, false otherwise.
*/
static bool ensureJournalGone(const QString &path);
/**
* Creates a new and empty local directory.
*/
bool startFromScratch( const QString& );
/**
* called whenever proxy configuration changes
*/
void setProxy();
signals: signals:
/** /**
* signal to indicate a folder named by alias has changed its sync state. * signal to indicate a folder named by alias has changed its sync state.
@@ -92,7 +109,10 @@ public slots:
void slotReparseConfiguration(); void slotReparseConfiguration();
void terminateSyncProcess( const QString& ); void terminateSyncProcess( const QString& alias = QString::null );
/* delete all folder objects */
int unloadAllFolders();
// if enabled is set to false, no new folders will start to sync. // if enabled is set to false, no new folders will start to sync.
// the current one will finish. // the current one will finish.
@@ -112,6 +132,7 @@ private:
// and create the folders // and create the folders
int setupKnownFolders(); int setupKnownFolders();
void terminateCurrentSync(); void terminateCurrentSync();
QString getBackupName( const QString& ) const;
// Escaping of the alias which is used in QSettings AND the file // Escaping of the alias which is used in QSettings AND the file
// system, thus need to be escaped. // system, thus need to be escaped.

View File

@@ -36,7 +36,8 @@ FolderWizardSourcePage::FolderWizardSourcePage()
{ {
_ui.setupUi(this); _ui.setupUi(this);
registerField(QLatin1String("sourceFolder*"), _ui.localFolderLineEdit); registerField(QLatin1String("sourceFolder*"), _ui.localFolderLineEdit);
_ui.localFolderLineEdit->setText( QString::fromLatin1( "%1/%2").arg( QDir::homePath() ).arg(Theme::instance()->appName() ) ); QString defaultPath = QString::fromLatin1( "%1/%2").arg( QDir::homePath() ).arg(Theme::instance()->appName() );
_ui.localFolderLineEdit->setText( QDir::toNativeSeparators( defaultPath ) );
registerField(QLatin1String("alias*"), _ui.aliasLineEdit); registerField(QLatin1String("alias*"), _ui.aliasLineEdit);
_ui.aliasLineEdit->setText( Theme::instance()->appNameGUI() ); _ui.aliasLineEdit->setText( Theme::instance()->appNameGUI() );
@@ -64,7 +65,7 @@ void FolderWizardSourcePage::cleanupPage()
bool FolderWizardSourcePage::isComplete() const bool FolderWizardSourcePage::isComplete() const
{ {
QFileInfo selFile( _ui.localFolderLineEdit->text() ); QFileInfo selFile( QDir::fromNativeSeparators(_ui.localFolderLineEdit->text()) );
QString userInput = selFile.canonicalFilePath(); QString userInput = selFile.canonicalFilePath();
QString warnString; QString warnString;
@@ -94,7 +95,8 @@ bool FolderWizardSourcePage::isComplete() const
qDebug() << "Checking local path: " << folderDir << " <-> " << userInput; qDebug() << "Checking local path: " << folderDir << " <-> " << userInput;
if( QFileInfo( f->path() ) == userInput ) { if( QFileInfo( f->path() ) == userInput ) {
isOk = false; isOk = false;
warnString.append( tr("The local path %1 is already an upload folder.<br/>Please pick another one!").arg(userInput) ); warnString.append( tr("The local path %1 is already an upload folder.<br/>Please pick another one!")
.arg(QDir::toNativeSeparators(userInput)) );
} }
if( isOk && folderDir.startsWith( userInput )) { if( isOk && folderDir.startsWith( userInput )) {
qDebug() << "A already configured folder is child of the current selected"; qDebug() << "A already configured folder is child of the current selected";
@@ -148,7 +150,7 @@ void FolderWizardSourcePage::on_localFolderChooseBtn_clicked()
tr("Select the source folder"), tr("Select the source folder"),
QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
if (!dir.isEmpty()) { if (!dir.isEmpty()) {
_ui.localFolderLineEdit->setText(dir); _ui.localFolderLineEdit->setText(QDir::toNativeSeparators(dir));
} }
} }
@@ -166,7 +168,7 @@ FolderWizardTargetPage::FolderWizardTargetPage()
_ui.setupUi(this); _ui.setupUi(this);
_ui.warnFrame->hide(); _ui.warnFrame->hide();
registerField(QLatin1String("targetOCFolder"), _ui.OCFolderLineEdit); registerField(QLatin1String("OCFolderLineEdit"), _ui.OCFolderLineEdit);
connect( _ui.OCFolderLineEdit, SIGNAL(textChanged(QString)), connect( _ui.OCFolderLineEdit, SIGNAL(textChanged(QString)),
SLOT(slotFolderTextChanged(QString))); SLOT(slotFolderTextChanged(QString)));
@@ -213,11 +215,10 @@ void FolderWizardTargetPage::slotDirCheckReply(const QString &url, QNetworkReply
void FolderWizardTargetPage::slotCreateRemoteFolder() void FolderWizardTargetPage::slotCreateRemoteFolder()
{ {
_ui.OCFolderLineEdit->setEnabled( false );
const QString folder = _ui.OCFolderLineEdit->text(); const QString folder = _ui.OCFolderLineEdit->text();
if( folder.isEmpty() ) return; if( folder.isEmpty() ) return;
_ui.OCFolderLineEdit->setEnabled( false );
qDebug() << "creating folder on ownCloud: " << folder; qDebug() << "creating folder on ownCloud: " << folder;
ownCloudInfo::instance()->mkdirRequest( folder ); ownCloudInfo::instance()->mkdirRequest( folder );
} }
@@ -244,8 +245,8 @@ FolderWizardTargetPage::~FolderWizardTargetPage()
bool FolderWizardTargetPage::isComplete() const bool FolderWizardTargetPage::isComplete() const
{ {
QString dir = _ui.OCFolderLineEdit->text(); QString dir = _ui.OCFolderLineEdit->text();
if( dir.isEmpty() ) { if( dir.isEmpty() || dir == QLatin1String("/") ) {
showWarn( tr("Better do not use the remote root directory.<br/>If you do, you can <b>not</b> mirror another local folder."), false); showWarn( tr("If you sync the root folder, you can <b>not</b> configure another sync directory."), false);
return true; return true;
} else { } else {
if( _dirChecked ) { if( _dirChecked ) {

View File

@@ -98,9 +98,7 @@ public:
enum { enum {
Page_Source, Page_Source,
Page_Target, Page_Target
Page_Network,
Page_Owncloud
}; };
FolderWizard(QWidget *parent = 0); FolderWizard(QWidget *parent = 0);

View File

@@ -113,15 +113,12 @@ LogBrowser::LogBrowser(QWidget *parent) :
setModal(false); setModal(false);
// needs to be a queued connection as logs from other threads come in // Direct connection for log comming from this thread, and queued for the one in a different thread
connect(Logger::instance(), SIGNAL(newLog(QString)),this,SLOT(slotNewLog(QString)), Qt::QueuedConnection); connect(Logger::instance(), SIGNAL(newLog(QString)),this,SLOT(slotNewLog(QString)), Qt::AutoConnection);
} }
LogBrowser::~LogBrowser() LogBrowser::~LogBrowser()
{ {
if( _logstream ) {
_logFile.close();
}
} }
void LogBrowser::slotNewLog( const QString& msg ) void LogBrowser::slotNewLog( const QString& msg )
@@ -138,6 +135,9 @@ void LogBrowser::slotNewLog( const QString& msg )
void LogBrowser::setLogFile( const QString & name, bool flush ) void LogBrowser::setLogFile( const QString & name, bool flush )
{ {
if( _logstream ) {
_logFile.close();
}
_logFile.setFileName( name ); _logFile.setFileName( name );
if(!_logFile.open(QIODevice::WriteOnly)) { if(!_logFile.open(QIODevice::WriteOnly)) {
@@ -150,7 +150,7 @@ void LogBrowser::setLogFile( const QString & name, bool flush )
return; return;
} }
_doFileFlush = flush; _doFileFlush = flush;
_logstream = new QTextStream( &_logFile ); _logstream.reset(new QTextStream( &_logFile ));
} }
void LogBrowser::slotFind() void LogBrowser::slotFind()

View File

@@ -67,7 +67,7 @@ private:
QFile _logFile; QFile _logFile;
bool _doFileFlush; bool _doFileFlush;
QTextStream *_logstream; QScopedPointer<QTextStream> _logstream;
}; };
} // namespace } // namespace

View File

@@ -515,7 +515,7 @@ void MirallConfigFile::acceptCustomConfig()
void MirallConfigFile::setProxyType(int proxyType, void MirallConfigFile::setProxyType(int proxyType,
const QString& host, const QString& host,
int port, int port, bool needsAuth,
const QString& user, const QString& user,
const QString& pass) const QString& pass)
{ {
@@ -524,11 +524,15 @@ void MirallConfigFile::setProxyType(int proxyType,
settings.beginGroup(QLatin1String("proxy")); settings.beginGroup(QLatin1String("proxy"));
settings.setValue(QLatin1String("type"), proxyType); settings.setValue(QLatin1String("type"), proxyType);
settings.setValue(QLatin1String("host"), host);
settings.setValue(QLatin1String("port"), port);
settings.setValue(QLatin1String("user"), user);
settings.setValue(QLatin1String("pass"), pass.toUtf8().toBase64());
if (proxyType == QNetworkProxy::HttpProxy ||
proxyType == QNetworkProxy::Socks5Proxy) {
settings.setValue(QLatin1String("host"), host);
settings.setValue(QLatin1String("port"), port);
settings.setValue(QLatin1String("needsAuth"), needsAuth);
settings.setValue(QLatin1String("user"), user);
settings.setValue(QLatin1String("pass"), pass.toUtf8().toBase64());
}
settings.sync(); settings.sync();
} }
@@ -556,6 +560,11 @@ int MirallConfigFile::proxyPort() const
return getValue(QLatin1String("port"), QLatin1String("proxy")).toInt(); return getValue(QLatin1String("port"), QLatin1String("proxy")).toInt();
} }
bool MirallConfigFile::proxyNeedsAuth() const
{
return getValue(QLatin1String("needsAuth"), QLatin1String("proxy")).toInt();
}
QString MirallConfigFile::proxyUser() const QString MirallConfigFile::proxyUser() const
{ {
return getValue(QLatin1String("user"), QLatin1String("proxy")).toString(); return getValue(QLatin1String("user"), QLatin1String("proxy")).toString();

View File

@@ -89,13 +89,14 @@ public:
// proxy settings // proxy settings
void setProxyType(int proxyType, void setProxyType(int proxyType,
const QString& host = QString(), const QString& host = QString(),
int port = 0, int port = 0, bool needsAuth = false,
const QString& user = QString(), const QString& user = QString(),
const QString& pass = QString()); const QString& pass = QString());
int proxyType() const; int proxyType() const;
QString proxyHostName() const; QString proxyHostName() const;
int proxyPort() const; int proxyPort() const;
bool proxyNeedsAuth() const;
QString proxyUser() const; QString proxyUser() const;
QString proxyPassword() const; QString proxyPassword() const;

View File

@@ -33,6 +33,8 @@
#include <QNetworkProxy> #include <QNetworkProxy>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkProxyFactory> #include <QNetworkProxyFactory>
#include <QMessageBox>
#include <QPushButton>
namespace Mirall { namespace Mirall {
@@ -100,23 +102,8 @@ ownCloudFolder::ownCloudFolder(const QString &alias,
qDebug() << "Could not initialize csync!"; qDebug() << "Could not initialize csync!";
_csync_ctx = 0; _csync_ctx = 0;
} }
setProxy();
if( _csync_ctx ) {
/* Store proxy */
QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QUrl(cfgFile.ownCloudUrl()));
// We set at least one in Application
Q_ASSERT(proxies.count() > 0);
QNetworkProxy proxy = proxies.first();
int proxyPort = proxy.port();
csync_set_module_property(_csync_ctx, "proxy_type", (char*) proxyTypeToCStr(proxy.type()) );
csync_set_module_property(_csync_ctx, "proxy_host", proxy.hostName().toUtf8().data() );
csync_set_module_property(_csync_ctx, "proxy_port", &proxyPort );
csync_set_module_property(_csync_ctx, "proxy_user", proxy.user().toUtf8().data() );
csync_set_module_property(_csync_ctx, "proxy_pwd" , proxy.password().toUtf8().data() );
csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
}
} }
} }
@@ -127,10 +114,39 @@ ownCloudFolder::~ownCloudFolder()
csync_request_abort(_csync_ctx); csync_request_abort(_csync_ctx);
_thread->wait(); _thread->wait();
} }
delete _csync;
// Destroy csync here. // Destroy csync here.
csync_destroy(_csync_ctx); csync_destroy(_csync_ctx);
} }
void ownCloudFolder::setProxy()
{
if( _csync_ctx ) {
/* Store proxy */
MirallConfigFile cfgFile;
QUrl proxyUrl(cfgFile.ownCloudUrl());
QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(proxyUrl);
// We set at least one in Application
Q_ASSERT(proxies.count() > 0);
QNetworkProxy proxy = proxies.first();
if (proxy.type() == QNetworkProxy::NoProxy) {
qDebug() << "Passing NO proxy to csync for" << cfgFile.ownCloudUrl();
} else {
qDebug() << "Passing" << proxy.hostName() << "of proxy type " << proxy.type()
<< " to csync for" << cfgFile.ownCloudUrl();
}
int proxyPort = proxy.port();
csync_set_module_property(_csync_ctx, "proxy_type", (char*) proxyTypeToCStr(proxy.type()) );
csync_set_module_property(_csync_ctx, "proxy_host", proxy.hostName().toUtf8().data() );
csync_set_module_property(_csync_ctx, "proxy_port", &proxyPort );
csync_set_module_property(_csync_ctx, "proxy_user", proxy.user().toUtf8().data() );
csync_set_module_property(_csync_ctx, "proxy_pwd" , proxy.password().toUtf8().data() );
csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
}
}
const char* ownCloudFolder::proxyTypeToCStr(QNetworkProxy::ProxyType type) const char* ownCloudFolder::proxyTypeToCStr(QNetworkProxy::ProxyType type)
{ {
switch (type) { switch (type) {
@@ -270,6 +286,8 @@ void ownCloudFolder::startSync(const QStringList &pathList)
_csync->moveToThread(_thread); _csync->moveToThread(_thread);
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector"); qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");
connect( _csync, SIGNAL(treeWalkResult(const SyncFileItemVector&)), connect( _csync, SIGNAL(treeWalkResult(const SyncFileItemVector&)),
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection); this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
@@ -277,6 +295,11 @@ void ownCloudFolder::startSync(const QStringList &pathList)
connect(_csync, SIGNAL(finished()), SLOT(slotCSyncFinished()), Qt::QueuedConnection); connect(_csync, SIGNAL(finished()), SLOT(slotCSyncFinished()), Qt::QueuedConnection);
connect(_csync, SIGNAL(csyncError(QString)), SLOT(slotCSyncError(QString)), Qt::QueuedConnection); connect(_csync, SIGNAL(csyncError(QString)), SLOT(slotCSyncError(QString)), Qt::QueuedConnection);
connect(_csync, SIGNAL(csyncUnavailable()), SLOT(slotCsyncUnavailable()), Qt::QueuedConnection); connect(_csync, SIGNAL(csyncUnavailable()), SLOT(slotCsyncUnavailable()), Qt::QueuedConnection);
//blocking connection so the message box happens in this thread, but block the csync thread.
connect(_csync, SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)),
SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*)), Qt::BlockingQueuedConnection);
_thread->start(); _thread->start();
QMetaObject::invokeMethod(_csync, "startSync", Qt::QueuedConnection); QMetaObject::invokeMethod(_csync, "startSync", Qt::QueuedConnection);
emit syncStarted(); emit syncStarted();
@@ -475,5 +498,30 @@ void ServerActionNotifier::slotSyncFinished(const SyncResult &result)
} }
} }
void ownCloudFolder::slotAboutToRemoveAllFiles(SyncFileItem::Direction direction, bool *cancel)
{
QString msg = direction == SyncFileItem::Down ?
tr("This sync would remove all the files in the local sync folder '%1'.\n"
"If you or your administrator have reset your account on the server, choose"
"\"Keep files\". If you want your data to be removed, choose \"Remove all files\".") :
tr("This sync would remove all the files in the sync folder '%1'.\n"
"This might be because the folder was silently reconfigured, or that all"
"the file were manually removed.\n"
"Are you sure you want to perform this operation?");
QMessageBox msgBox(QMessageBox::Warning, tr("Remove All Files?"),
msg.arg(alias()));
msgBox.addButton(tr("Remove all files"), QMessageBox::DestructiveRole);
QPushButton* keepBtn = msgBox.addButton(tr("Keep files"), QMessageBox::ActionRole);
if (msgBox.exec() == -1) {
*cancel = true;
return;
}
*cancel = msgBox.clickedButton() == keepBtn;
if (*cancel) {
wipe();
}
}
} // ns } // ns

View File

@@ -72,9 +72,12 @@ public:
/* get status about a singel file. */ /* get status about a singel file. */
SyncFileStatus fileStatus( const QString& ); SyncFileStatus fileStatus( const QString& );
void setProxy();
public slots: public slots:
void startSync(); void startSync();
void slotTerminateSync(); void slotTerminateSync();
void slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool*);
protected slots: protected slots:
void slotLocalPathChanged( const QString& ); void slotLocalPathChanged( const QString& );

View File

@@ -14,8 +14,9 @@
#include "mirall/owncloudinfo.h" #include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h" #include "mirall/mirallconfigfile.h"
#include "mirall/version.h"
#include "mirall/theme.h" #include "mirall/theme.h"
#include "mirall/utility.h"
#include "mirall/logger.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@@ -64,7 +65,8 @@ ownCloudInfo::ownCloudInfo() :
_manager(0) _manager(0)
{ {
_connection = Theme::instance()->appName(); _connection = Theme::instance()->appName();
connect(this, SIGNAL(guiLog(QString,QString)),
Logger::instance(), SIGNAL(guiLog(QString,QString)));
setNetworkAccessManager( new QNetworkAccessManager( this ) ); setNetworkAccessManager( new QNetworkAccessManager( this ) );
} }
@@ -164,10 +166,9 @@ QNetworkReply* ownCloudInfo::mkdirRequest( const QString& dir )
connect(qhttp, SIGNAL(requestFinished(int, bool)), this,SLOT(qhttpRequestFinished(int,bool))); connect(qhttp, SIGNAL(requestFinished(int, bool)), this,SLOT(qhttpRequestFinished(int,bool)));
connect(qhttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(qhttpResponseHeaderReceived(QHttpResponseHeader))); connect(qhttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(qhttpResponseHeaderReceived(QHttpResponseHeader)));
//connect(qhttp, SIGNAL(authenticationRequired(QString,quint16,QAuthenticator*)), this, SLOT(qhttpAuthenticationRequired(QString,quint16,QAuthenticator*))); //connect(qhttp, SIGNAL(authenticationRequired(QString,quint16,QAuthenticator*)), this, SLOT(qhttpAuthenticationRequired(QString,quint16,QAuthenticator*)));
QHttpRequestHeader header("MKCOL", QString(url.encodedPath()), 1,1); /* header */ QHttpRequestHeader header("MKCOL", QString(url.encodedPath()), 1,1); /* header */
header.setValue("Host", QString(url.encodedHost())); header.setValue("Host", QString(url.encodedHost()));
header.setValue("User-Agent", QString("mirall-%1").arg(MIRALL_STRINGIFY(MIRALL_VERSION)).toAscii() ); header.setValue("User-Agent", Utility::userAgentString());
header.setValue("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); header.setValue("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
header.setValue("Accept-Language", "it,de-de;q=0.8,it-it;q=0.6,en-us;q=0.4,en;q=0.2"); header.setValue("Accept-Language", "it,de-de;q=0.8,it-it;q=0.6,en-us;q=0.4,en;q=0.2");
header.setValue("Connection", "keep-alive"); header.setValue("Connection", "keep-alive");
@@ -482,7 +483,36 @@ bool ownCloudInfo::certsUntrusted()
void ownCloudInfo::slotError( QNetworkReply::NetworkError err) void ownCloudInfo::slotError( QNetworkReply::NetworkError err)
{ {
qDebug() << "ownCloudInfo Network Error: " << err; qDebug() << "ownCloudInfo Network Error: " << err;
switch (err) {
case QNetworkReply::ProxyConnectionRefusedError:
emit guiLog(tr("Proxy Refused Connection "),
tr("The configured proxy has refused the connection. "
"Please check the proxy settings."));
break;
case QNetworkReply::ProxyConnectionClosedError:
emit guiLog(tr("Proxy Closed Connection"),
tr("The configured proxy has closed the connection. "
"Please check the proxy settings."));
break;
case QNetworkReply::ProxyNotFoundError:
emit guiLog(tr("Proxy Not Found"),
tr("The configured proxy could not be found. "
"Please check the proxy settings."));
break;
case QNetworkReply::ProxyAuthenticationRequiredError:
emit guiLog(tr("Proxy Authentication Error"),
tr("The configured proxy requires login but the proxy credentials "
"are invalid. Please check the proxy settings."));
break;
case QNetworkReply::ProxyTimeoutError:
emit guiLog(tr("Proxy Connection Timed Out"),
tr("The connection to the configured proxy has timed out."));
break;
default:
break;
}
} }
void ownCloudInfo::setCredentials( const QString& user, const QString& passwd, void ownCloudInfo::setCredentials( const QString& user, const QString& passwd,
@@ -511,8 +541,7 @@ void ownCloudInfo::setupHeaders( QNetworkRequest & req, quint64 size )
QUrl url( cfgFile.ownCloudUrl( QString::null, false ) ); QUrl url( cfgFile.ownCloudUrl( QString::null, false ) );
qDebug() << "Setting up host header: " << url.host(); qDebug() << "Setting up host header: " << url.host();
req.setRawHeader( QByteArray("Host"), url.host().toUtf8() ); req.setRawHeader( QByteArray("Host"), url.host().toUtf8() );
req.setRawHeader( QByteArray("User-Agent"), QString::fromLatin1("mirall-%1") req.setRawHeader( QByteArray("User-Agent"), Utility::userAgentString());
.arg(QLatin1String(MIRALL_STRINGIFY(MIRALL_VERSION))).toAscii());
QString con = _configHandle; QString con = _configHandle;
if( con.isEmpty() ) con = DEFAULT_CONNECTION; if( con.isEmpty() ) con = DEFAULT_CONNECTION;

View File

@@ -118,7 +118,7 @@ signals:
void webdavColCreated( QNetworkReply::NetworkError ); void webdavColCreated( QNetworkReply::NetworkError );
void sslFailed( QNetworkReply *reply, QList<QSslError> errors ); void sslFailed( QNetworkReply *reply, QList<QSslError> errors );
void guiLog( const QString& title, const QString& content );
public slots: public slots:
protected slots: protected slots:

View File

@@ -6,14 +6,39 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>540</width> <width>583</width>
<height>374</height> <height>448</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="topLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
@@ -30,6 +55,194 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="4" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0" colspan="3">
<layout class="QHBoxLayout" name="resultLayout">
<property name="spacing">
<number>0</number>
</property>
</layout>
</item>
<item row="5" column="0" colspan="3">
<widget class="QWidget" name="advancedBox" native="true">
<property name="enabled">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Local Folder</string>
</property>
<property name="buddy">
<cstring>pbSelectLocalFolder</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pbSelectLocalFolder">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>pbSelectLocalFolder</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="resolutionWidget" native="true">
<layout class="QFormLayout" name="formLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item row="0" column="0" colspan="2">
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string>&amp;Keep local data</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;small&gt;Syncs your existing data to new location.&lt;/small&gt;</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QRadioButton" name="cbSyncFromScratch">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If this box is checked, existing content in the local directory will be erased to start a clean sync from the server.&lt;/p&gt;&lt;p&gt;Do not check this if the local content should be uploaded to the servers directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;Start a clean sync</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;small&gt;Erases the contents of the local folder before syncing using the new settings.&lt;/small&gt;</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<item row="0" column="0"> <item row="0" column="0">
@@ -128,28 +341,12 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>TextLabel</string> <string>Error Label</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>58</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1"> <item row="2" column="1">
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">
@@ -209,132 +406,10 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="4" column="0" colspan="3"> <item row="8" column="0" colspan="3">
<widget class="QGroupBox" name="advancedBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string/>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Local Folder</string>
</property>
<property name="buddy">
<cstring>pbSelectLocalFolder</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pbSelectLocalFolder">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>/home/kf/ownCloud</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="selectiveSyncLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Selective Sync:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="selectiveSyncLayout">
<item>
<widget class="QPushButton" name="pbBoxMode">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Sync Entire &amp;Account</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbSelectiveMode">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Choose &amp;Folders</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="5" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>43</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="0" colspan="3">
<layout class="QHBoxLayout" name="resultLayout"/>
</item>
<item row="7" column="0" colspan="3">
<widget class="QLabel" name="syncModeLabel"> <widget class="QLabel" name="syncModeLabel">
<property name="text"> <property name="text">
<string>Street Creds Homie!</string> <string>Status message</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
@@ -344,28 +419,44 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="0" colspan="3"> <item row="1" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>58</height>
</size>
</property>
</spacer>
</item>
<item row="9" column="0">
<widget class="QLabel" name="bottomLabel"> <widget class="QLabel" name="bottomLabel">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0" colspan="3"> <item row="6" column="0">
<widget class="QLabel" name="topLabel"> <spacer name="verticalSpacer">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="text"> <property name="sizeType">
<string>TextLabel</string> <enum>QSizePolicy::Expanding</enum>
</property> </property>
<property name="alignment"> <property name="sizeHint" stdset="0">
<set>Qt::AlignCenter</set> <size>
<width>20</width>
<height>40</height>
</size>
</property> </property>
</widget> </spacer>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@@ -34,7 +34,7 @@ OwncloudSetupWizard::OwncloudSetupWizard( FolderMan *folderMan, Theme *theme, QO
_checkInstallationRequest(0), _checkInstallationRequest(0),
_folderMan(folderMan) _folderMan(folderMan)
{ {
_ocWizard = new OwncloudWizard; _ocWizard = new OwncloudWizard();
connect( _ocWizard, SIGNAL(connectToOCUrl( const QString& ) ), connect( _ocWizard, SIGNAL(connectToOCUrl( const QString& ) ),
this, SLOT(slotConnectToOCUrl( const QString& ))); this, SLOT(slotConnectToOCUrl( const QString& )));
@@ -44,13 +44,12 @@ OwncloudSetupWizard::OwncloudSetupWizard( FolderMan *folderMan, Theme *theme, QO
connect( _ocWizard, SIGNAL(clearPendingRequests()), connect( _ocWizard, SIGNAL(clearPendingRequests()),
this, SLOT(slotClearPendingRequests())); this, SLOT(slotClearPendingRequests()));
_ocWizard->setWindowTitle( tr("%1 Connection Wizard").arg( theme ? theme->appNameGUI() : QLatin1String("Mirall") ) ); _ocWizard->setWindowTitle( tr("%1 Connection Wizard").arg( theme->appNameGUI() ) );
} }
OwncloudSetupWizard::~OwncloudSetupWizard() OwncloudSetupWizard::~OwncloudSetupWizard()
{ {
// delete _ocWizard; FIXME: this crashes! _ocWizard->deleteLater();
} }
OwncloudWizard *OwncloudSetupWizard::wizard() { OwncloudWizard *OwncloudSetupWizard::wizard() {
@@ -63,28 +62,37 @@ void OwncloudSetupWizard::startWizard()
MirallConfigFile cfgFile; MirallConfigFile cfgFile;
// Fill the entry fields with existing values. // Fill the entry fields with existing values.
QString url = cfgFile.ownCloudUrl(); QString url = cfgFile.ownCloudUrl();
if( !url.isEmpty() ) {
_ocWizard->setOCUrl( url );
}
QString user = cfgFile.ownCloudUser(); QString user = cfgFile.ownCloudUser();
bool configExists = !( url.isEmpty() || user.isEmpty() );
_ocWizard->setConfigExists( configExists );
if( !user.isEmpty() ) { if( !user.isEmpty() ) {
_ocWizard->setOCUser( user ); _ocWizard->setOCUser( user );
} }
if( !url.isEmpty() ) {
_ocWizard->setOCUrl( url );
}
_remoteFolder = Theme::instance()->defaultServerFolder(); _remoteFolder = Theme::instance()->defaultServerFolder();
// remoteFolder may be empty, which means / // remoteFolder may be empty, which means /
_localFolder = Theme::instance()->defaultClientFolder(); QString localFolder = Theme::instance()->defaultClientFolder();
// if its a relative path, prepend with users home dir, otherwise use as absolute path // if its a relative path, prepend with users home dir, otherwise use as absolute path
if( !_localFolder.startsWith(QLatin1Char('/')) ) { if( !localFolder.startsWith(QLatin1Char('/')) ) {
_localFolder = QDir::homePath() + QDir::separator() + Theme::instance()->defaultClientFolder(); localFolder = QDir::homePath() + QDir::separator() + Theme::instance()->defaultClientFolder();
} }
_ocWizard->setFolderNames(_localFolder, _remoteFolder); _ocWizard->setProperty("localFolder", localFolder);
_ocWizard->setRemoteFolder(_remoteFolder);
_ocWizard->setStartId(OwncloudWizard::Page_oCSetup); _ocWizard->setStartId(OwncloudWizard::Page_oCSetup);
_ocWizard->restart(); _ocWizard->restart();
// settings re-initialized in initPage must be set here after restart
_ocWizard->setMultipleFoldersExist(_folderMan->map().count() > 1);
_ocWizard->show(); _ocWizard->show();
} }
@@ -105,26 +113,61 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
// go through all folders and remove the journals if the server changed. // go through all folders and remove the journals if the server changed.
MirallConfigFile prevCfg; MirallConfigFile prevCfg;
if( prevCfg.ownCloudUrl() != cfg.ownCloudUrl() ) { QUrl prevUrl( prevCfg.ownCloudUrl() );
qDebug() << "ownCloud URL has changed, journals needs to be wiped."; QUrl newUrl( cfg.ownCloudUrl() );
_folderMan->wipeAllJournals();
bool urlHasChanged = (prevUrl.host() != newUrl.host() || prevUrl.path() != newUrl.path());
// if the user changed, its also a changed url.
if( prevCfg.ownCloudUser() != cfg.ownCloudUser() ) {
urlHasChanged = true;
qDebug() << "The User has changed, same as url change.";
} }
// save the user credentials and afterwards clear the cred store. const QString localFolder = _ocWizard->localFolder();
cfg.acceptCustomConfig(); bool acceptCfg = true;
// Now write the resulting folder definition if folder names are set. if( urlHasChanged ) {
if( !( _localFolder.isEmpty() || _remoteFolder.isEmpty() ) ) { // both variables are set. _folderMan->unloadAllFolders();
if( _folderMan ) {
_folderMan->addFolderDefinition( QLatin1String("owncloud"), Theme::instance()->appName(), bool startFromScratch = _ocWizard->field( "OCSyncFromScratch" ).toBool();
_localFolder, _remoteFolder, false ); if( startFromScratch ) {
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(_localFolder)); // first try to rename (backup) the current local dir.
} else { bool renameOk = false;
qDebug() << "WRN: Folderman is zero in Setup Wizzard."; while( !renameOk ) {
renameOk = _folderMan->startFromScratch(localFolder);
if( ! renameOk ) {
QMessageBox::StandardButton but;
but = QMessageBox::question( 0, tr("Folder rename failed"),
tr("Can't remove and back up the folder because the folder or a file in it is open in another program."
"Please close the folder or file and hit retry or cancel the setup."), QMessageBox::Retry | QMessageBox::Abort, QMessageBox::Retry);
if( but == QMessageBox::Abort ) {
renameOk = true;
acceptCfg = false;
}
}
}
}
}
// save the user credentials and afterwards clear the cred store.
if( acceptCfg ) {
cfg.acceptCustomConfig();
}
// Now write the resulting folder definition if folder names are set.
if( acceptCfg && urlHasChanged ) {
_folderMan->removeAllFolderDefinitions();
_folderMan->addFolderDefinition( QLatin1String("owncloud"), Theme::instance()->appName(),
localFolder, _remoteFolder, false );
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
} else {
// url is unchanged. Only the password was changed.
if( acceptCfg ) {
qDebug() << "Only password was changed, no changes to folder configuration.";
} else {
qDebug() << "User interrupted change of configuration.";
} }
} }
} else {
qDebug() << "WRN: Got unknown dialog result code " << result;
} }
// clear the custom config handle // clear the custom config handle
@@ -194,7 +237,7 @@ void OwncloudSetupWizard::testOwnCloudConnect()
MirallConfigFile prevCfg; MirallConfigFile prevCfg;
if( prevCfg.proxyType() != QNetworkProxy::DefaultProxy ) { if( prevCfg.proxyType() != QNetworkProxy::DefaultProxy ) {
cfgFile.setProxyType( prevCfg.proxyType(), prevCfg.proxyHostName(), prevCfg.proxyPort(), cfgFile.setProxyType( prevCfg.proxyType(), prevCfg.proxyHostName(), prevCfg.proxyPort(),
prevCfg.proxyUser(), prevCfg.proxyPassword() ); prevCfg.proxyNeedsAuth(), prevCfg.proxyUser(), prevCfg.proxyPassword() );
} }
} }
@@ -251,26 +294,27 @@ void OwncloudSetupWizard::setupLocalSyncFolder()
{ {
if( ! _folderMan ) return; if( ! _folderMan ) return;
qDebug() << "Setup local sync folder for new oC connection " << _localFolder; const QString localFolder = _ocWizard->property("localFolder").toString();
QDir fi( _localFolder ); qDebug() << "Setup local sync folder for new oC connection " << localFolder;
QDir fi( localFolder );
// FIXME: Show problems with local folder properly. // FIXME: Show problems with local folder properly.
bool localFolderOk = true; bool localFolderOk = true;
if( fi.exists() ) { if( fi.exists() ) {
// there is an existing local folder. If its non empty, it can only be synced if the // there is an existing local folder. If its non empty, it can only be synced if the
// ownCloud is newly created. // ownCloud is newly created.
_ocWizard->appendToConfigurationLog( tr("Local sync folder %1 already exists, setting it up for sync.<br/><br/>").arg(_localFolder)); _ocWizard->appendToConfigurationLog( tr("Local sync folder %1 already exists, setting it up for sync.<br/><br/>").arg(localFolder));
} else { } else {
QString res = tr("Creating local sync folder %1... ").arg(_localFolder); QString res = tr("Creating local sync folder %1... ").arg(localFolder);
if( fi.mkpath( _localFolder ) ) { if( fi.mkpath( localFolder ) ) {
Utility::setupFavLink( _localFolder ); Utility::setupFavLink( localFolder );
// FIXME: Create a local sync folder. // FIXME: Create a local sync folder.
res += tr("ok"); res += tr("ok");
} else { } else {
res += tr("failed."); res += tr("failed.");
qDebug() << "Failed to create " << fi.path(); qDebug() << "Failed to create " << fi.path();
localFolderOk = false; localFolderOk = false;
_ocWizard->displayError(tr("Could not create local folder %1").arg(_localFolder)); _ocWizard->displayError(tr("Could not create local folder %1").arg(localFolder));
} }
_ocWizard->appendToConfigurationLog( res ); _ocWizard->appendToConfigurationLog( res );
} }
@@ -305,7 +349,7 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep
qDebug() << "******** Remote folder found, all cool!"; qDebug() << "******** Remote folder found, all cool!";
} else if( errId == QNetworkReply::AuthenticationRequiredError ) { // returned if the user is wrong. } else if( errId == QNetworkReply::AuthenticationRequiredError ) { // returned if the user is wrong.
qDebug() << "******** Password is wrong!"; qDebug() << "******** Password is wrong!";
error = tr("Credentials are wrong!"); error = tr("The given credentials do not authenticate.");
ok = false; ok = false;
} else if( errId == QNetworkReply::OperationCanceledError ) { } else if( errId == QNetworkReply::OperationCanceledError ) {
// the username was wrong and ownCloudInfo was closing the request after a couple of auth tries. // the username was wrong and ownCloudInfo was closing the request after a couple of auth tries.
@@ -328,7 +372,7 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep
if( !ok ) { if( !ok ) {
_ocWizard->displayError(error); _ocWizard->displayError(error);
} else { } else {
_ocWizard->setFolderNames( _localFolder, _remoteFolder ); _ocWizard->setRemoteFolder( _remoteFolder );
} }
finalizeSetup( ok ); finalizeSetup( ok );
@@ -369,13 +413,11 @@ void OwncloudSetupWizard::slotCreateRemoteFolderFinished( QNetworkReply::Network
"<br/>Please go back and check your credentials.</p>")); "<br/>Please go back and check your credentials.</p>"));
_ocWizard->appendToConfigurationLog( tr("<p><font color=\"red\">Remote folder creation failed probably because the provided credentials are wrong.</font>" _ocWizard->appendToConfigurationLog( tr("<p><font color=\"red\">Remote folder creation failed probably because the provided credentials are wrong.</font>"
"<br/>Please go back and check your credentials.</p>")); "<br/>Please go back and check your credentials.</p>"));
_localFolder.clear();
_remoteFolder.clear(); _remoteFolder.clear();
success = false; success = false;
} else { } else {
_ocWizard->appendToConfigurationLog( tr("Remote folder %1 creation failed with error <tt>%2</tt>.").arg(_remoteFolder).arg(error)); _ocWizard->appendToConfigurationLog( tr("Remote folder %1 creation failed with error <tt>%2</tt>.").arg(_remoteFolder).arg(error));
_ocWizard->displayError( tr("Remote folder %1 creation failed with error <tt>%2</tt>.").arg(_remoteFolder).arg(error) ); _ocWizard->displayError( tr("Remote folder %1 creation failed with error <tt>%2</tt>.").arg(_remoteFolder).arg(error) );
_localFolder.clear();
_remoteFolder.clear(); _remoteFolder.clear();
success = false; success = false;
} }
@@ -388,10 +430,11 @@ void OwncloudSetupWizard::finalizeSetup( bool success )
// enable/disable the finish button. // enable/disable the finish button.
_ocWizard->enableFinishOnResultWidget(success); _ocWizard->enableFinishOnResultWidget(success);
const QString localFolder = _ocWizard->property("localFolder").toString();
if( success ) { if( success ) {
if( !(_localFolder.isEmpty() || _remoteFolder.isEmpty() )) { if( !(localFolder.isEmpty() || _remoteFolder.isEmpty() )) {
_ocWizard->appendToConfigurationLog( tr("A sync connection from %1 to remote directory %2 was set up.") _ocWizard->appendToConfigurationLog( tr("A sync connection from %1 to remote directory %2 was set up.")
.arg(_localFolder).arg(_remoteFolder)); .arg(localFolder).arg(_remoteFolder));
} }
_ocWizard->appendToConfigurationLog( QLatin1String(" ")); _ocWizard->appendToConfigurationLog( QLatin1String(" "));
_ocWizard->appendToConfigurationLog( QLatin1String("<p><font color=\"green\"><b>") _ocWizard->appendToConfigurationLog( QLatin1String("<p><font color=\"green\"><b>")

View File

@@ -95,7 +95,6 @@ private:
FolderMan *_folderMan; FolderMan *_folderMan;
QString _configHandle; QString _configHandle;
QString _localFolder;
QString _remoteFolder; QString _remoteFolder;
}; };

View File

@@ -118,7 +118,7 @@ QIcon ownCloudTheme::folderDisabledIcon( ) const
QIcon ownCloudTheme::applicationIcon( ) const QIcon ownCloudTheme::applicationIcon( ) const
{ {
return themeIcon( QLatin1String("owncloud") ); return themeIcon( QLatin1String("owncloud-icon") );
} }
QColor ownCloudTheme::wizardHeaderBackgroundColor() const QColor ownCloudTheme::wizardHeaderBackgroundColor() const

View File

@@ -15,7 +15,8 @@
#include "mirall/owncloudwizard.h" #include "mirall/owncloudwizard.h"
#include "mirall/mirallconfigfile.h" #include "mirall/mirallconfigfile.h"
#include "mirall/theme.h" #include "mirall/theme.h"
#include <QProgressIndicator.h>
#include "QProgressIndicator.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@@ -52,26 +53,23 @@ OwncloudSetupPage::OwncloudSetupPage()
_ui.setupUi(this); _ui.setupUi(this);
Theme *theme = Theme::instance(); Theme *theme = Theme::instance();
setTitle( tr("<font color=\"%1\" size=\"5\">Connect to your %2 Server</font>") setTitle( tr("<font color=\"%1\" size=\"5\">Connect to %2</font>")
.arg(theme->wizardHeaderTitleColor().name()).arg( theme->appNameGUI())); .arg(theme->wizardHeaderTitleColor().name()).arg( theme->appNameGUI()));
setSubTitle( tr("<font color=\"%1\">Enter user credentials to access your %2</font>") setSubTitle( tr("<font color=\"%1\">Enter user credentials</font>")
.arg(theme->wizardHeaderTitleColor().name()).arg(theme->appNameGUI())); .arg(theme->wizardHeaderTitleColor().name()));
connect(_ui.leUrl, SIGNAL(textChanged(QString)), SLOT(handleNewOcUrl(QString)));
registerField( QLatin1String("OCUrl"), _ui.leUrl ); registerField( QLatin1String("OCUrl"), _ui.leUrl );
registerField( QLatin1String("OCUser"), _ui.leUsername ); registerField( QLatin1String("OCUser"), _ui.leUsername );
registerField( QLatin1String("OCPasswd"), _ui.lePassword); registerField( QLatin1String("OCPasswd"), _ui.lePassword);
connect( _ui.lePassword, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged())); registerField( QLatin1String("OCSyncFromScratch"), _ui.cbSyncFromScratch);
connect( _ui.leUsername, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged()));
connect( _ui.cbAdvanced, SIGNAL(stateChanged (int)), SLOT(slotToggleAdvanced(int)));
connect( _ui.pbSelectLocalFolder, SIGNAL(clicked()), SLOT(slotSelectFolder()));
_ui.errorLabel->setVisible(true); _ui.errorLabel->setVisible(true);
_ui.advancedBox->setVisible(false); _ui.advancedBox->setVisible(false);
_progressIndi = new QProgressIndicator; _progressIndi = new QProgressIndicator;
_ui.resultLayout->addWidget( _progressIndi ); _ui.resultLayout->addWidget( _progressIndi );
_progressIndi->setVisible(false); _progressIndi->setVisible(false);
_ui.resultLayout->setEnabled(false);
// Error label // Error label
QString style = QLatin1String("border: 1px solid #eed3d7; border-radius: 5px; padding: 3px;" QString style = QLatin1String("border: 1px solid #eed3d7; border-radius: 5px; padding: 3px;"
@@ -82,20 +80,17 @@ OwncloudSetupPage::OwncloudSetupPage()
_ui.errorLabel->setWordWrap(true); _ui.errorLabel->setWordWrap(true);
_ui.errorLabel->setVisible(false); _ui.errorLabel->setVisible(false);
// ButtonGroup for
_selectiveSyncButtons = new QButtonGroup;
_selectiveSyncButtons->addButton( _ui.pbBoxMode );
_selectiveSyncButtons->addButton( _ui.pbSelectiveMode );
connect( _selectiveSyncButtons, SIGNAL(buttonClicked (QAbstractButton*)),
SLOT(slotChangedSelective(QAbstractButton*)));
_ui.selectiveSyncLabel->setVisible(false);
_ui.pbBoxMode->setVisible(false);
_ui.pbSelectiveMode->setVisible(false);
_checking = false; _checking = false;
setupCustomization(); setupCustomization();
connect(_ui.leUrl, SIGNAL(textChanged(QString)), SLOT(slotUrlChanged(QString)));
connect( _ui.leUsername, SIGNAL(textChanged(QString)), this, SLOT(slotUserChanged(QString)));
connect( _ui.lePassword, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged()));
connect( _ui.leUsername, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged()));
connect( _ui.cbAdvanced, SIGNAL(stateChanged (int)), SLOT(slotToggleAdvanced(int)));
connect( _ui.pbSelectLocalFolder, SIGNAL(clicked()), SLOT(slotSelectFolder()));
} }
OwncloudSetupPage::~OwncloudSetupPage() OwncloudSetupPage::~OwncloudSetupPage()
@@ -106,34 +101,30 @@ OwncloudSetupPage::~OwncloudSetupPage()
void OwncloudSetupPage::slotToggleAdvanced(int state) void OwncloudSetupPage::slotToggleAdvanced(int state)
{ {
_ui.advancedBox->setVisible( state == Qt::Checked ); _ui.advancedBox->setVisible( state == Qt::Checked );
wizard()->resize(wizard()->sizeHint()); slotHandleUserInput();
} QSize size = wizard()->sizeHint();
// need to substract header for some reason
size -= QSize(0, 63);
void OwncloudSetupPage::slotChangedSelective(QAbstractButton* button) wizard()->setMinimumSize(size);
{ wizard()->resize(size);
if( button = _ui.pbBoxMode ) {
// box mode - sync the entire oC
} else {
// content mode, select folder list.
}
} }
void OwncloudSetupPage::setOCUser( const QString & user ) void OwncloudSetupPage::setOCUser( const QString & user )
{ {
if( _ui.leUsername->text().isEmpty() ) { _ocUser = user;
_ui.leUsername->setText(user); _ui.leUsername->setText(user);
}
} }
void OwncloudSetupPage::setServerUrl( const QString& newUrl ) void OwncloudSetupPage::setServerUrl( const QString& newUrl )
{ {
QString url( newUrl ); _oCUrl = newUrl;
if( url.isEmpty() ) { if( _oCUrl.isEmpty() ) {
_ui.leUrl->clear(); _ui.leUrl->clear();
return; return;
} }
_ui.leUrl->setText( url ); _ui.leUrl->setText( _oCUrl );
} }
void OwncloudSetupPage::setupCustomization() void OwncloudSetupPage::setupCustomization()
@@ -157,19 +148,27 @@ void OwncloudSetupPage::setupCustomization()
QString fixUrl = theme->overrideServerUrl(); QString fixUrl = theme->overrideServerUrl();
if( !fixUrl.isEmpty() ) { if( !fixUrl.isEmpty() ) {
_ui.label_2->hide();
setServerUrl( fixUrl ); setServerUrl( fixUrl );
_ui.leUrl->setEnabled( false ); _ui.leUrl->setEnabled( false );
_ui.leUrl->hide(); _ui.leUrl->hide();
} }
} }
// slot hit from textChanged of the url entry field. void OwncloudSetupPage::slotUserChanged(const QString& user )
void OwncloudSetupPage::handleNewOcUrl(const QString& ocUrl)
{ {
QString url = ocUrl; slotHandleUserInput();
int len = 0; }
bool visible = false;
// slot hit from textChanged of the url entry field.
void OwncloudSetupPage::slotUrlChanged(const QString& ocUrl)
{
slotHandleUserInput();
#if 0 #if 0
QString url = ocUrl;
bool visible = false;
if (url.startsWith(QLatin1String("https://"))) { if (url.startsWith(QLatin1String("https://"))) {
_ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-high.png")); _ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-high.png"));
_ui.urlLabel->setToolTip(tr("This url is secure. You can use it.")); _ui.urlLabel->setToolTip(tr("This url is secure. You can use it."));
@@ -181,7 +180,6 @@ void OwncloudSetupPage::handleNewOcUrl(const QString& ocUrl)
visible = true; visible = true;
} }
#endif #endif
} }
bool OwncloudSetupPage::isComplete() const bool OwncloudSetupPage::isComplete() const
@@ -196,6 +194,107 @@ void OwncloudSetupPage::initializePage()
{ {
_connected = false; _connected = false;
_checking = false; _checking = false;
_multipleFoldersExist = false;
// call to init label
slotHandleUserInput();
if( _configExists ) {
_ui.lePassword->setFocus();
} else {
_ui.leUrl->setFocus();
}
}
bool OwncloudSetupPage::urlHasChanged()
{
bool change = false;
const QChar slash('/');
QUrl currentUrl( url() );
QUrl initialUrl( _oCUrl );
QString currentPath = currentUrl.path();
QString initialPath = initialUrl.path();
// add a trailing slash.
if( ! currentPath.endsWith( slash )) currentPath += slash;
if( ! initialPath.endsWith( slash )) initialPath += slash;
if( currentUrl.host() != initialUrl.host() ||
currentPath != initialPath ) {
change = true;
}
if( !change) { // no change yet, check the user.
QString user = _ui.leUsername->text().simplified();
if( user != _ocUser ) change = true;
}
return change;
}
// Called if the user changes the user- or url field. Adjust the texts and
// evtl. warnings on the dialog.
void OwncloudSetupPage::slotHandleUserInput()
{
// if the url has not changed, return.
if( ! urlHasChanged() ) {
// disable the advanced button as nothing has changed.
_ui.cbAdvanced->setEnabled(false);
_ui.advancedBox->setEnabled(false);
} else {
// Enable advanced stuff for new connection configuration.
_ui.cbAdvanced->setEnabled(true);
_ui.advancedBox->setEnabled(true);
}
const QString locFolder = localFolder();
// check if the local folder exists. If so, and if its not empty, show a warning.
QDir dir( locFolder );
QStringList entries = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
QString t;
if( !urlHasChanged() && _configExists ) {
// This is the password change mode: No change to the url and a config
// to an ownCloud exists.
t = tr("Change the Password for your configured account.");
} else {
// Complete new setup.
_ui.pbSelectLocalFolder->setText(QDir::toNativeSeparators(locFolder));
if( _remoteFolder.isEmpty() || _remoteFolder == QLatin1String("/") ) {
t = tr("Your entire account will be synced to the local folder '%1'.")
.arg(QDir::toNativeSeparators(locFolder));
} else {
t = tr("%1 folder '%2' is synced to local folder '%3'")
.arg(Theme::instance()->appName()).arg(_remoteFolder)
.arg(QDir::toNativeSeparators(locFolder));
}
if ( _multipleFoldersExist ) {
t += tr("<p><small><strong>Warning:</strong> You currently have multiple folders "
"configured. If you continue with the current settings, the folder configurations "
"will be discarded and a single root folder sync will be created!</small></p>");
}
if( entries.count() > 0) {
// the directory is not empty
if (!_ui.cbAdvanced->isChecked()) {
t += tr("<p><small><strong>Warning:</strong> The local directory is not empty. "
"Pick a resolution in the advanced settings!</small></p>");
}
_ui.resolutionWidget->setVisible(true);
} else {
// the dir is empty, which means that there is no problem.
_ui.resolutionWidget->setVisible(false);
}
}
_ui.syncModeLabel->setText(t);
_ui.syncModeLabel->setFixedHeight(_ui.syncModeLabel->sizeHint().height());
} }
int OwncloudSetupPage::nextId() const int OwncloudSetupPage::nextId() const
@@ -209,9 +308,16 @@ QString OwncloudSetupPage::url() const
return url; return url;
} }
QString OwncloudSetupPage::localFolder() const
{
QString folder = wizard()->property("localFolder").toString();
return folder;
}
void OwncloudSetupPage::setConnected( bool comp ) void OwncloudSetupPage::setConnected( bool comp )
{ {
_connected = comp; _connected = comp;
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(false); _progressIndi->setVisible(false);
_progressIndi->stopAnimation(); _progressIndi->stopAnimation();
} }
@@ -223,6 +329,7 @@ bool OwncloudSetupPage::validatePage()
if( ! _connected) { if( ! _connected) {
setErrorString(QString::null); setErrorString(QString::null);
_checking = true; _checking = true;
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(true); _progressIndi->setVisible(true);
_progressIndi->startAnimation(); _progressIndi->startAnimation();
emit completeChanged(); emit completeChanged();
@@ -253,40 +360,26 @@ void OwncloudSetupPage::setErrorString( const QString& err )
void OwncloudSetupPage::stopSpinner() void OwncloudSetupPage::stopSpinner()
{ {
// _ui.addressLayout->removeWidget( _progressIndi ); _ui.resultLayout->setEnabled(false);
_progressIndi->setVisible(false); _progressIndi->setVisible(false);
_progressIndi->stopAnimation(); _progressIndi->stopAnimation();
} }
OwncloudSetupPage::SyncMode OwncloudSetupPage::syncMode() OwncloudSetupPage::SyncMode OwncloudSetupPage::syncMode()
{ {
if( _selectiveSyncButtons->checkedButton() &&
_selectiveSyncButtons->checkedButton() == _ui.pbSelectiveMode ) {
return SelectiveMode;
}
return BoxMode; return BoxMode;
} }
void OwncloudSetupPage::setFolderNames( const QString& localFolder, const QString& remoteFolder ) void OwncloudSetupPage::setRemoteFolder( const QString& remoteFolder )
{ {
_ui.pbSelectLocalFolder->setText(localFolder); if( !remoteFolder.isEmpty() ) {
if( !remoteFolder.isEmpty() )
_remoteFolder = remoteFolder; _remoteFolder = remoteFolder;
QString t;
if( _remoteFolder.isEmpty() || _remoteFolder == QLatin1String("/") ) {
t = tr("Your entire account will be synced to the local folder '%1'").arg(localFolder);
} else {
t = tr("ownCloud folder '%1' is synced to local folder '%2'").arg(_remoteFolder).arg(localFolder);
} }
_ui.syncModeLabel->setText(t);
} }
QString OwncloudSetupPage::selectedLocalFolder() const void OwncloudSetupPage::setMultipleFoldersExist(bool exist)
{ {
return _ui.pbSelectLocalFolder->text(); _multipleFoldersExist = exist;
} }
void OwncloudSetupPage::slotSelectFolder() void OwncloudSetupPage::slotSelectFolder()
@@ -294,7 +387,9 @@ void OwncloudSetupPage::slotSelectFolder()
QString dir = QFileDialog::getExistingDirectory(0, tr("Local Sync Folder"), QDir::homePath()); QString dir = QFileDialog::getExistingDirectory(0, tr("Local Sync Folder"), QDir::homePath());
if( !dir.isEmpty() ) { if( !dir.isEmpty() ) {
setFolderNames(dir); _ui.pbSelectLocalFolder->setText(dir);
wizard()->setProperty("localFolder", dir);
slotHandleUserInput();
} }
} }
@@ -304,6 +399,18 @@ OwncloudSetupPage::SyncMode OwncloudWizard::syncMode()
return OwncloudSetupPage::BoxMode; return OwncloudSetupPage::BoxMode;
} }
void OwncloudWizard::setMultipleFoldersExist(bool exist)
{
_setupPage->setMultipleFoldersExist(exist);
}
void OwncloudSetupPage::setConfigExists( bool config )
{
_configExists = config;
setSubTitle( tr("<font color=\"%1\">Change your user credentials</font>")
.arg(Theme::instance()->wizardHeaderTitleColor().name()));
}
// ====================================================================== // ======================================================================
OwncloudWizardResultPage::OwncloudWizardResultPage() OwncloudWizardResultPage::OwncloudWizardResultPage()
@@ -314,8 +421,8 @@ OwncloudWizardResultPage::OwncloudWizardResultPage()
Theme *theme = Theme::instance(); Theme *theme = Theme::instance();
setTitle( tr("<font color=\"%1\" size=\"5\">Everything set up!</font>") setTitle( tr("<font color=\"%1\" size=\"5\">Everything set up!</font>")
.arg(theme->wizardHeaderTitleColor().name())); .arg(theme->wizardHeaderTitleColor().name()));
setSubTitle( tr("<font color=\"%1\">Enter user credentials to access your %2</font>") // required to show header in QWizard's modern style
.arg(theme->wizardHeaderTitleColor().name()).arg(theme->appNameGUI())); setSubTitle( QLatin1String(" ") );
_ui.pbOpenLocal->setText("Open local folder"); _ui.pbOpenLocal->setText("Open local folder");
_ui.pbOpenServer->setText(tr("Open %1").arg(Theme::instance()->appNameGUI())); _ui.pbOpenServer->setText(tr("Open %1").arg(Theme::instance()->appNameGUI()));
@@ -327,8 +434,8 @@ OwncloudWizardResultPage::OwncloudWizardResultPage()
_ui.pbOpenLocal->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); _ui.pbOpenLocal->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
// _ui.pbOpenServer->setIcon(QIcon(":/mirall/resources/owncloud_logo_blue.png")); QIcon appIcon = theme->applicationIcon();
_ui.pbOpenServer->setIcon(theme->applicationIcon().pixmap(48)); _ui.pbOpenServer->setIcon(appIcon.pixmap(48));
_ui.pbOpenServer->setText(tr("Open %1").arg(theme->appNameGUI())); _ui.pbOpenServer->setText(tr("Open %1").arg(theme->appNameGUI()));
_ui.pbOpenServer->setIconSize(QSize(48, 48)); _ui.pbOpenServer->setIconSize(QSize(48, 48));
_ui.pbOpenServer->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); _ui.pbOpenServer->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
@@ -351,19 +458,25 @@ bool OwncloudWizardResultPage::isComplete() const
return _complete; return _complete;
} }
void OwncloudWizardResultPage::setFolderNames( const QString& localFolder, const QString& remoteFolder ) void OwncloudWizardResultPage::initializePage()
{ {
_localFolder = localFolder; const QString localFolder = wizard()->property("localFolder").toString();
QString text; QString text;
if( remoteFolder == QLatin1String("/") || if( _remoteFolder == QLatin1String("/") || _remoteFolder.isEmpty() ) {
remoteFolder.isEmpty() ) { text = tr("Your entire account is synced to the local folder <i>%1</i>")
text = tr("Your entire account is synced to the local folder <i>%1</i>").arg(localFolder); .arg(QDir::toNativeSeparators(localFolder));
} else { } else {
text = tr("ownCloud folder <i>%1</i> is synced to local folder <i>%2</i>").arg(remoteFolder).arg(localFolder); text = tr("ownCloud folder <i>%1</i> is synced to local folder <i>%2</i>")
.arg(_remoteFolder).arg(QDir::toNativeSeparators(localFolder));
} }
_ui.localFolderLabel->setText( text ); _ui.localFolderLabel->setText( text );
} }
void OwncloudWizardResultPage::setRemoteFolder(const QString &remoteFolder)
{
_remoteFolder = remoteFolder;
}
void OwncloudWizardResultPage::setupCustomization() void OwncloudWizardResultPage::setupCustomization()
{ {
@@ -382,7 +495,8 @@ void OwncloudWizardResultPage::setupCustomization()
*/ */
OwncloudWizard::OwncloudWizard(QWidget *parent) OwncloudWizard::OwncloudWizard(QWidget *parent)
: QWizard(parent) : QWizard(parent),
_configExists(false)
{ {
_setupPage = new OwncloudSetupPage; _setupPage = new OwncloudSetupPage;
_resultPage = new OwncloudWizardResultPage; _resultPage = new OwncloudWizardResultPage;
@@ -409,6 +523,11 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
setSubTitleFormat(Qt::RichText); setSubTitleFormat(Qt::RichText);
} }
QString OwncloudWizard::localFolder() const
{
return(_setupPage->localFolder());
}
QString OwncloudWizard::ocUrl() const QString OwncloudWizard::ocUrl() const
{ {
QString url = field("OCUrl").toString().simplified(); QString url = field("OCUrl").toString().simplified();
@@ -420,10 +539,10 @@ void OwncloudWizard::enableFinishOnResultWidget(bool enable)
_resultPage->setComplete(enable); _resultPage->setComplete(enable);
} }
void OwncloudWizard::setFolderNames( const QString& localFolder, const QString& remoteFolder ) void OwncloudWizard::setRemoteFolder( const QString& remoteFolder )
{ {
_setupPage->setFolderNames( localFolder, remoteFolder ); _setupPage->setRemoteFolder( remoteFolder );
_resultPage->setFolderNames( localFolder, remoteFolder ); _resultPage->setRemoteFolder( remoteFolder );
} }
void OwncloudWizard::showConnectInfo( const QString& msg ) void OwncloudWizard::showConnectInfo( const QString& msg )
@@ -471,7 +590,6 @@ void OwncloudWizard::appendToConfigurationLog( const QString& msg, LogType type
void OwncloudWizard::setOCUrl( const QString& url ) void OwncloudWizard::setOCUrl( const QString& url )
{ {
_oCUrl = url;
_setupPage->setServerUrl( url ); _setupPage->setServerUrl( url );
} }
@@ -481,9 +599,21 @@ void OwncloudWizard::setOCUser( const QString& user )
_setupPage->setOCUser( user ); _setupPage->setOCUser( user );
} }
void OwncloudWizard::setConfigExists( bool config )
{
_configExists = config;
_setupPage->setConfigExists( config );
}
bool OwncloudWizard::configExists()
{
return _configExists;
}
void OwncloudWizardResultPage::slotOpenLocal() void OwncloudWizardResultPage::slotOpenLocal()
{ {
QDesktopServices::openUrl(QUrl(_localFolder)); const QString localFolder = wizard()->property("localFolder").toString();
QDesktopServices::openUrl(QUrl::fromLocalFile(localFolder));
} }
void OwncloudWizardResultPage::slotOpenServer() void OwncloudWizardResultPage::slotOpenServer()
@@ -493,4 +623,5 @@ void OwncloudWizardResultPage::slotOpenServer()
QDesktopServices::openUrl(url); QDesktopServices::openUrl(url);
} }
} // end namespace } // end namespace

View File

@@ -50,31 +50,46 @@ public:
void setAllowPasswordStorage( bool ); void setAllowPasswordStorage( bool );
bool validatePage(); bool validatePage();
QString url() const; QString url() const;
QString localFolder() const;
void setConnected(bool complete); void setConnected(bool complete);
QString selectedLocalFolder() const; void setRemoteFolder( const QString& remoteFolder);
void setFolderNames( const QString&, const QString& remoteFolder = QString::null); void setMultipleFoldersExist( bool exist );
SyncMode syncMode(); SyncMode syncMode();
public slots: public slots:
void setErrorString( const QString& ); void setErrorString( const QString& );
void setConfigExists( bool );
void stopSpinner(); void stopSpinner();
protected slots: protected slots:
void handleNewOcUrl(const QString& ocUrl); void slotUrlChanged(const QString&);
void slotUserChanged(const QString&);
void setupCustomization(); void setupCustomization();
void slotToggleAdvanced(int state); void slotToggleAdvanced(int state);
void slotChangedSelective(QAbstractButton*);
void slotSelectFolder(); void slotSelectFolder();
signals: signals:
void connectToOCUrl( const QString& ); void connectToOCUrl( const QString& );
protected:
void updateFoldersInfo();
private slots:
void slotHandleUserInput();
private: private:
bool urlHasChanged();
Ui_OwncloudSetupPage _ui; Ui_OwncloudSetupPage _ui;
QString _oCUrl; QString _oCUrl;
QString _ocUser;
bool _connected; bool _connected;
bool _checking; bool _checking;
bool _configExists;
bool _multipleFoldersExist;
QProgressIndicator *_progressIndi; QProgressIndicator *_progressIndi;
QButtonGroup *_selectiveSyncButtons; QButtonGroup *_selectiveSyncButtons;
QString _remoteFolder; QString _remoteFolder;
@@ -95,21 +110,25 @@ public:
LogParagraph LogParagraph
}; };
OwncloudWizard(QWidget *parent = 0L); OwncloudWizard(QWidget *parent = 0);
void setOCUrl( const QString& ); void setOCUrl( const QString& );
void setOCUser( const QString& ); void setOCUser( const QString& );
void setupCustomMedia( QVariant, QLabel* ); void setupCustomMedia( QVariant, QLabel* );
QString ocUrl() const; QString ocUrl() const;
QString localFolder() const;
void enableFinishOnResultWidget(bool enable); void enableFinishOnResultWidget(bool enable);
void displayError( const QString& ); void displayError( const QString& );
OwncloudSetupPage::SyncMode syncMode(); OwncloudSetupPage::SyncMode syncMode();
void setMultipleFoldersExist( bool );
void setConfigExists( bool );
bool configExists();
public slots: public slots:
void setFolderNames( const QString&, const QString& ); void setRemoteFolder( const QString& );
void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph ); void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph );
void slotCurrentPageChanged( int ); void slotCurrentPageChanged( int );
@@ -125,9 +144,9 @@ private:
OwncloudWizardResultPage *_resultPage; OwncloudWizardResultPage *_resultPage;
QString _configFile; QString _configFile;
QString _oCUrl;
QString _oCUser; QString _oCUser;
QStringList _setupLog; QStringList _setupLog;
bool _configExists;
}; };
@@ -146,10 +165,11 @@ public:
~OwncloudWizardResultPage(); ~OwncloudWizardResultPage();
bool isComplete() const; bool isComplete() const;
void initializePage();
void setRemoteFolder( const QString& remoteFolder);
public slots: public slots:
void setComplete(bool complete); void setComplete(bool complete);
void setFolderNames( const QString&, const QString& );
protected slots: protected slots:
void slotOpenLocal(); void slotOpenLocal();
@@ -160,6 +180,7 @@ protected:
private: private:
QString _localFolder; QString _localFolder;
QString _remoteFolder;
bool _complete; bool _complete;
Ui_OwncloudWizardResultPage _ui; Ui_OwncloudWizardResultPage _ui;

View File

@@ -35,21 +35,33 @@ Mirall::ProxyDialog::ProxyDialog( QWidget* parent )
// load current proxy settings // load current proxy settings
Mirall::MirallConfigFile cfgFile; Mirall::MirallConfigFile cfgFile;
if (cfgFile.proxyType() == QNetworkProxy::NoProxy) switch (cfgFile.proxyType()) {
case QNetworkProxy::NoProxy:
noProxyRadioButton->setChecked(true); noProxyRadioButton->setChecked(true);
if (cfgFile.proxyType() == QNetworkProxy::DefaultProxy) break;
case QNetworkProxy::DefaultProxy:
systemProxyRadioButton->setChecked(true); systemProxyRadioButton->setChecked(true);
if (cfgFile.proxyType() == QNetworkProxy::HttpProxy) break;
{ case QNetworkProxy::Socks5Proxy:
cbSocks->setChecked(true);
// fall through
case QNetworkProxy::HttpProxy:
case QNetworkProxy::HttpCachingProxy:
manualProxyRadioButton->setChecked(true); manualProxyRadioButton->setChecked(true);
hostLineEdit->setText(cfgFile.proxyHostName()); break;
portSpinBox->setValue(cfgFile.proxyPort()); default:
if (!cfgFile.proxyUser().isEmpty()) break;
{ }
authRequiredcheckBox->setChecked(true);
userLineEdit->setText(cfgFile.proxyUser()); hostLineEdit->setText(cfgFile.proxyHostName());
passwordLineEdit->setText(cfgFile.proxyPassword()); int port = cfgFile.proxyPort();
} if (port == 0) port = 8080;
portSpinBox->setValue(port);
if (!cfgFile.proxyUser().isEmpty())
{
authRequiredcheckBox->setChecked(true);
userLineEdit->setText(cfgFile.proxyUser());
passwordLineEdit->setText(cfgFile.proxyPassword());
} }
} }
@@ -67,18 +79,14 @@ void Mirall::ProxyDialog::saveSettings()
} }
if (manualProxyRadioButton->isChecked()) if (manualProxyRadioButton->isChecked())
{ {
if (authRequiredcheckBox->isChecked()) int proxyType = cbSocks->isChecked() ? QNetworkProxy::Socks5Proxy
{ : QNetworkProxy::HttpProxy;
QString user = userLineEdit->text(); QString user = userLineEdit->text();
QString pass = passwordLineEdit->text(); QString pass = passwordLineEdit->text();
cfgFile.setProxyType(QNetworkProxy::HttpProxy, hostLineEdit->text(), cfgFile.setProxyType(proxyType, hostLineEdit->text(),
portSpinBox->value(), user, pass); portSpinBox->value(),
} authRequiredcheckBox->isChecked(),
else user, pass);
{
cfgFile.setProxyType(QNetworkProxy::HttpProxy, hostLineEdit->text(),
portSpinBox->value(), QString::null, QString::null);
}
} }
} }

View File

@@ -6,38 +6,15 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>465</width> <width>405</width>
<height>291</height> <height>319</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Proxy Settings</string> <string>Proxy Settings</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item row="1" column="0"> <item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@@ -76,18 +53,82 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy"> <item row="0" column="0">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum> <widget class="QLabel" name="hostLabel">
</property> <property name="text">
<property name="verticalSpacing"> <string>Host</string>
<number>6</number> </property>
</property> </widget>
<property name="leftMargin"> </item>
<number>40</number> <item row="0" column="1">
</property> <widget class="QLineEdit" name="hostLineEdit">
<property name="topMargin"> <property name="maximumSize">
<number>0</number> <size>
</property> <width>300</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="portLabel">
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="portSpinBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>8080</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbSocks">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use as SOCKSv5 proxy</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="authRequiredcheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Proxy server requires password</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="proxyUserLabel"> <widget class="QLabel" name="proxyUserLabel">
<property name="enabled"> <property name="enabled">
@@ -143,70 +184,34 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="portLabel">
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="hostLabel">
<property name="text">
<string>Host</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="hostLineEdit">
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="authRequiredcheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Proxy server requires password</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="portSpinBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>8080</number>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@@ -64,40 +64,33 @@ FolderViewDelegate::~FolderViewDelegate()
QSize FolderViewDelegate::sizeHint(const QStyleOptionViewItem & option , QSize FolderViewDelegate::sizeHint(const QStyleOptionViewItem & option ,
const QModelIndex & index) const const QModelIndex & index) const
{ {
int w = 0; Q_UNUSED(option)
QFont aliasFont = option.font;
QString p = qvariant_cast<QString>(index.data(FolderPathRole)); QFont font = option.font;
QFont aliasFont = QApplication::font();
QFont font = QApplication::font();
aliasFont.setPointSize( font.pointSize() +2 ); aliasFont.setPointSize( font.pointSize() +2 );
QFontMetrics fm(font); QFontMetrics fm(font);
QFontMetrics aliasFm(aliasFont); QFontMetrics aliasFm(aliasFont);
int margin = aliasFm.height()/2; int aliasMargin = aliasFm.height()/2;
int margin = fm.height()/4;
w = 8 + fm.boundingRect( p ).width();
// calc height // calc height
int h = margin; // margin to top int h = aliasMargin; // margin to top
h += aliasFm.height(); // alias h += aliasFm.height(); // alias
h += fm.height()/2; // between alias and local path h += margin; // between alias and local path
h += fm.height(); // local path h += fm.height(); // local path
h += fm.height()/2; // between local and remote path h += margin; // between local and remote path
h += fm.height(); // remote path h += fm.height(); // remote path
h += margin; // bottom margin h += aliasMargin; // bottom margin
int minHeight = 48 + margin + margin; // icon + margins
if( h < minHeight ) h = minHeight;
// add some space to show an error condition. // add some space to show an error condition.
if( ! qvariant_cast<QString>(index.data(FolderErrorMsg)).isEmpty() ) { if( ! qvariant_cast<QString>(index.data(FolderErrorMsg)).isEmpty() ) {
h += margin+fm.height(); h += aliasMargin*2+fm.height();
} }
return QSize( w, h ); return QSize( 0, h);
} }
void FolderViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, void FolderViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
@@ -107,8 +100,8 @@ void FolderViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
painter->save(); painter->save();
QFont aliasFont = QApplication::font(); QFont aliasFont = option.font;
QFont subFont = QApplication::font(); QFont subFont = option.font;
QFont errorFont = subFont; QFont errorFont = subFont;
//font.setPixelSize(font.weight()+); //font.setPixelSize(font.weight()+);
@@ -117,10 +110,11 @@ void FolderViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
QFontMetrics subFm( subFont ); QFontMetrics subFm( subFont );
QFontMetrics aliasFm( aliasFont ); QFontMetrics aliasFm( aliasFont );
int margin = aliasFm.height()/2;
QIcon folderIcon = qvariant_cast<QIcon>(index.data(FolderIconRole)); int aliasMargin = aliasFm.height()/2;
QIcon statusIcon = qvariant_cast<QIcon>(index.data(FolderStatusIcon)); int margin = subFm.height()/4;
QIcon statusIcon = qvariant_cast<QIcon>(index.data(FolderStatusIconRole));
QString aliasText = qvariant_cast<QString>(index.data(FolderAliasRole)); QString aliasText = qvariant_cast<QString>(index.data(FolderAliasRole));
QString pathText = qvariant_cast<QString>(index.data(FolderPathRole)); QString pathText = qvariant_cast<QString>(index.data(FolderPathRole));
QString remotePath = qvariant_cast<QString>(index.data(FolderSecondPathRole)); QString remotePath = qvariant_cast<QString>(index.data(FolderSecondPathRole));
@@ -130,72 +124,80 @@ void FolderViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
bool syncEnabled = index.data(FolderSyncEnabled).toBool(); bool syncEnabled = index.data(FolderSyncEnabled).toBool();
// QString syncStatus = syncEnabled? tr( "Enabled" ) : tr( "Disabled" ); // QString syncStatus = syncEnabled? tr( "Enabled" ) : tr( "Disabled" );
QSize iconsize(48, 48); // = icon.actualSize(option.decorationSize);
QRect aliasRect = option.rect;
QRect iconRect = option.rect; QRect iconRect = option.rect;
QRect aliasRect = option.rect;
iconRect.setLeft( margin ); iconRect.setLeft( aliasMargin );
iconRect.setWidth( 48 ); iconRect.setTop( iconRect.top() + aliasMargin ); // (iconRect.height()-iconsize.height())/2);
iconRect.setTop( iconRect.top() + margin ); // (iconRect.height()-iconsize.height())/2);
QRect statusRect = iconRect; // local directory box
statusRect.setLeft( option.rect.right() - margin - 48 ); aliasRect.setTop(aliasRect.top() + aliasMargin );
statusRect.setRight( option.rect.right() - margin ); aliasRect.setBottom(aliasRect.top() + aliasFm.height());
aliasRect.setRight(aliasRect.right() - aliasMargin );
aliasRect.setLeft(iconRect.right()+margin);
aliasRect.setTop(aliasRect.top() + aliasFm.height()/2 );
aliasRect.setBottom(aliasRect.top()+subFm.height());
// local directory box // local directory box
QRect localPathRect = aliasRect; QRect localPathRect = aliasRect;
localPathRect.setTop(aliasRect.bottom() + margin / 3); localPathRect.setTop(aliasRect.bottom() + margin );
localPathRect.setBottom(localPathRect.top()+subFm.height()); localPathRect.setBottom(localPathRect.top() + subFm.height());
// remote directory box // remote directory box
QRect remotePathRect = localPathRect; QRect remotePathRect = localPathRect;
remotePathRect.setTop( localPathRect.bottom() + subFm.height()/2 ); remotePathRect.setTop( localPathRect.bottom() + margin );
remotePathRect.setBottom( remotePathRect.top() + subFm.height()); remotePathRect.setBottom( remotePathRect.top() + subFm.height());
iconRect.setBottom(remotePathRect.bottom()); iconRect.setBottom(remotePathRect.bottom());
iconRect.setWidth(iconRect.height());
//painter->drawPixmap(QPoint(iconRect.right()/2,iconRect.top()/2),icon.pixmap(iconsize.width(),iconsize.height())); int nextToIcon = iconRect.right()+aliasMargin;
if( syncEnabled ) { aliasRect.setLeft(nextToIcon);
painter->drawPixmap(QPoint(iconRect.left(),iconRect.top()), folderIcon.pixmap(iconsize.width(),iconsize.height())); localPathRect.setLeft(nextToIcon);
remotePathRect.setLeft(nextToIcon);
int iconSize = iconRect.width();
QPixmap pm = statusIcon.pixmap(iconSize, iconSize, syncEnabled ? QIcon::Normal : QIcon::Disabled );
painter->drawPixmap(QPoint(iconRect.left(), iconRect.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
&& !Application::style()->inherits("QWindowsVistaStyle")) {
painter->setPen(option.palette.color(QPalette::HighlightedText));
} else { } else {
painter->drawPixmap(QPoint(iconRect.left(),iconRect.top()), folderIcon.pixmap(iconsize.width(),iconsize.height(), QIcon::Disabled )); painter->setPen(option.palette.color(QPalette::Text));
} }
QString elidedAlias = aliasFm.elidedText(aliasText, Qt::ElideRight, aliasRect.width());
painter->drawPixmap(QPoint(statusRect.left(), statusRect.top()), statusIcon.pixmap(48,48));
painter->setFont(aliasFont); painter->setFont(aliasFont);
painter->drawText(aliasRect, aliasText); painter->drawText(aliasRect, elidedAlias);
painter->setFont(subFont); painter->setFont(subFont);
painter->drawText(localPathRect.left(),localPathRect.top()+17, pathText); QString elidedPathText = subFm.elidedText(pathText, Qt::ElideMiddle, localPathRect.width());
painter->drawText(remotePathRect, tr("Remote path: %1").arg(remotePath)); painter->drawText(localPathRect, elidedPathText);
QString elidedRemotePathText = subFm.elidedText(tr("Remote path: %1").arg(remotePath),
Qt::ElideMiddle, remotePathRect.width());
painter->drawText(remotePathRect, elidedRemotePathText);
// paint an error overlay if there is an error string // paint an error overlay if there is an error string
if( !errorText.isEmpty() ) { if( !errorText.isEmpty() ) {
QRect errorRect = localPathRect; QRect errorRect = localPathRect;
errorRect.setLeft( iconRect.left()); errorRect.setLeft( iconRect.left());
errorRect.setTop( iconRect.bottom()+subFm.height()/2 ); errorRect.setTop( iconRect.bottom()+subFm.height()/2 );
errorRect.setHeight(subFm.height()+margin); errorRect.setHeight(subFm.height()+aliasMargin);
errorRect.setRight( statusRect.right() ); errorRect.setRight( option.rect.right()-aliasMargin );
painter->setBrush( QColor(0xbb, 0x4d, 0x4d) ); painter->setBrush( QColor(0xbb, 0x4d, 0x4d) );
painter->setPen( QColor(0xaa, 0xaa, 0xaa)); painter->setPen( QColor(0xaa, 0xaa, 0xaa));
painter->drawRoundedRect( errorRect, 4, 4 ); painter->drawRoundedRect( errorRect, 4, 4 );
QIcon warnIcon(":/mirall/resources/warning-16"); QIcon warnIcon(":/mirall/resources/warning-16");
painter->drawPixmap( QPoint(errorRect.left()+2, errorRect.top()+2), warnIcon.pixmap(QSize(16,16))); QPoint warnPos(errorRect.left()+aliasMargin/2, errorRect.top()+aliasMargin/2);
painter->drawPixmap( warnPos, warnIcon.pixmap(QSize(16,16)));
painter->setPen( Qt::white ); painter->setPen( Qt::white );
painter->setFont(errorFont); painter->setFont(errorFont);
QRect errorTextRect = errorRect; QRect errorTextRect = errorRect;
errorTextRect.setLeft( errorTextRect.left()+margin/2 +16); errorTextRect.setLeft( errorTextRect.left()+aliasMargin +16);
errorTextRect.setTop( errorTextRect.top()+margin/2 ); errorTextRect.setTop( errorTextRect.top()+aliasMargin/2 );
int linebreak = errorText.indexOf(QLatin1String("<br")); int linebreak = errorText.indexOf(QLatin1String("<br"));
QString eText = errorText; QString eText = errorText;
@@ -370,7 +372,7 @@ void StatusDialog::folderToModelItem( QStandardItem *item, Folder *f )
if( ! item || !f ) return; if( ! item || !f ) return;
QIcon icon = _theme->folderIcon( f->backend() ); QIcon icon = _theme->folderIcon( f->backend() );
item->setData( icon, FolderViewDelegate::FolderIconRole ); item->setData( icon, FolderViewDelegate::FolderStatusIconRole );
item->setData( f->nativePath(), FolderViewDelegate::FolderPathRole ); item->setData( f->nativePath(), FolderViewDelegate::FolderPathRole );
item->setData( f->secondPath(), FolderViewDelegate::FolderSecondPathRole ); item->setData( f->secondPath(), FolderViewDelegate::FolderSecondPathRole );
item->setData( f->alias(), FolderViewDelegate::FolderAliasRole ); item->setData( f->alias(), FolderViewDelegate::FolderAliasRole );
@@ -383,9 +385,9 @@ void StatusDialog::folderToModelItem( QStandardItem *item, Folder *f )
item->setData( _theme->statusHeaderText( status ), Qt::ToolTipRole ); item->setData( _theme->statusHeaderText( status ), Qt::ToolTipRole );
if( f->syncEnabled() ) { if( f->syncEnabled() ) {
item->setData( _theme->syncStateIcon( status ), FolderViewDelegate::FolderStatusIcon ); item->setData( _theme->syncStateIcon( status ), FolderViewDelegate::FolderStatusIconRole );
} else { } else {
item->setData( _theme->folderDisabledIcon( ), FolderViewDelegate::FolderStatusIcon ); // size 48 before item->setData( _theme->folderDisabledIcon( ), FolderViewDelegate::FolderStatusIconRole ); // size 48 before
} }
item->setData( _theme->statusHeaderText( status ), FolderViewDelegate::FolderStatus ); item->setData( _theme->statusHeaderText( status ), FolderViewDelegate::FolderStatus );
item->setData( errors, FolderViewDelegate::FolderErrorMsg ); item->setData( errors, FolderViewDelegate::FolderErrorMsg );

View File

@@ -45,15 +45,14 @@ class FolderViewDelegate : public QStyledItemDelegate
FolderViewDelegate(); FolderViewDelegate();
virtual ~FolderViewDelegate(); virtual ~FolderViewDelegate();
enum datarole { FolderAliasRole = Qt::UserRole + 100, enum datarole { FolderAliasRole = Qt::UserRole + 100,
FolderPathRole = Qt::UserRole + 101, FolderPathRole,
FolderSecondPathRole = Qt::UserRole + 102, FolderSecondPathRole,
FolderIconRole = Qt::UserRole + 103, FolderRemotePath,
FolderRemotePath = Qt::UserRole + 104, FolderStatus,
FolderStatus = Qt::UserRole + 105, FolderErrorMsg,
FolderErrorMsg = Qt::UserRole + 106, FolderSyncEnabled,
FolderStatusIcon = Qt::UserRole + 107, FolderStatusIconRole
FolderSyncEnabled = Qt::UserRole + 108
}; };
void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const; void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const;
QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const; QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const;

View File

@@ -17,6 +17,7 @@
#include "mirall/version.h" #include "mirall/version.h"
#include "mirall/mirallconfigfile.h" #include "mirall/mirallconfigfile.h"
#include "mirall/occinfo.h" #include "mirall/occinfo.h"
#include "mirall/utility.h"
#include <QtCore> #include <QtCore>
#include <QtNetwork> #include <QtNetwork>
@@ -56,9 +57,13 @@ void UpdateDetector::versionCheck( Theme *theme )
} }
url.addQueryItem( QLatin1String("version"), ver ); url.addQueryItem( QLatin1String("version"), ver );
url.addQueryItem( QLatin1String("platform"), platform ); url.addQueryItem( QLatin1String("platform"), platform );
url.addQueryItem( QLatin1String("oem"), theme->appName()); url.addQueryItem( QLatin1String("oem"), theme->appName() );
_accessManager->get( QNetworkRequest( url )); QNetworkRequest req( url );
req.setRawHeader( QByteArray("Host"), url.host().toUtf8() );
req.setRawHeader( QByteArray("User-Agent"), Utility::userAgentString() );
_accessManager->get( req );
} }
void UpdateDetector::slotOpenUpdateUrl() void UpdateDetector::slotOpenUpdateUrl()

View File

@@ -13,6 +13,9 @@
#include "utility.h" #include "utility.h"
#include "mirall/version.h"
#include <QCoreApplication>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QUrl> #include <QUrl>
@@ -90,4 +93,36 @@ void Utility::setupFavLink(const QString &folder)
#endif #endif
} }
// Qtified version of get_platforms() in csync_owncloud.c
QString Utility::platform()
{
#if defined(Q_OS_WIN32)
return QLatin1String("Windows");
#elif defined(Q_OS_MAC)
return QLatin1String("Macintosh");
#elif defined(Q_OS_LINUX)
return QLatin1String("Linux");
#elif defined(__DragonFly__) // Q_OS_FREEBSD also defined
return "DragonFlyBSD";
#elif defined(Q_OS_FREEBSD)
return QLatin1String("FreeBSD");
#elif defined(Q_OS_NETBSD)
return QLatin1String("NetBSD");
#elif defined(Q_OS_OPENBSD)
return QLatin1String("OpenBSD");
#elif defined(Q_OS_SOLARIS)
return "Solaris";
#else
return "Unknown OS"
#endif
} }
QByteArray Utility::userAgentString()
{
return QString::fromLatin1("Mozilla/5.0 (%1) mirall/%2")
.arg(Utility::platform())
.arg(QLatin1String(MIRALL_STRINGIFY(MIRALL_VERSION)))
.toLatin1();
}
} // namespace Mirall

View File

@@ -25,6 +25,8 @@ class Utility
public: public:
static QString formatFingerprint( const QByteArray& ); static QString formatFingerprint( const QByteArray& );
static void setupFavLink( const QString &folder ); static void setupFavLink( const QString &folder );
static QString platform();
static QByteArray userAgentString();
}; };
} }

48
test/scripts/README.rst Normal file
View File

@@ -0,0 +1,48 @@
Torture for Mirall
==================
This is a set of scripts comprising of two parts:
* ``torture_gen_layout.pl``: Generation of layout files (random)
* ``torture_create_files.pl``: Generation of a real file tree based on the
layout files (deterministic)
These scripts allow to produce a data set with the following criteria:
* realistic in naming
* realistic in file size
* realistic in structural size
without checking in the actual data. Instead, a layout file that gets generated
once (reference.lay) is checked in. This makes it possible to produce
standardized benchmarks for mirall. It allows allows to check for files gone
missing in action and other kinds of corruption produced during sync run.
``torture_create_files.pl`` can be fine tuned via variables in the script
header. It sources its file names from ``dict`` wordlist, file extensions and
other parameters can be added as needed. The defaults should be reasonable
in terms of size.
The ``references/`` directory contains default folder layouts.
Usage
-----
In order to create a reference layout and create a tree from it::
./torture_gen_layout.pl > reference.lay
./torture_create_files.pl reference.lay <targetdir>
TODO
----
* Based on the layout file, write a validator that checks files for existence
and size without requiring a full reference tree to be created via
``./torture_gen_layout.pl``.
* The current file naming is fairly tame (i.e. almost within ASCII range).
Extending it randomly is dangerous, we first need to filter all
characters forbidden by various OSes. Or maybe not, because we want to
see what happens? :-). Anyway, you have been warned.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env perl
use strict;
use File::Path qw(make_path);
use File::Basename qw(dirname);
if (scalar @ARGV < 2) {
print "Usage: $0 input.lay <offsetdir>\n";
exit;
}
my ($file, $offset_dir) = @ARGV;
open FILE, "<", $file or die $!;
while (<FILE>) {
my ($fillfile, $size) = split(/:/, $_);
$fillfile = $offset_dir . '/' . $fillfile;
my $dir = dirname $fillfile;
if (!-d $dir) { make_path $dir; }
open FILLFILE, ">", $fillfile;
print "writing $fillfile with $size bytes\n...";
print FILLFILE 0x01 x $size;
close FILLFILE;
}

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env perl
use strict;
use Data::Random::WordList;
############################################################################
# Which extensions to randomly assign
my @exts = ('txt', 'pdf', 'html', 'docx', 'xlsx', 'pptx', 'odt', 'ods', 'odp');
# Maximum depth of the target structure
my $depth = 4;
# Maximum amount of subfolders within a folder
my $max_subfolder = 10;
# Maximum amount of files within a folder
my $max_files_per_folder = 100;
# Maximum file size
my $max_file_size = 1024**2;
############################################################################
sub gen_entries($)
{
my ($count) = @_;
my $wl = new Data::Random::WordList( wordlist => '/usr/share/dict/words' );
my @rand_words = $wl->get_words($count);
foreach(@rand_words) {
$_ =~ s/\'//g;
}
$wl->close();
return @rand_words;
}
sub create_subdir($)
{
my ($depth) = @_;
$depth--;
my %dir_tree = ( );
my @dirs = gen_entries(int(rand($max_subfolders)));
my @files = gen_entries(int(rand($max_files_per_folder)));
foreach my $file(@files) {
$dir_tree{$file} = int(rand($max_file_size));
}
if ($depth > 0) {
foreach my $dir(@dirs) {
$dir_tree{$dir} = create_subdir($depth);
}
}
return \%dir_tree;
}
sub create_dir_listing(@)
{
my ($tree, $prefix) = @_;
foreach my $key(keys %$tree) {
my $entry = $tree->{$key};
#print "$entry:".scalar $entry.":".ref $entry."\n";
if (ref $entry eq "HASH") {
create_dir_listing($tree->{$key}, "$prefix/$key");
} else {
my $ext = @exts[rand @exts];
print "$prefix/$key.$ext:$entry\n";
}
}
}
srand();
my $dir = create_subdir($depth);
create_dir_listing($dir, '.');