Merge branch '1.4', brings in the changes we did for 1.4.1

This commit is contained in:
Klaas Freitag 2013-09-24 14:18:25 +02:00
commit 27b9a5aed9
22 changed files with 193 additions and 83 deletions

View file

@ -1,5 +1,27 @@
ChangeLog
=========
version 1.4.1 (release 2013-09-24 ), csync 0.90.1 required
* Translation and documentation fixes.
* Fixed error display in settings/status dialog, displays multi
line error messages now correctly.
* Wait up to 30 secs before complaining about missing systray
Fixes bug #949
* Fixed utf8 issues with basic auth authentication, fixes bug #941
* Fixed remote folder selector, avoid recursive syncing, fixes bug #962
* Handle and display network problems at startup correctly.
* Enable and disable the folder watcher during syncs correctly.
* Fix setting of thread priority.
* Fixed file size display.
* Fixed various folder wizard issues, bug #992
* Made "Sync started" message optional, fixes bug #934
* Fixed shutdown, avoid crashed config on win32, fixes bug #945
* Pop up config wizard if no server url is configured, fixes bug #1018
* Settings: calculate sidebar width dynamically, fixes bug #1020
* Fixed a crash if sync folders were removed, fixes bug #713
* Do proper resync after network disconnect, fixes bug #1007
* Various minor code fixes
version 1.4.0 (release 2013-09-04 ), csync 0.90.0 required
* New Scheduler: Only sync when there are actual changes in the server

View file

