mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-04 03:11:32 +02:00
Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc1121ef00 | ||
|
|
6f9938a2b2 | ||
|
|
a650dce17f | ||
|
|
7ddd3a36c7 | ||
|
|
c46f1aba89 | ||
|
|
2ab19b23d7 | ||
|
|
d770f9cc1a | ||
|
|
9d3b09159e | ||
|
|
819cb74cc3 | ||
|
|
2407469104 | ||
|
|
c1faff513e | ||
|
|
e5b4438d5c | ||
|
|
7ec43e9f36 | ||
|
|
c4dabe7ed2 | ||
|
|
6b4f11f4aa | ||
|
|
1edf3dd503 | ||
|
|
1daf9bc80b | ||
|
|
b7a91a6998 | ||
|
|
69dffc8882 | ||
|
|
753aa9132e | ||
|
|
cfdfd6a860 | ||
|
|
0c9d57228d | ||
|
|
5254c9785c | ||
|
|
0f37484b8a | ||
|
|
3d0c009719 | ||
|
|
208011f6ab | ||
|
|
f84e0010ee | ||
|
|
c97f46d403 | ||
|
|
1fb52f0d8b | ||
|
|
d4de024f15 | ||
|
|
1d9d88ca85 | ||
|
|
beb9300b4e | ||
|
|
c35880d4f1 | ||
|
|
d8ebebaf12 | ||
|
|
af3fae9c28 | ||
|
|
d3b72940fd | ||
|
|
e8de3e855a | ||
|
|
71338000a4 | ||
|
|
d697969f36 | ||
|
|
51e9c5fd96 | ||
|
|
0202351a27 | ||
|
|
63cd5ef563 | ||
|
|
82c254fecf | ||
|
|
86bea9a9af | ||
|
|
88f26fb548 | ||
|
|
a9f1de84f0 | ||
|
|
e17243bc1f | ||
|
|
0e45dd7a3d | ||
|
|
65f313f1b4 | ||
|
|
da4958c716 | ||
|
|
653b8494f5 | ||
|
|
6ed6f84f6e | ||
|
|
ff0ba56bc3 | ||
|
|
e795d04f30 | ||
|
|
8d3806b080 | ||
|
|
5597ebe455 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -3,4 +3,4 @@
|
||||
url = https://github.com/owncloud/documentation
|
||||
[submodule "src/3rdparty/qtmacgoodies"]
|
||||
path = src/3rdparty/qtmacgoodies
|
||||
url = git://github.com/shadone/qtmacgoodies.git
|
||||
url = git://github.com/guruz/qtmacgoodies.git
|
||||
|
||||
23
ChangeLog
23
ChangeLog
@@ -1,5 +1,28 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 1.6.3 (release 2014-09-03)
|
||||
* Fixed updater on OS X
|
||||
* Fixed memory leak in SSL button that could lead to quick memory draining
|
||||
* Fixed upload problem with files >4 GB
|
||||
* MacOSX, Linux: Bring Settings window to front properly
|
||||
* Branded clients: If no configuration is detected, try to import the data
|
||||
from a previously configured community edition.
|
||||
|
||||
version 1.6.2 (release 2014-07-28 )
|
||||
* Limit the HTTP buffer size when downloading to limit memory consumption.
|
||||
* Another small mem leak fixed in HTTP Credentials.
|
||||
* Fix local file name clash detection for MacOSX.
|
||||
* Limit maximum wait time to ten seconds in network limiting.
|
||||
* Fix data corruption while trying to resume and the server does
|
||||
not support it.
|
||||
* HTTP Credentials: Read password from legacy place if not found.
|
||||
* Shibboleth: Fix the waiting curser that would not disapear (#1915)
|
||||
* Limit memory usage to avoid mem wasting and crashes
|
||||
* Propagator: Fix crash when logging out during upload (#1957)
|
||||
* Propagator_qnam: Fix signal slot connection (#1963)
|
||||
* Use more elaborated way to detect that the server was reconfigured (#1948)
|
||||
* Setup Wizard: Reconfigure Server also if local path was changed (#1948)
|
||||
|
||||
version 1.6.1 (release 2014-06-26 )
|
||||
* Fix 'precondition failed' bug with broken upload
|
||||
* Fix openSSL problems for windows deployment
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set( MIRALL_VERSION_MAJOR 1 )
|
||||
set( MIRALL_VERSION_MINOR 6 )
|
||||
set( MIRALL_VERSION_PATCH 1 )
|
||||
set( MIRALL_VERSION_PATCH 3 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
@@ -111,8 +111,8 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
||||
!define MUI_HEADERIMAGE
|
||||
!define MUI_HEADERIMAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/page_header.bmp
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
!define MUI_FINISHPAGE_LINK "www.${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK "${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
|
||||
!ifdef OPTION_FINISHPAGE_RELEASE_NOTES
|
||||
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
||||
@@ -414,9 +414,9 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
|
||||
;Qt deps
|
||||
File "${MING_BIN}\libpng16-16.dll"
|
||||
File "${MING_BIN}\icudata51.dll"
|
||||
File "${MING_BIN}\icui18n51.dll"
|
||||
File "${MING_BIN}\icuuc51.dll"
|
||||
File "${MING_BIN}\icudata53.dll"
|
||||
File "${MING_BIN}\icui18n53.dll"
|
||||
File "${MING_BIN}\icuuc53.dll"
|
||||
File "${MING_BIN}\libEGL.dll"
|
||||
File "${MING_BIN}\libGLESv2.dll"
|
||||
File "${MING_BIN}\libjpeg-8.dll"
|
||||
|
||||
@@ -34,6 +34,7 @@ use LWP::UserAgent;
|
||||
use LWP::Protocol::https;
|
||||
use HTTP::Request::Common qw( POST GET DELETE );
|
||||
use File::Basename;
|
||||
use POSIX qw/strftime/;
|
||||
|
||||
use Encode qw(from_to);
|
||||
use utf8;
|
||||
@@ -128,8 +129,9 @@ sub initTesting(;$)
|
||||
# $d->DebugLevel(3);
|
||||
$prefix = "t1" unless( defined $prefix );
|
||||
|
||||
my $dirId = sprintf("%#.3o", rand(1000));
|
||||
my $dir = sprintf( "%s-%s/", $prefix, $dirId );
|
||||
my $dirId = sprintf("%02d", rand(100));
|
||||
my $dateTime = strftime('%Y%m%d%H%M%S',localtime);
|
||||
my $dir = sprintf( "%s-%s-%s/", $prefix, $dateTime, $dirId );
|
||||
|
||||
$localDir = $dir;
|
||||
$localDir .= "/" unless( $localDir =~ /\/$/ );
|
||||
|
||||
@@ -4,7 +4,7 @@ if(SPHINX_FOUND)
|
||||
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
|
||||
# HTML output directory
|
||||
set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man")
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man1")
|
||||
set(SPHINX_PDF_DIR "${CMAKE_CURRENT_BINARY_DIR}/latex")
|
||||
set(SPHINX_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/qthelp")
|
||||
set(SPHINX_HTMLHELP_DIR "${CMAKE_CURRENT_BINARY_DIR}/htmlhelp")
|
||||
|
||||
Submodule doc/ocdoc updated: 2c3e584b23...c612df399e
2
src/3rdparty/qtmacgoodies
vendored
2
src/3rdparty/qtmacgoodies
vendored
Submodule src/3rdparty/qtmacgoodies updated: cf09d34dc7...fa06775714
@@ -45,6 +45,7 @@ if (APPLE)
|
||||
list(APPEND 3rdparty_SRC
|
||||
3rdparty/qtmacgoodies/src/macpreferenceswindow.mm
|
||||
3rdparty/qtmacgoodies/src/macstandardicon.mm
|
||||
3rdparty/qtmacgoodies/src/macwindow.mm
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -82,6 +83,7 @@ set(libsync_SRCS
|
||||
mirall/folderman.cpp
|
||||
mirall/folder.cpp
|
||||
mirall/folderwatcher.cpp
|
||||
mirall/authenticationdialog.cpp
|
||||
mirall/syncresult.cpp
|
||||
mirall/mirallconfigfile.cpp
|
||||
mirall/syncengine.cpp
|
||||
@@ -105,6 +107,7 @@ set(libsync_SRCS
|
||||
mirall/clientproxy.cpp
|
||||
mirall/syncrunfilelog.cpp
|
||||
mirall/cookiejar.cpp
|
||||
mirall/accountmigrator.cpp
|
||||
creds/dummycredentials.cpp
|
||||
creds/abstractcredentials.cpp
|
||||
creds/credentialsfactory.cpp
|
||||
@@ -124,7 +127,6 @@ else()
|
||||
creds/shibbolethcredentials.cpp
|
||||
creds/shibboleth/shibbolethwebview.cpp
|
||||
creds/shibboleth/shibbolethrefresher.cpp
|
||||
creds/shibboleth/authenticationdialog.cpp
|
||||
creds/shibboleth/shibbolethuserjob.cpp
|
||||
)
|
||||
endif()
|
||||
@@ -246,7 +248,7 @@ else()
|
||||
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
|
||||
if (SPARKLE_FOUND)
|
||||
install(DIRECTORY "${SPARKLE_LIBRARY}"
|
||||
DESTINATION "${OWNCLOUD_OSX_BUNDLE}/Contents/Frameworks")
|
||||
DESTINATION "${OWNCLOUD_OSX_BUNDLE}/Contents/Frameworks" USE_SOURCE_PERMISSIONS)
|
||||
endif (SPARKLE_FOUND)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -101,7 +101,8 @@ HttpCredentials::HttpCredentials()
|
||||
: _user(),
|
||||
_password(),
|
||||
_ready(false),
|
||||
_fetchJobInProgress(false)
|
||||
_fetchJobInProgress(false),
|
||||
_readPwdFromDeprecatedPlace(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -230,6 +231,7 @@ void HttpCredentials::fetch(Account *account)
|
||||
job->setProperty("account", QVariant::fromValue(account));
|
||||
job->start();
|
||||
_fetchJobInProgress = true;
|
||||
_readPwdFromDeprecatedPlace = true;
|
||||
}
|
||||
}
|
||||
bool HttpCredentials::stillValid(QNetworkReply *reply)
|
||||
@@ -261,18 +263,40 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
|
||||
_ready = true;
|
||||
emit fetched();
|
||||
} else {
|
||||
if( error != NoError ) {
|
||||
qDebug() << "Error while reading password" << job->errorString();
|
||||
// we come here if the password is empty or any other keychain
|
||||
// error happend.
|
||||
// In all error conditions it should
|
||||
// ask the user for the password interactively now.
|
||||
if( _readPwdFromDeprecatedPlace ) {
|
||||
// there simply was not a password. Lets restart a read job without
|
||||
// a settings object as we did it in older client releases.
|
||||
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
|
||||
|
||||
const QString kck = keychainKey(account->url().toString(), _user);
|
||||
job->setKey(kck);
|
||||
|
||||
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
|
||||
job->setProperty("account", QVariant::fromValue(account));
|
||||
job->start();
|
||||
_readPwdFromDeprecatedPlace = false; // do try that only once.
|
||||
_fetchJobInProgress = true;
|
||||
// Note: if this read job succeeds, the value from the old place is still
|
||||
// NOT persisted into the new account.
|
||||
} else {
|
||||
// interactive password dialog starts here
|
||||
bool ok;
|
||||
QString pwd = queryPassword(&ok);
|
||||
_fetchJobInProgress = false;
|
||||
if (ok) {
|
||||
_password = pwd;
|
||||
_ready = true;
|
||||
persist(account);
|
||||
} else {
|
||||
_password = QString::null;
|
||||
_ready = false;
|
||||
}
|
||||
emit fetched();
|
||||
}
|
||||
bool ok;
|
||||
QString pwd = queryPassword(&ok);
|
||||
_fetchJobInProgress = false;
|
||||
if (ok) {
|
||||
_password = pwd;
|
||||
_ready = true;
|
||||
persist(account);
|
||||
}
|
||||
emit fetched();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +366,8 @@ void HttpCredentials::slotWriteJobDone(QKeychain::Job *job)
|
||||
default:
|
||||
qDebug() << "Error while writing password" << job->errorString();
|
||||
}
|
||||
WritePasswordJob *wjob = qobject_cast<WritePasswordJob*>(job);
|
||||
wjob->deleteLater();
|
||||
}
|
||||
|
||||
void HttpCredentials::slotAuthentication(QNetworkReply* reply, QAuthenticator* authenticator)
|
||||
|
||||
@@ -63,6 +63,7 @@ private:
|
||||
QString _password;
|
||||
bool _ready;
|
||||
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
|
||||
bool _readPwdFromDeprecatedPlace;
|
||||
};
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -34,6 +34,7 @@ ShibbolethWebView::ShibbolethWebView(Account* account, QWidget* parent)
|
||||
: QWebView(parent)
|
||||
, _account(account)
|
||||
, _accepted(false)
|
||||
, _cursorOverriden(false)
|
||||
{
|
||||
// no minimize
|
||||
setWindowFlags(Qt::Dialog);
|
||||
@@ -79,6 +80,10 @@ void ShibbolethWebView::onNewCookiesForUrl (const QList<QNetworkCookie>& cookieL
|
||||
|
||||
void ShibbolethWebView::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (_cursorOverriden) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
if (!_accepted) {
|
||||
Q_EMIT rejected();
|
||||
}
|
||||
@@ -87,12 +92,17 @@ void ShibbolethWebView::closeEvent(QCloseEvent *event)
|
||||
|
||||
void ShibbolethWebView::slotLoadStarted()
|
||||
{
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
if (!_cursorOverriden) {
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
_cursorOverriden = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ShibbolethWebView::slotLoadFinished(bool success)
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (_cursorOverriden) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
if (!title().isNull()) {
|
||||
setWindowTitle(tr("%1 - %2").arg(Theme::instance()->appNameGUI(), title()));
|
||||
|
||||
@@ -55,6 +55,7 @@ private:
|
||||
void setup(Account *account, ShibbolethCookieJar* jar);
|
||||
QPointer<Account> _account;
|
||||
bool _accepted;
|
||||
bool _cursorOverriden;
|
||||
};
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "creds/shibbolethcredentials.h"
|
||||
#include "creds/shibboleth/authenticationdialog.h"
|
||||
#include "creds/shibboleth/shibbolethwebview.h"
|
||||
#include "creds/shibboleth/shibbolethrefresher.h"
|
||||
#include "creds/shibbolethcredentials.h"
|
||||
@@ -173,8 +172,6 @@ QNetworkAccessManager* ShibbolethCredentials::getQNAM() const
|
||||
QNetworkAccessManager* qnam(new MirallAccessManager);
|
||||
connect(qnam, SIGNAL(finished(QNetworkReply*)),
|
||||
this, SLOT(slotReplyFinished(QNetworkReply*)));
|
||||
connect(qnam, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
|
||||
SLOT(slotHandleAuthentication(QNetworkReply*,QAuthenticator*)));
|
||||
return qnam;
|
||||
}
|
||||
|
||||
@@ -319,23 +316,6 @@ void ShibbolethCredentials::invalidateAndFetch(Account* account)
|
||||
job->start();
|
||||
}
|
||||
|
||||
void ShibbolethCredentials::slotHandleAuthentication(QNetworkReply *reply, QAuthenticator *authenticator)
|
||||
{
|
||||
Q_UNUSED(reply)
|
||||
QUrl url = reply->url();
|
||||
// show only scheme, host and port
|
||||
QUrl reducedUrl;
|
||||
reducedUrl.setScheme(url.scheme());
|
||||
reducedUrl.setHost(url.host());
|
||||
reducedUrl.setPort(url.port());
|
||||
|
||||
AuthenticationDialog dialog(authenticator->realm(), reducedUrl.toString());
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
authenticator->setUser(dialog.user());
|
||||
authenticator->setPassword(dialog.password());
|
||||
}
|
||||
}
|
||||
|
||||
void ShibbolethCredentials::slotInvalidateAndFetchInvalidateDone(QKeychain::Job* job)
|
||||
{
|
||||
Account *account = qvariant_cast<Account*>(job->property("account"));
|
||||
@@ -405,7 +385,7 @@ void ShibbolethCredentials::showLoginWindow(Account* account)
|
||||
|
||||
QList<QNetworkCookie> ShibbolethCredentials::accountCookies(Account *account)
|
||||
{
|
||||
return account->networkAccessManager()->cookieJar()->cookiesForUrl(account->url());
|
||||
return account->networkAccessManager()->cookieJar()->cookiesForUrl(account->davUrl());
|
||||
}
|
||||
|
||||
QNetworkCookie ShibbolethCredentials::findShibCookie(Account *account, QList<QNetworkCookie> cookies)
|
||||
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
|
||||
public Q_SLOTS:
|
||||
void invalidateAndFetch(Account *account);
|
||||
void slotHandleAuthentication(QNetworkReply*,QAuthenticator*);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onShibbolethCookieReceived(const QNetworkCookie&, Account*);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
#include "mirall/mirallaccessmanager.h"
|
||||
#include "mirall/quotainfo.h"
|
||||
#include "mirall/owncloudtheme.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "creds/credentialsfactory.h"
|
||||
|
||||
@@ -27,6 +28,8 @@
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QSslSocket>
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
@@ -36,6 +39,7 @@ static const char urlC[] = "url";
|
||||
static const char authTypeC[] = "authType";
|
||||
static const char userC[] = "user";
|
||||
static const char httpUserC[] = "http_user";
|
||||
static const char caCertsKeyC[] = "CaCertificates";
|
||||
|
||||
AccountManager *AccountManager::_instance = 0;
|
||||
|
||||
@@ -71,6 +75,7 @@ Account::Account(AbstractSslErrorHandler *sslErrorHandler, QObject *parent)
|
||||
, _treatSslErrorsAsFailure(false)
|
||||
, _state(Account::Disconnected)
|
||||
, _davPath("remote.php/webdav/")
|
||||
, _wasMigrated(false)
|
||||
{
|
||||
qRegisterMetaType<Account*>("Account*");
|
||||
}
|
||||
@@ -98,25 +103,66 @@ void Account::save()
|
||||
}
|
||||
settings->sync();
|
||||
|
||||
// ### TODO port away from MirallConfigFile
|
||||
MirallConfigFile cfg;
|
||||
// Save accepted certificates.
|
||||
settings->beginGroup(QLatin1String("General"));
|
||||
qDebug() << "Saving " << approvedCerts().count() << " unknown certs.";
|
||||
QByteArray certs;
|
||||
Q_FOREACH( const QSslCertificate& cert, approvedCerts() ) {
|
||||
certs += cert.toPem() + '\n';
|
||||
}
|
||||
if (!certs.isEmpty()) {
|
||||
cfg.setCaCerts( certs );
|
||||
settings->setValue( QLatin1String(caCertsKeyC), certs );
|
||||
}
|
||||
}
|
||||
|
||||
Account* Account::restore()
|
||||
{
|
||||
// try to open the correctly themed settings
|
||||
QScopedPointer<QSettings> settings(settingsWithGroup(Theme::instance()->appName()));
|
||||
|
||||
Account *acc = 0;
|
||||
bool migratedCreds = false;
|
||||
|
||||
// if the settings file could not be opened, the childKeys list is empty
|
||||
if( settings->childKeys().isEmpty() ) {
|
||||
// Now try to open the original ownCloud settings to see if they exist.
|
||||
QString oCCfgFile = QDir::fromNativeSeparators( settings->fileName() );
|
||||
// replace the last two segments with ownCloud/owncloud.cfg
|
||||
oCCfgFile = oCCfgFile.left( oCCfgFile.lastIndexOf('/'));
|
||||
oCCfgFile = oCCfgFile.left( oCCfgFile.lastIndexOf('/'));
|
||||
oCCfgFile += QLatin1String("/ownCloud/owncloud.cfg");
|
||||
|
||||
qDebug() << "Migrate: checking old config " << oCCfgFile;
|
||||
|
||||
QFileInfo fi( oCCfgFile );
|
||||
if( fi.isReadable() ) {
|
||||
QSettings *oCSettings = new QSettings(oCCfgFile, QSettings::IniFormat);
|
||||
oCSettings->beginGroup(QLatin1String("ownCloud"));
|
||||
|
||||
// Check the theme url to see if it is the same url that the oC config was for
|
||||
QString overrideUrl = Theme::instance()->overrideServerUrl();
|
||||
if( !overrideUrl.isEmpty() ) {
|
||||
if (overrideUrl.endsWith('/')) { overrideUrl.chop(1); }
|
||||
QString oCUrl = oCSettings->value(QLatin1String(urlC)).toString();
|
||||
if (oCUrl.endsWith('/')) { oCUrl.chop(1); }
|
||||
|
||||
// in case the urls are equal reset the settings object to read from
|
||||
// the ownCloud settings object
|
||||
qDebug() << "Migrate oC config if " << oCUrl << " == " << overrideUrl << ":"
|
||||
<< (oCUrl == overrideUrl ? "Yes" : "No");
|
||||
if( oCUrl == overrideUrl ) {
|
||||
migratedCreds = true;
|
||||
settings.reset( oCSettings );
|
||||
} else {
|
||||
delete oCSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings->childKeys().isEmpty()) {
|
||||
Account *acc = new Account;
|
||||
MirallConfigFile cfg;
|
||||
acc->setApprovedCerts(QSslCertificate::fromData(cfg.caCerts()));
|
||||
acc = new Account;
|
||||
|
||||
acc->setUrl(settings->value(QLatin1String(urlC)).toUrl());
|
||||
acc->setCredentials(CredentialsFactory::create(settings->value(QLatin1String(authTypeC)).toString()));
|
||||
|
||||
@@ -128,6 +174,11 @@ Account* Account::restore()
|
||||
continue;
|
||||
acc->_settingsMap.insert(key, settings->value(key));
|
||||
}
|
||||
|
||||
// now the cert, it is in the general group
|
||||
settings->beginGroup(QLatin1String("General"));
|
||||
acc->setApprovedCerts(QSslCertificate::fromData(settings->value(caCertsKeyC).toByteArray()));
|
||||
acc->setMigrated(migratedCreds);
|
||||
return acc;
|
||||
}
|
||||
return 0;
|
||||
@@ -364,4 +415,14 @@ void Account::slotHandleErrors(QNetworkReply *reply , QList<QSslError> errors)
|
||||
}
|
||||
}
|
||||
|
||||
bool Account::wasMigrated()
|
||||
{
|
||||
return _wasMigrated;
|
||||
}
|
||||
|
||||
void Account::setMigrated(bool mig)
|
||||
{
|
||||
_wasMigrated = mig;
|
||||
}
|
||||
|
||||
} // namespace Mirall
|
||||
|
||||
@@ -108,6 +108,13 @@ public:
|
||||
/** Returns webdav entry URL, based on url() */
|
||||
QUrl davUrl() const;
|
||||
|
||||
/** set and retrieve the migration flag: if an account of a branded
|
||||
* client was migrated from a former ownCloud Account, this is true
|
||||
*/
|
||||
void setMigrated(bool mig);
|
||||
bool wasMigrated();
|
||||
|
||||
|
||||
QList<QNetworkCookie> lastAuthCookies() const;
|
||||
|
||||
QNetworkReply* headRequest(const QString &relPath);
|
||||
@@ -166,6 +173,7 @@ private:
|
||||
int _state;
|
||||
static QString _configFileName;
|
||||
QString _davPath; // default "remote.php/webdav/";
|
||||
bool _wasMigrated;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
89
src/mirall/accountmigrator.cpp
Normal file
89
src/mirall/accountmigrator.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "mirall/accountmigrator.h"
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
#include "mirall/folderman.h"
|
||||
#include "mirall/theme.h"
|
||||
|
||||
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
// The purpose of this class is to migrate an existing account that
|
||||
// was set up with an unbranded client to an branded one.
|
||||
// The usecase is: Usually people try first with the community client,
|
||||
// later they maybe switch to a branded client. When they install the
|
||||
// branded client first, it should automatically pick the information
|
||||
// from the already configured account.
|
||||
|
||||
AccountMigrator::AccountMigrator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// the list of folder definitions which are files in the directory "folders"
|
||||
// underneath the ownCloud configPath (with ownCloud as a last segment)
|
||||
// need to be copied to the themed path and adjusted.
|
||||
|
||||
QStringList AccountMigrator::migrateFolderDefinitons()
|
||||
{
|
||||
MirallConfigFile cfg;
|
||||
QStringList re;
|
||||
|
||||
QString themePath = cfg.configPath();
|
||||
// create the original ownCloud config path out of the theme path
|
||||
// by removing the theme folder and append ownCloud.
|
||||
QString oCPath = themePath;
|
||||
if( oCPath.endsWith(QLatin1Char('/')) ) {
|
||||
oCPath.truncate( oCPath.length()-1 );
|
||||
}
|
||||
oCPath = oCPath.left( oCPath.lastIndexOf('/'));
|
||||
|
||||
themePath += QLatin1String( "folders");
|
||||
oCPath += QLatin1String( "/ownCloud/folders" );
|
||||
|
||||
qDebug() << "Migrator: theme-path: " << themePath;
|
||||
qDebug() << "Migrator: ownCloud path: " << oCPath;
|
||||
|
||||
// get a dir listing of the ownCloud folder definitions and copy
|
||||
// them over to the theme dir
|
||||
QDir oCDir(oCPath);
|
||||
oCDir.setFilter( QDir::Files );
|
||||
QStringList files = oCDir.entryList();
|
||||
|
||||
foreach( const QString& file, files ) {
|
||||
QString escapedAlias = FolderMan::instance()->escapeAlias(file);
|
||||
QString themeFile = themePath + QDir::separator() + file;
|
||||
QString oCFile = oCPath+QDir::separator()+file;
|
||||
if( QFile::copy( oCFile, themeFile ) ) {
|
||||
re.append(file);
|
||||
qDebug() << "Migrator: Folder definition migrated: " << file;
|
||||
|
||||
// fix the connection entry of the folder definition
|
||||
QSettings settings(themeFile, QSettings::IniFormat);
|
||||
settings.beginGroup( escapedAlias );
|
||||
settings.setValue(QLatin1String("connection"), Theme::instance()->appName());
|
||||
settings.sync();
|
||||
}
|
||||
}
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
}
|
||||
38
src/mirall/accountmigrator.h
Normal file
38
src/mirall/accountmigrator.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef ACCOUNTMIGRATOR_H
|
||||
#define ACCOUNTMIGRATOR_H
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
class AccountMigrator {
|
||||
|
||||
public:
|
||||
explicit AccountMigrator();
|
||||
|
||||
/**
|
||||
* @brief migrateFolderDefinitons - migrate the folder definition files
|
||||
* @return the list of migrated folder definitions
|
||||
*/
|
||||
QStringList migrateFolderDefinitons();
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ACCOUNTMIGRATOR_H
|
||||
@@ -713,7 +713,7 @@ void AccountSettings::slotIgnoreFilesEditor()
|
||||
_ignoreEditor->setAttribute( Qt::WA_DeleteOnClose, true );
|
||||
_ignoreEditor->open();
|
||||
} else {
|
||||
Utility::raiseDialog(_ignoreEditor);
|
||||
ownCloudGui::raiseDialog(_ignoreEditor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -704,10 +704,7 @@ void Folder::slotTransmissionProgress(const Progress::Info &pi)
|
||||
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction direction, bool *cancel)
|
||||
{
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
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\".") :
|
||||
QString msg =
|
||||
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"
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
*/
|
||||
|
||||
#include "mirall/folderman.h"
|
||||
#include "mirall/account.h"
|
||||
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
#include "mirall/folder.h"
|
||||
#include "mirall/syncresult.h"
|
||||
#include "mirall/theme.h"
|
||||
#include "mirall/accountmigrator.h"
|
||||
|
||||
#include <neon/ne_socket.h>
|
||||
|
||||
@@ -147,6 +150,15 @@ int FolderMan::setupFolders()
|
||||
dir.setFilter(QDir::Files | QDir::Hidden);
|
||||
QStringList list = dir.entryList();
|
||||
|
||||
if( list.count() == 0 ) {
|
||||
// maybe the account was just migrated.
|
||||
Account *acc = AccountManager::instance()->account();
|
||||
if ( acc && acc->wasMigrated() ) {
|
||||
AccountMigrator accMig;
|
||||
list = accMig.migrateFolderDefinitons();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( const QString& alias, list ) {
|
||||
Folder *f = setupFolderFromConfigFile( alias );
|
||||
if( f ) {
|
||||
|
||||
@@ -83,6 +83,8 @@ public:
|
||||
void removeMonitorPath( const QString& alias, const QString& path );
|
||||
void addMonitorPath( const QString& alias, const QString& path );
|
||||
|
||||
QString escapeAlias( const QString& ) const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* signal to indicate a folder named by alias has changed its sync state.
|
||||
@@ -130,7 +132,6 @@ private:
|
||||
|
||||
// Escaping of the alias which is used in QSettings AND the file
|
||||
// system, thus need to be escaped.
|
||||
QString escapeAlias( const QString& ) const;
|
||||
QString unescapeAlias( const QString& ) const;
|
||||
|
||||
void removeFolder( const QString& );
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkProxy>
|
||||
#include <QAuthenticator>
|
||||
#include <QSslConfiguration>
|
||||
@@ -19,6 +20,8 @@
|
||||
#include "mirall/cookiejar.h"
|
||||
#include "mirall/mirallaccessmanager.h"
|
||||
#include "mirall/utility.h"
|
||||
#include "mirall/authenticationdialog.h"
|
||||
|
||||
|
||||
namespace Mirall
|
||||
{
|
||||
@@ -33,8 +36,11 @@ MirallAccessManager::MirallAccessManager(QObject* parent)
|
||||
setProxy(proxy);
|
||||
#endif
|
||||
setCookieJar(new CookieJar);
|
||||
QObject::connect(this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
|
||||
this, SLOT(slotProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
|
||||
connect(this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
|
||||
this, SLOT(slotProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
|
||||
connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
|
||||
this, SLOT(slotAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
|
||||
|
||||
}
|
||||
|
||||
QNetworkReply* MirallAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
|
||||
@@ -60,5 +66,27 @@ void MirallAccessManager::slotProxyAuthenticationRequired(const QNetworkProxy &p
|
||||
authenticator->setPassword(proxy.password());
|
||||
}
|
||||
}
|
||||
void MirallAccessManager::slotAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
|
||||
{
|
||||
// do not handle 401 created by the networkjobs. We may want
|
||||
// to eventually exempt some, but for now we need
|
||||
// it only for other things, e.g. the browser. Would we handle
|
||||
// network jobs, this would break the wizard logic
|
||||
if (reply->property("doNotHandleAuth").toBool()) {
|
||||
return;
|
||||
}
|
||||
QUrl url = reply->url();
|
||||
// show only scheme, host and port
|
||||
QUrl reducedUrl;
|
||||
reducedUrl.setScheme(url.scheme());
|
||||
reducedUrl.setHost(url.host());
|
||||
reducedUrl.setPort(url.port());
|
||||
|
||||
AuthenticationDialog dialog(authenticator->realm(), reducedUrl.toString());
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
authenticator->setUser(dialog.user());
|
||||
authenticator->setPassword(dialog.password());
|
||||
}
|
||||
}
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -31,6 +31,8 @@ protected:
|
||||
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0);
|
||||
protected slots:
|
||||
void slotProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
|
||||
void slotAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
|
||||
|
||||
};
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -57,6 +57,7 @@ void AbstractNetworkJob::setReply(QNetworkReply *reply)
|
||||
if (_reply) {
|
||||
_reply->deleteLater();
|
||||
}
|
||||
reply->setProperty("doNotHandleAuth", true);
|
||||
_reply = reply;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "mirall/owncloudsetupwizard.h"
|
||||
#if defined(Q_OS_MAC)
|
||||
# include "mirall/settingsdialogmac.h"
|
||||
# include "macwindow.h" // qtmacgoodies
|
||||
#else
|
||||
# include "mirall/settingsdialog.h"
|
||||
#endif
|
||||
@@ -33,6 +34,10 @@
|
||||
#include <QMessageBox>
|
||||
#include <QSignalMapper>
|
||||
|
||||
#if defined(Q_OS_X11)
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
ownCloudGui::ownCloudGui(Application *parent) :
|
||||
@@ -111,6 +116,14 @@ void ownCloudGui::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
|
||||
if( reason == QSystemTrayIcon::Trigger ) {
|
||||
slotOpenSettingsDialog(true); // start settings if config is existing.
|
||||
}
|
||||
#else
|
||||
// On Mac, if the settings dialog is already visible but hidden
|
||||
// by other applications, this will bring it to the front.
|
||||
if( reason == QSystemTrayIcon::Trigger ) {
|
||||
if (!_settingsDialog.isNull() && _settingsDialog->isVisible()) {
|
||||
slotShowSettings();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -475,7 +488,7 @@ void ownCloudGui::slotShowSettings()
|
||||
_settingsDialog->show();
|
||||
}
|
||||
_settingsDialog->setGeneralErrors( _startupFails );
|
||||
Utility::raiseDialog(_settingsDialog.data());
|
||||
ownCloudGui::raiseDialog(_settingsDialog.data());
|
||||
}
|
||||
|
||||
void ownCloudGui::slotShowSyncProtocol()
|
||||
@@ -503,7 +516,7 @@ void ownCloudGui::slotToggleLogBrowser()
|
||||
if (_logBrowser->isVisible() ) {
|
||||
_logBrowser->hide();
|
||||
} else {
|
||||
Utility::raiseDialog(_logBrowser);
|
||||
ownCloudGui::raiseDialog(_logBrowser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,5 +532,35 @@ void ownCloudGui::slotHelp()
|
||||
QDesktopServices::openUrl(QUrl(Theme::instance()->helpUrl()));
|
||||
}
|
||||
|
||||
void ownCloudGui::raiseDialog( QWidget *raiseWidget )
|
||||
{
|
||||
if( raiseWidget && raiseWidget->parentWidget() == 0) {
|
||||
// Qt has a bug which causes parent-less dialogs to pop-under.
|
||||
raiseWidget->showNormal();
|
||||
raiseWidget->raise();
|
||||
raiseWidget->activateWindow();
|
||||
}
|
||||
#if defined(Q_OS_MAC)
|
||||
// viel hilft viel ;-)
|
||||
MacWindow::bringToFront(raiseWidget);
|
||||
#endif
|
||||
#if defined(Q_OS_X11)
|
||||
WId wid = widget->winId();
|
||||
NETWM::init();
|
||||
|
||||
XEvent e;
|
||||
e.xclient.type = ClientMessage;
|
||||
e.xclient.message_type = NETWM::NET_ACTIVE_WINDOW;
|
||||
e.xclient.display = QX11Info::display();
|
||||
e.xclient.window = wid;
|
||||
e.xclient.format = 32;
|
||||
e.xclient.data.l[0] = 2;
|
||||
e.xclient.data.l[1] = QX11Info::appTime();
|
||||
e.xclient.data.l[2] = 0;
|
||||
e.xclient.data.l[3] = 0l;
|
||||
e.xclient.data.l[4] = 0l;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
|
||||
bool checkAccountExists(bool openSettings);
|
||||
|
||||
static void raiseDialog( QWidget *raiseWidget );
|
||||
|
||||
signals:
|
||||
void setupProxy();
|
||||
|
||||
|
||||
@@ -337,8 +337,15 @@ bool OwncloudPropagator::localFileNameClash( const QString& relFile )
|
||||
QFileInfo fileInfo(file);
|
||||
if (!fileInfo.exists()) {
|
||||
re = false;
|
||||
qDebug() << Q_FUNC_INFO << "No valid fileinfo";
|
||||
} else {
|
||||
re = ( ! fileInfo.canonicalFilePath().endsWith(relFile, Qt::CaseSensitive) );
|
||||
// Need to normalize to composited form because of
|
||||
// https://bugreports.qt-project.org/browse/QTBUG-39622
|
||||
const QString cName = fileInfo.canonicalFilePath().normalized(QString::NormalizationForm_C);
|
||||
// qDebug() << Q_FUNC_INFO << "comparing " << cName << " with " << file;
|
||||
bool equal = (file == cName);
|
||||
re = (!equal && ! cName.endsWith(relFile, Qt::CaseSensitive) );
|
||||
// qDebug() << Q_FUNC_INFO << "Returning for localFileNameClash: " << re;
|
||||
}
|
||||
#elif defined(Q_OS_WIN)
|
||||
const QString file( _localDir + relFile );
|
||||
|
||||
@@ -111,6 +111,15 @@ void OwncloudSetupWizard::startWizard()
|
||||
}
|
||||
|
||||
_ocWizard->setProperty("localFolder", localFolder);
|
||||
|
||||
// remember the local folder to compare later if it changed, but clean first
|
||||
QString lf = QDir::fromNativeSeparators(localFolder);
|
||||
if( !lf.endsWith(QLatin1Char('/'))) {
|
||||
lf.append(QLatin1Char('/'));
|
||||
}
|
||||
|
||||
_initLocalFolder = lf;
|
||||
|
||||
_ocWizard->setRemoteFolder(_remoteFolder);
|
||||
|
||||
_ocWizard->setStartId(WizardCommon::Page_ServerSetup);
|
||||
@@ -135,6 +144,8 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
|
||||
}
|
||||
Account *account = _ocWizard->account();
|
||||
account->setUrl(url);
|
||||
// Set fake credentials beforfe we check what credidential it actually is.
|
||||
account->setCredentials(CredentialsFactory::create("dummy"));
|
||||
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), false, this);
|
||||
job->setIgnoreCredentialFailure(true);
|
||||
connect(job, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotOwnCloudFoundAuth(QUrl,QVariantMap)));
|
||||
@@ -392,10 +403,17 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
||||
|
||||
Account *newAccount = _ocWizard->account();
|
||||
Account *origAccount = AccountManager::instance()->account();
|
||||
const QString localFolder = _ocWizard->localFolder();
|
||||
|
||||
QString localFolder = QDir::fromNativeSeparators(_ocWizard->localFolder());
|
||||
if( !localFolder.endsWith(QLatin1Char('/'))) {
|
||||
localFolder.append(QLatin1Char('/'));
|
||||
}
|
||||
|
||||
bool isInitialSetup = (origAccount == 0);
|
||||
bool reinitRequired = newAccount->changed(origAccount, true /* ignoreProtocol, allows http->https */);
|
||||
|
||||
// check if either the account or the local folder changed, than reinit
|
||||
bool reinitRequired = _initLocalFolder != localFolder ||
|
||||
newAccount->changed(origAccount, true /* ignoreProtocol, allows http->https */);
|
||||
bool startFromScratch = _ocWizard->field("OCSyncFromScratch").toBool();
|
||||
|
||||
// This distinguishes three possibilities:
|
||||
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
|
||||
Account* _account;
|
||||
OwncloudWizard* _ocWizard;
|
||||
QString _initLocalFolder;
|
||||
QString _remoteFolder;
|
||||
|
||||
};
|
||||
|
||||
@@ -124,6 +124,16 @@ QPixmap ownCloudTheme::wizardHeaderLogo() const
|
||||
}
|
||||
#endif
|
||||
|
||||
QString ownCloudTheme::appName() const
|
||||
{
|
||||
return QLatin1String("ownCloud");
|
||||
}
|
||||
|
||||
QString ownCloudTheme::appNameGUI() const
|
||||
{
|
||||
return QLatin1String("ownCloud");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ public:
|
||||
QIcon trayFolderIcon( const QString& ) const;
|
||||
QIcon folderDisabledIcon() const;
|
||||
QIcon applicationIcon() const;
|
||||
QString appName() const;
|
||||
QString appNameGUI() const;
|
||||
|
||||
|
||||
QVariant customMedia(CustomMediaType type);
|
||||
QString helpUrl() const;
|
||||
|
||||
@@ -328,8 +328,7 @@ void PropagateNeonJob::limitBandwidth(qint64 progress, qint64 bandwidth_limit)
|
||||
// -bandwidth_limit is the % of bandwidth
|
||||
int64_t wait_time = -diff * (1 + 100.0 / bandwidth_limit);
|
||||
if (wait_time > 0) {
|
||||
Mirall::Utility::usleep(wait_time);
|
||||
|
||||
Mirall::Utility::usleep(qMin(wait_time, int64_t(1000000*10)));
|
||||
}
|
||||
}
|
||||
_lastTime.start();
|
||||
@@ -397,24 +396,39 @@ void PropagateDownloadFileLegacy::install_content_reader( ne_request *req, void
|
||||
|
||||
if (etag.isEmpty()) {
|
||||
qDebug() << Q_FUNC_INFO << "No E-Tag reply by server, considering it invalid" << ne_get_response_header(req, "etag");
|
||||
that->errorString = tr("No E-Tag received from server, check Proxy/Gateway");
|
||||
ne_set_error(that->_propagator->_session, "%s", that->errorString.toUtf8().data());
|
||||
ne_add_response_body_reader( req, do_not_accept,
|
||||
do_not_download_content_reader,
|
||||
(void*) that );
|
||||
that->abortTransfer(req, tr("No E-Tag received from server, check Proxy/Gateway"));
|
||||
return;
|
||||
} else if (!that->_expectedEtagForResume.isEmpty() && that->_expectedEtagForResume != etag) {
|
||||
qDebug() << Q_FUNC_INFO << "We received a different E-Tag for resuming!"
|
||||
<< QString::fromLatin1(that->_expectedEtagForResume.data()) << "vs"
|
||||
<< QString::fromLatin1(etag.data());
|
||||
that->errorString = tr("We received a different E-Tag for resuming. Retrying next time.");
|
||||
ne_set_error(that->_propagator->_session, "%s", that->errorString.toUtf8().data());
|
||||
ne_add_response_body_reader( req, do_not_accept,
|
||||
do_not_download_content_reader,
|
||||
(void*) that );
|
||||
that->abortTransfer(req, tr("We received a different E-Tag for resuming. Retrying next time."));
|
||||
return;
|
||||
}
|
||||
|
||||
quint64 start = 0;
|
||||
QByteArray ranges = ne_get_response_header(req, "content-range");
|
||||
if (!ranges.isEmpty()) {
|
||||
QRegExp rx("bytes (\\d+)-");
|
||||
if (rx.indexIn(ranges) >= 0) {
|
||||
start = rx.cap(1).toULongLong();
|
||||
}
|
||||
}
|
||||
if (start != that->_resumeStart) {
|
||||
qDebug() << Q_FUNC_INFO << "Wrong content-range: "<< ranges << " while expecting start was" << that->_resumeStart;
|
||||
if (start == 0) {
|
||||
// device don't support range, just stry again from scratch
|
||||
that->_file->close();
|
||||
if (!that->_file->open(QIODevice::WriteOnly)) {
|
||||
that->abortTransfer(req, that->_file->errorString());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
that->abortTransfer(req, tr("Server returned wrong content-range"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *enc = ne_get_response_header( req, "Content-Encoding" );
|
||||
qDebug("Content encoding ist <%s> with status %d", enc ? enc : "empty",
|
||||
@@ -431,6 +445,16 @@ void PropagateDownloadFileLegacy::install_content_reader( ne_request *req, void
|
||||
}
|
||||
}
|
||||
|
||||
void PropagateDownloadFileLegacy::abortTransfer(ne_request* req, const QString& error)
|
||||
{
|
||||
errorString = error;
|
||||
ne_set_error(_propagator->_session, "%s", errorString.toUtf8().data());
|
||||
ne_add_response_body_reader( req, do_not_accept,
|
||||
do_not_download_content_reader,
|
||||
this);
|
||||
}
|
||||
|
||||
|
||||
void PropagateDownloadFileLegacy::notify_status_cb(void* userdata, ne_session_status status,
|
||||
const ne_session_status_info* info)
|
||||
{
|
||||
@@ -521,6 +545,7 @@ void PropagateDownloadFileLegacy::start()
|
||||
ne_add_request_header(req.data(), "Range", rangeRequest.constData());
|
||||
ne_add_request_header(req.data(), "Accept-Ranges", "bytes");
|
||||
qDebug() << "Retry with range " << rangeRequest;
|
||||
_resumeStart = done;
|
||||
}
|
||||
|
||||
/* hook called before the content is parsed to set the correct reader,
|
||||
|
||||
@@ -53,13 +53,14 @@ class PropagateDownloadFileLegacy: public PropagateNeonJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PropagateDownloadFileLegacy(OwncloudPropagator* propagator,const SyncFileItem& item)
|
||||
: PropagateNeonJob(propagator, item), _file(0) {}
|
||||
: PropagateNeonJob(propagator, item), _file(0), _resumeStart(0) {}
|
||||
void start();
|
||||
private:
|
||||
QFile *_file;
|
||||
QScopedPointer<ne_decompress, ScopedPointerHelpers> _decompress;
|
||||
QString errorString;
|
||||
QByteArray _expectedEtagForResume;
|
||||
quint64 _resumeStart;
|
||||
|
||||
static int do_not_accept (void *userdata, ne_request *req, const ne_status *st)
|
||||
{
|
||||
@@ -78,6 +79,9 @@ private:
|
||||
static void install_content_reader( ne_request *req, void *userdata, const ne_status *status );
|
||||
static void notify_status_cb(void* userdata, ne_session_status status,
|
||||
const ne_session_status_info* info);
|
||||
|
||||
/** To be called from install_content_reader if we want to abort the transfer */
|
||||
void abortTransfer(ne_request *req, const QString &error);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
static uint chunkSize() {
|
||||
static qint64 chunkSize() {
|
||||
static uint chunkSize;
|
||||
if (!chunkSize) {
|
||||
chunkSize = qgetenv("OWNCLOUD_CHUNK_SIZE").toUInt();
|
||||
@@ -119,14 +119,15 @@ void PropagateUploadFileQNAM::start()
|
||||
|
||||
struct ChunkDevice : QIODevice {
|
||||
public:
|
||||
QIODevice *_file;
|
||||
QPointer<QIODevice> _file;
|
||||
qint64 _read;
|
||||
qint64 _size;
|
||||
qint64 _start;
|
||||
|
||||
ChunkDevice(QIODevice *file, qint64 start, qint64 size)
|
||||
: QIODevice(file), _file(file), _read(0), _size(size), _start(start) {
|
||||
_file->seek(start);
|
||||
_file = QPointer<QIODevice>(file);
|
||||
_file.data()->seek(start);
|
||||
}
|
||||
|
||||
virtual qint64 writeData(const char* , qint64 ) {
|
||||
@@ -135,10 +136,15 @@ public:
|
||||
}
|
||||
|
||||
virtual qint64 readData(char* data, qint64 maxlen) {
|
||||
if (_file.isNull()) {
|
||||
qDebug() << Q_FUNC_INFO << "Upload file object deleted during upload";
|
||||
close();
|
||||
return -1;
|
||||
}
|
||||
maxlen = qMin(maxlen, chunkSize() - _read);
|
||||
if (maxlen == 0)
|
||||
return 0;
|
||||
qint64 ret = _file->read(data, maxlen);
|
||||
qint64 ret = _file.data()->read(data, maxlen);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
_read += ret;
|
||||
@@ -146,7 +152,11 @@ public:
|
||||
}
|
||||
|
||||
virtual bool atEnd() const {
|
||||
return _read >= chunkSize() || _file->atEnd();
|
||||
if (_file.isNull()) {
|
||||
qDebug() << Q_FUNC_INFO << "Upload file object deleted during upload";
|
||||
return true;
|
||||
}
|
||||
return _read >= chunkSize() || _file.data()->atEnd();
|
||||
}
|
||||
|
||||
virtual qint64 size() const{
|
||||
@@ -164,8 +174,13 @@ public:
|
||||
}
|
||||
|
||||
virtual bool seek ( qint64 pos ) {
|
||||
if (_file.isNull()) {
|
||||
qDebug() << Q_FUNC_INFO << "Upload file object deleted during upload";
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
_read = pos;
|
||||
return _file->seek(pos + _start);
|
||||
return _file.data()->seek(pos + _start);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -214,7 +229,7 @@ void PropagateUploadFileQNAM::startNextChunk()
|
||||
currentChunkSize = chunkSize();
|
||||
}
|
||||
}
|
||||
device = new ChunkDevice(_file, chunkSize() * sendingChunk, currentChunkSize);
|
||||
device = new ChunkDevice(_file, chunkSize() * quint64(sendingChunk), currentChunkSize);
|
||||
} else {
|
||||
device = _file;
|
||||
}
|
||||
@@ -288,7 +303,7 @@ void PropagateUploadFileQNAM::slotPutFinished()
|
||||
}
|
||||
|
||||
if (Utility::qDateTimeToTime_t(fi.lastModified()) != _item._modtime) {
|
||||
/* Uh oh: The local file has changed during upload */
|
||||
qDebug() << "The local file has changed during upload:" << _item._modtime << "!=" << Utility::qDateTimeToTime_t(fi.lastModified()) << fi.lastModified();
|
||||
_propagator->_activeJobs--;
|
||||
done(SyncFileItem::SoftError, tr("Local file changed during sync."));
|
||||
// FIXME: the legacy code was retrying for a few seconds.
|
||||
@@ -387,6 +402,7 @@ void GETFileJob::start() {
|
||||
|
||||
setReply(davRequest("GET", path(), req));
|
||||
setupConnections(reply());
|
||||
reply()->setReadBufferSize(128 * 1024);
|
||||
|
||||
if( reply()->error() != QNetworkReply::NoError ) {
|
||||
qWarning() << Q_FUNC_INFO << " Network error: " << reply()->errorString();
|
||||
@@ -423,11 +439,39 @@ void GETFileJob::slotMetaDataChanged()
|
||||
reply()->abort();
|
||||
return;
|
||||
}
|
||||
|
||||
quint64 start = 0;
|
||||
QByteArray ranges = parseEtag(reply()->rawHeader("Content-Range"));
|
||||
if (!ranges.isEmpty()) {
|
||||
QRegExp rx("bytes (\\d+)-");
|
||||
if (rx.indexIn(ranges) >= 0) {
|
||||
start = rx.cap(1).toULongLong();
|
||||
}
|
||||
}
|
||||
if (start != _resumeStart) {
|
||||
qDebug() << Q_FUNC_INFO << "Wrong content-range: "<< ranges << " while expecting start was" << _resumeStart;
|
||||
if (start == 0) {
|
||||
// device don't support range, just stry again from scratch
|
||||
_device->close();
|
||||
if (!_device->open(QIODevice::WriteOnly)) {
|
||||
_errorString = _device->errorString();
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
reply()->abort();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
_errorString = tr("Server returned wrong content-range");
|
||||
_errorStatus = SyncFileItem::NormalError;
|
||||
reply()->abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GETFileJob::slotReadyRead()
|
||||
{
|
||||
int bufferSize = qMax(1024*8ll , reply()->bytesAvailable());
|
||||
int bufferSize = qMin(1024*8ll , reply()->bytesAvailable());
|
||||
QByteArray buffer(bufferSize, Qt::Uninitialized);
|
||||
|
||||
while(reply()->bytesAvailable() > 0) {
|
||||
@@ -529,7 +573,7 @@ void PropagateDownloadFileQNAM::start()
|
||||
|
||||
_job = new GETFileJob(AccountManager::instance()->account(),
|
||||
_propagator->_remoteFolder + _item._file,
|
||||
&_tmpFile, headers, expectedEtagForResume);
|
||||
&_tmpFile, headers, expectedEtagForResume, _startSize);
|
||||
_job->setTimeout(_propagator->httpTimeout() * 1000);
|
||||
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotGetFinished()));
|
||||
connect(_job, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(slotDownloadProgress(qint64,qint64)));
|
||||
|
||||
@@ -99,26 +99,27 @@ private slots:
|
||||
void slotUploadProgress(qint64,qint64);
|
||||
void abort();
|
||||
void startNextChunk();
|
||||
void finalize(const Mirall::SyncFileItem&);
|
||||
void finalize(const SyncFileItem&);
|
||||
};
|
||||
|
||||
|
||||
class GETFileJob : public AbstractNetworkJob {
|
||||
Q_OBJECT
|
||||
QIODevice* _device;
|
||||
QFile* _device;
|
||||
QMap<QByteArray, QByteArray> _headers;
|
||||
QString _errorString;
|
||||
QByteArray _expectedEtagForResume;
|
||||
quint64 _resumeStart;
|
||||
SyncFileItem::Status _errorStatus;
|
||||
public:
|
||||
|
||||
// DOES NOT take owncership of the device.
|
||||
explicit GETFileJob(Account* account, const QString& path, QIODevice *device,
|
||||
explicit GETFileJob(Account* account, const QString& path, QFile *device,
|
||||
const QMap<QByteArray, QByteArray> &headers, QByteArray expectedEtagForResume,
|
||||
QObject* parent = 0)
|
||||
quint64 resumeStart, QObject* parent = 0)
|
||||
: AbstractNetworkJob(account, path, parent),
|
||||
_device(device), _headers(headers), _expectedEtagForResume(expectedEtagForResume),
|
||||
_errorStatus(SyncFileItem::NoStatus) {}
|
||||
_resumeStart(resumeStart), _errorStatus(SyncFileItem::NoStatus) {}
|
||||
|
||||
virtual void start();
|
||||
virtual bool finished() {
|
||||
|
||||
@@ -131,6 +131,13 @@ void ProtocolWidget::slotClearBlacklist()
|
||||
void ProtocolWidget::cleanIgnoreItems(const QString& folder)
|
||||
{
|
||||
int itemCnt = _ui->_treeWidget->topLevelItemCount();
|
||||
|
||||
// Limit the number of items
|
||||
while(itemCnt > 2000) {
|
||||
delete _ui->_treeWidget->takeTopLevelItem(itemCnt - 1);
|
||||
itemCnt--;
|
||||
}
|
||||
|
||||
for( int cnt = itemCnt-1; cnt >=0 ; cnt-- ) {
|
||||
QTreeWidgetItem *item = _ui->_treeWidget->topLevelItem(cnt);
|
||||
bool isErrorItem = item->data(0, IgnoredIndicatorRole).toBool();
|
||||
|
||||
@@ -46,6 +46,13 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
_ui->setupUi(this);
|
||||
|
||||
// People perceive this as a Window, so also make Ctrl+W work
|
||||
QAction *closeWindowAction = new QAction(this);
|
||||
closeWindowAction->setShortcut(QKeySequence("Ctrl+W"));
|
||||
connect(closeWindowAction, SIGNAL(triggered()), SLOT(accept()));
|
||||
addAction(closeWindowAction);
|
||||
|
||||
setObjectName("Settings"); // required as group for saveGeometry call
|
||||
|
||||
setWindowTitle(tr("%1").arg(Theme::instance()->appNameGUI()));
|
||||
|
||||
@@ -30,8 +30,13 @@ SettingsDialogMac::SettingsDialogMac(ownCloudGui *gui, QWidget *parent)
|
||||
|
||||
|
||||
// Emulate dialog behavior: Escape means close
|
||||
QAction *closeDialogAction = new QAction(this);
|
||||
closeDialogAction->setShortcut(QKeySequence(Qt::Key_Escape));
|
||||
connect(closeDialogAction, SIGNAL(triggered()), SLOT(close()));
|
||||
addAction(closeDialogAction);
|
||||
// People perceive this as a Window, so also make Ctrl+W work
|
||||
QAction *closeWindowAction = new QAction(this);
|
||||
closeWindowAction->setShortcut(QKeySequence(Qt::Key_Escape));
|
||||
closeWindowAction->setShortcut(QKeySequence("Ctrl+W"));
|
||||
connect(closeWindowAction, SIGNAL(triggered()), SLOT(close()));
|
||||
addAction(closeWindowAction);
|
||||
|
||||
|
||||
@@ -176,6 +176,11 @@ void SslButton::updateAccountInfo(Account *account)
|
||||
} else {
|
||||
setVisible(true);
|
||||
}
|
||||
if(QMenu *oldMenu = menu()) {
|
||||
oldMenu->hide(); // Need to be hidden because the QToolButton would be left in invalid state if the menu is deleted while it is visible
|
||||
setMenu(0);
|
||||
oldMenu->deleteLater(); // setMenu do not delete the previous menu.
|
||||
}
|
||||
if (account->url().scheme() == QLatin1String("https")) {
|
||||
setIcon(QIcon(QPixmap(":/mirall/resources/lock-https.png")));
|
||||
QSslCipher cipher = account->sslConfiguration().sessionCipher();
|
||||
@@ -212,7 +217,6 @@ void SslButton::updateAccountInfo(Account *account)
|
||||
} else {
|
||||
setIcon(QIcon(QPixmap(":/mirall/resources/lock-http.png")));
|
||||
setToolTip(tr("This connection is NOT secure as it is not encrypted.\n"));
|
||||
setMenu(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ SyncEngine::SyncEngine(CSYNC *ctx, const QString& localPath, const QString& remo
|
||||
, _remoteUrl(remoteURL)
|
||||
, _remotePath(remotePath)
|
||||
, _journal(journal)
|
||||
, _hasFiles(false)
|
||||
, _hasNoneFiles(false)
|
||||
, _hasRemoveFile(false)
|
||||
, _downloadLimit(0)
|
||||
, _uploadLimit(0)
|
||||
|
||||
@@ -330,7 +331,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
dir = SyncFileItem::None;
|
||||
} else {
|
||||
// No need to do anything.
|
||||
_hasFiles = true;
|
||||
_hasNoneFiles = true;
|
||||
|
||||
emit syncItemDiscovered(item);
|
||||
return re;
|
||||
@@ -343,8 +344,9 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
_renamedFolders.insert(item._file, item._renameTarget);
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_REMOVE:
|
||||
_hasRemoveFile = true;
|
||||
dir = !remote ? SyncFileItem::Down : SyncFileItem::Up;
|
||||
break;
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_CONFLICT:
|
||||
case CSYNC_INSTRUCTION_IGNORE:
|
||||
case CSYNC_INSTRUCTION_ERROR:
|
||||
@@ -356,6 +358,11 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
case CSYNC_INSTRUCTION_STAT_ERROR:
|
||||
default:
|
||||
dir = remote ? SyncFileItem::Down : SyncFileItem::Up;
|
||||
if (!remote && file->instruction == CSYNC_INSTRUCTION_SYNC) {
|
||||
// An upload of an existing file means that the file was left unchanged on the server
|
||||
// This count as a NONE for detecting if all the file on the server were changed
|
||||
_hasNoneFiles = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -364,11 +371,6 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
// if the item is on blacklist, the instruction was set to IGNORE
|
||||
checkBlacklisting( &item );
|
||||
|
||||
if (file->instruction != CSYNC_INSTRUCTION_IGNORE
|
||||
&& file->instruction != CSYNC_INSTRUCTION_REMOVE) {
|
||||
_hasFiles = true;
|
||||
}
|
||||
|
||||
if (!item._isDirectory) {
|
||||
_progressInfo._totalFileCount++;
|
||||
if (Progress::isSizeDependent(file->instruction)) {
|
||||
@@ -526,7 +528,8 @@ void SyncEngine::slotUpdateFinished(int updateResult)
|
||||
|
||||
_progressInfo = Progress::Info();
|
||||
|
||||
_hasFiles = false;
|
||||
_hasNoneFiles = false;
|
||||
_hasRemoveFile = false;
|
||||
bool walkOk = true;
|
||||
_seenFiles.clear();
|
||||
|
||||
@@ -556,8 +559,8 @@ void SyncEngine::slotUpdateFinished(int updateResult)
|
||||
emit aboutToPropagate(_syncedItems);
|
||||
emit transmissionProgress(_progressInfo);
|
||||
|
||||
if (!_hasFiles && !_syncedItems.isEmpty()) {
|
||||
qDebug() << Q_FUNC_INFO << "All the files are going to be removed, asking the user";
|
||||
if (!_hasNoneFiles && _hasRemoveFile) {
|
||||
qDebug() << Q_FUNC_INFO << "All the files are going to be changed, asking the user";
|
||||
bool cancel = false;
|
||||
emit aboutToRemoveAllFiles(_syncedItems.first()._direction, &cancel);
|
||||
if (cancel) {
|
||||
|
||||
@@ -127,7 +127,8 @@ private:
|
||||
QHash<QString, QString> _renamedFolders;
|
||||
QString adjustRenamedPath(const QString &original);
|
||||
|
||||
bool _hasFiles; // true if there is at least one file that is not ignored or removed
|
||||
bool _hasNoneFiles; // true if there is at least one file with instruction NONE
|
||||
bool _hasRemoveFile; // true if there is at leasr one file with instruction REMOVE
|
||||
|
||||
int _downloadLimit;
|
||||
int _uploadLimit;
|
||||
|
||||
@@ -164,18 +164,6 @@ QByteArray Utility::userAgentString()
|
||||
.toLatin1();
|
||||
}
|
||||
|
||||
void Utility::raiseDialog( QWidget *raiseWidget )
|
||||
{
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
if( raiseWidget && raiseWidget->parentWidget() == 0) {
|
||||
// Qt has a bug which causes parent-less dialogs to pop-under.
|
||||
raiseWidget->showNormal();
|
||||
raiseWidget->raise();
|
||||
raiseWidget->activateWindow();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Utility::hasLaunchOnStartup(const QString &appName)
|
||||
{
|
||||
return hasLaunchOnStartup_private(appName);
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace Utility
|
||||
OWNCLOUDSYNC_EXPORT QString octetsToString( qint64 octets );
|
||||
OWNCLOUDSYNC_EXPORT QString platform();
|
||||
OWNCLOUDSYNC_EXPORT QByteArray userAgentString();
|
||||
OWNCLOUDSYNC_EXPORT void raiseDialog(QWidget *);
|
||||
OWNCLOUDSYNC_EXPORT bool hasLaunchOnStartup(const QString &appName);
|
||||
OWNCLOUDSYNC_EXPORT void setLaunchOnStartup(const QString &appName, const QString& guiName, bool launch);
|
||||
OWNCLOUDSYNC_EXPORT qint64 freeDiskSpace(const QString &path, bool *ok = 0);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
@@ -145,9 +146,12 @@ void OwncloudSetupPage::initializePage()
|
||||
if (Theme::instance()->overrideServerUrl().isEmpty()) {
|
||||
_ui.leUrl->setFocus();
|
||||
} else {
|
||||
setVisible(false);
|
||||
setCommitPage(true);
|
||||
validatePage();
|
||||
setVisible(false);
|
||||
// because the wizard will call show on us right after this call, we need to hide in the
|
||||
// next event loop iteration.
|
||||
QTimer::singleShot(0, this, SLOT(hide()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,6 @@ void OwncloudWizard::slotCurrentPageChanged( int id )
|
||||
|
||||
if( id == WizardCommon::Page_ServerSetup ) {
|
||||
emit clearPendingRequests();
|
||||
_setupPage->initializePage();
|
||||
}
|
||||
|
||||
if( id == WizardCommon::Page_Result ) {
|
||||
|
||||
Reference in New Issue
Block a user