@ -271,7 +271,15 @@ set( final_src
include( AddAppIconMacro )
set(ownCloud_old ${ownCloud})
kde4_add_app_icon( ownCloud "${theme_dir}/colored/${APPLICATION_EXECUTABLE}-icon*.png")
# set an icon_app_name. For historical reasons we can not use the
# application_shortname for ownCloud but must rather set it manually.
if ( EXISTS ${OEM_THEME_DIR}/OEM.cmake )
set(ICON_APP_NAME ${APPLICATION_SHORTNAME})
else()
set(ICON_APP_NAME "owncloud")
endif()
kde4_add_app_icon( ownCloud "${theme_dir}/colored/${ICON_APP_NAME}-icon*.png")
list(APPEND final_src ${ownCloud})
set(ownCloud ${ownCloud_old})
@ -283,11 +291,11 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
if(NOT WIN32)
file( GLOB _icons "${theme_dir}/colored/${APPLICATION_EXECUTABLE}-icon-*.png" )
file( GLOB _icons "${theme_dir}/colored/${ICON_APP_NAME}-icon-*.png" )
foreach( _file ${_icons} )
string( REPLACE "${theme_dir}/colored/${APPLICATION_EXECUTABLE}-icon-" "" _res ${_file} )
string( REPLACE "${theme_dir}/colored/${ICON_APP_NAME}-icon-" "" _res ${_file} )
string( REPLACE ".png" "" _res ${_res} )
install( FILES ${_file} RENAME ${APPLICATION_EXECUTABLE}.png DESTINATION ${DATADIR}/icons/hicolor/${_res}x${_res}/apps )
install( FILES ${_file} RENAME ${ICON_APP_NAME}.png DESTINATION ${DATADIR}/icons/hicolor/${_res}x${_res}/apps )
endforeach( _file )
endif(NOT WIN32)

View file

@ -50,8 +50,7 @@ static const char progressBarStyleC[] =
AccountSettings::AccountSettings(QWidget *parent) :
QWidget(parent),
ui(new Ui::AccountSettings),
_item(0)
ui(new Ui::AccountSettings)
{
ui->setupUi(this);
@ -205,11 +204,6 @@ void AccountSettings::buttonsSetEnabled()
ui->_ButtonInfo->setEnabled(isSelected);
}
void AccountSettings::setListWidgetItem( QListWidgetItem *item )
{
_item = item;
}
void AccountSettings::setGeneralErrors( const QStringList& errors )
{
_generalErrors = errors;
@ -261,6 +255,8 @@ void AccountSettings::slotRemoveCurrentFolder()
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
if( selected.isValid() ) {
int row = selected.row();
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
qDebug() << "Remove Folder alias " << alias;
if( !alias.isEmpty() ) {
@ -274,9 +270,22 @@ void AccountSettings::slotRemoveCurrentFolder()
if( ret == QMessageBox::No ) {
return;
}
/* Remove the selected item from the timer hash. */
QStandardItem *item = NULL;
if( selected.isValid() )
item = _model->itemFromIndex(selected);
if( selected.isValid() && item && _hideProgressTimers.contains(item) ) {
QTimer *t = _hideProgressTimers[item];
t->stop();
_hideProgressTimers.remove(item);
delete(t);
}
FolderMan *folderMan = FolderMan::instance();
folderMan->slotRemoveFolder( alias );
setFolderList(folderMan->map());
_model->removeRow(row);
emit folderChanged();
slotCheckConnection();
}
@ -349,8 +358,14 @@ void AccountSettings::slotCheckConnection()
void AccountSettings::setFolderList( const Folder::Map &folders )
{
_model->clear();
foreach(QTimer *t, _hideProgressTimers) {
t->stop();
delete t;
}
_hideProgressTimers.clear();
foreach( Folder *f, folders ) {
qDebug() << "Folder: " << f;
slotAddFolder( f );
}
@ -674,12 +689,21 @@ void AccountSettings::slotHideProgress()
while (i != _hideProgressTimers.constEnd()) {
if( i.value() == send_timer ) {
QStandardItem *item = i.key();
item->setData( QVariant(false), FolderStatusDelegate::AddProgressSpace );
item->setData( QVariant(QString::null), FolderStatusDelegate::SyncProgressOverallString );
item->setData( QVariant(QString::null), FolderStatusDelegate::SyncProgressItemString );
item->setData( 0, FolderStatusDelegate::SyncProgressOverallPercent );
ui->_folderList->repaint();
/* Check if this item is still existing */
bool ok = false;
for( int r = 0; !ok && r < _model->rowCount(); r++) {
if( item == _model->item(r,0) ) {
ok = true;
}
}
if( ok ) {
item->setData( QVariant(false), FolderStatusDelegate::AddProgressSpace );
item->setData( QVariant(QString::null), FolderStatusDelegate::SyncProgressOverallString );
item->setData( QVariant(QString::null), FolderStatusDelegate::SyncProgressItemString );
item->setData( 0, FolderStatusDelegate::SyncProgressOverallPercent );
}
_hideProgressTimers.remove(item);
break;
}

View file

@ -51,7 +51,6 @@ public:
void setFolderList( const Folder::Map& );
void buttonsSetEnabled();
void setListWidgetItem(QListWidgetItem* item);
signals:
void folderChanged();
@ -98,7 +97,6 @@ private:
QPointer<ItemProgressDialog> _fileItemDialog;
QPointer<IgnoreListEditor> _ignoreEditor;
QStandardItemModel *_model;
QListWidgetItem *_item;
QUrl _OCUrl;
QHash<QStandardItem*, QTimer*> _hideProgressTimers;
QString _kindContext;

View file

@ -23,7 +23,6 @@
#include "mirall/folder.h"
#include "mirall/folderman.h"
#include "mirall/folderwatcher.h"
#include "mirall/folderwizard.h"
#include "mirall/networklocation.h"
#include "mirall/folder.h"
#include "mirall/owncloudsetupwizard.h"
@ -179,18 +178,13 @@ Application::Application(int &argc, char **argv) :
connect( ownCloudInfo::instance(), SIGNAL(quotaUpdated(qint64,qint64)),
SLOT(slotRefreshQuotaDisplay(qint64, qint64)));
connect (this, SIGNAL(aboutToQuit()), SLOT(slotCleanup()));
qDebug() << "Network Location: " << NetworkLocation::currentLocation().encoded();
}
Application::~Application()
{
if (_settingsDialog) {
delete _settingsDialog.data();
}
delete _logBrowser;
delete _tray; // needed, see ctor
qDebug() << "* Mirall shutdown";
}
@ -229,6 +223,20 @@ void Application::slotCredentialsFetched()
runValidator();
}
void Application::slotCleanup()
{
// explicitly close windows. This is somewhat of a hack to ensure
// that saving the geometries happens ASAP during a OS shutdown
// those do delete on close
if (!_settingsDialog.isNull()) _settingsDialog->close();
if (!_progressDialog.isNull()) _progressDialog->close();
// those need an extra invitation
if (!_tray.isNull()) _tray->deleteLater();
if (!_logBrowser.isNull()) _logBrowser->deleteLater();
}
void Application::runValidator()
{
_startupFail.clear();
@ -251,7 +259,7 @@ void Application::slotConnectionValidatorResult(ConnectionValidator::Status stat
_tray->show();
int cnt = folderMan->map().size();
slotShowTrayMessage(tr("%1 Sync Started").arg(_theme->appNameGUI()),
slotShowOptionalTrayMessage(tr("%1 Sync Started").arg(_theme->appNameGUI()),
tr("Sync started for %n configured sync folder(s).","", cnt));
// queue up the sync for all folders.
@ -350,7 +358,7 @@ void Application::setupSystemTray()
_tray = new Systray();
_tray->setIcon( _theme->syncStateIcon( SyncResult::NotYetStarted, true ) );
connect(_tray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
connect(_tray.data(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
setupContextMenu();
@ -428,7 +436,7 @@ void Application::setupContextMenu()
void Application::setupLogBrowser()
{
// might be called from second instance
if (!_logBrowser) {
if (_logBrowser.isNull()) {
// init the log browser.
qInstallMsgHandler( mirallLogCatcher );
_logBrowser = new LogBrowser;
@ -665,7 +673,7 @@ bool Application::checkConfigExists(bool openSettings)
// if no config file is there, start the configuration wizard.
MirallConfigFile cfgFile;
if( cfgFile.exists() ) {
if( cfgFile.exists() && !cfgFile.ownCloudUrl().isEmpty() ) {
if( openSettings ) {
slotSettings();
}
@ -699,7 +707,7 @@ void Application::slotSettings()
}
_settingsDialog->setGeneralErrors( _startupFail );
Utility::raiseDialog(_settingsDialog);
Utility::raiseDialog(_settingsDialog.data());
}
void Application::slotItemProgressDialog()
@ -710,7 +718,7 @@ void Application::slotItemProgressDialog()
_progressDialog->setupList();
_progressDialog->show();
}
Utility::raiseDialog(_progressDialog);
Utility::raiseDialog(_progressDialog.data());
}
void Application::slotParseOptions(const QString &opts)

View file

@ -40,7 +40,6 @@ namespace Mirall {
class Theme;
class Folder;
class FolderWatcher;
class FolderWizard;
class ownCloudInfo;
class SslErrorDialog;
class SettingsDialog;
@ -107,13 +106,14 @@ protected slots:
void slotDisplayIdle();
void slotHelp();
void slotCredentialsFetched();
void slotCleanup();
private:
void setHelp();
void raiseDialog( QWidget* );
void rebuildRecentMenus();
void runValidator();
Systray *_tray;
QPointer<Systray> _tray;
QAction *_actionOpenoC;
QAction *_actionSettings;
QAction *_actionQuota;
@ -124,7 +124,6 @@ private:
QNetworkConfigurationManager *_networkMgr;
QPointer<FolderWizard> _folderWizard;
SslErrorDialog *_sslErrorDialog;
ConnectionValidator *_conValidator;
@ -134,7 +133,7 @@ private:
Theme *_theme;
QSignalMapper *_folderOpenActionMapper;
LogBrowser *_logBrowser;
QPointer<LogBrowser>_logBrowser;
QPointer<SettingsDialog> _settingsDialog;
QPointer<ItemProgressDialog> _progressDialog;

View file

@ -116,6 +116,7 @@ bool Folder::init()
}
return _csync_ctx;
}
Folder::~Folder()
{
if( _thread ) {
@ -202,9 +203,8 @@ void Folder::setSyncEnabled( bool doit )
{
_enabled = doit;
qDebug() << "setSyncEnabled - ############################ " << doit;
if( doit ) {
evaluateSync( QStringList() );
// qDebug() << "Syncing enabled on folder " << name();
} else {
// do not stop or start the watcher here, that is done internally by
// folder class. Even if the watcher fires, the folder does not
@ -240,8 +240,9 @@ void Folder::slotPollTimerTimeout()
{
qDebug() << "* Polling" << alias() << "for changes. (time since next sync:" << (_timeSinceLastSync.elapsed() / 1000) << "s)";
if (quint64(_timeSinceLastSync.elapsed()) > MirallConfigFile().forceSyncInterval()) {
qDebug() << "* Force Sync now";
if (quint64(_timeSinceLastSync.elapsed()) > MirallConfigFile().forceSyncInterval() ||
_syncResult.status() != SyncResult::Success ) {
qDebug() << "** Force Sync now";
evaluateSync(QStringList());
} else {
RequestEtagJob* job = new RequestEtagJob(secondPath(), this);

View file

@ -280,6 +280,7 @@ void FolderMan::slotEnableFolder( const QString& alias, bool enable )
Folder *f = _folderMap[alias];
if( f ) {
f->setSyncEnabled(enable);
f->evaluateSync(QStringList());
}
}
@ -471,7 +472,10 @@ void FolderMan::removeFolder( const QString& alias )
qDebug() << "Remove folder config file " << file.fileName();
file.remove();
}
f->deleteLater();
// FIXME: this is a temporar dirty fix against a crash happening because
// the csync owncloud module still has static components. Activate the
// delete once the module is fixed.
// f->deleteLater();
}
}

View file

@ -243,6 +243,7 @@ static void recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QStr
item = new QTreeWidgetItem(parent);
item->setIcon(0, folderIcon);
item->setText(0, pathTrail.first());
item->setData(0, Qt::UserRole, pathTrail.first());
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
}
@ -253,17 +254,13 @@ static void recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QStr
void FolderWizardTargetPage::slotUpdateDirectories(QStringList list)
{
QFileIconProvider prov;
QIcon folderIcon = prov.icon(QFileIconProvider::Folder);
QString webdavFolder = QUrl(ownCloudInfo::instance()->webdavUrl()).path();
connect(_ui.folderTreeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)), SLOT(slotItemExpanded(QTreeWidgetItem*)));
QTreeWidgetItem *root = _ui.folderTreeWidget->topLevelItem(0);
if (!root) {
root = new QTreeWidgetItem(_ui.folderTreeWidget);
root->setText(0, tr("Root (\"/\")", "root folder"));
root->setIcon(0, folderIcon);
root->setText(0, Theme::instance()->appNameGUI());
root->setIcon(0, Theme::instance()->applicationIcon());
root->setToolTip(0, tr("Choose this to sync the entire account"));
root->setData(0, Qt::UserRole, "/");
}
@ -284,7 +281,7 @@ void FolderWizardTargetPage::slotRefreshFolders()
void FolderWizardTargetPage::slotItemExpanded(QTreeWidgetItem *item)
{
ownCloudInfo::instance()->getDirectoryListing(item->text(0));
ownCloudInfo::instance()->getDirectoryListing(item->data(0, Qt::UserRole).toString());
}
FolderWizardTargetPage::~FolderWizardTargetPage()
@ -342,6 +339,8 @@ void FolderWizardTargetPage::initializePage()
SLOT(slotCreateRemoteFolderFinished( QNetworkReply::NetworkError )));
connect( ocInfo, SIGNAL(directoryListingUpdated(QStringList)),
SLOT(slotUpdateDirectories(QStringList)));
connect(_ui.folderTreeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)),
SLOT(slotItemExpanded(QTreeWidgetItem*)));
slotRefreshFolders();
}

View file

@ -127,11 +127,16 @@ LogBrowser::LogBrowser(QWidget *parent) :
}
LogBrowser::~LogBrowser()
{
}
void LogBrowser::closeEvent(QCloseEvent *)
{
MirallConfigFile cfg;
cfg.saveGeometry(this);
}
void LogBrowser::slotNewLog( const QString& msg )
{
if( _logWidget->isVisible() ) {

View file

@ -47,6 +47,9 @@ public:
void setLogFile(const QString& , bool );
protected:
void closeEvent(QCloseEvent *);
protected slots:
void slotNewLog( const QString &msg );
void slotFind();

View file

@ -139,7 +139,8 @@ QNetworkReply* ownCloudInfo::mkdirRequest( const QString& dir )
_authAttempts = 0;
QNetworkRequest req;
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
QUrl url(webdavUrl(_connection));
QUrl url( webdavUrl(_connection) );
// ensure #, ? and co are interpreted as part of the path and nothing else
url.setEncodedPath(url.encodedPath()+QUrl::toPercentEncoding(dir, "/"));
#else
QUrl url(webdavUrl(_connection));
@ -166,7 +167,7 @@ QNetworkReply* ownCloudInfo::mkdirRequest( const QString& dir )
QNetworkReply* ownCloudInfo::getQuotaRequest( const QString& dir )
{
QNetworkRequest req;
req.setUrl( QUrl( webdavUrl(_connection) + dir ) );
req.setUrl( QUrl( webdavUrl(_connection) + QUrl::toPercentEncoding(dir, "/") ) );
req.setRawHeader("Depth", "0");
QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"
@ -194,7 +195,10 @@ QNetworkReply* ownCloudInfo::getQuotaRequest( const QString& dir )
QNetworkReply* ownCloudInfo::getDirectoryListing( const QString& dir )
{
QNetworkRequest req;
req.setUrl( QUrl( webdavUrl(_connection) + dir ) );
QUrl url( webdavUrl(_connection) );
// ensure #, ? and co are interpreted as part of the path and nothing else
url.setPath(url.path() + dir );
req.setUrl( url );
req.setRawHeader("Depth", "1");
QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"

View file

@ -63,8 +63,15 @@ OwncloudSetupWizard::~OwncloudSetupWizard()
void OwncloudSetupWizard::runWizard(QObject* obj, const char* amember, QWidget *parent)
{
OwncloudSetupWizard *wiz = new OwncloudSetupWizard(parent);
static QPointer<OwncloudSetupWizard> wiz;
if (!wiz.isNull()) {
return;
}
wiz = new OwncloudSetupWizard(parent);
connect( wiz, SIGNAL(ownCloudWizardDone(int)), obj, amember);
connect( wiz, SIGNAL(ownCloudWizardDone(int)), wiz, SLOT(deleteLater()));
FolderMan::instance()->setSyncEnabled(false);
wiz->startWizard();
}

View file

@ -95,15 +95,29 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
connect(showLogWindow, SIGNAL(triggered()), app, SLOT(slotOpenLogBrowser()));
addAction(showLogWindow);
int iconSize = 32;
QListWidget *listWidget = _ui->labelWidget;
int spacing = 20;
// reverse at least ~8 characters
int effectiveWidth = fontMetrics().averageCharWidth() * 8 + iconSize + spacing;
// less than ~16 characters, elide otherwise
int maxWidth = fontMetrics().averageCharWidth() * 16 + iconSize + spacing;
for (int i = 0; i < listWidget->count(); i++) {
QListWidgetItem *item = listWidget->item(i);
QFontMetrics fm(item->font());
int curWidth = fm.width(item->text()) + iconSize + spacing;
effectiveWidth = qMax(curWidth, effectiveWidth);
if (curWidth > maxWidth) item->setToolTip(item->text());
}
effectiveWidth = qMin(effectiveWidth, maxWidth);
listWidget->setFixedWidth(effectiveWidth);
MirallConfigFile cfg;
cfg.restoreGeometry(this);
}
SettingsDialog::~SettingsDialog()
{
MirallConfigFile cfg;
cfg.saveGeometry(this);
delete _ui;
}
@ -128,4 +142,17 @@ void SettingsDialog::setGeneralErrors(const QStringList &errors)
_accountSettings->setGeneralErrors(errors);
}
// close event is not being called here
void SettingsDialog::reject() {
MirallConfigFile cfg;
cfg.saveGeometry(this);
QDialog::reject();
}
void SettingsDialog::accept() {
MirallConfigFile cfg;
cfg.saveGeometry(this);
QDialog::accept();
}
} // namespace Mirall

View file

@ -42,6 +42,10 @@ public:
void addAccount(const QString &title, QWidget *widget);
void setGeneralErrors( const QStringList& errors );
protected:
void reject();
void accept();
protected slots:
void slotUpdateAccountState();

View file

@ -14,16 +14,7 @@
<string>Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
@ -37,12 +28,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1">

View file

@ -22,13 +22,13 @@
class QSslError;
class QSslCertificate;
namespace Mirall
{
namespace Ui {
class SslErrorDialog;
}
namespace Mirall
{
class SslErrorDialog : public QDialog
{
Q_OBJECT
@ -57,7 +57,7 @@ private:
QList<QSslCertificate> _unknownCerts;
QString _customConfigHandle;
::Ui::SslErrorDialog *_ui;
Ui::SslErrorDialog *_ui;
};
} // end namespace

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SslErrorDialog</class>
<widget class="QWidget" name="SslErrorDialog">
<class>Mirall::SslErrorDialog</class>
<widget class="QWidget" name="Mirall::SslErrorDialog">
<property name="geometry">
<rect>
<x>0</x>

View file

@ -1,3 +1,16 @@
/*
* 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 SYNCFILEITEM_H
#define SYNCFILEITEM_H

View file

@ -393,7 +393,6 @@ QString Utility::dataLocation()
#endif
}
void Utility::sleep(int sec)
{
#ifdef Q_OS_WIN

View file

@ -17,6 +17,7 @@
#include <QDir>
#include <QFileDialog>
#include <QUrl>
#include <QTimer>
#include "QProgressIndicator.h"
@ -26,7 +27,6 @@
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "creds/abstractcredentials.h"
namespace Mirall
{
@ -89,8 +89,8 @@ void OwncloudAdvancedSetupPage::initializePage()
// call to init label
updateStatus();
// TODO: focus
_ui.pbSelectLocalFolder->setFocus();
// ensure "next" gets the focus, not obSelectLocalFolder
QTimer::singleShot(0, wizard()->button(QWizard::NextButton), SLOT(setFocus()));
}
// Called if the user changes the user- or url field. Adjust the texts and

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 781 B