Comparar commits

..

22 Commits

Autor SHA1 Mensagem Data
Jenkins for ownCloud b66125baa7 [tx-robot] updated from transifex 2013-07-30 01:26:48 -04:00
Jenkins for ownCloud 1bc7468287 [tx-robot] updated from transifex 2013-07-28 01:27:25 -04:00
Jenkins for ownCloud bb5ea68807 [tx-robot] updated from transifex 2013-07-24 01:26:42 -04:00
Jenkins for ownCloud 9641ed1202 [tx-robot] updated from transifex 2013-07-22 01:26:25 -04:00
Jenkins for ownCloud c736439440 [tx-robot] updated from transifex 2013-07-21 01:26:20 -04:00
Jenkins for ownCloud 50674cf153 [tx-robot] updated from transifex 2013-07-18 01:26:22 -04:00
Jenkins for ownCloud 7270644e84 [tx-robot] updated from transifex 2013-07-17 02:15:53 -04:00
Jenkins for ownCloud 43b4ddd722 [tx-robot] updated from transifex 2013-07-16 01:27:18 -04:00
Jenkins for ownCloud bdd91712e7 [tx-robot] updated from transifex 2013-07-15 17:11:07 -04:00
Jenkins for ownCloud 72efce1416 [tx-robot] updated from transifex 2013-07-14 01:45:10 +02:00
Jenkins for ownCloud 3ff8db10e8 [tx-robot] updated from transifex 2013-07-13 01:26:34 +02:00
Klaas Freitag 24bdf60bd7 Documented the docexpire option.
(cherry picked from commit 5da6103fb5)
2013-07-12 18:17:18 +02:00
Daniel Molkentin 79924d5eec Detect missing system tray
Fixes #497
(cherry picked from commit a63863b65c)
2013-07-12 18:16:48 +02:00
Daniel Molkentin 4cebcce735 Folder wizard: Warn if a chosen dir is read-only
Fixes #755
2013-07-12 13:36:25 +02:00
Jenkins for ownCloud 48441ccb96 [tx-robot] updated from transifex 2013-07-11 01:28:57 +02:00
Jenkins for ownCloud 183fe2735d [tx-robot] updated from transifex 2013-07-09 01:29:53 +02:00
Jenkins for ownCloud 957dea03a6 [tx-robot] updated from transifex 2013-07-06 01:28:00 +02:00
Jenkins for ownCloud 859f79087f [tx-robot] updated from transifex 2013-07-05 01:26:53 +02:00
Jenkins for ownCloud 9be49c0c9a [tx-robot] updated from transifex 2013-07-04 09:37:46 +02:00
Jenkins for ownCloud 3fdc8aeecb [tx-robot] updated from transifex 2013-07-02 15:39:13 +02:00
Jenkins for ownCloud 68085915c4 [tx-robot] updated from transifex 2013-06-29 01:58:03 +02:00
Jenkins for ownCloud ca4ad7b71c [tx-robot] updated from transifex 2013-06-28 01:27:27 +02:00
201 arquivos alterados com 64051 adições e 48911 exclusões
+2 -4
Ver Arquivo
@@ -4,8 +4,6 @@ project(mirall)
set(PACKAGE "mirall")
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
include(Warnings)
set(OEM_THEME_DIR "" CACHE STRING "Define directory containing a custom theme")
if ( EXISTS ${OEM_THEME_DIR}/OEM.cmake )
include ( ${OEM_THEME_DIR}/OEM.cmake )
@@ -64,9 +62,9 @@ endif()
####
#### find libs
find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest QtWebkit REQUIRED )
find_package(Qt4 4.6.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest REQUIRED )
if( UNIX AND NOT APPLE ) # Fdo notifications
find_package(Qt4 4.7.0 COMPONENTS QtDBus REQUIRED )
find_package(Qt4 4.6.0 COMPONENTS QtDBus REQUIRED )
endif()
find_package(Csync REQUIRED)
if(UNIX)
-28
Ver Arquivo
@@ -1,33 +1,5 @@
ChangeLog
=========
version 1.4.0beta1 (release 2013-08-08 ), csync 0.81.0 required
* New Scheduler: Only sync when there are actual changes in the server
* Add a Settings Dialog, move Proxy Settings there
* Transform folder Status Dialog into Account Settings, provide feedback via context menu
* Add Bandwidth Control
* Add a visual storage/quota indicator (context menu and account settings)
* Add progress indication (context menu and account settings)
* Introduce a sync history, persisting results across syncs
* Move ability to switch to mono icons from a switch to a Settings option
* Add "Launch on System Startup" GUI option
* Add "Show Desktop Nofications"GUI option (enabled by default)
top optionally disable sync notifications
* Add Help item, pointing to online reference
* Implement graphical selection of remote folders in FolderWizard
* Allow custom ignore patterns
* Add an editor for ingore patterns
* ALlow to flag certain ignore patterns as discardable
* Ensure to ship with all valid translations
* Add preliminary support for Shibboleth authentication
* Linux: Provide more icon sizes
* Linux: Do not trigger notifier on ignored files
* Windows: Reduce priority of CSync thread
* Documentation: Prem. updates to reflect UI changes
* Significant code refactorings
* Require Qt 4.7
* Known issue: Under certain conditions, a file will only get uploaded after up to five minutes
version 1.3.0 (release 2013-06-25 ), csync 0.80.0 required
* Default proxy port to 8080
+2 -2
Ver Arquivo
@@ -1,6 +1,6 @@
set( VERSION_MAJOR 1 )
set( VERSION_MINOR 4 )
set( VERSION_MINOR 3 )
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})
set( SOVERSION 0 )
+93 -12
Ver Arquivo
@@ -18,6 +18,7 @@
!define OPTION_SECTION_SC_START_MENU
!define OPTION_SECTION_SC_DESKTOP
!define OPTION_SECTION_SC_QUICK_LAUNCH
!define OPTION_SECTION_SC_AUTOSTART
!define OPTION_FINISHPAGE
!define OPTION_FINISHPAGE_LAUNCHER
; !define OPTION_FINISHPAGE_RELEASE_NOTES
@@ -282,20 +283,84 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
!ifndef INSTALL_PATH
;Main executable.
File "${BUILD_PATH}\bin\${APPLICATION_EXECUTABLE}"
File "${BUILD_PATH}\src\lib${APPLICATION_SHORTNAME}sync.dll"
File "${BUILD_PATH}\src\libowncloudsync.dll"
File "${BUILD_PATH}\src\mirall_*.qm"
; Make sure only to copy qt, not qt_help, etc
File "${MING_SHARE}\qt4\translations\qt_??.qm"
File "${MING_SHARE}\qt4\translations\qt_??_??.qm"
File "${MING_SHARE}\qt4\translations\qtkeychain_*.qm"
File "${BUILD_PATH}\src\mirall_ca.qm"
File "${BUILD_PATH}\src\mirall_cs_CZ.qm"
File "${BUILD_PATH}\src\mirall_da.qm"
File "${BUILD_PATH}\src\mirall_de.qm"
File "${BUILD_PATH}\src\mirall_el.qm"
File "${BUILD_PATH}\src\mirall_en.qm"
File "${BUILD_PATH}\src\mirall_eo.qm"
File "${BUILD_PATH}\src\mirall_es.qm"
File "${BUILD_PATH}\src\mirall_es_AR.qm"
File "${BUILD_PATH}\src\mirall_et_EE.qm"
File "${BUILD_PATH}\src\mirall_eu.qm"
File "${BUILD_PATH}\src\mirall_fa.qm"
File "${BUILD_PATH}\src\mirall_fi_FI.qm"
File "${BUILD_PATH}\src\mirall_fr.qm"
File "${BUILD_PATH}\src\mirall_gl.qm"
File "${BUILD_PATH}\src\mirall_he.qm"
File "${BUILD_PATH}\src\mirall_hr.qm"
File "${BUILD_PATH}\src\mirall_hu_HU.qm"
File "${BUILD_PATH}\src\mirall_it.qm"
File "${BUILD_PATH}\src\mirall_ja_JP.qm"
File "${BUILD_PATH}\src\mirall_ko.qm"
File "${BUILD_PATH}\src\mirall_lb.qm"
File "${BUILD_PATH}\src\mirall_lt_LT.qm"
File "${BUILD_PATH}\src\mirall_lv.qm"
File "${BUILD_PATH}\src\mirall_mk.qm"
File "${BUILD_PATH}\src\mirall_ms_MY.qm"
File "${BUILD_PATH}\src\mirall_nb_NO.qm"
File "${BUILD_PATH}\src\mirall_nl.qm"
File "${BUILD_PATH}\src\mirall_oc.qm"
File "${BUILD_PATH}\src\mirall_pl.qm"
File "${BUILD_PATH}\src\mirall_pt_BR.qm"
File "${BUILD_PATH}\src\mirall_pt_PT.qm"
File "${BUILD_PATH}\src\mirall_ro.qm"
File "${BUILD_PATH}\src\mirall_ru.qm"
File "${BUILD_PATH}\src\mirall_ru_RU.qm"
File "${BUILD_PATH}\src\mirall_si_LK.qm"
File "${BUILD_PATH}\src\mirall_sk_SK.qm"
File "${BUILD_PATH}\src\mirall_sl.qm"
File "${BUILD_PATH}\src\mirall_sr@latin.qm"
File "${BUILD_PATH}\src\mirall_sv.qm"
File "${BUILD_PATH}\src\mirall_ta_LK.qm"
File "${BUILD_PATH}\src\mirall_th_TH.qm"
File "${BUILD_PATH}\src\mirall_tr.qm"
File "${BUILD_PATH}\src\mirall_uk.qm"
File "${BUILD_PATH}\src\mirall_vi.qm"
File "${BUILD_PATH}\src\mirall_zh_CN.qm"
File "${BUILD_PATH}\src\mirall_zh_TW.qm"
#File "${MING_SHARE}\qt4\translations\qt_ar.qm"
File "${MING_SHARE}\qt4\translations\qt_cs.qm"
File "${MING_SHARE}\qt4\translations\qt_da.qm"
File "${MING_SHARE}\qt4\translations\qt_de.qm"
File "${MING_SHARE}\qt4\translations\qt_es.qm"
File "${MING_SHARE}\qt4\translations\qt_fa.qm"
File "${MING_SHARE}\qt4\translations\qt_fr.qm"
File "${MING_SHARE}\qt4\translations\qt_gl.qm"
File "${MING_SHARE}\qt4\translations\qt_he.qm"
File "${MING_SHARE}\qt4\translations\qt_hu.qm"
File "${MING_SHARE}\qt4\translations\qt_ja.qm"
File "${MING_SHARE}\qt4\translations\qt_ko.qm"
File "${MING_SHARE}\qt4\translations\qt_lt.qm"
File "${MING_SHARE}\qt4\translations\qt_pl.qm"
File "${MING_SHARE}\qt4\translations\qt_pt.qm"
File "${MING_SHARE}\qt4\translations\qt_ru.qm"
File "${MING_SHARE}\qt4\translations\qt_sk.qm"
File "${MING_SHARE}\qt4\translations\qt_sl.qm"
File "${MING_SHARE}\qt4\translations\qt_sv.qm"
File "${MING_SHARE}\qt4\translations\qt_uk.qm"
File "${MING_SHARE}\qt4\translations\qt_zh_CN.qm"
File "${MING_SHARE}\qt4\translations\qt_zh_TW.qm"
File "${MING_SHARE}\qt4\translations\qt_zh_TW.qm"
File "${MING_SHARE}\qt4\translations\qtkeychain_de.qm"
SetOutPath "$INSTDIR\accessible"
File "${ACCESSIBLE_DLL_PATH}\qtaccessiblewidgets4.dll"
SetOutPath "$INSTDIR\imageformats"
File "${IMAGEFORMATS_DLL_PATH}\qgif4.dll"
File "${IMAGEFORMATS_DLL_PATH}\qjpeg4.dll"
File "${IMAGEFORMATS_DLL_PATH}\qico4.dll"
SetOutPath "$INSTDIR\modules"
; FIXME: fix installation dir of module, currently needs manual copying to
@@ -316,7 +381,6 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
File "${QT_DLL_PATH}\QtGui4.dll"
File "${QT_DLL_PATH}\QtNetwork4.dll"
File "${QT_DLL_PATH}\QtXml4.dll"
File "${QT_DLL_PATH}\QtWebKit4.dll"
;QtKeyChain stuff
File "${MING_BIN}\libqtkeychain.dll"
@@ -340,7 +404,7 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
; Other
;File "${MING_BIN}\libpng15-15.dll"
File "${MING_BIN}\libjpeg-8.dll"
;File "${MING_BIN}\libjpeg-8.dll"
File "${MING_BIN}\zlib1.dll"
File "${MING_BIN}\libcrypto-10.dll"
File "${MING_BIN}\libssl-10.dll"
@@ -391,6 +455,17 @@ SectionGroup "Shortcuts"
SectionGroupEnd
!ifdef OPTION_SECTION_SC_AUTOSTART
${MementoSection} "Autostart" SEC_AUTOSTART
SectionIn 1 2
SetDetailsPrint textonly
DetailPrint "Creating Windows Start Entry"
SetDetailsPrint listonly
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Run" \
"${APPLICATION_NAME}" "$INSTDIR\${APPLICATION_EXECUTABLE}"
${MementoSectionEnd}
!endif
${MementoSectionDone}
; Installer section descriptions
@@ -400,6 +475,7 @@ ${MementoSectionDone}
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_START_MENU} "${APPLICATION_NAME} program group."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_DESKTOP} "Desktop shortcut for ${APPLICATION_NAME}."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_QUICK_LAUNCH} "Quick Launch shortcut for ${APPLICATION_NAME}."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_AUTOSTART} "Register ${APPLICATION_NAME} to run on Windows startup."
!insertmacro MUI_FUNCTION_DESCRIPTION_END
Section -post
@@ -502,6 +578,11 @@ Section Uninstall
DeleteRegKey HKCR "${APPLICATION_NAME}"
;Windows Start entry
!ifdef OPTION_SECTION_SC_AUTOSTART
DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "${APPLICATION_NAME}"
!endif
;Start menu shortcuts.
!ifdef OPTION_SECTION_SC_START_MENU
SetShellVarContext all
-20
Ver Arquivo
@@ -1,20 +0,0 @@
if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic -Wno-long-long")
else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -pedantic -Wno-long-long")
endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
endif(CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_CXX_COMPILER MATCHES "clang")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -pedantic -Wno-long-long")
endif(CMAKE_CXX_COMPILER MATCHES "clang")
# TODO: handle msvc compilers warnings?
if(DEFINED MIRALL_FATAL_WARNINGS)
if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER MATCHES "clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER MATCHES "clang")
# TODO: handle msvc compilers warnings?
endif(DEFINED MIRALL_FATAL_WARNINGS)
+1
Ver Arquivo
@@ -2,6 +2,7 @@
#define CONFIG_H
#cmakedefine USE_INOTIFY 1
#cmakedefine WITH_CSYNC 1
#cmakedefine WITH_QTKEYCHAIN 1
#cmakedefine GIT_SHA1 "@GIT_SHA1@"
+19 -53
Ver Arquivo
@@ -34,13 +34,8 @@ server is always master.
This is the major difference to other systems like a file backup where just
changes and new files are propagated but files never get deleted.
The oCC checks both repositories for changes frequently after a certain time
span. That is refered to as a sync run. In between the local repository is
monitored by a file system monitor system that starts a sync run immediately
if something was edited, added or removed.
Sync by Time versus ETag
------------------------
Sync Direction and Strategies
-----------------------------
.. index:: time stamps, file times, etag, unique id
Until the release of ownCloud 4.5 and ownCloud Client 1.1, ownCloud employed
@@ -49,7 +44,7 @@ synced to the other repository: the files modification time.
The *modification timestamp* is part of the files metadata. It is available on
every relevant filesystem and is the natural indicator for a file change.
Modification timestamps do not require special action to create and have
modification timestamps do not require special action to create and have
a general meaning. One design goal of csync is to not require a special server
component, thats why it was chosen as the backend component.
@@ -62,22 +57,29 @@ machines.
Since this strategy is rather fragile without NTP, ownCloud 4.5 introduced a
unique number, which changes whenever the file changes. Although it is a unique
value, it is not a hash of the file, but a randomly chosen number, which it will
transmit in the Etag_ field. Since the file number is guaranteed to change if the
file changes, it can now be used to determine if one of the files has changed.
transmit in the Etag_ field. The client will store this number in a
per-directory database, located in the application directory (version 1.1) or
as a hidden file right in the directory to be synced (later versions).
Since the file number is guaranteed to change if the file changes, it can now be
used to determine if one of the files has changed.
.. note:: oCC 1.1 and newer require file ID capabilities on the ownCloud server,
hence using them with a server earlier than 4.5.0 is not supported.
Before the 1.3.0 release of the client the sync process might create faux conflict
files if time deviates. The original and the conflict files only differed in the
timestamp, but not in content. This behaviour was changed towards a binary check
if the files are different.
.. todo:: describe what happens if both sides change
If the per-directory database gets removed, oCC's CSync backend will fall back
to a time-stamp based sync process to rebuild the database. Thus it should be
made sure that both server and client synchronized to NTP time before
restarting the client after a database removal. If time deviates, the sync
process might create faux conflict files, which only differ in their time.
Those need to be cleaned up manually later on and will not be synced back
to the server. However, no files will get deleted in this process.
Just like files, directories also hold a unique id, which changes whenever
one of the contained files or directories gets modified. Since this is a
recursive process, it significantly reduces the effort required for a sync
cycle, because the client will only walk directories with a modified unique id.
.. note:: oCC 1.1 and newer require file ID capabilities on the ownCloud server,
hence using them with a server earlier than 4.5.0 is not supported.
This table outlines the different sync methods attempted depending
on server/client combination:
@@ -104,39 +106,3 @@ are involved and one of them is not in sync with NTP time.
.. _`NTP time synchronisation`: http://en.wikipedia.org/wiki/Network_Time_Protocol
.. _Etag: http://en.wikipedia.org/wiki/HTTP_ETag
Comparison and Conflict Cases
----------------------------
In a sync run the client first has to detect if one of the two repositories have
changed files. On the local repository, the client traverses the file
tree and compares the modification time of each file with the value it was
before. The previous value is stored in the client's database. If it is not, it
means that the file has been added to the local repository. Note that on
the local side, the modificaton time a good attribute to detect changes because
it does not depend on time shifts and such.
For the remote (ie. ownCloud) repository, the client compares the ETag of each
file with it's previous value. Again the previous value is queried from the
database. If the ETag is still the same, the file has not changed.
So what happens if a file has changed on both, the local and the remote repository
since the last sync run? That means it can not easily be decided which version
of the file is the one that should be used. Moreover, changes to any side must
not be lost. That is called the conflict case and the client solves it by creating
a conflict file of the older of the two files and save the newer one under the
original file name. Conflict files are always created on the client and never on
the server. The conflict file has the same name as the original file appended
with the timestamp of the conflict detection.
The Sync Journal
----------------
The client stores the ETag number in a per-directory database, called the journal.
It is located in the application directory (until version 1.1) or as a hidden file
right in the directory to be synced (later versions).
If the journal database gets removed, oCC's CSync backend will rebuild the database
by comparing the files and their modification times. Thus it should be made sure
that both server and client synchronized to NTP time before restarting the client
after a database removal.
The oCC also provides a button in the Settings Dialog that allows to "reset" the
journal. That can be used to recreate the journal database.
+1 -1
Ver Arquivo
@@ -37,7 +37,7 @@ Next, install the missing dependencies::
brew install $(brew deps ocsync)
brew install $(brew deps mirall)
To build mirall and csync, follow the `generic build instructions`_.
To build mirall and cmake, follow the `generic build instructions`_.
.. note::
You should not call ``make install`` at any time, since the product of the
+6 -12
Ver Arquivo
@@ -1,23 +1,17 @@
ownCloud Client supports the following command line switches:
``--logwindow``
open a window to show log output.
open a window to show log output at startup.
``--logfile`` `<filename>`
write log output to file <filename>.
``--logfile`` `<file>`
write log output to a single file
``--logdir`` `<name>`
write each sync log output in a new file in directory <name>
``--logdir`` `<dir>`
write log output to dir, one for each sync run.
``--logexpire`` `<hours>`
removes logs older than <hours> hours. (to be used with --logdir)
``--logflush``
``--flushlog``
flush the log file after every write.
``--monoicons``
Use black/white pictograms for systray.
``--confdir`` `<dirname>`
Use the given configuration directory.
+11 -51
Ver Arquivo
@@ -26,63 +26,23 @@ also opens the status dialog.
The dialog provides an overview on the configured sync folders and allows to add
and remove more sync folder connections as well as pausing a sync connection.
Changing Your Password and Account Settings
-------------------------------------------
Changing your password
----------------------
In the ``Settings`` Dialog, choose ``Account`` -> ``Modify Account``. It will open
Setup Wizard, which next to reconfiguring your connection to use a different
user or server also will allow to change the password for the local account,
or to switch from HTTP to HTTPS.
Use the ``Configure`` option. It will open the Connection Wizard, which next to
reconfiguring your connection to use a different user or server also will allow
to change the password for the local account, or to switch from HTTP to HTTPS.
Setting up a Proxy
Setting up a proxy
------------------
By default, the configured system proxy will be picked up. This may not be
working reliably on some Linux distributions, as only the ``http_proxy``
variable gets picked up. You can configure a proxy different from your
system default in the ``Network`` section of the ``Settings`` dialog.
working reliable on some Linux distributions, as only the ``http_proxy``
variable gets parsed. You can configure a proxy different from your
system default by choosing ``Configure proxy...`` from the menu.
The default settings assume an HTTP proxy, which is the typical use case.
If you require SOCKS 5 proxy, pick ``SOCKS5 proxy`` instead of ``HTTP(S) proxy``
from the drop down menu. SOCKS 5 proxies are typically provided by some
SSH implementations, for instance OpenSSH's ``-D`` parameter. This is
useful for scenarios where SSH is employed to securely tunnel a client
to the network running the ownCloud server.
Limiting Bandwidth
------------------
Starting with Version 1.4, the Client provides bandwidth limiter.
This option can be found in the ``Network`` section of the
``Settings Dialog``.
You will find two settings for ``Download Bandwidth`` and
``Upload Bandwidth``.
Upload Bandwidth
~~~~~~~~~~~~~~~~
The default is to automatically limit the upload. The rationale
for this default is that typically, Computers and laptops are
not directly connected to the server, but via a Cable Modems
or DSL lines, which provide significantly more downstream than
upstream bandwith. Sataurating the upstream bandwidth would
interfere with other applications, especially Voice-Over-IP or
Games.
The automatic limiter will throttle the speed to about 75%
of the available upstream bandwidth. If you are communicating
with the server via a fast, symetric connection, you can set the
Limiter to ``No Limit`` instead. If want a stronger limitation,
choose ``Limit to`` and specify a limit manually.
Download Bandwidth
~~~~~~~~~~~~~~~~~~
Because the download bandwidth is usually no concern, it is not
automatically limited. Should you find that the Client is taking
up too much bandwidth, you can manually specify a limit (in KB).
By default, ownCloud expects a HTTP proxy. If you want to specify a SOCKS5
proxy instead, tick the "Use as SOCKSv5 proxy" option.
Options
-------
-2
Ver Arquivo
@@ -10,8 +10,6 @@
<file>resources/task-ongoing.png</file>
<file>resources/view-refresh.png</file>
<file>resources/warning-16.png</file>
<file>resources/settings.png</file>
<file>resources/network.png</file>
<file>resources/owncloud_logo_blue.png</file>
</qresource>
</RCC>
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.1 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 2.7 KiB

+26 -88
Ver Arquivo
@@ -11,23 +11,15 @@ else()
set(theme_dir ${CMAKE_CURRENT_SOURCE_DIR}/../theme)
endif()
set(synclib_NAME ${APPLICATION_SHORTNAME}sync)
set(mirall_UI
mirall/folderwizardsourcepage.ui
mirall/folderwizardtargetpage.ui
mirall/statusdialog.ui
mirall/owncloudsetuppage_ng.ui
mirall/owncloudwizardresultpage.ui
mirall/sslerrordialog.ui
mirall/settingsdialog.ui
mirall/generalsettings.ui
mirall/networksettings.ui
mirall/accountsettings.ui
mirall/ignorelisteditor.ui
mirall/proxydialog.ui
mirall/fileitemdialog.ui
mirall/itemprogressdialog.ui
wizard/owncloudsetupnocredspage.ui
wizard/owncloudhttpcredspage.ui
wizard/owncloudwizardresultpage.ui
wizard/owncloudadvancedsetuppage.ui
)
set(3rdparty_SRC
@@ -70,6 +62,8 @@ set(libsync_SRCS
mirall/syncresult.cpp
mirall/networklocation.cpp
mirall/mirallconfigfile.cpp
mirall/credentialstore.cpp
mirall/owncloudfolder.cpp
mirall/csyncthread.cpp
mirall/fileutils.cpp
mirall/theme.cpp
@@ -78,47 +72,17 @@ set(libsync_SRCS
mirall/logger.cpp
mirall/utility.cpp
mirall/connectionvalidator.cpp
mirall/progressdispatcher.cpp
mirall/mirallaccessmanager.cpp
creds/dummycredentials.cpp
creds/httpcredentials.cpp
creds/credentialsfactory.cpp
creds/http/credentialstore.cpp
creds/http/httpconfigfile.cpp
creds/shibbolethcredentials.cpp
creds/shibboleth/shibbolethaccessmanager.cpp
creds/shibboleth/shibbolethcookiejar.cpp
creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethrefresher.cpp
creds/shibboleth/shibbolethconfigfile.cpp
creds/credentialscommon.cpp
)
set(libsync_HEADERS
set(libsync_HEADERS
mirall/folderman.h
mirall/folder.h
mirall/folderwatcher.h
mirall/owncloudfolder.h
mirall/csyncthread.h
mirall/theme.h
mirall/owncloudtheme.h
mirall/owncloudinfo.h
mirall/credentialstore.h
mirall/logger.h
mirall/connectionvalidator.h
mirall/progressdispatcher.h
mirall/mirallaccessmanager.h
creds/abstractcredentials.h
creds/dummycredentials.h
creds/httpcredentials.h
creds/credentialsfactory.h
creds/http/credentialstore.h
creds/http/httpconfigfile.h
creds/shibbolethcredentials.h
creds/shibboleth/shibbolethaccessmanager.h
creds/shibboleth/shibbolethcookiejar.h
creds/shibboleth/shibbolethwebview.h
creds/shibboleth/shibbolethrefresher.h
creds/shibboleth/shibbolethconfigfile.h
creds/credentialscommon.h
)
IF( INOTIFY_FOUND )
@@ -149,20 +113,20 @@ if(QTKEYCHAIN_FOUND)
include_directories(${QTKEYCHAIN_INCLUDE_DIR})
endif()
add_library(${synclib_NAME} SHARED ${libsync_SRCS} ${syncMoc})
set_target_properties( ${synclib_NAME} PROPERTIES
add_library(owncloudsync SHARED ${libsync_SRCS} ${syncMoc})
set_target_properties( owncloudsync PROPERTIES
VERSION ${VERSION}
SOVERSION ${SOVERSION}
)
target_link_libraries(${synclib_NAME} ${libsync_LINK_TARGETS} )
target_link_libraries(owncloudsync ${libsync_LINK_TARGETS} )
if ( APPLE )
target_link_libraries(${synclib_NAME} /System/Library/Frameworks/CoreServices.framework)
target_link_libraries(owncloudsync /System/Library/Frameworks/CoreServices.framework)
endif()
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
install(TARGETS ${synclib_NAME}
install(TARGETS owncloudsync
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -173,33 +137,22 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_SHORTNAME}.desktop DESTINATION share/applications )
endif()
else()
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
install(TARGETS owncloudsync DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
endif()
set(mirall_SRCS
mirall/application.cpp
mirall/systray.cpp
mirall/folderwizard.cpp
mirall/folderstatusmodel.cpp
wizard/owncloudwizard.cpp
wizard/owncloudsetuppage.cpp
wizard/owncloudhttpcredspage.cpp
wizard/owncloudwizardresultpage.cpp
wizard/owncloudwizardcommon.cpp
wizard/owncloudshibbolethcredspage.cpp
wizard/owncloudadvancedsetuppage.cpp
mirall/statusdialog.cpp
mirall/owncloudwizard.cpp
mirall/owncloudsetupwizard.cpp
mirall/updatedetector.cpp
mirall/occinfo.cpp
mirall/sslerrordialog.cpp
mirall/logbrowser.cpp
mirall/proxydialog.cpp
mirall/fileitemdialog.cpp
mirall/settingsdialog.cpp
mirall/generalsettings.cpp
mirall/networksettings.cpp
mirall/accountsettings.cpp
mirall/ignorelisteditor.cpp
mirall/itemprogressdialog.cpp
)
set(mirall_HEADERS
@@ -207,24 +160,13 @@ set(mirall_HEADERS
mirall/systray.h
mirall/folderwizard.h
mirall/owncloudsetupwizard.h
wizard/owncloudwizard.h
wizard/owncloudsetuppage.h
wizard/owncloudhttpcredspage.h
wizard/owncloudwizardresultpage.h
wizard/owncloudwizardcommon.h
wizard/owncloudshibbolethcredspage.h
wizard/owncloudadvancedsetuppage.h
mirall/folderstatusmodel.h
mirall/owncloudwizard.h
mirall/statusdialog.h
mirall/updatedetector.h
mirall/sslerrordialog.h
mirall/logbrowser.h
mirall/proxydialog.h
mirall/fileitemdialog.h
mirall/settingsdialog.h
mirall/generalsettings.h
mirall/networksettings.h
mirall/accountsettings.h
mirall/ignorelisteditor.h
mirall/itemprogressdialog.h
)
if( UNIX AND NOT APPLE)
@@ -265,16 +207,12 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
if(NOT WIN32)
file( GLOB _icons "${theme_dir}/colored/${APPLICATION_SHORTNAME}-icon-*.png" )
foreach( _file ${_icons} )
string( REPLACE "${theme_dir}/colored/${APPLICATION_SHORTNAME}-icon-" "" _res ${_file} )
string( REPLACE ".png" "" _res ${_res} )
install( FILES ${_file} RENAME ${APPLICATION_SHORTNAME}.png DESTINATION
${CMAKE_INSTALL_DATADIR}/icons/hicolor/${_res}x${_res}/apps )
endforeach( _file )
install(FILES
${theme_dir}/colored/${APPLICATION_SHORTNAME}-icon-48.png
DESTINATION share/icons/hicolor/48x48/apps/ RENAME ${APPLICATION_SHORTNAME}.png)
endif(NOT WIN32)
install(FILES ${mirall_I18N} DESTINATION share/${APPLICATION_SHORTNAME}/i18n)
install(FILES ${mirall_I18N} DESTINATION share/mirall/i18n)
# we may not add MACOSX_BUNDLE here, if not building one
@@ -312,7 +250,7 @@ set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
)
target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
target_link_libraries( ${APPLICATION_EXECUTABLE} owncloudsync )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${CSYNC_LIBRARY} )
install(TARGETS ${APPLICATION_EXECUTABLE}
-47
Ver Arquivo
@@ -1,47 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_CREDS_ABSTRACT_CREDENTIALS_H
#define MIRALL_CREDS_ABSTRACT_CREDENTIALS_H
#include <QObject>
#include <csync.h>
class QNetworkAccessManager;
namespace Mirall
{
class AbstractCredentials : public QObject
{
Q_OBJECT
public:
// No need for virtual destructor - QObject already has one.
virtual void syncContextPreInit(CSYNC* ctx) = 0;
virtual void syncContextPreStart(CSYNC* ctx) = 0;
virtual bool changed(AbstractCredentials* credentials) const = 0;
virtual QString authType() const = 0;
virtual QNetworkAccessManager* getQNAM() const = 0;
virtual bool ready() const = 0;
virtual void fetch() = 0;
virtual void persistForUrl(const QString& url) = 0;
Q_SIGNALS:
void fetched();
};
} // ns Mirall
#endif
-77
Ver Arquivo
@@ -1,77 +0,0 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <QList>
#include <QRegExp>
#include <QString>
#include <QSslCertificate>
#include "creds/credentialscommon.h"
#include "mirall/utility.h"
#include "mirall/owncloudinfo.h"
namespace Mirall
{
int handleNeonSSLProblems(const char* prompt,
char* buf,
size_t /*len*/,
int /*echo*/,
int /*verify*/,
void* /*userdata*/)
{
int re = 0;
const QString qPrompt = QString::fromLatin1( prompt ).trimmed();
if( qPrompt.startsWith( QLatin1String("There are problems with the SSL certificate:"))) {
// SSL is requested. If the program came here, the SSL check was done by mirall
// It needs to be checked if the chain is still equal to the one which
// was verified by the user.
const QRegExp regexp("fingerprint: ([\\w\\d:]+)");
bool certOk = false;
int pos = 0;
// This is the set of certificates which QNAM accepted, so we should accept
// them as well
QList<QSslCertificate> certs = ownCloudInfo::instance()->certificateChain();
while (!certOk && (pos = regexp.indexIn(qPrompt, 1+pos)) != -1) {
QString neon_fingerprint = regexp.cap(1);
foreach( const QSslCertificate& c, certs ) {
QString verified_shasum = Utility::formatFingerprint(c.digest(QCryptographicHash::Sha1).toHex());
qDebug() << "SSL Fingerprint from neon: " << neon_fingerprint << " compared to verified: " << verified_shasum;
if( verified_shasum == neon_fingerprint ) {
certOk = true;
break;
}
}
}
// certOk = false; DEBUG setting, keep disabled!
if( !certOk ) { // Problem!
qstrcpy( buf, "no" );
re = -1;
} else {
qstrcpy( buf, "yes" ); // Certificate is fine!
}
} else {
qDebug() << "Unknown prompt: <" << prompt << ">";
re = -1;
}
return re;
}
} // ns Mirall
-32
Ver Arquivo
@@ -1,32 +0,0 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MIRALL_CREDS_COMMON_H
#define MIRALL_CREDS_COMMON_H
namespace Mirall
{
int handleNeonSSLProblems(const char* prompt,
char* buf,
size_t len,
int echo,
int verify,
void* userdata);
} // ns Mirall
#endif
-43
Ver Arquivo
@@ -1,43 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 <QString>
#include "creds/httpcredentials.h"
#include "creds/dummycredentials.h"
#include "creds/shibbolethcredentials.h"
namespace Mirall
{
namespace CredentialsFactory
{
AbstractCredentials* create(const QString& type)
{
// empty string might happen for old version of configuration
if (type == "http" || type == "") {
return new HttpCredentials;
} else if (type == "dummy") {
return new DummyCredentials;
} else if (type == "shibboleth") {
return new ShibbolethCredentials;
} else {
qWarning("Unknown credentials type: %s", qPrintable(type));
return new DummyCredentials;
}
}
} // ns CredentialsFactory
} // ns Mirall
-32
Ver Arquivo
@@ -1,32 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_CREDS_CREDENTIALS_FACTORY_H
#define MIRALL_CREDS_CREDENTIALS_FACTORY_H
class AbstractCredentials;
class QString;
namespace Mirall
{
namespace CredentialsFactory
{
AbstractCredentials* create(const QString& type);
} // ns CredentialsFactory
} // ns Mirall
#endif
-56
Ver Arquivo
@@ -1,56 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 "creds/dummycredentials.h"
#include "mirall/mirallaccessmanager.h"
namespace Mirall
{
void DummyCredentials::syncContextPreInit(CSYNC*)
{}
void DummyCredentials::syncContextPreStart(CSYNC*)
{}
bool DummyCredentials::changed(AbstractCredentials* credentials) const
{
DummyCredentials* dummy(dynamic_cast< DummyCredentials* >(credentials));
return dummy == 0;
}
QString DummyCredentials::authType() const
{
return QString::fromLatin1("dummy");
}
QNetworkAccessManager* DummyCredentials::getQNAM() const
{
return new MirallAccessManager;
}
bool DummyCredentials::ready() const
{
return true;
}
void DummyCredentials::fetch()
{
Q_EMIT(fetched());
}
void DummyCredentials::persistForUrl(const QString&)
{}
} // ns Mirall
-39
Ver Arquivo
@@ -1,39 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_CREDS_DUMMY_CREDENTIALS_H
#define MIRALL_CREDS_DUMMY_CREDENTIALS_H
#include "creds/abstractcredentials.h"
namespace Mirall
{
class DummyCredentials : public AbstractCredentials
{
Q_OBJECT
public:
void syncContextPreInit(CSYNC* ctx);
void syncContextPreStart(CSYNC* ctx);
bool changed(AbstractCredentials* credentials) const;
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
};
} // ns Mirall
#endif
-81
Ver Arquivo
@@ -1,81 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 "creds/http/httpconfigfile.h"
namespace Mirall
{
namespace
{
const char userC[] = "user";
const char passwdC[] = "passwd";
const char oldPasswdC[] = "password";
} // ns
QString HttpConfigFile::user() const
{
return retrieveData(QString(), QLatin1String(userC)).toString();
}
void HttpConfigFile::setUser(const QString& user)
{
storeData(QString(), QLatin1String(userC), QVariant(user));
}
QString HttpConfigFile::password() const
{
const QVariant passwd(retrieveData(QString(), QLatin1String(passwdC)));
if (passwd.isValid()) {
return QString::fromUtf8(QByteArray::fromBase64(passwd.toByteArray()));
}
return QString();
}
void HttpConfigFile::setPassword(const QString& password)
{
QByteArray pwdba = password.toUtf8();
storeData( QString(), QLatin1String(passwdC), QVariant(pwdba.toBase64()) );
removeOldPassword();
}
bool HttpConfigFile::passwordExists() const
{
return dataExists(QString(), QLatin1String(passwdC));
}
void HttpConfigFile::removePassword()
{
removeOldPassword();
removeData(QString(), QLatin1String(passwdC));
}
void HttpConfigFile::fixupOldPassword()
{
const QString old(QString::fromLatin1(oldPasswdC));
if (dataExists(QString(), old)) {
setPassword(retrieveData(QString(), old).toString());
}
}
void HttpConfigFile::removeOldPassword()
{
removeData(QString(), QLatin1String(oldPasswdC));
}
} // ns Mirall
-40
Ver Arquivo
@@ -1,40 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_CREDS_HTTP_CONFIG_FILE_H
#define MIRALL_CREDS_HTTP_CONFIG_FILE_H
#include "mirall/mirallconfigfile.h"
namespace Mirall
{
class HttpConfigFile : public MirallConfigFile
{
public:
QString user() const;
void setUser(const QString& user);
QString password() const;
void setPassword(const QString& password);
bool passwordExists() const;
void removePassword();
void fixupOldPassword();
private:
void removeOldPassword();
};
} // ns Mirall
#endif
-218
Ver Arquivo
@@ -1,218 +0,0 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <QMutex>
#include "creds/httpcredentials.h"
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/mirallaccessmanager.h"
#include "mirall/utility.h"
#include "creds/http/credentialstore.h"
#include "creds/credentialscommon.h"
namespace Mirall
{
namespace
{
int getauth(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata)
{
int re = 0;
QMutex mutex;
MirallConfigFile cfg;
HttpCredentials* http_credentials = dynamic_cast< HttpCredentials* > (cfg.getCredentials());
if (!http_credentials) {
qDebug() << "Not a HTTP creds instance!";
return -1;
}
QString qPrompt = QString::fromLatin1( prompt ).trimmed();
QString user = http_credentials->user();
QString pwd = http_credentials->password();
if( qPrompt == QLatin1String("Enter your username:") ) {
// qDebug() << "OOO Username requested!";
QMutexLocker locker( &mutex );
qstrncpy( buf, user.toUtf8().constData(), len );
} else if( qPrompt == QLatin1String("Enter your password:") ) {
QMutexLocker locker( &mutex );
// qDebug() << "OOO Password requested!";
qstrncpy( buf, pwd.toUtf8().constData(), len );
} else {
re = handleNeonSSLProblems(prompt, buf, len, echo, verify, userdata);
}
return re;
}
} // ns
HttpCredentials::HttpCredentials()
: _user(),
_password(),
_ready(false),
_attempts()
{}
HttpCredentials::HttpCredentials(const QString& user, const QString& password)
: _user(user),
_password(password),
_ready(true)
{}
void HttpCredentials::syncContextPreInit (CSYNC* ctx)
{
csync_set_auth_callback (ctx, getauth);
}
void HttpCredentials::syncContextPreStart (CSYNC* ctx)
{
// TODO: This should not be a part of this method, but we don't have
// any way to get "session_key" module property from csync. Had we
// have it, then we could remove this code and keep it in
// csyncthread code (or folder code, git remembers).
QList<QNetworkCookie> cookies(ownCloudInfo::instance()->getLastAuthCookies());
QString cookiesAsString;
// Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
// when https://github.com/owncloud/core/pull/4042 is merged.
foreach(QNetworkCookie c, cookies) {
cookiesAsString += c.name();
cookiesAsString += '=';
cookiesAsString += c.value();
cookiesAsString += "; ";
}
csync_set_module_property(ctx, "session_key", cookiesAsString.toLatin1().data());
}
bool HttpCredentials::changed(AbstractCredentials* credentials) const
{
HttpCredentials* other(dynamic_cast< HttpCredentials* >(credentials));
if (!other || other->user() != this->user()) {
return true;
}
return false;
}
QString HttpCredentials::authType() const
{
return QString::fromLatin1("http");
}
QString HttpCredentials::user() const
{
return _user;
}
QString HttpCredentials::password() const
{
return _password;
}
QNetworkAccessManager* HttpCredentials::getQNAM() const
{
MirallAccessManager* qnam = new MirallAccessManager;
connect( qnam, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
this, SLOT(slotAuthentication(QNetworkReply*,QAuthenticator*)));
return qnam;
}
bool HttpCredentials::ready() const
{
return _ready;
}
void HttpCredentials::fetch()
{
if (_ready) {
Q_EMIT fetched();
} else {
// TODO: merge CredentialStore into HttpCredentials?
CredentialStore* store(CredentialStore::instance());
connect(store, SIGNAL(fetchCredentialsFinished(bool)),
this, SLOT(slotCredentialsFetched(bool)));
store->fetchCredentials();
}
}
void HttpCredentials::persistForUrl(const QString& url)
{
CredentialStore* store(CredentialStore::instance());
store->setCredentials(url, _user, _password);
store->saveCredentials();
}
void HttpCredentials::slotCredentialsFetched(bool ok)
{
_ready = ok;
if (_ready) {
CredentialStore* store(CredentialStore::instance());
_user = store->user();
_password = store->password();
}
Q_EMIT fetched();
}
void HttpCredentials::slotAuthentication(QNetworkReply* reply, QAuthenticator* authenticator)
{
if( !(authenticator && reply) ) return;
qDebug() << "Authenticating request for " << reply->url();
if (_attempts.contains(reply)) {
++_attempts[reply];
} else {
connect(reply, SIGNAL(finished()),
this, SLOT(slotReplyFinished()));
_attempts[reply] = 1;
}
// TODO: Replace it with something meaningful...
//if( reply->url().toString().startsWith( webdavUrl( _connection ) ) ) {
if (_attempts[reply] > 1) {
qDebug() << "Too many attempts to authenticate. Stop request.";
reply->close();
} else {
authenticator->setUser( _user );
authenticator->setPassword( _password );
}
//} else {
// qDebug() << "WRN: attempt to authenticate to different url - closing.";
// reply->close();
//}
}
void HttpCredentials::slotReplyFinished()
{
QNetworkReply* reply = qobject_cast< QNetworkReply* >(sender());
disconnect(reply, SIGNAL(finished()),
this, SLOT(slotReplyFinished()));
_attempts.remove (reply);
}
} // ns Mirall
-64
Ver Arquivo
@@ -1,64 +0,0 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MIRALL_CREDS_HTTP_CREDENTIALS_H
#define MIRALL_CREDS_HTTP_CREDENTIALS_H
#include <QMap>
#include "creds/abstractcredentials.h"
class QNetworkReply;
class QAuthenticator;
namespace Mirall
{
class HttpCredentials : public AbstractCredentials
{
Q_OBJECT
public:
HttpCredentials();
HttpCredentials(const QString& user, const QString& password);
void syncContextPreInit(CSYNC* ctx);
void syncContextPreStart(CSYNC* ctx);
bool changed(AbstractCredentials* credentials) const;
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
QString user() const;
QString password() const;
private Q_SLOTS:
void slotCredentialsFetched(bool);
void slotAuthentication(QNetworkReply*, QAuthenticator*);
void slotReplyFinished();
private:
QString _user;
QString _password;
bool _ready;
QMap<QNetworkReply*, int> _attempts;
};
} // ns Mirall
#endif
@@ -1,55 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 <QDebug>
#include <QNetworkRequest>
#include "creds/shibboleth/shibbolethaccessmanager.h"
namespace Mirall
{
ShibbolethAccessManager::ShibbolethAccessManager(const QNetworkCookie& cookie, QObject* parent)
: MirallAccessManager (parent),
_cookie(cookie)
{}
QNetworkReply* ShibbolethAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
{
if (!_cookie.name().isEmpty()) {
QNetworkCookieJar* jar(cookieJar());
QUrl url(request.url());
QList<QNetworkCookie> cookies;
Q_FOREACH(const QNetworkCookie& cookie, jar->cookiesForUrl(url)) {
if (!cookie.name().startsWith("_shibsession_")) {
cookies << cookie;
}
}
cookies << _cookie;
jar->setCookiesFromUrl(cookies, url);
}
qDebug() << "Creating a request to " << request.url().toString() << " with shibboleth cookie:" << _cookie.name();
return MirallAccessManager::createRequest (op, request, outgoingData);
}
void ShibbolethAccessManager::setCookie(const QNetworkCookie& cookie)
{
qDebug() << "Got new shibboleth cookie:" << cookie.name();
_cookie = cookie;
}
} // ns Mirall
@@ -1,43 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_WIZARD_SHIBBOLETH_ACCESS_MANAGER_H
#define MIRALL_WIZARD_SHIBBOLETH_ACCESS_MANAGER_H
#include <QNetworkCookie>
#include "mirall/mirallaccessmanager.h"
namespace Mirall
{
class ShibbolethAccessManager : public MirallAccessManager
{
Q_OBJECT
public:
ShibbolethAccessManager(const QNetworkCookie& cookie, QObject* parent = 0);
public Q_SLOTS:
void setCookie(const QNetworkCookie& cookie);
protected:
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0);
private:
QNetworkCookie _cookie;
};
} // ns Mirall
#endif
-104
Ver Arquivo
@@ -1,104 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 <QDebug>
#include <QTextStream>
#include "creds/shibboleth/shibbolethconfigfile.h"
#include "creds/shibboleth/shibbolethcookiejar.h"
namespace Mirall
{
namespace
{
const char otherCookiesC[] = "otherCookies";
} // ns
void ShibbolethConfigFile::storeCookies(const QMap<QUrl, QList<QNetworkCookie> >& cookiesForUrl)
{
if (cookiesForUrl.isEmpty()) {
removeData(QString(), QString::fromLatin1(otherCookiesC));
} else {
QByteArray data;
QTextStream stream(&data);
Q_FOREACH (const QUrl& url, cookiesForUrl.keys()) {
const QList<QNetworkCookie>& cookies(cookiesForUrl[url]);
if (cookies.isEmpty()) {
continue;
}
stream << "URL: " << url.toString().toUtf8() << "\n";
qDebug() << "URL: " << url.toString().toUtf8();
Q_FOREACH (const QNetworkCookie& cookie, cookies) {
stream << cookie.toRawForm(QNetworkCookie::NameAndValueOnly) << "\n";
qDebug() << cookie.toRawForm(QNetworkCookie::NameAndValueOnly);
}
}
stream.flush();
const QByteArray encodedCookies(data.toBase64());
qDebug() << "Raw cookies:\n" << data;
qDebug() << "Encoded cookies: " << encodedCookies;
storeData(QString(), QString::fromLatin1(otherCookiesC), QVariant(encodedCookies));
}
}
ShibbolethCookieJar* ShibbolethConfigFile::createCookieJar() const
{
ShibbolethCookieJar* jar = new ShibbolethCookieJar();
const QVariant variant(retrieveData(QString(), QString::fromLatin1(otherCookiesC)));
if (variant.isValid()) {
QByteArray data(QByteArray::fromBase64(variant.toByteArray()));
QTextStream stream (&data);
const QString urlHeader(QString::fromLatin1("URL: "));
QUrl currentUrl;
QList<QNetworkCookie> currentCookies;
qDebug() << "Got valid cookies variant: " << data;
while (!stream.atEnd()) {
const QString line(stream.readLine());
qDebug() << line;
if (line.startsWith(urlHeader)) {
if (!currentUrl.isEmpty() && !currentCookies.isEmpty()) {
jar->setCookiesFromUrl(currentCookies, currentUrl);
currentCookies.clear();
currentUrl.clear();
}
currentUrl = QUrl(line.mid(5));
} else if (!currentUrl.isEmpty()) {
const int equalPos(line.indexOf('='));
currentCookies << QNetworkCookie(line.left(equalPos).toUtf8(), line.mid(equalPos + 1).toUtf8());
}
}
if (!currentUrl.isEmpty() && !currentCookies.isEmpty()) {
jar->setCookiesFromUrl(currentCookies, currentUrl);
}
}
return jar;
}
} // ns Mirall
-38
Ver Arquivo
@@ -1,38 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_CREDS_SHIBBOLETH_CONFIG_FILE_H
#define MIRALL_CREDS_SHIBBOLETH_CONFIG_FILE_H
#include <QList>
#include <QMap>
#include <QNetworkCookie>
#include <QUrl>
#include "mirall/mirallconfigfile.h"
namespace Mirall
{
class ShibbolethCookieJar;
class ShibbolethConfigFile : public MirallConfigFile
{
public:
void storeCookies(const QMap<QUrl, QList<QNetworkCookie> >& cookies);
ShibbolethCookieJar* createCookieJar() const;
};
} // ns Mirall
#endif
-34
Ver Arquivo
@@ -1,34 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 "creds/shibboleth/shibbolethcookiejar.h"
namespace Mirall
{
ShibbolethCookieJar::ShibbolethCookieJar (QObject* parent)
: QNetworkCookieJar (parent)
{}
bool ShibbolethCookieJar::setCookiesFromUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url)
{
if (QNetworkCookieJar::setCookiesFromUrl (cookieList, url)) {
Q_EMIT newCookiesForUrl (cookieList, url);
return true;
}
return false;
}
} // ns Mirall
-41
Ver Arquivo
@@ -1,41 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_WIZARD_SHIBBOLETH_COOKIE_JAR_H
#define MIRALL_WIZARD_SHIBBOLETH_COOKIE_JAR_H
#include <QNetworkCookieJar>
#include <QList>
class QUrl;
class QNetworkCookie;
namespace Mirall
{
class ShibbolethCookieJar : public QNetworkCookieJar
{
Q_OBJECT
public:
ShibbolethCookieJar (QObject* parent = 0);
virtual bool setCookiesFromUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url);
Q_SIGNALS:
void newCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url);
};
} // ns Mirall
#endif
-52
Ver Arquivo
@@ -1,52 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 <QEventLoop>
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibbolethcredentials.h"
namespace Mirall
{
ShibbolethRefresher::ShibbolethRefresher(ShibbolethCredentials* creds, CSYNC* csync_ctx, QObject* parent)
: QObject(parent),
_creds(creds),
_csync_ctx(csync_ctx)
{}
void ShibbolethRefresher::refresh()
{
QEventLoop loop;
connect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
this, SLOT(onInvalidatedAndFetched(QByteArray)));
connect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
&loop, SLOT(quit()));
QMetaObject::invokeMethod(_creds, "invalidateAndFetch", Qt::QueuedConnection);
loop.exec();
disconnect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
&loop, SLOT(quit()));
}
void ShibbolethRefresher::onInvalidatedAndFetched(const QByteArray& cookies)
{
// "cookies" is const and its data() return const void*. We want just void*.
QByteArray myCookies(cookies);
disconnect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
this, SLOT(onInvalidatedAndFetched(QByteArray)));
csync_set_module_property(_csync_ctx, "session_key", myCookies.data());
}
} // ns Mirall
-47
Ver Arquivo
@@ -1,47 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_CREDS_SHIBBOLETH_REFRESHER_H
#define MIRALL_CREDS_SHIBBOLETH_REFRESHER_H
#include <QObject>
#include <csync.h>
class QByteArray;
namespace Mirall
{
class ShibbolethCredentials;
class ShibbolethRefresher : public QObject
{
Q_OBJECT
public:
ShibbolethRefresher(ShibbolethCredentials* creds, CSYNC* csync_ctx, QObject* parent = 0);
void refresh();
private Q_SLOTS:
void onInvalidatedAndFetched(const QByteArray& cookieData);
private:
ShibbolethCredentials* _creds;
CSYNC* _csync_ctx;
};
} // ns Mirall
#endif
-104
Ver Arquivo
@@ -1,104 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 <QApplication>
#include <QDebug>
#include <QNetworkCookie>
#include <QWebFrame>
#include <QWebPage>
#include "creds/shibboleth/shibbolethcookiejar.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "mirall/mirallaccessmanager.h"
namespace Mirall
{
void ShibbolethWebView::setup(const QUrl& url, ShibbolethCookieJar* jar)
{
MirallAccessManager* nm = new MirallAccessManager(this);
QWebPage* page = new QWebPage(this);
jar->setParent(this);
connect(jar, SIGNAL (newCookiesForUrl (QList<QNetworkCookie>, QUrl)),
this, SLOT (onNewCookiesForUrl (QList<QNetworkCookie>, QUrl)));
connect(page, SIGNAL(loadStarted()),
this, SLOT(slotLoadStarted()));
connect(page, SIGNAL(loadFinished(bool)),
this, SLOT(slotLoadFinished()));
nm->setCookieJar(jar);
page->setNetworkAccessManager(nm);
page->mainFrame ()->load (url);
this->setPage (page);
}
ShibbolethWebView::ShibbolethWebView(const QUrl& url, QWidget* parent)
: QWebView(parent)
{
setup(url, new ShibbolethCookieJar(this));
}
ShibbolethWebView::~ShibbolethWebView()
{
slotLoadFinished();
}
ShibbolethWebView::ShibbolethWebView(const QUrl& url, ShibbolethCookieJar* jar, QWidget* parent)
: QWebView(parent)
{
setup(url, jar);
}
void ShibbolethWebView::onNewCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url)
{
QList<QNetworkCookie> otherCookies;
QNetworkCookie shibCookie;
Q_FOREACH (const QNetworkCookie& cookie, cookieList) {
if (cookie.name().startsWith ("_shibsession_")) {
if (shibCookie.name().isEmpty()) {
shibCookie = cookie;
} else {
qWarning() << "Too many Shibboleth session cookies at once!";
}
} else {
otherCookies << cookie;
}
}
if (!otherCookies.isEmpty()) {
Q_EMIT otherCookiesReceived(otherCookies, url);
}
if (!shibCookie.name().isEmpty()) {
Q_EMIT shibbolethCookieReceived(shibCookie);
}
}
void ShibbolethWebView::hideEvent(QHideEvent* event)
{
Q_EMIT viewHidden();
QWebView::hideEvent(event);
}
void ShibbolethWebView::slotLoadStarted()
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
}
void ShibbolethWebView::slotLoadFinished()
{
QApplication::restoreOverrideCursor();
}
} // ns Mirall
-56
Ver Arquivo
@@ -1,56 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_WIZARD_SHIBBOLETH_WEB_VIEW_H
#define MIRALL_WIZARD_SHIBBOLETH_WEB_VIEW_H
#include <QList>
#include <QWebView>
class QNetworkCookie;
class QUrl;
namespace Mirall
{
class ShibbolethCookieJar;
class ShibbolethWebView : public QWebView
{
Q_OBJECT
public:
ShibbolethWebView(const QUrl& url, QWidget* parent = 0);
ShibbolethWebView(const QUrl& url, ShibbolethCookieJar* jar, QWidget* parent = 0);
~ShibbolethWebView();
protected:
void hideEvent(QHideEvent* event);
Q_SIGNALS:
void shibbolethCookieReceived(const QNetworkCookie& cookie);
void viewHidden();
void otherCookiesReceived(const QList<QNetworkCookie>& cookieList, const QUrl& url);
private Q_SLOTS:
void onNewCookiesForUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url);
void slotLoadStarted();
void slotLoadFinished();
private:
void setup(const QUrl& url, ShibbolethCookieJar* jar);
};
} // ns Mirall
#endif
-231
Ver Arquivo
@@ -1,231 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
* 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 "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethaccessmanager.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibboleth/shibbolethconfigfile.h"
#include "creds/credentialscommon.h"
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
namespace Mirall
{
namespace
{
int shibboleth_redirect_callback(CSYNC* csync_ctx,
const char* uri)
{
if (!csync_ctx || !uri) {
return 1;
}
const QString qurl(QString::fromLatin1(uri));
QRegExp shibbolethyWords ("SAML|wayf");
shibbolethyWords.setCaseSensitivity (Qt::CaseInsensitive);
if (!qurl.contains(shibbolethyWords)) {
return 1;
}
QMutex mutex;
QMutexLocker locker(&mutex);
MirallConfigFile cfg;
ShibbolethCredentials* creds = dynamic_cast< ShibbolethCredentials* > (cfg.getCredentials());
if (!creds) {
qDebug() << "Not a Shibboleth creds instance!";
return 1;
}
ShibbolethRefresher refresher(creds, csync_ctx);
// blocks
refresher.refresh();
return creds->ready() ? 0 : 1;
}
} // ns
ShibbolethCredentials::ShibbolethCredentials()
: _shibCookie(),
_ready(false),
_browser(0),
_otherCookies()
{}
ShibbolethCredentials::ShibbolethCredentials(const QNetworkCookie& cookie, const QMap<QUrl, QList<QNetworkCookie> >& otherCookies)
: _shibCookie(cookie),
_ready(true),
_browser(0),
_otherCookies(otherCookies)
{}
void ShibbolethCredentials::syncContextPreInit(CSYNC* ctx)
{
csync_set_auth_callback (ctx, handleNeonSSLProblems);
}
QByteArray ShibbolethCredentials::prepareCookieData() const
{
QString cookiesAsString;
// TODO: This should not be a part of this method, but we don't
// have any way to get "session_key" module property from
// csync. Had we have it, then we could just append shibboleth
// cookies to the "session_key" value and set it in csync module.
QList<QNetworkCookie> cookies(ownCloudInfo::instance()->getLastAuthCookies());
QMap<QString, QString> uniqueCookies;
cookies << _shibCookie;
// Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
// when https://github.com/owncloud/core/pull/4042 is merged.
foreach(QNetworkCookie c, cookies) {
const QString cookieName(c.name());
if (cookieName.startsWith("_shibsession_")) {
continue;
}
uniqueCookies.insert(cookieName, c.value());
}
if (!_shibCookie.name().isEmpty()) {
uniqueCookies.insert(_shibCookie.name(), _shibCookie.value());
}
foreach(const QString& cookieName, uniqueCookies.keys()) {
cookiesAsString += cookieName;
cookiesAsString += '=';
cookiesAsString += uniqueCookies[cookieName];
cookiesAsString += "; ";
}
return cookiesAsString.toLatin1();
}
void ShibbolethCredentials::syncContextPreStart (CSYNC* ctx)
{
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
csync_owncloud_redirect_callback_t cb = shibboleth_redirect_callback;
csync_set_module_property(ctx, "session_key", prepareCookieData().data());
csync_set_module_property(ctx, "redirect_callback", &cb);
}
bool ShibbolethCredentials::changed(AbstractCredentials* credentials) const
{
ShibbolethCredentials* other(dynamic_cast< ShibbolethCredentials* >(credentials));
if (!other || other->cookie() != this->cookie()) {
return true;
}
return false;
}
QString ShibbolethCredentials::authType() const
{
return QString::fromLatin1("shibboleth");
}
QNetworkCookie ShibbolethCredentials::cookie() const
{
return _shibCookie;
}
QNetworkAccessManager* ShibbolethCredentials::getQNAM() const
{
ShibbolethAccessManager* qnam(new ShibbolethAccessManager(_shibCookie));
connect(this, SIGNAL(newCookie(QNetworkCookie)),
qnam, SLOT(setCookie(QNetworkCookie)));
return qnam;
}
bool ShibbolethCredentials::ready() const
{
return _ready;
}
void ShibbolethCredentials::fetch()
{
if (_ready) {
Q_EMIT fetched();
} else {
ShibbolethConfigFile cfg;
_browser = new ShibbolethWebView(QUrl(cfg.ownCloudUrl()), cfg.createCookieJar());
connect(_browser, SIGNAL(shibbolethCookieReceived(QNetworkCookie)),
this, SLOT(onShibbolethCookieReceived(QNetworkCookie)));
connect(_browser, SIGNAL(viewHidden()),
this, SLOT(slotBrowserHidden()));
_browser->show ();
}
}
void ShibbolethCredentials::persistForUrl(const QString& /*url*/)
{
ShibbolethConfigFile cfg;
cfg.storeCookies(_otherCookies);
}
void ShibbolethCredentials::disposeBrowser()
{
disconnect(_browser, SIGNAL(viewHidden()),
this, SLOT(slotBrowserHidden()));
disconnect(_browser, SIGNAL(shibbolethCookieReceived(QNetworkCookie)),
this, SLOT(onShibbolethCookieReceived(QNetworkCookie)));
_browser->hide();
_browser->deleteLater();
_browser = 0;
}
void ShibbolethCredentials::onShibbolethCookieReceived(const QNetworkCookie& cookie)
{
disposeBrowser();
_ready = true;
_shibCookie = cookie;
Q_EMIT newCookie(_shibCookie);
Q_EMIT fetched();
}
void ShibbolethCredentials::slotBrowserHidden()
{
disposeBrowser();
_ready = false;
_shibCookie = QNetworkCookie();
Q_EMIT fetched();
}
void ShibbolethCredentials::invalidateAndFetch()
{
_ready = false;
connect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
fetch();
}
void ShibbolethCredentials::onFetched()
{
disconnect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
Q_EMIT invalidatedAndFetched(prepareCookieData());
}
} // ns Mirall
-72
Ver Arquivo
@@ -1,72 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_CREDS_SHIBBOLETH_CREDENTIALS_H
#define MIRALL_CREDS_SHIBBOLETH_CREDENTIALS_H
#include <QList>
#include <QMap>
#include <QNetworkCookie>
#include <QUrl>
#include "creds/abstractcredentials.h"
namespace Mirall
{
class ShibbolethWebView;
class ShibbolethCredentials : public AbstractCredentials
{
Q_OBJECT
public:
ShibbolethCredentials();
ShibbolethCredentials(const QNetworkCookie& cookie, const QMap<QUrl, QList<QNetworkCookie> >& otherCookies);
void syncContextPreInit(CSYNC* ctx);
void syncContextPreStart(CSYNC* ctx);
bool changed(AbstractCredentials* credentials) const;
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
QNetworkCookie cookie() const;
public Q_SLOTS:
void invalidateAndFetch();
private Q_SLOTS:
void onShibbolethCookieReceived(const QNetworkCookie& cookie);
void slotBrowserHidden();
void onFetched();
Q_SIGNALS:
void newCookie(const QNetworkCookie& cookie);
void invalidatedAndFetched(const QByteArray& cookieData);
private:
QByteArray prepareCookieData() const;
void disposeBrowser();
QNetworkCookie _shibCookie;
bool _ready;
ShibbolethWebView* _browser;
QMap<QUrl, QList<QNetworkCookie> > _otherCookies;
};
} // ns Mirall
#endif
-670
Ver Arquivo
@@ -1,670 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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 "accountsettings.h"
#include "ui_accountsettings.h"
#include "mirall/theme.h"
#include "mirall/folderman.h"
#include "mirall/owncloudinfo.h"
#include "mirall/folderwizard.h"
#include "mirall/folderstatusmodel.h"
#include "mirall/utility.h"
#include "mirall/application.h"
#include "mirall/fileitemdialog.h"
#include "mirall/owncloudsetupwizard.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/ignorelisteditor.h"
#include "mirall/itemprogressdialog.h"
#include <math.h>
#include <QDebug>
#include <QDesktopServices>
#include <QListWidgetItem>
#include <QMessageBox>
namespace Mirall {
AccountSettings::AccountSettings(QWidget *parent) :
QWidget(parent),
ui(new Ui::AccountSettings),
_item(0)
{
ui->setupUi(this);
_model = new FolderStatusModel;
_model->setParent(this);
FolderStatusDelegate *delegate = new FolderStatusDelegate;
ui->_folderList->setItemDelegate( delegate );
ui->_folderList->setModel( _model );
ui->_folderList->setMinimumWidth( 300 );
ui->_folderList->setEditTriggers( QAbstractItemView::NoEditTriggers );
ui->_ButtonRemove->setEnabled(false);
ui->_ButtonReset->setEnabled(false);
ui->_ButtonEnable->setEnabled(false);
ui->_ButtonInfo->setEnabled(false);
ui->_ButtonAdd->setEnabled(true);
connect(ui->_ButtonRemove, SIGNAL(clicked()), this, SLOT(slotRemoveCurrentFolder()));
connect(ui->_ButtonReset, SIGNAL(clicked()), this, SLOT(slotResetCurrentFolder()));
connect(ui->_ButtonEnable, SIGNAL(clicked()), this, SLOT(slotEnableCurrentFolder()));
connect(ui->_ButtonInfo, SIGNAL(clicked()), this, SLOT(slotInfoAboutCurrentFolder()));
connect(ui->_ButtonAdd, SIGNAL(clicked()), this, SLOT(slotAddFolder()));
connect(ui->modifyAccountButton, SIGNAL(clicked()), SLOT(slotOpenAccountWizard()));
connect(ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));;
connect(ui->_folderList, SIGNAL(clicked(QModelIndex)), SLOT(slotFolderActivated(QModelIndex)));
connect(ui->_folderList, SIGNAL(doubleClicked(QModelIndex)),SLOT(slotDoubleClicked(QModelIndex)));
ownCloudInfo *ocInfo = ownCloudInfo::instance();
slotUpdateQuota(ocInfo->lastQuotaTotalBytes(), ocInfo->lastQuotaUsedBytes());
connect(ocInfo, SIGNAL(quotaUpdated(qint64,qint64)), SLOT(slotUpdateQuota(qint64,qint64)));
ui->connectLabel->setWordWrap( true );
setFolderList(FolderMan::instance()->map());
slotCheckConnection();
}
void AccountSettings::slotFolderActivated( const QModelIndex& indx )
{
bool state = indx.isValid();
ui->_ButtonRemove->setEnabled( state );
ui->_ButtonReset->setEnabled( state );
ui->_ButtonReset->setEnabled( state );
ui->_ButtonEnable->setEnabled( state );
ui->_ButtonInfo->setEnabled( state );
if ( state ) {
bool folderEnabled = _model->data( indx, FolderStatusDelegate::FolderSyncEnabled).toBool();
qDebug() << "folder is sync enabled: " << folderEnabled;
if ( folderEnabled ) {
ui->_ButtonEnable->setText( tr( "Pause" ) );
} else {
ui->_ButtonEnable->setText( tr( "Resume" ) );
}
}
}
void AccountSettings::slotAddFolder()
{
FolderMan *folderMan = FolderMan::instance();
folderMan->setSyncEnabled(false); // do not start more syncs.
FolderWizard *folderWizard = new FolderWizard(this);
Folder::Map folderMap = folderMan->map();
folderWizard->setFolderMap( folderMap );
connect(folderWizard, SIGNAL(accepted()), SLOT(slotFolderWizardAccepted()));
connect(folderWizard, SIGNAL(rejected()), SLOT(slotFolderWizardRejected()));
folderWizard->open();
}
void AccountSettings::slotFolderWizardAccepted()
{
FolderWizard *folderWizard = qobject_cast<FolderWizard*>(sender());
FolderMan *folderMan = FolderMan::instance();
qDebug() << "* Folder wizard completed";
QString alias = folderWizard->field(QLatin1String("alias")).toString();
QString sourceFolder = folderWizard->field(QLatin1String("sourceFolder")).toString();
QString targetPath = folderWizard->property("targetPath").toString();
if (!FolderMan::ensureJournalGone( sourceFolder ))
return;
folderMan->addFolderDefinition(alias, sourceFolder, targetPath );
Folder *f = folderMan->setupFolderFromConfigFile( alias );
slotAddFolder( f );
folderMan->setSyncEnabled(true);
if( f ) {
folderMan->slotScheduleAllFolders();
emit folderChanged();
}
}
void AccountSettings::slotFolderWizardRejected()
{
qDebug() << "* Folder wizard cancelled";
FolderMan *folderMan = FolderMan::instance();
folderMan->setSyncEnabled(true);
folderMan->slotScheduleAllFolders();
}
void AccountSettings::slotOpenAccountWizard()
{
this->topLevelWidget()->close();
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), 0);
}
void AccountSettings::slotAddFolder( Folder *folder )
{
if( ! folder || folder->alias().isEmpty() ) return;
QStandardItem *item = new QStandardItem();
folderToModelItem( item, folder );
_model->appendRow( item );
slotCheckConnection();
}
void AccountSettings::buttonsSetEnabled()
{
bool haveFolders = ui->_folderList->model()->rowCount() > 0;
ui->_ButtonRemove->setEnabled(false);
if( Theme::instance()->singleSyncFolder() ) {
// only one folder synced folder allowed.
ui->_ButtonAdd->setVisible(!haveFolders);
} else {
ui->_ButtonAdd->setVisible(true);
ui->_ButtonAdd->setEnabled(true);
}
QModelIndex selected = ui->_folderList->currentIndex();
bool isSelected = selected.isValid();
ui->_ButtonEnable->setEnabled(isSelected);
ui->_ButtonReset->setEnabled(isSelected);
ui->_ButtonRemove->setEnabled(isSelected);
ui->_ButtonInfo->setEnabled(isSelected);
}
void AccountSettings::setListWidgetItem( QListWidgetItem *item )
{
_item = item;
}
void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f )
{
if( ! item || !f ) return;
item->setData( f->nativePath(), FolderStatusDelegate::FolderPathRole );
item->setData( f->secondPath(), FolderStatusDelegate::FolderSecondPathRole );
item->setData( f->alias(), FolderStatusDelegate::FolderAliasRole );
item->setData( f->syncEnabled(), FolderStatusDelegate::FolderSyncEnabled );
SyncResult res = f->syncResult();
SyncResult::Status status = res.status();
QString errors = res.errorStrings().join(QLatin1String("<br/>"));
Theme *theme = Theme::instance();
item->setData( theme->statusHeaderText( status ), Qt::ToolTipRole );
if( f->syncEnabled() ) {
item->setData( theme->syncStateIcon( status ), FolderStatusDelegate::FolderStatusIconRole );
} else {
item->setData( theme->folderDisabledIcon( ), FolderStatusDelegate::FolderStatusIconRole ); // size 48 before
}
item->setData( theme->statusHeaderText( status ), FolderStatusDelegate::FolderStatus );
item->setData( errors, FolderStatusDelegate::FolderErrorMsg );
bool ongoing = false;
item->setData( QVariant(res.warnCount()), FolderStatusDelegate::WarningCount );
if( status == SyncResult::SyncRunning ) {
ongoing = true;
}
item->setData( ongoing, FolderStatusDelegate::SyncRunning);
}
void AccountSettings::slotRemoveCurrentFolder()
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
if( selected.isValid() ) {
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
qDebug() << "Remove Folder alias " << alias;
if( !alias.isEmpty() ) {
// remove from file system through folder man
// _model->removeRow( selected.row() );
int ret = QMessageBox::question( this, tr("Confirm Folder Remove"),
tr("<p>Do you really want to stop syncing the 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 );
if( ret == QMessageBox::No ) {
return;
}
FolderMan *folderMan = FolderMan::instance();
folderMan->slotRemoveFolder( alias );
setFolderList(folderMan->map());
emit folderChanged();
slotCheckConnection();
}
}
}
void AccountSettings::slotResetCurrentFolder()
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
if( selected.isValid() ) {
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
int ret = QMessageBox::question( 0, tr("Confirm Folder Reset"),
tr("<p>Do you really want to reset folder <i>%1</i> and rebuild your client database?</p>"
"<p><b>Note:</b> While no files will be removed, this can cause significant data "
"traffic and take several minutes to hours, depending on the size of the folder.</p>").arg(alias),
QMessageBox::Yes|QMessageBox::No );
if( ret == QMessageBox::Yes ) {
FolderMan *folderMan = FolderMan::instance();
Folder *f = folderMan->folder(alias);
f->slotTerminateSync();
f->wipe();
folderMan->slotScheduleAllFolders();
}
}
}
void AccountSettings::slotDoubleClicked( const QModelIndex& indx )
{
if( ! indx.isValid() ) return;
QString alias = _model->data( indx, FolderStatusDelegate::FolderAliasRole ).toString();
emit openFolderAlias( alias );
}
void AccountSettings::slotCheckConnection()
{
if( ownCloudInfo::instance()->isConfigured() ) {
connect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(const QString&, const QString&, const QString&, const QString&)),
this, SLOT(slotOCInfo( const QString&, const QString&, const QString&, const QString& )));
connect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotOCInfoFail(QNetworkReply*)));
ui->connectLabel->setText( tr("Checking %1 connection...").arg(Theme::instance()->appNameGUI()));
qDebug() << "Check status.php from statusdialog.";
ownCloudInfo::instance()->checkInstallation();
} else {
// ownCloud is not yet configured.
ui->connectLabel->setText( tr("No %1 connection configured.").arg(Theme::instance()->appNameGUI()));
ui->_ButtonAdd->setEnabled( false);
}
}
void AccountSettings::setFolderList( const Folder::Map &folders )
{
_model->clear();
foreach( Folder *f, folders ) {
qDebug() << "Folder: " << f;
slotAddFolder( f );
}
QModelIndex idx = _model->index(0, 0);
if (idx.isValid())
ui->_folderList->setCurrentIndex(idx);
buttonsSetEnabled();
}
// move from Application
void AccountSettings::slotFolderOpenAction( const QString& alias )
{
Folder *f = FolderMan::instance()->folder(alias);
qDebug() << "opening local url " << f->path();
if( f ) {
QUrl url(f->path(), QUrl::TolerantMode);
url.setScheme( QLatin1String("file") );
#ifdef Q_OS_WIN32
// work around a bug in QDesktopServices on Win32, see i-net
QString filePath = f->path();
if (filePath.startsWith(QLatin1String("\\\\")) || filePath.startsWith(QLatin1String("//")))
url.setUrl(QDir::toNativeSeparators(filePath));
else
url = QUrl::fromLocalFile(filePath);
#endif
QDesktopServices::openUrl(url);
}
}
void AccountSettings::slotEnableCurrentFolder()
{
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
if( selected.isValid() ) {
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
bool folderEnabled = _model->data( selected, FolderStatusDelegate::FolderSyncEnabled).toBool();
qDebug() << "Toggle enabled/disabled Folder alias " << alias << " - current state: " << folderEnabled;
if( !alias.isEmpty() ) {
FolderMan *folderMan = FolderMan::instance();
qDebug() << "Application: enable folder with alias " << alias;
bool terminate = false;
// this sets the folder status to disabled but does not interrupt it.
Folder *f = folderMan->folder( alias );
if( f && !folderEnabled ) {
// check if a sync is still running and if so, ask if we should terminate.
if( f->isBusy() ) { // its still running
int reply = QMessageBox::question( 0, tr("Sync Running"),
tr("The syncing operation is running.<br/>Do you want to terminate it?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes );
if ( reply == QMessageBox::Yes )
terminate = true;
else
return; // do nothing
}
}
// message box can return at any time while the thread keeps running,
// so better check again after the user has responded.
if ( f->isBusy() && terminate )
folderMan->terminateSyncProcess( alias );
folderMan->slotEnableFolder( alias, !folderEnabled );
slotUpdateFolderState (f);
// set the button text accordingly.
slotFolderActivated( selected );
}
}
}
void AccountSettings::slotUpdateFolderState( Folder *folder )
{
QStandardItem *item = 0;
int row = 0;
if( ! folder ) return;
item = _model->item( row );
while( item ) {
if( item->data( FolderStatusDelegate::FolderAliasRole ) == folder->alias() ) {
// its the item to update!
break;
}
item = _model->item( ++row );
}
#if 0
if( !_fileItemDialog.isNull() && _fileItemDialog->isVisible() ) {
_fileItemDialog->setSyncResult( FolderMan::instance()->syncResult(folder) );
}
#endif
if( item ) {
folderToModelItem( item, folder );
} else {
// the dialog is not visible.
}
slotCheckConnection();
}
void AccountSettings::slotOCInfo( const QString& url, const QString& versionStr, const QString& version, const QString& )
{
#ifdef Q_OS_WIN32
// work around a bug in QDesktopServices on Win32, see i-net
QString filePath = url;
if (filePath.startsWith("\\\\") || filePath.startsWith("//"))
_OCUrl.setUrl(QDir::toNativeSeparators(filePath));
else
_OCUrl = QUrl::fromLocalFile(filePath);
#else
_OCUrl = QUrl::fromLocalFile(url);
#endif
qDebug() << "#-------# oC found on " << url;
/* enable the open button */
ui->connectLabel->setOpenExternalLinks(true);
ui->connectLabel->setText( tr("Connected to <a href=\"%1\">%1</a>.").arg(url) );
ui->connectLabel->setToolTip( tr("Version: %1 (%2)").arg(versionStr).arg(version));
ui->_ButtonAdd->setEnabled(true);
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(const QString&, const QString&, const QString&, const QString&)),
this, SLOT(slotOCInfo( const QString&, const QString&, const QString&, const QString& )));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotOCInfoFail(QNetworkReply*)));
}
void AccountSettings::slotOCInfoFail( QNetworkReply *reply)
{
QString errStr = tr("unknown problem.");
if( reply ) errStr = reply->errorString();
ui->connectLabel->setText( tr("<p>Failed to connect to %1: <tt>%2</tt></p>").arg(Theme::instance()->appNameGUI()).arg(errStr) );
ui->_ButtonAdd->setEnabled( false);
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(const QString&, const QString&, const QString&, const QString&)),
this, SLOT(slotOCInfo( const QString&, const QString&, const QString&, const QString& )));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotOCInfoFail(QNetworkReply*)));
}
void AccountSettings::slotOpenOC()
{
if( _OCUrl.isValid() )
QDesktopServices::openUrl( _OCUrl );
}
QStandardItem* AccountSettings::itemForFolder(const QString& folder)
{
QStandardItem *item = NULL;
if( folder.isEmpty() ) {
return item;
}
int row = 0;
item = _model->item( row );
while( item ) {
if( item->data( FolderStatusDelegate::FolderAliasRole ) == folder ) {
// its the item to update!
break;
}
item = _model->item( ++row );
}
return item;
}
QString AccountSettings::shortenFilename( const QString& folder, const QString& file ) const
{
// strip off the server prefix from the file name
QString shortFile(file);
if( shortFile.isEmpty() ) {
return QString::null;
}
if(shortFile.startsWith(QLatin1String("ownclouds://")) ||
shortFile.startsWith(QLatin1String("owncloud://")) ) {
// rip off the whole ownCloud URL.
Folder *f = FolderMan::instance()->folder(folder);
if( f ) {
QString remotePathUrl = ownCloudInfo::instance()->webdavUrl() + QLatin1Char('/') + f->secondPath();
shortFile.remove(Utility::toCSyncScheme(remotePathUrl));
}
}
return shortFile;
}
void AccountSettings::slotProgressProblem(const QString& folder, const Progress::SyncProblem& problem)
{
Q_UNUSED(problem);
QStandardItem *item = itemForFolder( folder );
if( !item ) return;
int warnCount = qvariant_cast<int>( item->data(FolderStatusDelegate::WarningCount) );
warnCount++;
item->setData( QVariant(warnCount), FolderStatusDelegate::WarningCount );
}
void AccountSettings::slotSetProgress(const QString& folder, const Progress::Info &progress )
{
// qDebug() << "================================> Progress for folder " << folder << " file " << file << ": "<< p1;
QStandardItem *item = itemForFolder( folder );
qint64 prog1 = progress.current_file_bytes;
qint64 prog2 = progress.file_size;
if( item == NULL ) {
return;
}
// Hotfix for a crash that I experienced in a very rare case/setup
if (progress.kind == Mirall::Progress::Invalid) {
qDebug() << "================================> INVALID Progress for folder " << folder;
return;
}
QString itemFileName = shortenFilename(folder, progress.current_file);
QString syncFileProgressString;
// stay with the previous kind-string for Context.
if( progress.kind != Progress::Context ) {
_kindContext = Progress::asActionString(progress.kind);
}
QString kindString = _kindContext;
switch( progress.kind ) {
case Progress::StartSync:
item->setData( QVariant(0), FolderStatusDelegate::WarningCount );
break;
case Progress::StartDownload:
case Progress::StartUpload:
case Progress::StartDelete:
syncFileProgressString = tr("Start");
if( _hideProgressTimers.contains(item) ) {
// The timer is still running.
QTimer *t = _hideProgressTimers.take(item);
t->stop();
t->deleteLater();
}
break;
case Progress::Context:
syncFileProgressString = tr("Currently");
break;
case Progress::EndDownload:
case Progress::EndUpload:
case Progress::EndDelete:
break;
case Progress::EndSync:
syncFileProgressString = tr("Completely");
// start a timer to stop the progress display
QTimer *timer;
if( _hideProgressTimers.contains(item) ) {
timer = _hideProgressTimers[item];
// there is already one timer running.
} else {
timer = new QTimer;
connect(timer, SIGNAL(timeout()), this, SLOT(slotHideProgress()));
timer->setSingleShot(true);
_hideProgressTimers.insert(item, timer);
}
timer->start(5000);
break;
case Progress::Invalid:
case Progress::Download:
case Progress::Upload:
case Progress::Inactive:
case Progress::Error:
break;
}
QString fileProgressString;
QString s1 = Utility::octetsToString( prog1 );
QString s2 = Utility::octetsToString( prog2 );
// switch on extra space.
item->setData( QVariant(true), FolderStatusDelegate::AddProgressSpace );
if( progress.kind != Progress::EndSync ) {
// Example text: "Currently uploading foobar.png (1MB of 2MB)"
fileProgressString = tr("%1 %2 %3 (%4 of %5)").arg(syncFileProgressString).arg(kindString).
arg(itemFileName).arg(s1).arg(s2);
} else {
fileProgressString = tr("Completely finished.");
}
item->setData( fileProgressString,FolderStatusDelegate::SyncProgressItemString);
// overall progress
s1 = Utility::octetsToString( progress.overall_current_bytes );
s2 = Utility::octetsToString( progress.overall_transmission_size );
QString overallSyncString = tr("%1 of %2, file %3 of %4").arg(s1).arg(s2)
.arg(progress.current_file_no).arg(progress.overall_file_count);
item->setData( overallSyncString, FolderStatusDelegate::SyncProgressOverallString );
int overallPercent = 0;
if( progress.overall_transmission_size > 0 ) {
overallPercent = qRound(double(progress.overall_current_bytes)/double(progress.overall_transmission_size) * 100.0);
}
item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent);
}
void AccountSettings::slotHideProgress()
{
QTimer *send_timer = qobject_cast<QTimer*>(this->sender());
QHash<QStandardItem*, QTimer*>::const_iterator i = _hideProgressTimers.constBegin();
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();
_hideProgressTimers.remove(item);
break;
}
++i;
}
send_timer->deleteLater();
}
void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)
{
ui->quotaProgressBar->setEnabled(true);
// workaround the label only accepting ints (which may be only 32 bit wide)
ui->quotaProgressBar->setMaximum(100);
ui->quotaProgressBar->setValue(round(used/(double)total * 100));
QString usedStr = Utility::octetsToString(used);
QString totalStr = Utility::octetsToString(total);
ui->quotaLabel->setText(tr("You are using %1 of your available %2 storage.").arg(usedStr, totalStr));
}
void AccountSettings::slotIgnoreFilesEditor()
{
if (_ignoreEditor.isNull()) {
_ignoreEditor = new IgnoreListEditor(this);
_ignoreEditor->setAttribute( Qt::WA_DeleteOnClose, true );
_ignoreEditor->open();
} else {
Utility::raiseDialog(_ignoreEditor);
}
}
void AccountSettings::slotInfoAboutCurrentFolder()
{
emit(openProgressDialog());
}
AccountSettings::~AccountSettings()
{
delete ui;
}
} // namespace Mirall
-107
Ver Arquivo
@@ -1,107 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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 ACCOUNTSETTINGS_H
#define ACCOUNTSETTINGS_H
#include <QWidget>
#include <QUrl>
#include <QPointer>
#include <QHash>
#include <QTimer>
#include <QStandardItem>
#include "mirall/folder.h"
#include "mirall/progressdispatcher.h"
#include "mirall/itemprogressdialog.h"
class QStandardItemModel;
class QModelIndex;
class QStandardItem;
class QNetworkReply;
class QListWidgetItem;
namespace Mirall {
namespace Ui {
class AccountSettings;
}
class FolderMan;
class ItemProgressDialog;
class IgnoreListEditor;
class AccountSettings : public QWidget
{
Q_OBJECT
public:
explicit AccountSettings(QWidget *parent = 0);
~AccountSettings();
void setFolderList( const Folder::Map& );
void buttonsSetEnabled();
void setListWidgetItem(QListWidgetItem* item);
signals:
void folderChanged();
void openProgressDialog();
void openFolderAlias( const QString& );
void infoFolderAlias( const QString& );
public slots:
void slotFolderActivated( const QModelIndex& );
void slotOpenOC();
void slotUpdateFolderState( Folder* );
void slotCheckConnection();
void slotOCInfo( const QString&, const QString&, const QString&, const QString& );
void slotOCInfoFail( QNetworkReply* );
void slotDoubleClicked( const QModelIndex& );
void slotFolderOpenAction( const QString& );
void slotSetProgress(const QString&, const Progress::Info& progress);
void slotProgressProblem(const QString& folder, const Progress::SyncProblem& problem);
void slotUpdateQuota( qint64,qint64 );
void slotIgnoreFilesEditor();
protected slots:
void slotAddFolder();
void slotAddFolder( Folder* );
void slotEnableCurrentFolder();
void slotRemoveCurrentFolder();
void slotInfoAboutCurrentFolder();
void slotResetCurrentFolder();
void slotFolderWizardAccepted();
void slotFolderWizardRejected();
void slotOpenAccountWizard();
void slotHideProgress();
private:
QString shortenFilename( const QString& folder, const QString& file ) const;
void folderToModelItem( QStandardItem *, Folder * );
QStandardItem* itemForFolder(const QString& );
Ui::AccountSettings *ui;
QPointer<ItemProgressDialog> _fileItemDialog;
QPointer<IgnoreListEditor> _ignoreEditor;
QStandardItemModel *_model;
QListWidgetItem *_item;
QUrl _OCUrl;
QHash<QStandardItem*, QTimer*> _hideProgressTimers;
QString _kindContext;
};
} // namespace Mirall
#endif // ACCOUNTSETTINGS_H
-180
Ver Arquivo
@@ -1,180 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mirall::AccountSettings</class>
<widget class="QWidget" name="Mirall::AccountSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>607</width>
<height>385</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QGroupBox" name="maintenanceGroupBox">
<property name="title">
<string>Account Maintenance</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="ignoredFilesButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Edit Ignored Files</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeAccountButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove Account</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="modifyAccountButton">
<property name="text">
<string>Modify Account</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="syncStatusGroupBox">
<property name="title">
<string>Sync Status</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="connectLabel">
<property name="text">
<string>Connected with &lt;server&gt; as &lt;user&gt;</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QListView" name="_folderList"/>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="_ButtonAdd">
<property name="text">
<string>Add Sync...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="_ButtonEnable">
<property name="text">
<string>Pause</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<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="QPushButton" name="_ButtonRemove">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="_ButtonReset">
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<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="QPushButton" name="_ButtonInfo">
<property name="text">
<string>Info...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="storageGroupBox">
<property name="title">
<string>Storage Usage</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QProgressBar" name="quotaProgressBar">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="quotaLabel">
<property name="text">
<string>Retrieving usage information...</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;b&gt;Note:&lt;/b&gt; Some folders, including network mounted or shared folders, might have different limits.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+45 -45
Ver Arquivo
@@ -19,15 +19,15 @@
#include <QNetworkReply>
#include <QSslError>
#include <QPointer>
#include <QQueue>
#include "qtsingleapplication.h"
#include "mirall/syncresult.h"
#include "mirall/folder.h"
#include "mirall/logbrowser.h"
#include "mirall/folderman.h"
#include "mirall/fileitemdialog.h"
#include "mirall/systray.h"
#include "mirall/connectionvalidator.h"
#include "mirall/progressdispatcher.h"
class QAction;
class QMenu;
@@ -38,13 +38,13 @@ class QNetworkReply;
namespace Mirall {
class Theme;
class Folder;
class FolderWatcher;
class FolderWizard;
class StatusDialog;
class OwncloudSetupWizard;
class ownCloudInfo;
class SslErrorDialog;
class SettingsDialog;
class ItemProgressDialog;
class ProxyDialog;
class Application : public SharedTools::QtSingleApplication
{
@@ -56,11 +56,24 @@ public:
bool giveHelp();
void showHelp();
public slots:
// TODO: this should not be public
void slotownCloudWizardDone(int);
signals:
protected slots:
void slotAddFolder();
void slotOpenStatus();
void slotRemoveFolder( const QString& );
void slotResetFolder( const QString& );
void slotEnableFolder( const QString&, const bool );
void slotInfoFolder( const QString& );
void slotConfigure();
void slotConfigureProxy();
void slotParseOptions( const QString& );
void slotShowTrayMessage(const QString&, const QString&);
void slotSyncStateChange( const QString& );
void slotownCloudWizardDone(int);
protected:
void parseOptions(const QStringList& );
void setupTranslations();
void setupActions();
@@ -68,7 +81,6 @@ protected:
void setupContextMenu();
void setupLogBrowser();
void enterNextLogFile();
bool checkConfigExists(bool openSettings);
//folders have to be disabled while making config changes
void computeOverallSyncStatus();
@@ -78,69 +90,57 @@ protected:
bool winEventFilter( MSG * message, long * result );
#endif
signals:
void folderRemoved();
void folderStateChanged(Folder*);
protected slots:
void slotFoldersChanged();
void slotSettings();
void slotItemProgressDialog();
void slotParseOptions( const QString& );
void slotShowTrayMessage(const QString&, const QString&);
void slotShowOptionalTrayMessage(const QString&, const QString&);
void slotShowGuiMessage(const QString& title, const QString& message);
void slotCheckConnection();
void slotConnectionValidatorResult(ConnectionValidator::Status);
void slotSyncStateChange( const QString& );
void slotTrayClicked( QSystemTrayIcon::ActivationReason );
void slotFolderOpenAction(const QString & );
void slotOpenOwnCloud();
void slotStartFolderSetup(int result = QDialog::Accepted); // defaulting to Accepted
void slotOwnCloudFound( const QString&, const QString&, const QString&, const QString& );
void slotNoOwnCloudFound( QNetworkReply* );
void slotCheckAuthentication();
void slotAuthCheck( const QString& ,QNetworkReply* );
void slotOpenLogBrowser();
void slotAbout();
void slotSSLFailed( QNetworkReply *reply, QList<QSslError> errors );
void slotFetchCredentials();
void slotCredentialsFetched( bool );
void slotStartUpdateDetector();
void slotSetupProxy();
void slotRefreshQuotaDisplay( qint64 total, qint64 used );
void slotUseMonoIconsChanged( bool );
void slotUpdateProgress(const QString&, const Progress::Info&);
void slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem &problem);
void slotDisplayIdle();
void slotHelp();
void slotCredentialsFetched();
private:
void setHelp();
void raiseDialog( QWidget* );
void rebuildRecentMenus();
void runValidator();
// configuration file -> folder
Systray *_tray;
QAction *_actionOpenoC;
QAction *_actionSettings;
QAction *_actionQuota;
QAction *_actionStatus;
QAction *_actionRecent;
QAction *_actionHelp;
QAction *_actionQuit;
QAction *_actionAddFolder;
QAction *_actionOpenStatus;
QAction *_actionConfigure;
QAction *_actionOpenoC;
QAction *_actionConfigureProxy;
QAction *_actionAbout;
#if QT_VERSION >= 0x040700
QNetworkConfigurationManager *_networkMgr;
#endif
QPointer<FolderWizard> _folderWizard;
QScopedPointer<OwncloudSetupWizard> _owncloudSetupWizard;
SslErrorDialog *_sslErrorDialog;
ConnectionValidator *_conValidator;
// tray's menu
QMenu *_contextMenu;
QMenu *_recentActionsMenu;
StatusDialog *_statusDialog;
FileItemDialog *_fileItemDialog;
FolderMan *_folderMan;
Theme *_theme;
QSignalMapper *_folderOpenActionMapper;
LogBrowser *_logBrowser;
QPointer<SettingsDialog> _settingsDialog;
QPointer<ItemProgressDialog> _progressDialog;
QPointer<ProxyDialog> _proxyDialog;
QString _logFile;
QString _logDirectory;
int _logExpire;
bool _showLogWindow;
bool _logFlush;
+67 -40
Ver Arquivo
@@ -17,6 +17,7 @@
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#include "mirall/credentialstore.h"
namespace Mirall {
@@ -27,8 +28,7 @@ ConnectionValidator::ConnectionValidator(QObject *parent) :
}
ConnectionValidator::ConnectionValidator(const QString& connection, QObject *parent)
: QObject(parent),
_connection(connection)
:_connection(connection)
{
ownCloudInfo::instance()->setCustomConfigHandle(_connection);
}
@@ -38,42 +38,9 @@ QStringList ConnectionValidator::errors() const
return _errors;
}
QString ConnectionValidator::statusString( Status stat ) const
QString ConnectionValidator::statusString( Status )
{
QString re;
switch( stat ) {
case Undefined:
re = QLatin1String("Undefined");
break;
case Connected:
re = QLatin1String("Connected");
break;
case NotConfigured:
re = QLatin1String("NotConfigured");
break;
case ServerVersionMismatch:
re = QLatin1String("Server Version Mismatch");
break;
case CredentialsTooManyAttempts:
re = QLatin1String("Credentials Too Many Attempts");
break;
case CredentialError:
re = QLatin1String("CredentialError");
break;
case CredentialsUserCanceled:
re = QLatin1String("Credential User Canceled");
break;
case CredentialsWrong:
re = QLatin1String("Credentials Wrong");
break;
case StatusNotFound:
re = QLatin1String("Status not found");
break;
default:
re = QLatin1String("status undeclared.");
}
return re;
return QLatin1String("Get your street creds!");
}
@@ -93,7 +60,7 @@ void ConnectionValidator::checkConnection()
}
}
void ConnectionValidator::slotStatusFound( const QString& url, const QString& versionStr, const QString& version, const QString& /*edition*/)
void ConnectionValidator::slotStatusFound( const QString& url, const QString& versionStr, const QString& version, const QString& edition)
{
// status.php was found.
qDebug() << "** Application: ownCloud found: " << url << " with version " << versionStr << "(" << version << ")";
@@ -115,7 +82,7 @@ void ConnectionValidator::slotStatusFound( const QString& url, const QString& ve
return;
}
QTimer::singleShot( 0, this, SLOT( slotCheckAuthentication() ));
QTimer::singleShot( 0, this, SLOT( slotFetchCredentials() ));
}
// status.php could not be loaded.
@@ -133,19 +100,77 @@ void ConnectionValidator::slotNoStatusFound(QNetworkReply *reply)
}
void ConnectionValidator::slotFetchCredentials()
{
if( _connection.isEmpty() ) {
if( CredentialStore::instance()->canTryAgain() ) {
connect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)),
this, SLOT(slotCredentialsFetched(bool)) );
CredentialStore::instance()->fetchCredentials();
}
if( CredentialStore::instance()->state() == CredentialStore::TooManyAttempts ) {
_errors << tr("Too many attempts to get a valid password.");
emit connectionResult( CredentialsTooManyAttempts );
}
} else {
// Pull credentials from Mirall config.
slotCredentialsFetched( true );
}
}
void ConnectionValidator::slotCredentialsFetched( bool ok )
{
qDebug() << "Credentials successfully fetched: " << ok;
disconnect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)) );
if( ! ok ) {
Status stat;
_errors << tr("Error: Could not retrieve the password!");
if( CredentialStore::instance()->state() == CredentialStore::UserCanceled ) {
_errors << tr("Password dialog was canceled!");
stat = CredentialsUserCanceled;
} else {
_errors << CredentialStore::instance()->errorMessage();
stat = CredentialError;
}
qDebug() << "Could not fetch credentials" << _errors;
emit connectionResult( stat );
} else {
QString user, pwd;
if( _connection.isEmpty() ) {
user = CredentialStore::instance()->user();
pwd = CredentialStore::instance()->password();
} else {
// in case of reconfiguration, the _connection is set.
MirallConfigFile cfg(_connection);
user = cfg.ownCloudUser();
pwd = cfg.ownCloudPasswd();
}
ownCloudInfo::instance()->setCredentials( user, pwd );
// Credential fetched ok.
QTimer::singleShot( 0, this, SLOT( slotCheckAuthentication() ));
}
}
void ConnectionValidator::slotCheckAuthentication()
{
connect( ownCloudInfo::instance(), SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
this, SLOT(slotAuthCheck(QString,QNetworkReply*)));
qDebug() << "# checking for authentication settings.";
ownCloudInfo::instance()->getWebDAVPath(QLatin1String("/") ); // this call needs to be authenticated.
ownCloudInfo::instance()->getRequest(QLatin1String("/"), true ); // this call needs to be authenticated.
// simply GET the webdav root, will fail if credentials are wrong.
// continue in slotAuthCheck here :-)
}
void ConnectionValidator::slotAuthCheck( const QString& ,QNetworkReply *reply )
{
bool ok = true;
Status stat = Connected;
if( reply->error() == QNetworkReply::AuthenticationRequiredError ||
@@ -153,6 +178,7 @@ void ConnectionValidator::slotAuthCheck( const QString& ,QNetworkReply *reply )
qDebug() << "******** Password is wrong!";
_errors << "The provided credentials are wrong.";
stat = CredentialsWrong;
ok = false;
}
// disconnect from ownCloud Info signals
@@ -160,6 +186,7 @@ void ConnectionValidator::slotAuthCheck( const QString& ,QNetworkReply *reply )
this,SLOT(slotAuthCheck(QString,QNetworkReply*)));
emit connectionResult( stat );
}
+5 -3
Ver Arquivo
@@ -45,12 +45,12 @@ public:
void checkConnection();
QString statusString( Status ) const;
QString statusString( Status );
signals:
void connectionResult( ConnectionValidator::Status );
// void connectionAvailable();
// void connectionFailed();
void connectionAvailable();
void connectionFailed();
public slots:
@@ -58,6 +58,8 @@ protected slots:
void slotStatusFound( const QString&, const QString&, const QString&, const QString& );
void slotNoStatusFound(QNetworkReply *);
void slotFetchCredentials();
void slotCredentialsFetched( bool );
void slotCheckAuthentication();
void slotAuthCheck( const QString& ,QNetworkReply * );
@@ -16,8 +16,8 @@
#include "config.h"
#include "creds/http/credentialstore.h"
#include "creds/http/httpconfigfile.h"
#include "mirall/credentialstore.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#ifdef WITH_QTKEYCHAIN
@@ -35,6 +35,7 @@ QString CredentialStore::_passwd = QString::null;
QString CredentialStore::_user = QString::null;
QString CredentialStore::_url = QString::null;
QString CredentialStore::_errorMsg = QString::null;
int CredentialStore::_tries = 0;
#ifdef WITH_QTKEYCHAIN
CredentialStore::CredentialType CredentialStore::_type = KeyChain;
#else
@@ -66,14 +67,39 @@ CredentialStore::CredState CredentialStore::state()
return _state;
}
bool CredentialStore::canTryAgain()
{
if( _tries > MAX_LOGIN_ATTEMPTS ) {
qDebug() << "canTryAgain: Max attempts reached.";
return false;
}
/* Since QtKeyChain is required now, it makes sense to only query once. */
if( _state == NotFetched || _state == AsyncWriting ) {
return true;
} else {
return false;
}
}
void CredentialStore::fetchCredentials()
{
HttpConfigFile cfgFile;
MirallConfigFile cfgFile;
if( ++_tries > MAX_LOGIN_ATTEMPTS ) {
qDebug() << "Too many attempts to enter password!";
_state = TooManyAttempts;
emit( fetchCredentialsFinished(false) );
return;
}
bool ok = false;
QString pwd;
_user = cfgFile.user();
_user = cfgFile.ownCloudUser();
_url = cfgFile.ownCloudUrl();
if( !cfgFile.passwordStorageAllowed() ) {
_type = CredentialStore::User;
}
QString key = keyChainKey(_url);
@@ -85,17 +111,26 @@ void CredentialStore::fetchCredentials()
}
switch( _type ) {
case CredentialStore::User: {
/* Ask the user for the password */
/* Fixme: Move user interaction out here. */
_state = AsyncFetching;
_inputDialog = new QInputDialog;
_inputDialog->setWindowTitle(QApplication::translate("MirallConfigFile","Password Required") );
_inputDialog->setLabelText( QApplication::translate("MirallConfigFile","Please enter your %1 password:")
.arg(Theme::instance()->appNameGUI()));
_inputDialog->setInputMode( QInputDialog::TextInput );
_inputDialog->setTextEchoMode( QLineEdit::Password );
connect(_inputDialog, SIGNAL(finished(int)), SLOT(slotUserDialogDone(int)));
_inputDialog->open();
break;
}
case CredentialStore::Settings: {
/* Read from config file. */
_state = Fetching;
cfgFile.fixupOldPassword();
if( cfgFile.passwordExists() ) {
pwd = cfgFile.password();
ok = true;
} else {
ok = false;
_state = EntryNotFound;
}
pwd = cfgFile.ownCloudPasswd();
ok = true;
break;
}
case CredentialStore::KeyChain: {
@@ -142,11 +177,25 @@ void CredentialStore::fetchCredentials()
}
}
void CredentialStore::slotUserDialogDone( int result )
{
if( result == QDialog::Accepted ) {
_passwd = _inputDialog->textValue();
_state = Ok;
} else {
_state = UserCanceled;
_passwd = QString::null;
}
_inputDialog->deleteLater();
emit(fetchCredentialsFinished(_state == Ok));
}
void CredentialStore::reset()
{
_state = NotFetched;
_user = QString::null;
_passwd = QString::null;
_tries = 0;
}
QString CredentialStore::keyChainKey( const QString& url ) const
@@ -193,6 +242,9 @@ void CredentialStore::slotKeyChainReadFinished(QKeychain::Job* job)
case QKeychain::CouldNotDeleteEntry:
_state = Error;
break;
case QKeychain::AccessDeniedByUser:
_state = AccessDeniedByUser;
break;
case QKeychain::AccessDenied:
_state = AccessDenied;
break;
@@ -241,36 +293,43 @@ QString CredentialStore::errorMessage()
}
void CredentialStore::setCredentials( const QString& url, const QString& user,
const QString& pwd )
const QString& pwd, bool allowToStore )
{
_passwd = pwd;
_user = user;
if( allowToStore ) {
#ifdef WITH_QTKEYCHAIN
_type = KeyChain;
_type = KeyChain;
#else
_type = Settings;
_type = Settings;
#endif
} else {
_type = User;
}
_url = url;
_state = Ok;
}
void CredentialStore::saveCredentials( )
{
HttpConfigFile cfgFile;
MirallConfigFile cfgFile;
QString key = keyChainKey(_url);
if( key.isNull() ) {
qDebug() << "Error: Can not save credentials, URL is zero!";
return;
}
#ifdef WITH_QTKEYCHAIN
WritePasswordJob *job = NULL;
#endif
cfgFile.setUser(_user);
switch( _type ) {
case CredentialStore::KeyChain: {
case CredentialStore::User:
deleteKeyChainCredential( key );
break;
case CredentialStore::KeyChain:
#ifdef WITH_QTKEYCHAIN
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
// Set password in KeyChain
job = new WritePasswordJob(Theme::instance()->appName());
job->setKey( key );
job->setTextData(_passwd);
@@ -279,10 +338,9 @@ void CredentialStore::saveCredentials( )
_state = AsyncWriting;
job->start();
#endif
}
break;
case CredentialStore::Settings:
cfgFile.setPassword( _passwd );
cfgFile.writePassword( _passwd );
reset();
break;
default:
@@ -311,9 +369,10 @@ void CredentialStore::slotKeyChainWriteFinished( QKeychain::Job *job )
} else {
qDebug() << "Successfully stored password for user " << _user;
// Try to remove password formerly stored in the config file.
HttpConfigFile cfgFile;
cfgFile.removePassword();
MirallConfigFile cfgFile;
cfgFile.clearPasswordFromConfig();
_state = NotFetched;
_tries = 0;
}
} else {
qDebug() << "Error: KeyChain Write Password Job failed!";
@@ -34,8 +34,10 @@ namespace Mirall {
* The fetchCredentials() call changes the internal state of the credential store
* to one of
* Ok: There are credentials. Note that it's unknown if they are correct!!
* UserCanceled: The fetching involved user interaction and the user canceled
* the operation. No valid credentials are there.
* TooManyAttempts: The user tried to often to enter a password.
* Fetching: The fetching is not yet finished.
* EntryNotFound: No password entry found in the storage.
* Error: A general error happened.
* After fetching has finished, signal fetchCredentialsFinished(bool) is emitted.
* The result can be retrieved with state() and password() and user() methods.
@@ -47,16 +49,20 @@ class CredentialStore : public QObject
public:
enum CredState { NotFetched = 0,
Ok,
UserCanceled,
Fetching,
AsyncFetching,
EntryNotFound,
AccessDeniedByUser,
AccessDenied,
NoKeychainBackend,
Error,
AsyncWriting };
AsyncWriting,
TooManyAttempts };
enum CredentialType {
Settings = 0,
User = 0,
Settings,
KeyChain
};
@@ -91,13 +97,19 @@ public:
* The function also sets the state to ok.
* @param url - the connection url
* @param user - the user name
* @param password - the password.
*/
void setCredentials( const QString& url, const QString& user, const QString& pwd);
void setCredentials( const QString&, const QString&, const QString&, bool );
void saveCredentials( );
QString errorMessage();
/**
* @brief canTryAgain - check if another try to get credentials makes sense.
*/
bool canTryAgain();
void reset();
signals:
/**
@@ -113,6 +125,7 @@ signals:
protected slots:
void slotKeyChainReadFinished( QKeychain::Job* );
void slotKeyChainWriteFinished( QKeychain::Job* );
void slotUserDialogDone(int);
private:
explicit CredentialStore(QObject *parent = 0);
@@ -125,7 +138,9 @@ private:
static QString _user;
static QString _url;
static QString _errorMsg;
static int _tries;
static CredentialType _type;
QInputDialog *_inputDialog;
};
}
+11 -127
Ver Arquivo
@@ -18,7 +18,6 @@
#include "mirall/theme.h"
#include "mirall/logger.h"
#include "mirall/owncloudinfo.h"
#include "creds/abstractcredentials.h"
#ifdef Q_OS_WIN
#include <windows.h>
@@ -233,20 +232,6 @@ int CSyncThread::treewalkFile( TREE_WALK_FILE *file, bool remote )
break;
}
switch( file->type ) {
case CSYNC_FTW_TYPE_DIR:
item._type = SyncFileItem::Directory;
break;
case CSYNC_FTW_TYPE_FILE:
item._type = SyncFileItem::File;
break;
case CSYNC_FTW_TYPE_SLINK:
item._type = SyncFileItem::SoftLink;
break;
default:
item._type = SyncFileItem::UnknownType;
}
item._dir = dir;
_mutex.lock();
_syncedItems.append(item);
@@ -266,7 +251,7 @@ int CSyncThread::treewalkError(TREE_WALK_FILE* file)
if( file &&
(file->instruction == CSYNC_INSTRUCTION_STAT_ERROR ||
file->instruction == CSYNC_INSTRUCTION_ERROR) ) {
file->instruction == CSYNC_INSTRUCTION_ERROR) ) {
_mutex.lock();
_syncedItems[indx]._instruction = file->instruction;
_mutex.unlock();
@@ -330,50 +315,11 @@ void CSyncThread::startSync()
// cleans up behind us and emits finished() to ease error handling
CSyncRunScopeHelper helper(_csync_ctx, this);
// maybe move this somewhere else where it can influence a running sync?
MirallConfigFile cfg;
int downloadLimit = 0;
if (cfg.useDownloadLimit()) {
downloadLimit = cfg.downloadLimit();
}
csync_set_module_property(_csync_ctx, "bandwidth_limit_download", &downloadLimit);
int uploadLimit = -75; // 75%
int useUpLimit = cfg.useUploadLimit();
if ( useUpLimit >= 1) {
uploadLimit = cfg.uploadLimit();
} else if (useUpLimit == 0) {
uploadLimit = 0;
}
csync_set_module_property(_csync_ctx, "bandwidth_limit_upload", &uploadLimit);
csync_set_progress_callback( _csync_ctx, cb_progress );
csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
csync_set_userdata(_csync_ctx, this);
// TODO: This should be a part of this method, but we don't have
// any way to get "session_key" module property from csync. Had we
// have it, then we could keep this code and remove it from
// AbstractCredentials implementations.
cfg.getCredentials()->syncContextPreStart(_csync_ctx);
// if (_lastAuthCookies.length() > 0) {
// // Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
// // when https://github.com/owncloud/core/pull/4042 is merged.
// QString cookiesAsString;
// foreach(QNetworkCookie c, _lastAuthCookies) {
// cookiesAsString += c.name();
// cookiesAsString += '=';
// cookiesAsString += c.value();
// cookiesAsString += "; ";
// }
// csync_set_module_property(_csync_ctx, "session_key", cookiesAsString.to
// }
// csync_set_auth_callback( _csync_ctx, getauth );
csync_set_progress_callback( _csync_ctx, progress );
qDebug() << "#### Update start #################################################### >>";
if( csync_update(_csync_ctx) < 0 ) {
@@ -383,7 +329,7 @@ void CSyncThread::startSync()
qDebug() << "<<#### Update end ###########################################################";
if( csync_reconcile(_csync_ctx) < 0 ) {
handleSyncError(_csync_ctx, "csync_reconcile");
handleSyncError(_csync_ctx, "cysnc_reconcile");
return;
}
@@ -417,7 +363,7 @@ void CSyncThread::startSync()
if( walkOk ) {
if( csync_walk_local_tree(_csync_ctx, &walkFinalize, 0) < 0 ||
csync_walk_remote_tree(_csync_ctx, &walkFinalize, 0 ) < 0 ) {
csync_walk_remote_tree( _csync_ctx, &walkFinalize, 0 ) < 0 ) {
qDebug() << "Error in finalize treewalk.";
} else {
// emit the treewalk results.
@@ -427,78 +373,16 @@ void CSyncThread::startSync()
qDebug() << Q_FUNC_INFO << "Sync finished";
}
Progress::Kind CSyncThread::csyncToProgressKind( enum csync_notify_type_e kind )
void CSyncThread::progress(const char *remote_url, enum csync_notify_type_e kind,
long long o1, long long o2, void *userdata)
{
Progress::Kind pKind = Progress::Invalid;
switch(kind) {
case CSYNC_NOTIFY_INVALID:
pKind = Progress::Invalid;
break;
case CSYNC_NOTIFY_START_SYNC_SEQUENCE:
pKind = Progress::StartSync;
break;
case CSYNC_NOTIFY_START_DOWNLOAD:
pKind = Progress::StartDownload;
break;
case CSYNC_NOTIFY_START_UPLOAD:
pKind = Progress::StartUpload;
break;
case CSYNC_NOTIFY_PROGRESS:
pKind = Progress::Context;
break;
case CSYNC_NOTIFY_FINISHED_DOWNLOAD:
pKind = Progress::EndDownload;
break;
case CSYNC_NOTIFY_FINISHED_UPLOAD:
pKind = Progress::EndUpload;
break;
case CSYNC_NOTIFY_FINISHED_SYNC_SEQUENCE:
pKind = Progress::EndSync;
break;
case CSYNC_NOTIFY_START_DELETE:
pKind = Progress::StartDelete;
break;
case CSYNC_NOTIFY_END_DELETE:
pKind = Progress::EndDelete;
break;
case CSYNC_NOTIFY_ERROR:
pKind = Progress::Error;
break;
default:
pKind = Progress::Invalid;
break;
(void) o1; (void) o2;
if (kind == CSYNC_NOTIFY_FINISHED_DOWNLOAD) {
QString path = QUrl::fromEncoded(remote_url).toString();
CSyncThread *thread = static_cast<CSyncThread*>(userdata);
thread->fileReceived(path);
}
return pKind;
}
void CSyncThread::cb_progress( CSYNC_PROGRESS *progress, void *userdata )
{
if( !progress ) {
qDebug() << "No progress block in progress callback found!";
return;
}
if( !userdata ) {
qDebug() << "No thread given in progress callback!";
return;
}
Progress::Info pInfo;
CSyncThread *thread = static_cast<CSyncThread*>(userdata);
pInfo.kind = thread->csyncToProgressKind( progress->kind );
pInfo.current_file = QUrl::fromEncoded( progress->path ).toString();
pInfo.file_size = progress->file_size;
pInfo.current_file_bytes = progress->curr_bytes;
pInfo.overall_file_count = progress->overall_file_count;
pInfo.current_file_no = progress->current_file_no;
pInfo.overall_transmission_size = progress->overall_transmission_size;
pInfo.overall_current_bytes = progress->current_overall_bytes;
pInfo.timestamp = QTime::currentTime();
// Connect to something in folder!
thread->transmissionProgress( pInfo );
}
} // ns Mirall
+5 -7
Ver Arquivo
@@ -22,12 +22,10 @@
#include <QThread>
#include <QString>
#include <QNetworkProxy>
#include <QNetworkCookie>
#include <csync.h>
#include "mirall/syncfileitem.h"
#include "mirall/progressdispatcher.h"
class QProcess;
@@ -52,7 +50,6 @@ signals:
void csyncUnavailable();
void treeWalkResult(const SyncFileItemVector&);
void transmissionProgress( const Progress::Info& progress );
void csyncStateDbFile( const QString& );
void wipeDb();
@@ -63,15 +60,16 @@ signals:
private:
void handleSyncError(CSYNC *ctx, const char *state);
static void cb_progress( CSYNC_PROGRESS *progress, void *userdata );
static void progress(const char *remote_url,
enum csync_notify_type_e kind,
long long o1, long long o2,
void *userdata);
static int treewalkLocal( TREE_WALK_FILE*, void *);
static int treewalkRemote( TREE_WALK_FILE*, void *);
int treewalkFile( TREE_WALK_FILE*, bool );
int treewalkError( TREE_WALK_FILE* );
Progress::Kind csyncToProgressKind( enum csync_notify_type_e kind );
static int walkFinalize(TREE_WALK_FILE*, void* );
@@ -85,7 +83,7 @@ private:
bool _hasFiles; // true if there is at least one file that is not ignored or removed
friend struct CSyncRunScopeHelper;
friend class CSyncRunScopeHelper;
};
}
+34 -39
Ver Arquivo
@@ -14,11 +14,10 @@
#include <QtGui>
#include "mirall/fileitemdialog.h"
#include "mirall/theme.h"
#include "mirall/syncresult.h"
#include "mirall/logger.h"
#include "ui_fileitemdialog.h"
#define TYPE_SUCCESS 1
#define TYPE_CONFLICT 2
#define TYPE_NEW 3
@@ -31,36 +30,32 @@
namespace Mirall {
FileItemDialog::FileItemDialog(QWidget *parent) :
FileItemDialog::FileItemDialog(Theme *theme, QWidget *parent) :
QDialog(parent),
_ui(new Ui::FileItemDialog)
_theme(theme)
{
_ui->setupUi(this);
connect(_ui->_dialogButtonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()),
setupUi(this);
connect(_dialogButtonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()),
this, SLOT(accept()));
QStringList header;
header << tr("Files");
QString firstColString = tr("File Count");
header << firstColString;
_ui->_treeWidget->setHeaderLabels( header );
_treeWidget->setHeaderLabels( header );
_ui->_treeWidget->setColumnWidth(0, 480);
_treeWidget->setColumnWidth(0, 480);
_timer.setInterval(1000);
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotSetFolderMessage()));
connect(this, SIGNAL(guiLog(QString,QString)), Logger::instance(), SIGNAL(guiLog(QString,QString)));
QPushButton *copyBtn = _ui->_dialogButtonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole);
QPushButton *copyBtn = _dialogButtonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole);
connect(copyBtn, SIGNAL(clicked()), SLOT(copyToClipboard()));
setWindowTitle(tr("Sync Protocol"));
}
FileItemDialog::~FileItemDialog()
{
delete _ui;
}
void FileItemDialog::setSyncResult( const SyncResult& result )
{
QString folderMessage;
@@ -99,17 +94,17 @@ void FileItemDialog::setSyncResult( const SyncResult& result )
_lastSyncTime = result.syncTime();
if( result.errorStrings().count() ) {
_ui->_errorLabel->setVisible(true);
_ui->_errorLabel->setTextFormat(Qt::RichText);
_errorLabel->setVisible(true);
_errorLabel->setTextFormat(Qt::RichText);
QString errStr;
foreach( QString err, result.errorStrings() ) {
errStr.append(QString("<p>%1</p>").arg(err));
}
_ui->_errorLabel->setText(errStr);
_errorLabel->setText(errStr);
} else {
_ui->_errorLabel->setText(QString::null);
_ui->_errorLabel->setVisible(false);
_errorLabel->setText(QString::null);
_errorLabel->setVisible(false);
}
slotSetFolderMessage();
@@ -129,9 +124,9 @@ void FileItemDialog::slotSetFolderMessage()
int secs = _lastSyncTime.secsTo(now);
if (secs < 60)
_ui->_timelabel->setText(tr("%1 (last finished %n sec. ago)", "", secs).arg(_folderMessage));
_timelabel->setText(tr("%1 (last finished %n sec. ago)", "", secs).arg(_folderMessage));
else
_ui->_timelabel->setText(tr("%1 (last finished %n min. ago)", "", secs/60).arg(_folderMessage));
_timelabel->setText(tr("%1 (last finished %n min. ago)", "", secs/60).arg(_folderMessage));
}
void FileItemDialog::copyToClipboard()
@@ -139,9 +134,9 @@ void FileItemDialog::copyToClipboard()
QString text;
QTextStream ts(&text);
int topLevelItems = _ui->_treeWidget->topLevelItemCount();
int topLevelItems = _treeWidget->topLevelItemCount();
for (int i = 0; i < topLevelItems; i++) {
QTreeWidgetItem *item = _ui->_treeWidget->topLevelItem(i);
QTreeWidgetItem *item = _treeWidget->topLevelItem(i);
ts << left << qSetFieldWidth(50)
<< item->data(0, Qt::DisplayRole).toString()
<< right << qSetFieldWidth(6)
@@ -160,7 +155,7 @@ void FileItemDialog::copyToClipboard()
}
QApplication::clipboard()->setText(text);
Logger::instance()->postGuiLog(tr("Copied to clipboard"), tr("The sync protocol has been copied to the clipboard."));
emit guiLog(tr("Copied to clipboard"), tr("The sync protocol has been copied to the clipboard."));
}
void FileItemDialog::accept()
@@ -171,52 +166,52 @@ void FileItemDialog::accept()
void FileItemDialog::setSyncFileItems( const SyncFileItemVector& list )
{
_ui->_treeWidget->clear();
_treeWidget->clear();
QStringList strings;
QFont headerFont;
headerFont.setWeight(QFont::Bold);
strings.clear();
strings.append(tr("Synced Files"));
_syncedFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_SUCCESS );
_syncedFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_SUCCESS );
_syncedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
_ui->_treeWidget->addTopLevelItem(_syncedFileItem);
_treeWidget->addTopLevelItem(_syncedFileItem);
strings.clear();
strings.append(tr("New Files"));
_newFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_NEW );
_newFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_NEW );
_newFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
_ui->_treeWidget->addTopLevelItem(_newFileItem);
_treeWidget->addTopLevelItem(_newFileItem);
strings.clear();
strings.append(tr("Deleted Files"));
_deletedFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_DELETED );
_deletedFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_DELETED );
_deletedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
_ui->_treeWidget->addTopLevelItem(_deletedFileItem);
_treeWidget->addTopLevelItem(_deletedFileItem);
strings.clear();
strings.append(tr("Renamed Files"));
_renamedFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_RENAME);
_renamedFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_RENAME);
_renamedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
_ui->_treeWidget->addTopLevelItem(_renamedFileItem);
_treeWidget->addTopLevelItem(_renamedFileItem);
strings.clear();
strings.append(tr("Ignored Files"));
_ignoredFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_IGNORE);
_ignoredFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_IGNORE);
_ignoredFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
_ui->_treeWidget->addTopLevelItem(_renamedFileItem);
_treeWidget->addTopLevelItem(_renamedFileItem);
strings.clear();
strings.append(tr("Errors"));
_errorFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_ERROR );
_errorFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_ERROR );
_errorFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
_ui->_treeWidget->addTopLevelItem(_errorFileItem);
_treeWidget->addTopLevelItem(_errorFileItem);
strings.clear();
strings.append(tr("Conflicts"));
_conflictFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_CONFLICT);
_conflictFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_CONFLICT);
_conflictFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
_ui->_treeWidget->addTopLevelItem(_conflictFileItem);
_treeWidget->addTopLevelItem(_conflictFileItem);
QList<QTreeWidgetItem*> syncedItems;
QList<QTreeWidgetItem*> renamedItems;
+7 -7
Ver Arquivo
@@ -23,18 +23,15 @@
#include "ui_fileitemdialog.h"
namespace Mirall {
class Theme;
class SyncResult;
namespace Ui {
class FileItemDialog;
}
class FileItemDialog : public QDialog
class FileItemDialog : public QDialog, public Ui::_fileItemDialog
{
Q_OBJECT
public:
explicit FileItemDialog(QWidget *parent = 0);
~FileItemDialog();
explicit FileItemDialog(Theme*, QWidget *parent = 0);
void setSyncResult( const SyncResult& );
signals:
@@ -46,6 +43,9 @@ protected slots:
void slotSetFolderMessage();
void copyToClipboard();
signals:
void guiLog(const QString&, const QString&);
private:
void setSyncFileItems( const SyncFileItemVector& list );
void formatHeaderItem( QTreeWidgetItem *, const QList<QTreeWidgetItem*>& );
@@ -58,10 +58,10 @@ private:
QTreeWidgetItem *_conflictFileItem;
QTreeWidgetItem *_ignoredFileItem;
Theme *_theme;
QString _folderMessage;
QDateTime _lastSyncTime;
QTimer _timer;
Ui::FileItemDialog *_ui;
};
}
+2 -2
Ver Arquivo
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mirall::FileItemDialog</class>
<widget class="QWidget" name="Mirall::FileItemDialog">
<class>_fileItemDialog</class>
<widget class="QWidget" name="_fileItemDialog">
<property name="geometry">
<rect>
<x>0</x>
+1 -1
Ver Arquivo
@@ -25,7 +25,7 @@ class FileUtils
public:
enum SubFolderListOption {
SubFolderNoOptions = 0x0,
SubFolderRecursive = 0x1
SubFolderRecursive = 0x1,
};
Q_DECLARE_FLAGS(SubFolderListOptions, SubFolderListOption)
+126 -470
Ver Arquivo
@@ -1,7 +1,5 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
* 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
@@ -19,111 +17,66 @@
#include "mirall/folderwatcher.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/syncresult.h"
#include "mirall/logger.h"
#include "mirall/owncloudinfo.h"
#include "mirall/utility.h"
#include "creds/abstractcredentials.h"
#include <QDebug>
#include <QTimer>
#include <QUrl>
#include <QFileSystemWatcher>
#include <QDir>
#include <QMessageBox>
#include <QPushButton>
namespace Mirall {
void csyncLogCatcher(CSYNC */*ctx*/,
int /*verbosity*/,
const char */*function*/,
const char *buffer,
void */*userdata*/)
{
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
}
Folder::Folder(const QString &alias, const QString &path, const QString& secondPath, QObject *parent)
: QObject(parent)
, _path(path)
, _secondPath(secondPath)
, _alias(alias)
, _enabled(true)
, _thread(0)
, _csync(0)
, _csyncError(false)
, _csyncUnavail(false)
, _csync_ctx(0)
: QObject(parent),
_errorCount(0),
_path(path),
_secondPath(secondPath),
_pollTimer(new QTimer(this)),
_alias(alias),
_onlyOnlineEnabled(false),
_onlyThisLANEnabled(false),
_online(false),
_enabled(true)
{
qsrand(QTime::currentTime().msec());
_timeSinceLastSync.start();
MirallConfigFile cfgFile;
_watcher = new FolderWatcher(path, this);
_pollTimer->setSingleShot(true);
int polltime = cfgFile.remotePollInterval()- 2000 + (int)( 4000.0*qrand()/(RAND_MAX+1.0));
qDebug() << "setting remote poll timer interval to" << polltime << "msec for folder " << alias;
_pollTimer->setInterval( polltime );
QObject::connect(_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout()));
_pollTimer->start();
_watcher = new Mirall::FolderWatcher(path, this);
MirallConfigFile cfg;
_watcher->addIgnoreListFile( cfg.excludeFile(MirallConfigFile::SystemScope) );
_watcher->addIgnoreListFile( cfg.excludeFile(MirallConfigFile::UserScope) );
_watcher->setIgnoreListFile( cfg.excludeFile() );
QObject::connect(_watcher, SIGNAL(folderChanged(const QStringList &)),
SLOT(slotChanged(const QStringList &)));
QObject::connect(this, SIGNAL(syncStarted()),
SLOT(slotSyncStarted()));
QObject::connect(this, SIGNAL(syncFinished(const SyncResult &)),
SLOT(slotSyncFinished(const SyncResult &)));
#if QT_VERSION >= 0x040700
_online = _networkMgr.isOnline();
QObject::connect(&_networkMgr, SIGNAL(onlineStateChanged(bool)), SLOT(slotOnlineChanged(bool)));
#else
_online = true;
#endif
_syncResult.setStatus( SyncResult::NotYetStarted );
ServerActionNotifier *notifier = new ServerActionNotifier(this);
connect(this, SIGNAL(syncFinished(SyncResult)), this, SLOT(slotSyncFinished(SyncResult)));
connect(this, SIGNAL(syncFinished(SyncResult)), notifier, SLOT(slotSyncFinished(SyncResult)));
// check if the local path exists
checkLocalPath();
int polltime = cfg.remotePollInterval();
qDebug() << "setting remote poll timer interval to" << polltime << "msec";
_pollTimer.setInterval( polltime );
QObject::connect(&_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout()));
_pollTimer.start();
_syncResult.setFolder(alias);
}
bool Folder::init()
{
QString url = Utility::toCSyncScheme(ownCloudInfo::instance()->webdavUrl() + secondPath());
QString localpath = path();
if( csync_create( &_csync_ctx, localpath.toUtf8().data(), url.toUtf8().data() ) < 0 ) {
qDebug() << "Unable to create csync-context!";
slotCSyncError(tr("Unable to create csync-context"));
_csync_ctx = 0;
} else {
csync_set_log_callback( _csync_ctx, csyncLogCatcher );
csync_set_log_verbosity(_csync_ctx, 11);
MirallConfigFile cfgFile;
csync_set_config_dir( _csync_ctx, cfgFile.configPath().toUtf8() );
csync_enable_conflictcopys(_csync_ctx);
setIgnoredFiles();
cfgFile.getCredentials()->syncContextPreInit(_csync_ctx);
if( csync_init( _csync_ctx ) < 0 ) {
qDebug() << "Could not initialize csync!" << csync_get_error(_csync_ctx) << csync_get_error_string(_csync_ctx);
slotCSyncError(CSyncThread::csyncErrorToString(csync_get_error(_csync_ctx), csync_get_error_string(_csync_ctx)));
csync_destroy(_csync_ctx);
_csync_ctx = 0;
}
}
return _csync_ctx;
}
Folder::~Folder()
{
if( _thread ) {
_thread->quit();
csync_request_abort(_csync_ctx);
_thread->wait();
}
delete _csync;
// Destroy csync here.
csync_destroy(_csync_ctx);
}
void Folder::checkLocalPath()
@@ -176,11 +129,6 @@ QString Folder::path() const
return p;
}
bool Folder::isBusy() const
{
return ( _thread && _thread->isRunning() );
}
QString Folder::secondPath() const
{
return _secondPath;
@@ -200,6 +148,9 @@ void Folder::setSyncEnabled( bool doit )
{
_enabled = doit;
_watcher->setEventsEnabled( doit );
if( doit && ! _pollTimer->isActive() ) {
_pollTimer->start();
}
qDebug() << "setSyncEnabled - ############################ " << doit;
if( doit ) {
@@ -212,22 +163,85 @@ void Folder::setSyncEnabled( bool doit )
}
}
bool Folder::onlyOnlineEnabled() const
{
return _onlyOnlineEnabled;
}
void Folder::setOnlyOnlineEnabled(bool enabled)
{
_onlyOnlineEnabled = enabled;
}
bool Folder::onlyThisLANEnabled() const
{
return _onlyThisLANEnabled;
}
void Folder::setOnlyThisLANEnabled(bool enabled)
{
_onlyThisLANEnabled = enabled;
}
int Folder::pollInterval() const
{
return _pollTimer->interval();
}
void Folder::setSyncState(SyncResult::Status state)
{
_syncResult.setStatus(state);
}
void Folder::setPollInterval(int milliseconds)
{
_pollTimer->setInterval( milliseconds );
}
int Folder::errorCount()
{
return _errorCount;
}
void Folder::resetErrorCount()
{
_errorCount = 0;
}
void Folder::incrementErrorCount()
{
// if the error count gets higher than three, the interval timer
// of the watcher is doubled.
_errorCount++;
if( _errorCount > 1 ) {
int interval = _watcher->eventInterval();
int newInt = 2*interval;
qDebug() << "Set new watcher interval to " << newInt;
_watcher->setEventInterval( newInt );
_errorCount = 0;
}
}
SyncResult Folder::syncResult() const
{
return _syncResult;
}
void Folder::evaluateSync(const QStringList &/*pathList*/)
void Folder::evaluateSync(const QStringList &pathList)
{
if( !_enabled ) {
qDebug() << "*" << alias() << "sync skipped, disabled!";
return;
}
if (!_online && onlyOnlineEnabled()) {
qDebug() << "*" << alias() << "sync skipped, not online";
return;
}
// stop the poll timer here. Its started again in the slot of
// sync finished.
qDebug() << "* " << alias() << "Poll timer disabled";
_pollTimer->stop();
_syncResult.setStatus( SyncResult::NotYetStarted );
emit scheduleToSync( alias() );
@@ -236,60 +250,53 @@ void Folder::evaluateSync(const QStringList &/*pathList*/)
void Folder::slotPollTimerTimeout()
{
qDebug() << "* Polling" << alias() << "for changes. Ignoring all pending events until now (time since next sync:" << (_timeSinceLastSync.elapsed() / 1000) << "s)";
qDebug() << "* Polling" << alias() << "for changes. Ignoring all pending events until now";
_watcher->clearPendingEvents();
if (quint64(_timeSinceLastSync.elapsed()) > MirallConfigFile().forceSyncInterval()) {
qDebug() << "* Force Sync now";
evaluateSync(QStringList());
} else {
// check if the etag is different
QObject::connect(new RequestEtagJob(secondPath(), this), SIGNAL(etagRetreived(QString)),
this, SLOT(etagRetreived(QString)));
}
evaluateSync(QStringList());
}
void Folder::etagRetreived(const QString& etag)
void Folder::slotOnlineChanged(bool online)
{
qDebug() << "* Compare etag " << etag << " with previous etag " << _lastEtag;
if (_lastEtag != etag) {
_lastEtag = etag;
evaluateSync(QStringList());
}
qDebug() << "* " << alias() << "is" << (online ? "now online" : "no longer online");
_online = online;
}
void Folder::slotChanged(const QStringList &pathList)
{
qDebug() << "** Changed was notified on " << pathList;
evaluateSync(pathList);
}
void Folder::slotSyncStarted()
{
// disable events until syncing is done
_watcher->setEventsEnabled(false);
}
void Folder::slotSyncFinished(const SyncResult &result)
{
_watcher->setEventsEnabledDelayed(2000);
_pollTimer.start();
_timeSinceLastSync.restart();
qDebug() << "OO folder slotSyncFinished: result: " << int(result.status());
emit syncStateChange();
// reenable the poll timer if folder is sync enabled
if( syncEnabled() ) {
qDebug() << "* " << alias() << "Poll timer enabled with " << _pollTimer->interval() << "milliseconds";
_pollTimer->start();
} else {
qDebug() << "* Not enabling poll timer for " << alias();
_pollTimer->stop();
}
}
void Folder::slotLocalPathChanged( const QString& dir )
{
QDir notifiedDir(dir);
QDir localPath( path() );
QDir localPath(_path );
if( notifiedDir.absolutePath() == localPath.absolutePath() ) {
if( notifiedDir == localPath ) {
if( !localPath.exists() ) {
qDebug() << "XXXXXXX The sync folder root was removed!!";
if( _thread && _thread->isRunning() ) {
qDebug() << "CSync currently running, set wipe flag!!";
} else {
qDebug() << "CSync not running, wipe it now!!";
wipe();
}
qDebug() << "ALARM: The local path was DELETED!";
}
}
@@ -305,371 +312,20 @@ QString Folder::configFile()
return _configFile;
}
void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
void Folder::setBackend( const QString& b )
{
_syncResult.setSyncFileItemVector(items);
_backend = b;
}
void Folder::slotCatchWatcherError(const QString& error)
QString Folder::backend() const
{
Logger::instance()->postGuiLog(tr("Error"), error);
return _backend;
}
void Folder::slotTerminateSync()
{
qDebug() << "folder " << alias() << " Terminating!";
MirallConfigFile cfg;
QString configDir = cfg.configPath();
qDebug() << "csync's Config Dir: " << configDir;
if( _thread && _csync ) {
csync_request_abort(_csync_ctx);
_thread->quit();
_thread->wait();
_csync->deleteLater();
delete _thread;
_csync = 0;
_thread = 0;
csync_resume(_csync_ctx);
}
if( ! configDir.isEmpty() ) {
QFile file( configDir + QLatin1String("/lock"));
if( file.exists() ) {
qDebug() << "After termination, lock file exists and gets removed.";
file.remove();
}
}
_errors.append( tr("The CSync thread terminated.") );
_csyncError = true;
qDebug() << "-> CSync Terminated!";
slotCSyncFinished();
}
// This removes the csync File database if the sync folder definition is removed
// permanentely. This is needed to provide a clean startup again in case another
// local folder is synced to the same ownCloud.
// See http://bugs.owncloud.org/thebuggenie/owncloud/issues/oc-788
void Folder::wipe()
{
QString stateDbFile = path()+QLatin1String(".csync_journal.db");
QFile file(stateDbFile);
if( file.exists() ) {
if( !file.remove()) {
qDebug() << "WRN: Failed to remove existing csync StateDB " << stateDbFile;
} else {
qDebug() << "wipe: Removed csync StateDB " << stateDbFile;
}
} else {
qDebug() << "WRN: statedb is empty, can not remove.";
}
// Check if the tmp database file also exists
QString ctmpName = path() + QLatin1String(".csync_journal.db.ctmp");
QFile ctmpFile( ctmpName );
if( ctmpFile.exists() ) {
ctmpFile.remove();
}
}
void Folder::setIgnoredFiles()
{
MirallConfigFile cfgFile;
csync_clear_exclude_list( _csync_ctx );
QString excludeList = cfgFile.excludeFile( MirallConfigFile::SystemScope );
if( !excludeList.isEmpty() ) {
qDebug() << "==== added system ignore list to csync:" << excludeList.toUtf8();
csync_add_exclude_list( _csync_ctx, excludeList.toUtf8() );
}
excludeList = cfgFile.excludeFile( MirallConfigFile::UserScope );
if( !excludeList.isEmpty() ) {
qDebug() << "==== added user defined ignore list to csync:" << excludeList.toUtf8();
csync_add_exclude_list( _csync_ctx, excludeList.toUtf8() );
}
}
void Folder::setProxy()
{
if( _csync_ctx ) {
/* Store proxy */
QUrl proxyUrl(ownCloudInfo::instance()->webdavUrl());
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" << proxyUrl;
} else {
qDebug() << "Passing" << proxy.hostName() << "of proxy type " << proxy.type()
<< " to csync for" << proxyUrl;
}
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() );
}
}
const char* Folder::proxyTypeToCStr(QNetworkProxy::ProxyType type)
{
switch (type) {
case QNetworkProxy::NoProxy:
return "NoProxy";
case QNetworkProxy::DefaultProxy:
return "DefaultProxy";
case QNetworkProxy::Socks5Proxy:
return "Socks5Proxy";
case QNetworkProxy::HttpProxy:
return "HttpProxy";
case QNetworkProxy::HttpCachingProxy:
return "HttpCachingProxy";
case QNetworkProxy::FtpCachingProxy:
return "FtpCachingProxy";
default:
return "NoProxy";
}
}
void Folder::startSync(const QStringList &pathList)
{
Q_UNUSED(pathList)
if (!_csync_ctx) {
// no _csync_ctx yet, initialize it.
init();
setProxy();
if (!_csync_ctx) {
qDebug() << Q_FUNC_INFO << "init failed.";
// the error should already be set
QMetaObject::invokeMethod(this, "slotCSyncFinished", Qt::QueuedConnection);
return;
}
}
if (_thread && _thread->isRunning()) {
qCritical() << "* ERROR csync is still running and new sync requested.";
return;
}
if (_thread)
_thread->quit();
delete _csync;
delete _thread;
_errors.clear();
_csyncError = false;
_csyncUnavail = false;
_syncResult.clearErrors();
_syncResult.setStatus( SyncResult::SyncPrepare );
emit syncStateChange();
qDebug() << "*** Start syncing";
_thread = new QThread(this);
_thread->setPriority(QThread::LowPriority);
setIgnoredFiles();
_csync = new CSyncThread( _csync_ctx );
_csync->moveToThread(_thread);
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");
connect( _csync, SIGNAL(treeWalkResult(const SyncFileItemVector&)),
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
connect(_csync, SIGNAL(started()), SLOT(slotCSyncStarted()), Qt::QueuedConnection);
connect(_csync, SIGNAL(finished()), SLOT(slotCSyncFinished()), Qt::QueuedConnection);
connect(_csync, SIGNAL(csyncError(QString)), SLOT(slotCSyncError(QString)), 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);
connect(_csync, SIGNAL(transmissionProgress(Progress::Info)), this, SLOT(slotTransmissionProgress(Progress::Info)));
_thread->start();
QMetaObject::invokeMethod(_csync, "startSync", Qt::QueuedConnection);
// disable events until syncing is done
_watcher->setEventsEnabled(false);
_pollTimer.stop();
emit syncStarted();
}
void Folder::slotCSyncError(const QString& err)
{
_errors.append( err );
_csyncError = true;
}
void Folder::slotCSyncStarted()
{
qDebug() << " * csync thread started";
_syncResult.setStatus(SyncResult::SyncRunning);
emit syncStateChange();
}
void Folder::slotCsyncUnavailable()
{
_csyncUnavail = true;
}
void Folder::slotCSyncFinished()
{
qDebug() << "-> CSync Finished slot with error " << _csyncError;
if (_csyncError) {
_syncResult.setStatus(SyncResult::Error);
qDebug() << " ** error Strings: " << _errors;
_syncResult.setErrorStrings( _errors );
qDebug() << " * owncloud csync thread finished with error";
} else if (_csyncUnavail) {
_syncResult.setStatus(SyncResult::Unavailable);
} else if( _syncResult.warnCount() > 0 ) {
// there have been warnings on the way.
_syncResult.setStatus(SyncResult::Problem);
} else {
_syncResult.setStatus(SyncResult::Success);
}
if( _thread && _thread->isRunning() ) {
_thread->quit();
}
ownCloudInfo::instance()->getQuotaRequest("/");
emit syncFinished( _syncResult );
}
void Folder::slotTransmissionProgress(const Progress::Info& progress)
{
Progress::Info newInfo = progress;
newInfo.folder = alias();
if(newInfo.current_file.startsWith(QLatin1String("ownclouds://")) ||
newInfo.current_file.startsWith(QLatin1String("owncloud://")) ) {
// rip off the whole ownCloud URL.
QString remotePathUrl = ownCloudInfo::instance()->webdavUrl() + secondPath();
newInfo.current_file.remove(Utility::toCSyncScheme(remotePathUrl));
}
QString localPath = path();
if( newInfo.current_file.startsWith(localPath) ) {
// remove the local dir.
newInfo.current_file = newInfo.current_file.right( newInfo.current_file.length() - localPath.length());
}
// remember problems happening to set the correct Sync status in slot slotCSyncFinished.
if( newInfo.kind == Progress::StartSync ) {
_syncResult.setWarnCount(0);
}
if( newInfo.kind == Progress::Error ) {
_syncResult.setWarnCount( _syncResult.warnCount()+1 );
}
ProgressDispatcher::instance()->setProgressInfo(alias(), newInfo);
}
ServerActionNotifier::ServerActionNotifier(QObject *parent)
: QObject(parent)
{
}
void ServerActionNotifier::slotSyncFinished(const SyncResult &result)
{
SyncFileItemVector items = result.syncFileItemVector();
if (items.count() == 0)
return;
int newItems = 0;
int removedItems = 0;
int updatedItems = 0;
SyncFileItem firstItemNew;
SyncFileItem firstItemDeleted;
SyncFileItem firstItemUpdated;
foreach (const SyncFileItem &item, items) {
if (item._dir == SyncFileItem::Down) {
switch (item._instruction) {
case CSYNC_INSTRUCTION_NEW:
newItems++;
if (firstItemNew.isEmpty())
firstItemNew = item;
break;
case CSYNC_INSTRUCTION_REMOVE:
removedItems++;
if (firstItemDeleted.isEmpty())
firstItemDeleted = item;
break;
case CSYNC_INSTRUCTION_UPDATED:
updatedItems++;
if (firstItemUpdated.isEmpty())
firstItemUpdated = item;
break;
case CSYNC_INSTRUCTION_ERROR:
qDebug() << "Got Instruction ERROR. " << result.errorString();
break;
default:
// nothing.
break;
}
}
}
Logger *logger = Logger::instance();
if (newItems > 0) {
QString file = QDir::toNativeSeparators(firstItemNew._file);
if (newItems == 1)
logger->postGuiLog(tr("New file available"), tr("'%1' has been synced to this machine.").arg(file));
else
logger->postGuiLog(tr("New files available"), tr("'%1' and %n other file(s) have been synced to this machine.",
"", newItems-1).arg(file));
}
if (removedItems > 0) {
QString file = QDir::toNativeSeparators(firstItemDeleted._file);
if (removedItems == 1)
logger->postGuiLog(tr("File removed"), tr("'%1' has been removed.").arg(file));
else
logger->postGuiLog(tr("Files removed"), tr("'%1' and %n other file(s) have been removed.",
"", removedItems-1).arg(file));
}
if (updatedItems > 0) {
QString file = QDir::toNativeSeparators(firstItemUpdated._file);
if (updatedItems == 1)
logger->postGuiLog(tr("File updated"), tr("'%1' has been updated.").arg(file));
else
logger->postGuiLog(tr("Files updated"), tr("'%1' and %n other file(s) have been updated.",
"", updatedItems-1).arg(file));
}
}
void Folder::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();
}
}
} // namespace Mirall
+110 -96
Ver Arquivo
@@ -1,7 +1,5 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
* 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
@@ -17,72 +15,38 @@
#ifndef MIRALL_FOLDER_H
#define MIRALL_FOLDER_H
#include "mirall/syncresult.h"
#include "mirall/progressdispatcher.h"
#include "mirall/csyncthread.h"
#include <QDir>
#include <QHash>
#include <QNetworkAccessManager>
#include <QNetworkProxy>
#include <QObject>
#include <QString>
#include <QStringList>
#include <QDebug>
#include <QHash>
#include <QTimer>
#include <qelapsedtimer.h>
#if QT_VERSION >= 0x040700
#include <QNetworkConfigurationManager>
#endif
#include "mirall/syncresult.h"
class QAction;
class QIcon;
class QFileSystemWatcher;
class QThread;
namespace Mirall {
class FolderWatcher;
typedef enum SyncFileStatus_s {
STATUS_NONE,
STATUS_EVAL,
STATUS_REMOVE,
STATUS_RENAME,
STATUS_NEW,
STATUS_CONFLICT,
STATUS_IGNORE,
STATUS_SYNC,
STATUS_STAT_ERROR,
STATUS_ERROR,
STATUS_UPDATED
} SyncFileStatus;
class ServerActionNotifier : public QObject
{
Q_OBJECT
public:
ServerActionNotifier(QObject *parent = 0);
public slots:
void slotSyncFinished(const SyncResult &result);
private:
};
class Folder : public QObject
{
Q_OBJECT
protected:
friend class FolderMan;
Folder(const QString&, const QString&, const QString& , QObject*parent = 0L);
public:
~Folder();
Folder(const QString&, const QString&, const QString& , QObject*parent = 0L);
virtual ~Folder();
typedef QHash<QString, Folder*> Map;
typedef QHashIterator<QString, Folder*> MapIterator;
/**
* Get status about a single file.
*/
SyncFileStatus fileStatus( const QString& );
/**
* alias or nickname
*/
@@ -92,16 +56,12 @@ public:
* local folder path
*/
QString path() const;
/**
* remote folder path
*/
QString secondPath() const;
virtual QString secondPath() const;
/**
* local folder path with native separators
*/
QString nativePath() const;
/**
* switch sync on or off
* If the sync is switched off, the startSync method is not going to
@@ -111,17 +71,69 @@ public:
bool syncEnabled() const;
/**
* Starts a sync operation
*
* If the list of changed files is known, it is passed.
*
* If the list of changed files is empty, the folder
* implementation should figure it by itself of
* perform a full scan of changes
*/
virtual void startSync(const QStringList &pathList) = 0;
/**
* True if the folder is busy and can't initiate
* a synchronization
*/
virtual bool isBusy() const;
virtual bool isBusy() const = 0;
/**
* only sync when online in the network
*/
bool onlyOnlineEnabled() const;
/**
* @see onlyOnlineEnabled
*/
void setOnlyOnlineEnabled(bool enabled);
/**
* only sync when online in the same LAN
* as the one used during setup
*/
bool onlyThisLANEnabled() const;
/**
* @see onlyThisLANEnabled
*/
void setOnlyThisLANEnabled(bool enabled);
/**
* error counter, stop syncing after the counter reaches a certain
* number.
*/
int errorCount();
void resetErrorCount();
void incrementErrorCount();
/**
* return the last sync result with error message and status
*/
SyncResult syncResult() const;
/**
* set the backend description string.
*/
void setBackend( const QString& );
/**
* get the backend description string.
*/
QString backend() const;
/**
* set the config file name.
*/
@@ -133,6 +145,9 @@ public:
*/
virtual void wipe();
QIcon icon( int size ) const;
QTimer *_pollTimer;
signals:
void syncStateChange();
void syncStarted();
@@ -150,44 +165,48 @@ public slots:
/**
* terminate the current sync run
*/
void slotTerminateSync();
void slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool*);
virtual void slotTerminateSync() = 0;
/**
* Starts a sync operation
*
* If the list of changed files is known, it is passed.
* Sets minimum amounts of milliseconds that will separate
* poll intervals
*/
void startSync(const QStringList &pathList = QStringList());
void setPollInterval( int );
private slots:
void slotCSyncStarted();
void slotCSyncError(const QString& );
void slotCsyncUnavailable();
void slotCSyncFinished();
/**
* If folder is network-based, reimplement to react to proxy changes
*/
virtual void setProxy() {}
void slotTransmissionProgress(const Progress::Info& progress);
protected:
/**
* The minimum amounts of seconds to wait before
* doing a full sync to see if the remote changed
*/
int pollInterval() const;
void setSyncState(SyncResult::Status state);
FolderWatcher *_watcher;
int _errorCount;
SyncResult _syncResult;
protected slots:
void slotOnlineChanged(bool online);
void slotPollTimerTimeout();
void etagRetreived(const QString &);
/* called when the watcher detect a list of changed
paths */
void slotSyncStarted();
/**
* Triggered by a file system watcher on the local sync dir
*/
void slotLocalPathChanged( const QString& );
void slotThreadTreeWalkResult(const SyncFileItemVector& );
void slotCatchWatcherError( const QString& );
virtual void slotLocalPathChanged( const QString& );
protected:
bool init();
void setSyncState(SyncResult::Status state);
void setIgnoredFiles();
void setProxy();
const char* proxyTypeToCStr(QNetworkProxy::ProxyType type);
private:
/**
* Starts a sync (calling startSync)
@@ -195,28 +214,23 @@ protected:
*/
void evaluateSync(const QStringList &pathList);
void checkLocalPath();
virtual void checkLocalPath();
QString _path;
QString _secondPath;
QString _alias;
bool _onlyOnlineEnabled;
bool _onlyThisLANEnabled;
QString _configFile;
QFileSystemWatcher *_pathWatcher;
bool _enabled;
FolderWatcher *_watcher;
SyncResult _syncResult;
QThread *_thread;
CSyncThread *_csync;
QStringList _errors;
bool _csyncError;
bool _csyncUnavail;
bool _wipeDb;
Progress::Kind _progressKind;
QTimer _pollTimer;
QString _lastEtag;
QElapsedTimer _timeSinceLastSync;
CSYNC *_csync_ctx;
QFileSystemWatcher *_pathWatcher;
#if QT_VERSION >= 0x040700
QNetworkConfigurationManager _networkMgr;
#endif
bool _online;
bool _enabled;
QString _backend;
};
+83 -136
Ver Arquivo
@@ -14,11 +14,10 @@
#include "mirall/folderman.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/folder.h"
#include "mirall/owncloudfolder.h"
#include "mirall/syncresult.h"
#include "mirall/inotify.h"
#include "mirall/theme.h"
#include "owncloudinfo.h"
#ifdef Q_OS_MAC
#include <CoreServices/CoreServices.h>
@@ -33,8 +32,6 @@
namespace Mirall {
FolderMan* FolderMan::_instance = 0;
FolderMan::FolderMan(QObject *parent) :
QObject(parent),
_syncEnabled( true )
@@ -51,17 +48,11 @@ FolderMan::FolderMan(QObject *parent) :
this, SIGNAL(folderSyncStateChange(const QString &)));
}
FolderMan *FolderMan::instance()
{
if(!_instance)
_instance = new FolderMan;
return _instance;
}
FolderMan::~FolderMan()
{
qDeleteAll(_folderMap);
foreach (Folder *folder, _folderMap) {
delete folder;
}
}
Mirall::Folder::Map FolderMan::map()
@@ -73,7 +64,15 @@ Mirall::Folder::Map FolderMan::map()
int FolderMan::setupFolders()
{
// setup a handler to look for configuration changes
return setupKnownFolders();
#ifdef CHECK_FOR_SETUP_CHANGES
_configFolderWatcher = new FolderWatcher( _folderConfigPath );
_configFolderWatcher->setEventInterval(20000);
connect(_configFolderWatcher, SIGNAL(folderChanged(const QStringList &)),
this, SLOT( slotReparseConfiguration()) );
#endif
int cnt = setupKnownFolders();
return cnt;
}
void FolderMan::slotReparseConfiguration()
@@ -83,6 +82,9 @@ void FolderMan::slotReparseConfiguration()
int FolderMan::unloadAllFolders()
{
// first terminate sync jobs.
terminateCurrentSync();
int cnt = 0;
// clear the list of existing folders.
@@ -244,28 +246,43 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
// QString connection = settings.value( QLatin1String("connection") ).toString();
QString alias = unescapeAlias( escapedAlias );
if (backend.isEmpty() || backend != QLatin1String("owncloud")) {
qWarning() << "obsolete configuration of type" << backend;
return 0;
if (!backend.isEmpty()) {
if( backend == QLatin1String("owncloud") ) {
MirallConfigFile cfgFile;
// assemble the owncloud url to pass to csync, incl. webdav
QString oCUrl = cfgFile.ownCloudUrl( QString::null, true );
// cut off the leading slash, oCUrl always has a trailing.
if( targetPath.startsWith(QLatin1Char('/')) ) {
targetPath.remove(0,1);
}
folder = new ownCloudFolder( alias, path, oCUrl + targetPath, this );
folder->setConfigFile(file);
} else {
qWarning() << "unknown backend" << backend;
return 0;
}
}
// cut off the leading slash, oCUrl always has a trailing.
if( targetPath.startsWith(QLatin1Char('/')) ) {
targetPath.remove(0,1);
if( folder ) {
folder->setBackend( backend );
// folder->setOnlyOnlineEnabled(settings.value("folder/onlyOnline", false).toBool());
folder->setOnlyThisLANEnabled(settings.value(QLatin1String("folder/onlyThisLAN"), false).toBool());
_folderMap[alias] = folder;
qDebug() << "Adding folder to Folder Map " << folder;
/* Use a signal mapper to connect the signals to the alias */
connect(folder, SIGNAL(scheduleToSync(const QString&)), SLOT(slotScheduleSync(const QString&)));
connect(folder, SIGNAL(syncStateChange()), _folderChangeSignalMapper, SLOT(map()));
connect(folder, SIGNAL(syncStarted()), SLOT(slotFolderSyncStarted()));
connect(folder, SIGNAL(syncFinished(SyncResult)), SLOT(slotFolderSyncFinished(SyncResult)));
_folderChangeSignalMapper->setMapping( folder, folder->alias() );
}
folder = new Folder( alias, path, targetPath, this );
folder->setConfigFile(file);
qDebug() << "Adding folder to Folder Map " << folder;
_folderMap[alias] = folder;
/* Use a signal mapper to connect the signals to the alias */
connect(folder, SIGNAL(scheduleToSync(const QString&)), SLOT(slotScheduleSync(const QString&)));
connect(folder, SIGNAL(syncStateChange()), _folderChangeSignalMapper, SLOT(map()));
connect(folder, SIGNAL(syncStarted()), SLOT(slotFolderSyncStarted()));
connect(folder, SIGNAL(syncFinished(SyncResult)), SLOT(slotFolderSyncFinished(SyncResult)));
_folderChangeSignalMapper->setMapping( folder, folder->alias() );
return folder;
}
@@ -296,7 +313,7 @@ void FolderMan::terminateSyncProcess( const QString& alias )
f->slotTerminateSync();
if(_currentSyncFolder == folderAlias )
_currentSyncFolder.clear();
_currentSyncFolder = QString::null;
}
}
}
@@ -313,21 +330,19 @@ Folder *FolderMan::folder( const QString& alias )
SyncResult FolderMan::syncResult( const QString& alias )
{
SyncResult res;
Folder *f = folder( alias );
return syncResult(f);
}
SyncResult FolderMan::syncResult( Folder *f )
{
return f ? f->syncResult() : SyncResult();
if( f ) {
res = f->syncResult();
}
return res;
}
void FolderMan::slotScheduleAllFolders()
{
foreach( Folder *f, _folderMap.values() ) {
if (f->syncEnabled()) {
slotScheduleSync( f->alias() );
}
slotScheduleSync( f->alias() );
}
}
@@ -346,11 +361,13 @@ void FolderMan::slotScheduleSync( const QString& alias )
}
if( ! _scheduleQueue.contains(alias )) {
_scheduleQueue.enqueue(alias);
_scheduleQueue.append(alias);
} else {
qDebug() << " II> Sync for folder " << alias << " already scheduled, do not enqueue!";
}
slotScheduleFolderSync();
}
void FolderMan::setSyncEnabled( bool enabled )
@@ -377,14 +394,11 @@ void FolderMan::slotScheduleFolderSync()
qDebug() << "XX slotScheduleFolderSync: folderQueue size: " << _scheduleQueue.count();
if( ! _scheduleQueue.isEmpty() ) {
const QString alias = _scheduleQueue.dequeue();
const QString alias = _scheduleQueue.takeFirst();
if( _folderMap.contains( alias ) ) {
ownCloudInfo::instance()->getQuotaRequest("/");
Folder *f = _folderMap[alias];
_currentSyncFolder = alias;
if (f->syncEnabled()) {
f->startSync( QStringList() );
}
f->startSync( QStringList() );
}
}
}
@@ -406,17 +420,28 @@ void FolderMan::slotFolderSyncFinished( const SyncResult& )
QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync()));
}
void FolderMan::addFolderDefinition(const QString& alias, const QString& sourceFolder, const QString& targetPath )
/**
* Add a folder definition to the config
* Params:
* QString backend
* QString alias
* QString sourceFolder on local machine
* QString targetPath on remote
* bool onlyThisLAN, currently unused.
*/
void FolderMan::addFolderDefinition( const QString& backend, const QString& alias,
const QString& sourceFolder, const QString& targetPath,
bool onlyThisLAN )
{
QString escapedAlias = escapeAlias(alias);
// Create a settings file named after the alias
QSettings settings( _folderConfigPath + QLatin1Char('/') + escapedAlias, QSettings::IniFormat);
settings.beginGroup(escapedAlias);
settings.setValue(QLatin1String("localPath"), sourceFolder );
settings.setValue(QLatin1String("targetPath"), targetPath );
// for compat reasons
settings.setValue(QLatin1String("backend"), "owncloud" );
settings.setValue(QLatin1String("connection"), Theme::instance()->appName());
settings.setValue(QString::fromLatin1("%1/localPath").arg(escapedAlias), sourceFolder );
settings.setValue(QString::fromLatin1("%1/targetPath").arg(escapedAlias), targetPath );
settings.setValue(QString::fromLatin1("%1/backend").arg(escapedAlias), backend );
settings.setValue(QString::fromLatin1("%1/connection").arg(escapedAlias), Theme::instance()->appName());
settings.setValue(QString::fromLatin1("%1/onlyThisLAN").arg(escapedAlias), onlyThisLAN );
settings.sync();
}
@@ -508,89 +533,11 @@ bool FolderMan::startFromScratch( const QString& localFolder )
return false;
}
SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
void FolderMan::setProxy()
{
SyncResult overallResult(SyncResult::Undefined);
foreach ( Folder *folder, folders ) {
SyncResult folderResult = folder->syncResult();
SyncResult::Status syncStatus = folderResult.status();
switch( syncStatus ) {
case SyncResult::Undefined:
if ( overallResult.status() != SyncResult::Error )
overallResult.setStatus(SyncResult::Error);
break;
case SyncResult::NotYetStarted:
overallResult.setStatus( SyncResult::NotYetStarted );
break;
case SyncResult::SyncPrepare:
overallResult.setStatus( SyncResult::SyncPrepare );
break;
case SyncResult::SyncRunning:
overallResult.setStatus( SyncResult::SyncRunning );
break;
case SyncResult::Unavailable:
overallResult.setStatus( SyncResult::Unavailable );
break;
case SyncResult::Success:
if( overallResult.status() == SyncResult::Undefined )
overallResult.setStatus( SyncResult::Success );
break;
case SyncResult::Error:
overallResult.setStatus( SyncResult::Error );
break;
case SyncResult::SetupError:
if ( overallResult.status() != SyncResult::Error )
overallResult.setStatus( SyncResult::SetupError );
break;
case SyncResult::Problem:
if ( overallResult.status() != SyncResult::Problem )
overallResult.setStatus( SyncResult::Problem );
break;
// no default case on purpose, check compiler warnings
}
foreach( Folder *f, _folderMap.values() ) {
f->setProxy();
}
return overallResult;
}
QString FolderMan::statusToString( SyncResult syncStatus, bool enabled ) const
{
QString folderMessage;
switch( syncStatus.status() ) {
case SyncResult::Undefined:
folderMessage = tr( "Undefined State." );
break;
case SyncResult::NotYetStarted:
folderMessage = tr( "Waits to start syncing." );
break;
case SyncResult::SyncPrepare:
folderMessage = tr( "Preparing for sync." );
break;
case SyncResult::SyncRunning:
folderMessage = tr( "Sync is running." );
break;
case SyncResult::Unavailable:
folderMessage = tr( "Server is currently not available." );
break;
case SyncResult::Success:
folderMessage = tr( "Last Sync was successful." );
break;
case SyncResult::Error:
break;
case SyncResult::Problem:
folderMessage = tr( "Last Sync was successful, but with warnings on individual files.");
break;
case SyncResult::SetupError:
folderMessage = tr( "Setup Error." );
break;
// no default case on purpose, check compiler warnings
}
if( !enabled ) {
// sync is disabled.
folderMessage = tr( "%1 (Sync is paused)" ).arg(folderMessage);
}
return folderMessage;
}
} // namespace Mirall
+32 -24
Ver Arquivo
@@ -18,7 +18,6 @@
#include <QObject>
#include <QQueue>
#include <QList>
#include "mirall/folder.h"
#include "mirall/folderwatcher.h"
@@ -26,15 +25,15 @@
class QSignalMapper;
class SyncResult;
namespace Mirall {
class SyncResult;
class FolderMan : public QObject
{
Q_OBJECT
public:
static FolderMan* instance();
explicit FolderMan(QObject *parent = 0);
~FolderMan();
int setupFolders();
@@ -44,43 +43,55 @@ public:
/**
* Add a folder definition to the config
* Params:
* QString backend
* QString alias
* QString sourceFolder on local machine
* QString targetPath on remote
* bool onlyThisLAN, currently unused.
*/
void addFolderDefinition(const QString&, const QString&, const QString& );
void addFolderDefinition( const QString&, const QString&, const QString&, const QString&, bool );
/** Returns the folder by alias or NULL if no folder with the alias exists. */
/**
* return the folder by alias or NULL if no folder with the alias exists.
*/
Folder *folder( const QString& );
/** Returns the last sync result by alias */
/**
* return the last sync result by alias
*/
SyncResult syncResult( const QString& );
/** Returns the last sync result by Folder */
SyncResult syncResult( Folder* );
/** Creates a folder for a specific configuration, identified by alias. */
/**
* creates a folder for a specific configuration, identified by alias.
*/
Folder* setupFolderFromConfigFile(const QString & );
/** Wipes all folder defintions. No way back! */
/**
* wipes all folder defintions. No way back!
*/
void removeAllFolderDefinitions();
/** Removes csync journals from all folders. */
/**
* Removes csync journals from all folders.
*/
void wipeAllJournals();
/**
* Ensures that a given directory does not contain a .csync_journal.
*
* @returns false if the journal could not be removed, true otherwise.
* @returns false if the journal could not be removed, false otherwise.
*/
static bool ensureJournalGone(const QString &path);
/** Creates a new and empty local directory. */
/**
* Creates a new and empty local directory.
*/
bool startFromScratch( const QString& );
QString statusToString( SyncResult, bool enabled ) const;
static SyncResult accountStatus( const QList<Folder*> &folders );
/**
* called whenever proxy configuration changes
*/
void setProxy();
signals:
/**
@@ -130,17 +141,14 @@ private:
void removeFolder( const QString& );
FolderWatcher *_configFolderWatcher;
Folder::Map _folderMap;
QString _folderConfigPath;
QSignalMapper *_folderChangeSignalMapper;
QString _currentSyncFolder;
QStringList _scheduleQueue;
bool _syncEnabled;
QQueue<QString> _scheduleQueue;
explicit FolderMan(QObject *parent = 0);
static FolderMan *_instance;
};
} // namespace Mirall
}
#endif // FOLDERMAN_H
-307
Ver Arquivo
@@ -1,307 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "mirall/folderstatusmodel.h"
#include "mirall/utility.h"
#include <QtCore>
#include <QtGui>
namespace Mirall {
FolderStatusModel::FolderStatusModel()
:QStandardItemModel()
{
}
Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex& ) const
{
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::EditRole)
return QVariant();
else
return QStandardItemModel::data(index,role);
}
// ====================================================================================
FolderStatusDelegate::FolderStatusDelegate()
:QStyledItemDelegate()
{
}
FolderStatusDelegate::~FolderStatusDelegate()
{
// TODO Auto-generated destructor stub
}
//alocate each item size in listview.
QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option ,
const QModelIndex & index) const
{
Q_UNUSED(option)
QFont aliasFont = option.font;
QFont font = option.font;
aliasFont.setPointSize( font.pointSize() +2 );
QFontMetrics fm(font);
QFontMetrics aliasFm(aliasFont);
int aliasMargin = aliasFm.height()/2;
int margin = fm.height()/4;
// calc height
int h = aliasMargin; // margin to top
h += aliasFm.height(); // alias
h += margin; // between alias and local path
h += fm.height(); // local path
h += margin; // between local and remote path
h += fm.height(); // remote path
h += aliasMargin; // bottom margin
// add some space to show an error condition.
if( ! qvariant_cast<QString>(index.data(FolderErrorMsg)).isEmpty() ) {
h += aliasMargin*2+fm.height();
}
if( qvariant_cast<bool>(index.data(AddProgressSpace)) ) {
int margin = fm.height()/4;
h += (5 * margin); // All the margins
h += 2* fm.boundingRect(tr("File")).height();
}
return QSize( 0, h);
}
void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyledItemDelegate::paint(painter,option,index);
painter->save();
QFont aliasFont = option.font;
QFont subFont = option.font;
QFont errorFont = subFont;
QFont progressFont = subFont;
progressFont.setPointSize( subFont.pointSize()-1);
//font.setPixelSize(font.weight()+);
aliasFont.setBold(true);
aliasFont.setPointSize( subFont.pointSize()+2 );
QFontMetrics subFm( subFont );
QFontMetrics aliasFm( aliasFont );
QFontMetrics progressFm( progressFont );
int aliasMargin = aliasFm.height()/2;
int margin = subFm.height()/4;
QIcon statusIcon = qvariant_cast<QIcon>(index.data(FolderStatusIconRole));
QString aliasText = qvariant_cast<QString>(index.data(FolderAliasRole));
QString pathText = qvariant_cast<QString>(index.data(FolderPathRole));
QString remotePath = qvariant_cast<QString>(index.data(FolderSecondPathRole));
QString errorText = qvariant_cast<QString>(index.data(FolderErrorMsg));
int overallPercent = qvariant_cast<int>(index.data(SyncProgressOverallPercent));
QString overallString = qvariant_cast<QString>(index.data(SyncProgressOverallString));
QString itemString = qvariant_cast<QString>(index.data(SyncProgressItemString));
int warningCount = qvariant_cast<int>(index.data(WarningCount));
bool syncOngoing = qvariant_cast<bool>(index.data(SyncRunning));
// QString statusText = qvariant_cast<QString>(index.data(FolderStatus));
bool syncEnabled = index.data(FolderSyncEnabled).toBool();
// QString syncStatus = syncEnabled? tr( "Enabled" ) : tr( "Disabled" );
QRect iconRect = option.rect;
QRect aliasRect = option.rect;
iconRect.setLeft( aliasMargin );
iconRect.setTop( iconRect.top() + aliasMargin ); // (iconRect.height()-iconsize.height())/2);
// alias box
aliasRect.setTop(aliasRect.top() + aliasMargin );
aliasRect.setBottom(aliasRect.top() + aliasFm.height());
aliasRect.setRight(aliasRect.right() - aliasMargin );
// remote directory box
QRect remotePathRect = aliasRect;
remotePathRect.setTop(aliasRect.bottom() + margin );
remotePathRect.setBottom(remotePathRect.top() + subFm.height());
// local directory box
QRect localPathRect = remotePathRect;
localPathRect.setTop( remotePathRect.bottom() + margin );
localPathRect.setBottom( localPathRect.top() + subFm.height());
iconRect.setBottom(localPathRect.bottom());
iconRect.setWidth(iconRect.height());
int nextToIcon = iconRect.right()+aliasMargin;
aliasRect.setLeft(nextToIcon);
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);
// only show the warning icon if the sync is running. Otherwise its
// encoded in the status icon.
if( warningCount > 0 && syncOngoing) {
QRect warnRect;
warnRect.setLeft(iconRect.left());
warnRect.setTop(iconRect.bottom()-17);
warnRect.setWidth(16);
warnRect.setHeight(16);
QIcon warnIcon(":/mirall/resources/warning-16");
QPixmap pm = warnIcon.pixmap(16,16, syncEnabled ? QIcon::Normal : QIcon::Disabled );
painter->drawPixmap(QPoint(warnRect.left(), warnRect.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
&& !qApp->style()->inherits("QWindowsVistaStyle")) {
painter->setPen(option.palette.color(QPalette::HighlightedText));
} else {
painter->setPen(option.palette.color(QPalette::Text));
}
QString elidedAlias = aliasFm.elidedText(aliasText, Qt::ElideRight, aliasRect.width());
painter->setFont(aliasFont);
painter->drawText(aliasRect, elidedAlias);
painter->setFont(subFont);
QString elidedRemotePathText;
if (remotePath.isEmpty() || remotePath == QLatin1String("/")) {
elidedRemotePathText = subFm.elidedText(tr("Syncing all files in your account with"),
Qt::ElideRight, remotePathRect.width());
} else {
elidedRemotePathText = subFm.elidedText(tr("Remote path: %1").arg(remotePath),
Qt::ElideMiddle, remotePathRect.width());
}
painter->drawText(remotePathRect, elidedRemotePathText);
QString elidedPathText = subFm.elidedText(pathText, Qt::ElideMiddle, localPathRect.width());
painter->drawText(localPathRect, elidedPathText);
// paint an error overlay if there is an error string
int h = iconRect.bottom();
if( !errorText.isEmpty() ) {
QRect errorRect = localPathRect;
errorRect.setLeft( iconRect.left());
errorRect.setTop( h );
errorRect.setHeight(subFm.height()+aliasMargin);
errorRect.setRight( option.rect.right()-aliasMargin );
painter->setBrush( QColor(0xbb, 0x4d, 0x4d) );
painter->setPen( QColor(0xaa, 0xaa, 0xaa));
painter->drawRoundedRect( errorRect, 4, 4 );
QIcon warnIcon(":/mirall/resources/warning-16");
QPoint warnPos(errorRect.left()+aliasMargin/2, errorRect.top()+aliasMargin/2);
painter->drawPixmap( warnPos, warnIcon.pixmap(QSize(16,16)));
painter->setPen( Qt::white );
painter->setFont(errorFont);
QRect errorTextRect = errorRect;
errorTextRect.setLeft( errorTextRect.left()+aliasMargin +16);
errorTextRect.setTop( errorTextRect.top()+aliasMargin/2 );
int linebreak = errorText.indexOf(QLatin1String("<br"));
QString eText = errorText;
if(linebreak) {
eText = errorText.left(linebreak);
}
painter->drawText(errorTextRect, eText);
h = errorRect.bottom();
}
h += aliasMargin;
// Sync File Progress Bar: Show it if syncFile is not empty.
if( !overallString.isEmpty()) {
int fileNameTextHeight = subFm.boundingRect(tr("File")).height();
int barHeight = fileNameTextHeight;
int overallWidth = option.rect.width()-2*aliasMargin;
painter->save();
// Sizes-Text
QRect octetRect = subFm.boundingRect( overallString );
int progressTextWidth = octetRect.width();
// Overall Progress Bar.
QRect pBRect;
pBRect.setTop( h );
pBRect.setLeft( iconRect.left());
pBRect.setHeight(barHeight);
pBRect.setWidth( overallWidth - progressTextWidth - margin );
QStyleOptionProgressBarV2 pBarOpt;
pBarOpt.state = option.state | QStyle::State_Horizontal;
pBarOpt.minimum = 0;
pBarOpt.maximum = 100;
pBarOpt.progress = overallPercent;
pBarOpt.orientation = Qt::Horizontal;
pBarOpt.palette = option.palette;
pBarOpt.rect = pBRect;
QApplication::style()->drawControl( QStyle::CE_ProgressBar, &pBarOpt, painter );
// Overall Progress Text
QRect overallProgressRect;
overallProgressRect.setTop( pBRect.top() );
overallProgressRect.setHeight( pBRect.height() );
overallProgressRect.setLeft( pBRect.right()+margin);
overallProgressRect.setWidth( progressTextWidth );
painter->setFont(progressFont);
QString elidedText = progressFm.elidedText(overallString, Qt::ElideLeft, overallProgressRect.width());
painter->drawText( overallProgressRect, Qt::AlignRight+Qt::AlignVCenter, elidedText);
// Individual File Progress
QRect fileRect;
fileRect.setTop( pBRect.bottom() + margin);
fileRect.setLeft( iconRect.left());
fileRect.setWidth(overallWidth);
fileRect.setHeight(fileNameTextHeight);
elidedText = progressFm.elidedText(itemString, Qt::ElideLeft, fileRect.width());
painter->drawText( fileRect, Qt::AlignLeft+Qt::AlignVCenter, elidedText);
painter->restore();
}
painter->restore();
}
bool FolderStatusDelegate::editorEvent ( QEvent * /*event*/, QAbstractItemModel * /*model*/, const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/ )
{
return false;
}
} // namespace Mirall
-66
Ver Arquivo
@@ -1,66 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef FOLDERSTATUSMODEL_H
#define FOLDERSTATUSMODEL_H
#include <QStyledItemDelegate>
#include <QStandardItemModel>
namespace Mirall {
class FolderStatusModel : public QStandardItemModel
{
public:
FolderStatusModel();
virtual Qt::ItemFlags flags( const QModelIndex& ) const;
QVariant data(const QModelIndex &index, int role) const;
};
class FolderStatusDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
FolderStatusDelegate();
virtual ~FolderStatusDelegate();
enum datarole { FolderAliasRole = Qt::UserRole + 100,
FolderPathRole,
FolderSecondPathRole,
FolderRemotePath,
FolderStatus,
FolderErrorMsg,
FolderSyncEnabled,
FolderStatusIconRole,
SyncProgressOverallPercent,
SyncProgressOverallString,
SyncProgressItemString,
AddProgressSpace,
WarningCount,
SyncRunning
};
void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const;
QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const;
bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
const QModelIndex& index );
private:
bool _addProgressSpace;
};
} // namespace Mirall
#endif // FOLDERSTATUSMODEL_H
+9 -3
Ver Arquivo
@@ -69,7 +69,7 @@ QString FolderWatcher::root() const
return _root;
}
void FolderWatcher::addIgnoreListFile( const QString& file )
void FolderWatcher::setIgnoreListFile( const QString& file )
{
if( file.isEmpty() ) return;
@@ -79,12 +79,18 @@ void FolderWatcher::addIgnoreListFile( const QString& file )
while (!infile.atEnd()) {
QString line = QString::fromLocal8Bit( infile.readLine() ).trimmed();
if( !line.startsWith( QLatin1Char('#') ) && line.isEmpty() ) {
_ignores.append(line);
if( !line.startsWith( QLatin1Char('#') )) {
addIgnore(line);
}
}
}
void FolderWatcher::addIgnore(const QString &pattern)
{
if( pattern.isEmpty() ) return;
_ignores.append(pattern);
}
QStringList FolderWatcher::ignores() const
{
return _ignores;
+13 -8
Ver Arquivo
@@ -43,7 +43,7 @@ class FolderWatcherPrivate;
*/
class FolderWatcher : public QObject
{
Q_OBJECT
Q_OBJECT
public:
/**
* @param root Path of the root of the folder
@@ -58,11 +58,16 @@ public:
/**
* Set a file name to load a file with ignore patterns.
*
* Valid entries do not start with a hash sign (#)
* and may contain wildcards
*/
void addIgnoreListFile( const QString& );
void setIgnoreListFile( const QString& );
/**
* Add an ignore pattern that will not be
* notified
*
* You can use wildcards
*/
void addIgnore(const QString &pattern);
/**
* If true, folderChanged() events are sent
@@ -104,10 +109,10 @@ public slots:
void setEventsEnabledDelayed( int );
signals:
/** Emitted when one of the paths is changed */
/**
* Emitted when one of the paths is changed
*/
void folderChanged(const QStringList &pathList);
/** Emitted if an error occurs */
void error(const QString& error);
protected:
void setProcessTimer();
+3 -8
Ver Arquivo
@@ -38,10 +38,10 @@ FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p)
{
_inotify = new INotify(this, standard_event_mask);
slotAddFolderRecursive(_parent->root());
QObject::connect(_inotify, SIGNAL(notifyEvent(int, int, const QString &)),
this, SLOT(slotINotifyEvent(int, int, const QString &)));
QMetaObject::invokeMethod(this, "slotAddFolderRecursive", Q_ARG(QString, _parent->root()));
}
void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
@@ -49,12 +49,7 @@ void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
int subdirs = 0;
qDebug() << "(+) Watcher:" << path;
if (!_inotify->addPath(path)) {
FolderWatcher *fw = qobject_cast<FolderWatcher*>(parent());
emit fw->error(tr("Could not monitor directories due to system limitations.\n"
"The application will not work reliably. Please check the\n"
"documentation for possible fixes."));
}
_inotify->addPath(path);
QStringList watchedFolders(_inotify->directories());
// qDebug() << "currently watching " << watchedFolders;
QStringListIterator subfoldersIt(FileUtils::subFoldersList(path, FileUtils::SubFolderRecursive));
@@ -83,7 +78,7 @@ void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
qDebug() << " `-> and" << subdirs << "subdirectories";
}
void FolderWatcherPrivate::slotINotifyEvent(int mask, int /*cookie*/, const QString &path)
void FolderWatcherPrivate::slotINotifyEvent(int mask, int cookie, const QString &path)
{
int lastMask = _lastMask;
QString lastPath = _lastPath;
-2
Ver Arquivo
@@ -26,8 +26,6 @@ class FolderWatcherPrivate : public QObject {
Q_OBJECT
public:
FolderWatcherPrivate(FolderWatcher *p);
signals:
void error(const QString& error);
private slots:
void slotAddFolderRecursive(const QString &path);
void slotINotifyEvent(int mask, int cookie, const QString &path);
+115 -120
Ver Arquivo
@@ -19,15 +19,12 @@
#include <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QFileIconProvider>
#include <QInputDialog>
#include <QUrl>
#include <QValidator>
#include <QWizardPage>
#include <QTreeWidget>
#include <QDir>
#include <stdlib.h>
@@ -35,7 +32,7 @@ namespace Mirall
{
FolderWizardSourcePage::FolderWizardSourcePage()
: QWizardPage()
:_folderMap(0)
{
_ui.setupUi(this);
registerField(QLatin1String("sourceFolder*"), _ui.localFolderLineEdit);
@@ -45,6 +42,10 @@ FolderWizardSourcePage::FolderWizardSourcePage()
_ui.aliasLineEdit->setText( Theme::instance()->appNameGUI() );
_ui.warnLabel->hide();
#if QT_VERSION >= 0x040700
_ui.localFolderLineEdit->setPlaceholderText(QApplication::translate("FolderWizardSourcePage", "/home/local1", 0, QApplication::UnicodeUTF8));
_ui.aliasLineEdit->setPlaceholderText(QApplication::translate("FolderWizardSourcePage", "Music", 0, QApplication::UnicodeUTF8));
#endif
}
FolderWizardSourcePage::~FolderWizardSourcePage()
@@ -80,11 +81,12 @@ bool FolderWizardSourcePage::isComplete() const
}
// check if the local directory isn't used yet in another ownCloud sync
Folder::Map map = _folderMap;
Folder::Map *map = _folderMap;
if( ! map ) return false;
if( isOk ) {
Folder::Map::const_iterator i = map.constBegin();
while( isOk && i != map.constEnd() ) {
Folder::Map::const_iterator i = map->constBegin();
while( isOk && i != map->constEnd() ) {
Folder *f = static_cast<Folder*>(i.value());
QString folderDir = QDir( f->path() ).canonicalPath();
if( folderDir.isEmpty() )
@@ -123,10 +125,10 @@ bool FolderWizardSourcePage::isComplete() const
isOk = false;
}
Folder::Map::const_iterator i = map.constBegin();
Folder::Map::const_iterator i = map->constBegin();
bool goon = true;
while( goon && i != map.constEnd() ) {
Folder *f = i.value();
while( goon && i != map->constEnd() ) {
Folder *f = static_cast<Folder*>(i.value());
qDebug() << "Checking local alias: " << f->alias();
if( f ) {
if( f->alias() == alias ) {
@@ -166,38 +168,64 @@ void FolderWizardSourcePage::on_localFolderLineEdit_textChanged()
// =================================================================================
FolderWizardTargetPage::FolderWizardTargetPage()
: _warnWasVisible(false)
: _dirChecked( false ),
_warnWasVisible(false)
{
_ui.setupUi(this);
_ui.warnFrame->hide();
connect(_ui.addFolderButton, SIGNAL(clicked()), SLOT(slotAddRemoteFolder()));
connect(_ui.refreshButton, SIGNAL(clicked()), SLOT(slotRefreshFolders()));
connect(_ui.folderTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SIGNAL(completeChanged()));
connect(_ui.folderTreeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), SIGNAL(completeChanged()));
registerField(QLatin1String("OCFolderLineEdit"), _ui.OCFolderLineEdit);
connect( _ui.OCFolderLineEdit, SIGNAL(textChanged(QString)),
SLOT(slotFolderTextChanged(QString)));
_timer = new QTimer(this);
_timer->setSingleShot( true );
connect( _timer, SIGNAL(timeout()), SLOT(slotTimerFires()));
}
void FolderWizardTargetPage::slotAddRemoteFolder()
void FolderWizardTargetPage::slotFolderTextChanged( const QString& t)
{
QTreeWidgetItem *current = _ui.folderTreeWidget->currentItem();
_dirChecked = false;
emit completeChanged();
QString parent('/');
if (current) {
parent = current->data(0, Qt::UserRole).toString();
if( t.isEmpty() ) {
_timer->stop();
return;
}
if( _timer->isActive() ) _timer->stop();
_timer->start(500);
}
void FolderWizardTargetPage::slotTimerFires()
{
const QString folder = _ui.OCFolderLineEdit->text();
qDebug() << "Querying folder " << folder;
ownCloudInfo::instance()->getWebDAVPath( folder );
}
void FolderWizardTargetPage::slotDirCheckReply(const QString &url, QNetworkReply *reply)
{
qDebug() << "Got reply from owncloud dir check: " << url << " :" << reply->error();
_dirChecked = (reply->error() == QNetworkReply::NoError);
if( _dirChecked ) {
showWarn();
} else {
showWarn( tr("The folder is not available on your %1.<br/>Click to create it." )
.arg( Theme::instance()->appNameGUI() ), true );
}
QInputDialog *dlg = new QInputDialog(this);
dlg->setWindowTitle(tr("Add Remote Folder"));
dlg->setLabelText(tr("Enter the name of the new folder:"));
dlg->setTextValue(parent);
dlg->open(this, SLOT(slotCreateRemoteFolder(QString)));
dlg->setAttribute(Qt::WA_DeleteOnClose);
emit completeChanged();
}
void FolderWizardTargetPage::slotCreateRemoteFolder(QString folder)
void FolderWizardTargetPage::slotCreateRemoteFolder()
{
const QString folder = _ui.OCFolderLineEdit->text();
if( folder.isEmpty() ) return;
_ui.OCFolderLineEdit->setEnabled( false );
qDebug() << "creating folder on ownCloud: " << folder;
ownCloudInfo::instance()->mkdirRequest( folder );
}
@@ -205,105 +233,32 @@ void FolderWizardTargetPage::slotCreateRemoteFolderFinished( QNetworkReply::Netw
{
qDebug() << "** webdav mkdir request finished " << error;
_ui.OCFolderLineEdit->setEnabled( true );
// the webDAV server seems to return a 202 even if mkdir was successful.
if( error == QNetworkReply::NoError ||
error == QNetworkReply::ContentOperationNotPermittedError) {
showWarn( tr("Folder was successfully created on %1.").arg( Theme::instance()->appNameGUI() ) );
slotRefreshFolders();
showWarn( tr("Folder was successfully created on %1.").arg( Theme::instance()->appNameGUI() ), false );
slotTimerFires();
} else {
showWarn( tr("Failed to create the folder on %1.<br/>Please check manually.").arg( Theme::instance()->appNameGUI() ) );
showWarn( tr("Failed to create the folder on %1.<br/>Please check manually.").arg( Theme::instance()->appNameGUI() ), false );
}
}
static QTreeWidgetItem* findFirstChild(QTreeWidgetItem *parent, const QString& text)
{
for (int i = 0; i < parent->childCount(); ++i) {
QTreeWidgetItem *child = parent->child(i);
if (child->text(0) == text) {
return child;
}
}
return 0;
}
static void recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path)
{
QFileIconProvider prov;
QIcon folderIcon = prov.icon(QFileIconProvider::Folder);
if (pathTrail.size() == 0) {
if (path.endsWith('/')) {
path.chop(1);
}
parent->setToolTip(0, path);
parent->setData(0, Qt::UserRole, path);
} else {
QTreeWidgetItem *item = findFirstChild(parent, pathTrail.first());
if (!item) {
item = new QTreeWidgetItem(parent);
item->setIcon(0, folderIcon);
item->setText(0, pathTrail.first());
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
}
pathTrail.removeFirst();
recursiveInsert(item, pathTrail, path);
}
}
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->setToolTip(0, tr("Choose this to sync the entire account"));
root->setData(0, Qt::UserRole, "/");
}
foreach (QString path, list) {
path.remove(webdavFolder);
QStringList paths = path.split('/');
if (paths.last().isEmpty()) paths.removeLast();
recursiveInsert(root, paths, path);
}
root->setExpanded(true);
}
void FolderWizardTargetPage::slotRefreshFolders()
{
ownCloudInfo::instance()->getDirectoryListing("/");
_ui.folderTreeWidget->clear();
}
void FolderWizardTargetPage::slotItemExpanded(QTreeWidgetItem *item)
{
ownCloudInfo::instance()->getDirectoryListing(item->text(0));
}
FolderWizardTargetPage::~FolderWizardTargetPage()
{
}
bool FolderWizardTargetPage::isComplete() const
{
if (!_ui.folderTreeWidget->currentItem())
return false;
QString dir = _ui.folderTreeWidget->currentItem()->data(0, Qt::UserRole).toString();
wizard()->setProperty("targetPath", dir);
if( dir == QLatin1String("/") ) {
showWarn( tr("If you sync the root folder, you can <b>not</b> configure another sync directory."));
QString dir = _ui.OCFolderLineEdit->text();
if( dir.isEmpty() || dir == QLatin1String("/") ) {
showWarn( tr("If you sync the root folder, you can <b>not</b> configure another sync directory."), false);
return true;
} else {
showWarn();
return true;
if( _dirChecked ) {
showWarn();
}
return _dirChecked;
}
}
@@ -319,19 +274,53 @@ void FolderWizardTargetPage::initializePage()
/* check the owncloud configuration file and query the ownCloud */
ownCloudInfo *ocInfo = ownCloudInfo::instance();
if( ocInfo->isConfigured() ) {
connect( ocInfo, SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
connect( ocInfo, SIGNAL(noOwncloudFound(QNetworkReply*)),
SLOT(slotNoOwnCloudFound(QNetworkReply*)));
connect( ocInfo, SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
SLOT(slotDirCheckReply(QString,QNetworkReply*)));
connect( ocInfo, SIGNAL(webdavColCreated(QNetworkReply::NetworkError)),
SLOT(slotCreateRemoteFolderFinished( QNetworkReply::NetworkError )));
connect( ocInfo, SIGNAL(directoryListingUpdated(QStringList)),
SLOT(slotUpdateDirectories(QStringList)));
slotRefreshFolders();
connect(_ui._buttCreateFolder, SIGNAL(clicked()), SLOT(slotCreateRemoteFolder()));
ocInfo->checkInstallation();
_ui.OCFolderLineEdit->setEnabled( false );
QString dir = _ui.OCFolderLineEdit->text();
if( !dir.isEmpty() ) {
slotFolderTextChanged( dir );
}
}
}
void FolderWizardTargetPage::slotOwnCloudFound( const QString& url, const QString& infoStr, const QString& version, const QString& edition)
{
Q_UNUSED(version);
Q_UNUSED(edition);
if( infoStr.isEmpty() ) {
} else {
// _ui.OCLabel->setText( tr("to your <a href=\"%1\">%2</a> (version %3)").arg(url)
// .arg(Theme::instance()->appNameGUI()).arg(infoStr));
_ui.OCFolderLineEdit->setEnabled( true );
qDebug() << "ownCloud found on " << url << " with version: " << infoStr;
}
}
void FolderWizardTargetPage::showWarn( const QString& msg ) const
void FolderWizardTargetPage::slotNoOwnCloudFound( QNetworkReply* error )
{
qDebug() << "No ownCloud configured: " << error->error();
// _ui.OCLabel->setText( tr("no configured %1 found!").arg(Theme::instance()->appNameGUI()) );
showWarn( tr("%1 could not be reached:<br/><tt>%2</tt>")
.arg(Theme::instance()->appNameGUI()).arg(error->errorString()));
_ui.OCFolderLineEdit->setEnabled( false );
}
void FolderWizardTargetPage::showWarn( const QString& msg, bool showCreateButton ) const
{
_ui._buttCreateFolder->setVisible( showCreateButton && !msg.isEmpty() );
if( msg.isEmpty() ) {
_ui.warnFrame->hide();
@@ -349,10 +338,11 @@ void FolderWizardTargetPage::showWarn( const QString& msg ) const
FolderWizard::FolderWizard( QWidget *parent )
: QWizard(parent),
_folderWizardSourcePage(new FolderWizardSourcePage),
_folderWizardSourcePage(0),
_folderWizardTargetPage(0)
{
setPage(Page_Source, _folderWizardSourcePage );
_folderWizardSourcePage = new FolderWizardSourcePage();
setPage(Page_Source, _folderWizardSourcePage );
if (!Theme::instance()->singleSyncFolder()) {
_folderWizardTargetPage = new FolderWizardTargetPage();
setPage(Page_Target, _folderWizardTargetPage );
@@ -366,11 +356,16 @@ FolderWizard::FolderWizard( QWidget *parent )
FolderWizard::~FolderWizard()
{
delete _folderWizardSourcePage;
if( _folderWizardTargetPage )
delete _folderWizardTargetPage;
}
void FolderWizard::setFolderMap( const Folder::Map& fm)
void FolderWizard::setFolderMap( Folder::Map *fm)
{
if( _folderWizardSourcePage ) {
_folderWizardSourcePage->setFolderMap( fm );
}
}
} // end namespace
+12 -9
Ver Arquivo
@@ -42,14 +42,14 @@ public:
void initializePage();
void cleanupPage();
void setFolderMap( const Folder::Map &fm ) { _folderMap = fm; }
void setFolderMap( Folder::Map *fm ) { _folderMap = fm; }
protected slots:
void on_localFolderChooseBtn_clicked();
void on_localFolderLineEdit_textChanged();
private:
Ui_FolderWizardSourcePage _ui;
Folder::Map _folderMap;
Folder::Map *_folderMap;
};
@@ -70,16 +70,19 @@ public:
virtual void cleanupPage();
protected slots:
void slotOwnCloudFound( const QString&, const QString&, const QString&, const QString& );
void slotNoOwnCloudFound(QNetworkReply*);
void showWarn( const QString& = QString() ) const;
void slotAddRemoteFolder();
void slotCreateRemoteFolder(QString);
void slotFolderTextChanged( const QString& );
void slotTimerFires();
void slotDirCheckReply( const QString&, QNetworkReply* );
void showWarn( const QString& = QString(), bool showCreateButton = false ) const;
void slotCreateRemoteFolder();
void slotCreateRemoteFolderFinished( QNetworkReply::NetworkError error );
void slotUpdateDirectories(QStringList);
void slotRefreshFolders();
void slotItemExpanded(QTreeWidgetItem*);
private:
Ui_FolderWizardTargetPage _ui;
QTimer *_timer;
ownCloudInfo *_ownCloudDirCheck;
bool _dirChecked;
bool _warnWasVisible;
@@ -100,7 +103,7 @@ public:
FolderWizard(QWidget *parent = 0);
~FolderWizard();
void setFolderMap( const Folder::Map &map );
void setFolderMap( Folder::Map* );
private:
+45 -44
Ver Arquivo
@@ -56,53 +56,44 @@
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QPushButton" name="addFolderButton">
<property name="text">
<string>Add Folder</string>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="refreshButton">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="4">
<widget class="QTreeWidget" name="folderTreeWidget">
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Folders</string>
</property>
</column>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Remote folder:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="OCFolderLineEdit"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<item row="2" column="0">
<widget class="QFrame" name="warnFrame">
<property name="palette">
<palette>
@@ -200,20 +191,30 @@
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>3</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="_buttCreateFolder">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>create</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
-86
Ver Arquivo
@@ -1,86 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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 "generalsettings.h"
#include "ui_generalsettings.h"
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/application.h"
#include "mirall/utility.h"
#include "mirall/mirallconfigfile.h"
#include <QNetworkProxy>
namespace Mirall {
GeneralSettings::GeneralSettings(QWidget *parent) :
QWidget(parent),
_ui(new Ui::GeneralSettings)
{
_ui->setupUi(this);
connect(_ui->desktopNotificationsCheckBox, SIGNAL(toggled(bool)),
SLOT(slotToggleOptionalDesktopNotifications(bool)));
_ui->autostartCheckBox->setChecked(Utility::hasLaunchOnStartup(Theme::instance()->appName()));
connect(_ui->autostartCheckBox, SIGNAL(toggled(bool)), SLOT(slotToggleLaunchOnStartup(bool)));
// setup about section
QString about = Theme::instance()->about();
if (about.isEmpty()) {
_ui->aboutGroupBox->hide();
} else {
_ui->aboutLabel->setText(about);
_ui->aboutLabel->setOpenExternalLinks(true);
}
loadMiscSettings();
// misc
connect(_ui->monoIconsCheckBox, SIGNAL(toggled(bool)), SLOT(saveMiscSettings()));
}
GeneralSettings::~GeneralSettings()
{
delete _ui;
}
void GeneralSettings::loadMiscSettings()
{
MirallConfigFile cfgFile;
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
_ui->desktopNotificationsCheckBox->setChecked(cfgFile.optionalDesktopNotifications());
}
void GeneralSettings::saveMiscSettings()
{
MirallConfigFile cfgFile;
bool isChecked = _ui->monoIconsCheckBox->isChecked();
cfgFile.setMonoIcons(isChecked);
Theme::instance()->setSystrayUseMonoIcons(isChecked);
}
void GeneralSettings::slotToggleLaunchOnStartup(bool enable)
{
Theme *theme = Theme::instance();
Utility::setLaunchOnStartup(theme->appName(), theme->appNameGUI(), enable);
}
void GeneralSettings::slotToggleOptionalDesktopNotifications(bool enable)
{
MirallConfigFile cfgFile;
cfgFile.setOptionalDesktopNotifications(enable);
}
} // namespace Mirall
-50
Ver Arquivo
@@ -1,50 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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 MIRALL_GENERALSETTINGS_H
#define MIRALL_GENERALSETTINGS_H
#include <QWidget>
namespace Mirall {
namespace Ui {
class GeneralSettings;
}
class GeneralSettings : public QWidget
{
Q_OBJECT
public:
explicit GeneralSettings(QWidget *parent = 0);
~GeneralSettings();
signals:
void proxySettingsChanged();
private slots:
void saveMiscSettings();
void slotToggleLaunchOnStartup(bool);
void slotToggleOptionalDesktopNotifications(bool);
private:
void loadMiscSettings();
Ui::GeneralSettings *_ui;
};
} // namespace Mirall
#endif // MIRALL_GENERALSETTINGS_H
-83
Ver Arquivo
@@ -1,83 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mirall::GeneralSettings</class>
<widget class="QWidget" name="Mirall::GeneralSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>468</width>
<height>169</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="generalGroupBox">
<property name="title">
<string>General</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QCheckBox" name="autostartCheckBox">
<property name="text">
<string>Launch on System Startup</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="desktopNotificationsCheckBox">
<property name="text">
<string>Show Desktop Notifications</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="monoIconsCheckBox">
<property name="text">
<string>Use Monochrome Icons</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="aboutGroupBox">
<property name="title">
<string>About</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="aboutLabel">
<property name="text">
<string>About</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="proxyButtonGroup"/>
</buttongroups>
</ui>
-160
Ver Arquivo
@@ -1,160 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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/mirallconfigfile.h"
#include "ignorelisteditor.h"
#include "ui_ignorelisteditor.h"
#include <QFile>
#include <QDir>
#include <QListWidget>
#include <QListWidgetItem>
#include <QColorGroup>
#include <QMessageBox>
#include <QInputDialog>
namespace Mirall {
IgnoreListEditor::IgnoreListEditor(QWidget *parent) :
QDialog(parent),
ui(new Ui::IgnoreListEditor)
{
ui->setupUi(this);
ui->descriptionLabel->setText(tr("Files or directories matching a pattern will not be synchronized.\n\n"
"Checked items will also be deleted if they prevent a directory from "
"being removed. This is useful for meta data."));
MirallConfigFile cfgFile;
readIgnoreFile(cfgFile.excludeFile(MirallConfigFile::SystemScope), true);
readIgnoreFile(cfgFile.excludeFile(MirallConfigFile::UserScope), false);
connect(this, SIGNAL(accepted()), SLOT(slotUpdateLocalIgnoreList()));
ui->removePushButton->setEnabled(false);
connect(ui->listWidget, SIGNAL(itemSelectionChanged()), SLOT(slotItemSelectionChanged()));
connect(ui->listWidget, SIGNAL(itemActivated(QListWidgetItem*)), SLOT(slotItemChanged(QListWidgetItem*)));
connect(ui->removePushButton, SIGNAL(clicked()), SLOT(slotRemoveCurrentItem()));
connect(ui->addPushButton, SIGNAL(clicked()), SLOT(slotAddPattern()));
connect(ui->listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), SLOT(slotEditPattern(QListWidgetItem*)));
}
static void setupItemFlags(QListWidgetItem* item)
{
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
}
IgnoreListEditor::~IgnoreListEditor()
{
delete ui;
}
void IgnoreListEditor::slotItemSelectionChanged()
{
QListWidgetItem *item = ui->listWidget->currentItem();
if (!item) {
ui->removePushButton->setEnabled(false);
return;
}
bool enable = item->flags() & Qt::ItemIsEnabled;
ui->removePushButton->setEnabled(enable);
}
void IgnoreListEditor::slotRemoveCurrentItem()
{
delete ui->listWidget->currentItem();
}
void IgnoreListEditor::slotUpdateLocalIgnoreList()
{
MirallConfigFile cfgFile;
QString ignoreFile = cfgFile.excludeFile(MirallConfigFile::UserScope);
QFile ignores(ignoreFile);
if (ignores.open(QIODevice::WriteOnly)) {
for(int i = 0; i < ui->listWidget->count(); ++i) {
QListWidgetItem *item = ui->listWidget->item(i);
if (item->flags() & Qt::ItemIsEnabled) {
QByteArray prepend;
if (item->checkState() == Qt::Checked) {
prepend = "]";
}
ignores.write(prepend+item->text().toUtf8()+'\n');
}
}
} else {
QMessageBox::warning(this, tr("Could not open file"),
tr("Cannot write changes to '%1'.").arg(ignoreFile));
}
}
void IgnoreListEditor::slotAddPattern()
{
QString pattern = QInputDialog::getText(this, tr("Add Ignore Pattern"), tr("Add a new ignore pattern:"));
QListWidgetItem *item = new QListWidgetItem;
setupItemFlags(item);
if (pattern.startsWith("]")) {
pattern = pattern.mid(1);
item->setCheckState(Qt::Checked);
}
item->setText(pattern);
ui->listWidget->addItem(item);
ui->listWidget->scrollToItem(item);
}
void IgnoreListEditor::slotEditPattern(QListWidgetItem *item)
{
if (!(item->flags() & Qt::ItemIsEnabled))
return;
QString pattern = QInputDialog::getText(this, tr("Add Ignore Pattern"),
tr("Add a new ignore pattern:"),
QLineEdit::Normal, item->text());
if (!pattern.isEmpty()) {
item->setText(pattern);
}
}
void IgnoreListEditor::readIgnoreFile(const QString &file, bool readOnly)
{
MirallConfigFile cfgFile;
const QString disabledTip(tr("This entry is provided by the system at '%1' "
"and cannot be modified in this view.")
.arg(QDir::toNativeSeparators(cfgFile.excludeFile(MirallConfigFile::SystemScope))));
QFile ignores(file);
if (ignores.open(QIODevice::ReadOnly)) {
while (!ignores.atEnd()) {
QString line = QString::fromUtf8(ignores.readLine());
line.chop(1);
if (!line.isEmpty() && !line.startsWith("#")) {
QListWidgetItem *item = new QListWidgetItem;
setupItemFlags(item);
if (line.startsWith("]")) {
line = line.mid(1);
item->setCheckState(Qt::Checked);
}
item->setText(line);
if (readOnly) {
item->setFlags(item->flags() ^ Qt::ItemIsEnabled);
item->setToolTip(disabledTip);
}
ui->listWidget->addItem(item);
}
}
}
}
} // namespace Mirall
-49
Ver Arquivo
@@ -1,49 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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 IGNORELISTEDITOR_H
#define IGNORELISTEDITOR_H
#include <QDialog>
class QListWidgetItem;
namespace Mirall {
namespace Ui {
class IgnoreListEditor;
}
class IgnoreListEditor : public QDialog
{
Q_OBJECT
public:
explicit IgnoreListEditor(QWidget *parent = 0);
~IgnoreListEditor();
private slots:
void slotItemSelectionChanged();
void slotRemoveCurrentItem();
void slotUpdateLocalIgnoreList();
void slotAddPattern();
void slotEditPattern(QListWidgetItem*);
private:
void readIgnoreFile(const QString& file, bool readOnly);
Ui::IgnoreListEditor *ui;
};
} // namespace Mirall
#endif // IGNORELISTEDITOR_H
-117
Ver Arquivo
@@ -1,117 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mirall::IgnoreListEditor</class>
<widget class="QDialog" name="Mirall::IgnoreListEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>471</width>
<height>359</height>
</rect>
</property>
<property name="windowTitle">
<string>Ignored Files Editor</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="enabled">
<bool>true</bool>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>213</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="3">
<widget class="QListWidget" name="listWidget">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="addPushButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="removePushButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="descriptionLabel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Mirall::IgnoreListEditor</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>348</x>
<y>333</y>
</hint>
<hint type="destinationlabel">
<x>361</x>
<y>355</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Mirall::IgnoreListEditor</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>210</x>
<y>333</y>
</hint>
<hint type="destinationlabel">
<x>385</x>
<y>297</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+5 -8
Ver Arquivo
@@ -47,7 +47,7 @@ INotify::INotify(QObject *parent, int mask)
_buffer = (char *) malloc(_buffer_size);
}
void INotify::slotActivated(int /*fd*/)
void INotify::slotActivated(int fd)
{
int len;
struct inotify_event* event;
@@ -82,7 +82,7 @@ void INotify::slotActivated(int /*fd*/)
// reset counter
i = 0;
// while there are enough events in the buffer
while(i + sizeof(struct inotify_event) < static_cast<unsigned int>(len)) {
while(i + sizeof(struct inotify_event) < len) {
// cast an inotify_event
event = (struct inotify_event*)&_buffer[i];
// with the help of watch descriptor, retrieve, corresponding INotify
@@ -115,17 +115,14 @@ INotify::~INotify()
delete _notifier;
}
bool INotify::addPath(const QString &path)
void INotify::addPath(const QString &path)
{
// Add an inotify watch.
int wd = inotify_add_watch(_fd, path.toUtf8().constData(), _mask);
if( wd > -1 ) {
if( wd > -1 )
_wds[path] = wd;
return true;
} else {
else
qDebug() << "WRN: Could not watch " << path << ':' << strerror(errno);
return false;
}
}
void INotify::removePath(const QString &path)
+4 -1
Ver Arquivo
@@ -38,7 +38,10 @@ public:
INotify(QObject *parent, int mask);
~INotify();
bool addPath(const QString &name);
static void initialize();
static void cleanup();
void addPath(const QString &name);
void removePath(const QString &name);
QStringList directories() const;
-374
Ver Arquivo
@@ -1,374 +0,0 @@
/*
* 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 <QtGui>
#include "mirall/itemprogressdialog.h"
#include "mirall/syncresult.h"
#include "mirall/logger.h"
#include "mirall/utility.h"
#include "mirall/theme.h"
#include "mirall/folderman.h"
#include "mirall/syncfileitem.h"
#include "ui_itemprogressdialog.h"
#define TYPE_SUCCESS 1
#define TYPE_CONFLICT 2
#define TYPE_NEW 3
#define TYPE_DELETED 4
#define TYPE_ERROR 5
#define TYPE_RENAME 6
#define TYPE_IGNORE 7
#define FILE_TYPE 100
namespace Mirall {
ItemProgressDialog::ItemProgressDialog(Application*, QWidget *parent) :
QDialog(parent),
ErrorIndicatorRole( Qt::UserRole +1 ),
_ui(new Ui::ItemProgressDialog)
{
_ui->setupUi(this);
connect(_ui->_dialogButtonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()),
this, SLOT(accept()));
connect(ProgressDispatcher::instance(), SIGNAL(progressInfo(QString,Progress::Info)),
this, SLOT(slotProgressInfo(QString,Progress::Info)));
connect(ProgressDispatcher::instance(), SIGNAL(progressSyncProblem(const QString&,const Progress::SyncProblem&)),
this, SLOT(slotProgressErrors(const QString&, const Progress::SyncProblem&)));
QStringList header;
header << tr("Folder/Time");
header << tr("File");
header << tr("Action");
header << tr("Size");
_ui->_treeWidget->setHeaderLabels( header );
_ui->_treeWidget->setColumnWidth(1, 180);
connect(this, SIGNAL(guiLog(QString,QString)), Logger::instance(), SIGNAL(guiLog(QString,QString)));
QPushButton *copyBtn = _ui->_dialogButtonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole);
connect(copyBtn, SIGNAL(clicked()), SLOT(copyToClipboard()));
setWindowTitle(tr("Sync Protocol"));
}
void ItemProgressDialog::setSyncResultStatus(const SyncResult& result )
{
QString folderMessage;
SyncResult::Status syncStatus = result.status();
switch( syncStatus ) {
case SyncResult::Undefined:
folderMessage = tr( "Undefined Folder State" );
break;
case SyncResult::NotYetStarted:
folderMessage = tr( "The folder waits to start syncing." );
break;
case SyncResult::SyncPrepare:
folderMessage = tr( "Determining which files to sync." );
break;
case SyncResult::Unavailable:
folderMessage = tr( "Server is currently not available." );
break;
case SyncResult::SyncRunning:
folderMessage = tr("Sync is running.");
break;
case SyncResult::Success:
folderMessage = tr("Last Sync was successful.");
break;
case SyncResult::Error:
folderMessage = tr( "Syncing Error." );
break;
case SyncResult::SetupError:
folderMessage = tr( "Setup Error." );
break;
case SyncResult::Problem:
folderMessage = tr( "Sync success, but warnings on individual files.");
break;
default:
folderMessage = tr( "Undefined Error State." );
}
_ui->_timelabel->setText(tr("%1").arg(folderMessage));
if( result.errorStrings().count() ) {
_ui->_errorLabel->setVisible(true);
_ui->_errorLabel->setTextFormat(Qt::RichText);
QString errStr;
foreach( QString err, result.errorStrings() ) {
errStr.append(QString("<p>%1</p>").arg(err));
}
_ui->_errorLabel->setText(errStr);
} else {
_ui->_errorLabel->setText(QString::null);
_ui->_errorLabel->setVisible(false);
}
}
void ItemProgressDialog::setSyncResult( const SyncResult& result )
{
setSyncResultStatus(result);
if(result.status() != SyncResult::Success ) {
return;
}
const QString& folder = result.folder();
qDebug() << "Setting sync result for folder " << folder;
QTreeWidgetItem *folderItem = findFolderItem(folder);
if( ! folderItem ) return;
SyncFileItemVector::const_iterator i;
const SyncFileItemVector& items = result.syncFileItemVector();
for (i = items.begin(); i != items.end(); ++i) {
const SyncFileItem& item = *i;
QString errMsg;
if( item._instruction == CSYNC_INSTRUCTION_IGNORE ) {
QStringList columns;
QString timeStr = QTime::currentTime().toString("hh:mm");
columns << timeStr;
columns << item._file;
if( item._type == SyncFileItem::File ) {
errMsg = tr("File ignored.");
} else if( item._type == SyncFileItem::Directory ){
errMsg = tr("Directory ignored.");
} else if( item._type == SyncFileItem::SoftLink ) {
errMsg = tr("Soft Link ignored.");
} else {
errMsg = tr("Ignored.");
}
columns << errMsg;
QTreeWidgetItem *twitem = new QTreeWidgetItem(folderItem, columns);
twitem->setData(0, ErrorIndicatorRole, QVariant(true) );
twitem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Problem, true));
Q_UNUSED(twitem);
}
}
}
void ItemProgressDialog::setupList()
{
// get the folders to set up the top level list.
Folder::Map map = FolderMan::instance()->map();
SyncResult lastResult;
QDateTime dt;
bool haveSyncResult = false;
foreach( Folder *f, map.values() ) {
findFolderItem(f->alias());
if( f->syncResult().syncTime() > dt ) {
dt = f->syncResult().syncTime();
lastResult = f->syncResult();
haveSyncResult = true;
}
}
if( haveSyncResult ) {
setSyncResult(lastResult);
}
QList<Progress::Info> progressList = ProgressDispatcher::instance()->recentChangedItems(0); // All.
QHash <QString, int> folderHash;
foreach( Progress::Info info, progressList ) {
slotProgressInfo( info.folder, info );
folderHash[info.folder] = 1;
}
QList<Progress::SyncProblem> problemList = ProgressDispatcher::instance()->recentProblems(0);
foreach( Progress::SyncProblem prob, problemList ) {
slotProgressErrors(prob.folder, prob);
folderHash[prob.folder] = 1;
}
foreach( const QString& folder, folderHash.keys() ) {
decorateFolderItem(folder);
}
}
ItemProgressDialog::~ItemProgressDialog()
{
delete _ui;
}
void ItemProgressDialog::copyToClipboard()
{
QString text;
QTextStream ts(&text);
int topLevelItems = _ui->_treeWidget->topLevelItemCount();
for (int i = 0; i < topLevelItems; i++) {
QTreeWidgetItem *item = _ui->_treeWidget->topLevelItem(i);
ts << left << qSetFieldWidth(50)
<< item->data(0, Qt::DisplayRole).toString()
<< right << qSetFieldWidth(6)
<< item->data(1, Qt::DisplayRole).toString()
<< endl;
int childItems = item->childCount();
for (int j = 0; j < childItems; j++) {
QTreeWidgetItem *child =item->child(j);
ts << left << qSetFieldWidth(0) << QLatin1String(" ")
<< child->data(0,Qt::DisplayRole).toString()
<< QString::fromLatin1(" (%1)").arg(
child->data(1, Qt::DisplayRole).toString()
)
<< endl;
}
}
QApplication::clipboard()->setText(text);
emit guiLog(tr("Copied to clipboard"), tr("The sync protocol has been copied to the clipboard."));
}
void ItemProgressDialog::accept()
{
QDialog::accept();
}
void ItemProgressDialog::decorateFolderItem( const QString& folder )
{
QTreeWidgetItem *folderItem = findFolderItem(folder);
if( ! folderItem ) return;
int errorCnt = 0;
int childCnt = folderItem->childCount();
for( int cnt = 0; cnt < childCnt; cnt++ ) {
bool isErrorItem = folderItem->child(cnt)->data(0, ErrorIndicatorRole).toBool();
if( isErrorItem ) {
errorCnt++;
}
}
if( errorCnt == 0 ) {
folderItem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Success));
} else {
// FIXME: Set a soft error icon here.
folderItem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Problem));
}
}
QTreeWidgetItem *ItemProgressDialog::createFolderItem(const QString& folder)
{
QStringList strings;
strings.append(folder);
QTreeWidgetItem *item = new QTreeWidgetItem( _ui->_treeWidget, strings );
item->setFirstColumnSpanned(true);
item->setExpanded(true);
return item;
}
QTreeWidgetItem *ItemProgressDialog::findFolderItem( const QString& folder )
{
QTreeWidgetItem *folderItem;
if( folder.isEmpty() ) return NULL;
if( !_folderItems.contains(folder)) {
_folderItems[folder] = createFolderItem(folder);
_ui->_treeWidget->addTopLevelItem(_folderItems[folder]);
}
folderItem = _folderItems[folder];
return folderItem;
}
void ItemProgressDialog::cleanErrors( const QString& folder )
{
_problemCounter = 0;
QList<QTreeWidgetItem*> wipeList;
QTreeWidgetItem *folderItem = findFolderItem(folder);
if( ! folderItem ) return;
int childCnt = folderItem->childCount();
for( int cnt = 0; cnt < childCnt; cnt++ ) {
bool isErrorItem = folderItem->child(cnt)->data(0, ErrorIndicatorRole).toBool();
if( isErrorItem ) {
wipeList.append(folderItem->child(cnt));
}
}
qDeleteAll(wipeList.begin(), wipeList.end());
}
void ItemProgressDialog::slotProgressErrors( const QString& folder, const Progress::SyncProblem& problem )
{
QTreeWidgetItem *folderItem;
folderItem = findFolderItem(folder);
if( !folderItem ) return;
QStringList columns;
QString timeStr = problem.timestamp.toString("hh:mm");
columns << timeStr;
columns << problem.current_file;
QString errMsg = tr("Problem: %1").arg(problem.error_message);
columns << errMsg;
// FIXME: Show the error code if available.
QTreeWidgetItem *item = new QTreeWidgetItem(folderItem, columns);
item->setData(0, ErrorIndicatorRole, QVariant(true) );
item->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Problem, true));
Q_UNUSED(item);
}
void ItemProgressDialog::slotProgressInfo( const QString& folder, const Progress::Info& progress )
{
QTreeWidgetItem *folderItem;
folderItem = findFolderItem(folder);
if( !folderItem ) return;
if( progress.kind == Progress::StartSync ) {
cleanErrors( folder );
folderItem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::SyncRunning));
}
if( progress.kind == Progress::EndSync ) {
decorateFolderItem( folder );
}
// Ingore other events than finishing an individual up- or download.
if( !(progress.kind == Progress::EndDownload || progress.kind == Progress::EndUpload || progress.kind == Progress::EndDelete)) {
return;
}
QStringList columns;
QString timeStr = progress.timestamp.toString("hh:mm");
columns << timeStr;
columns << progress.current_file;
columns << Progress::asResultString(progress.kind);
columns << Utility::octetsToString( progress.file_size );
QTreeWidgetItem *item = new QTreeWidgetItem(folderItem, columns);
Q_UNUSED(item);
}
}
-69
Ver Arquivo
@@ -1,69 +0,0 @@
/*
* 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 FILEITEMDIALOG_H
#define FILEITEMDIALOG_H
#include <QDialog>
#include <QDateTime>
#include "mirall/progressdispatcher.h"
#include "ui_fileitemdialog.h"
namespace Mirall {
class SyncResult;
namespace Ui {
class ItemProgressDialog;
}
class Application;
class ItemProgressDialog : public QDialog
{
Q_OBJECT
public:
explicit ItemProgressDialog(Application *app, QWidget *parent = 0);
~ItemProgressDialog();
void setupList();
void setSyncResult( const SyncResult& result );
signals:
public slots:
void accept();
void slotProgressInfo( const QString& folder, const Progress::Info& progress );
void slotProgressErrors( const QString& folder, const Progress::SyncProblem& problem );
protected slots:
void copyToClipboard();
signals:
void guiLog(const QString&, const QString&);
private:
void setSyncResultStatus(const SyncResult& result );
QTreeWidgetItem *createFolderItem(const QString& folder);
QTreeWidgetItem *findFolderItem( const QString& folder );
void cleanErrors( const QString& folder );
void decorateFolderItem( const QString& folder );
QHash<QString, QTreeWidgetItem*> _folderItems;
const int ErrorIndicatorRole;
Ui::ItemProgressDialog *_ui;
int _problemCounter;
};
}
#endif // FILEITEMDIALOG_H
-97
Ver Arquivo
@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mirall::ItemProgressDialog</class>
<widget class="QWidget" name="Mirall::ItemProgressDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>612</width>
<height>543</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Detailed Sync Protocol</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="_treeWidget">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rootIsDecorated">
<bool>true</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="columnCount">
<number>4</number>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
<column>
<property name="text">
<string>3</string>
</property>
</column>
<column>
<property name="text">
<string>4</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QLabel" name="_timelabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="_errorLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="_dialogButtonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+2 -14
Ver Arquivo
@@ -28,7 +28,6 @@
#include <QMessageBox>
#include <QCoreApplication>
#include <QDebug>
#include <QSettings>
#include "mirall/mirallconfigfile.h"
#include "mirall/logger.h"
@@ -57,10 +56,9 @@ LogWidget::LogWidget(QWidget *parent)
LogBrowser::LogBrowser(QWidget *parent) :
QDialog(parent),
_logWidget( new LogWidget(parent) ),
_doFileFlush(false),
_logstream(0)
_logstream(0),
_doFileFlush(false)
{
setObjectName("LogBrowser"); // for save/restoreGeometry()
setWindowTitle(tr("Log Output"));
setMinimumWidth(600);
@@ -117,9 +115,6 @@ LogBrowser::LogBrowser(QWidget *parent) :
// 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::AutoConnection);
MirallConfigFile cfg;
cfg.restoreGeometry(this);
}
LogBrowser::~LogBrowser()
@@ -216,11 +211,4 @@ void LogBrowser::slotClearLog()
_logWidget->clear();
}
void LogBrowser::closeEvent(QCloseEvent *event)
{
MirallConfigFile cfg;
cfg.saveGeometry(this);
QWidget::closeEvent(event);
}
} // namespace
+3 -2
Ver Arquivo
@@ -47,8 +47,9 @@ public:
void setLogFile(const QString& , bool );
protected:
void closeEvent(QCloseEvent *event);
signals:
public slots:
protected slots:
void slotNewLog( const QString &msg );
+1 -15
Ver Arquivo
@@ -22,6 +22,7 @@ Logger::Logger( QObject* parent)
: QObject(parent),
_showTime(true)
{
}
Logger *Logger::instance()
@@ -38,21 +39,6 @@ void Logger::destroy()
}
}
void Logger::postGuiLog(const QString &title, const QString &message)
{
emit guiLog(title, message);
}
void Logger::postOptionalGuiLog(const QString &title, const QString &message)
{
emit optionalGuiLog(title, message);
}
void Logger::postGuiMessage(const QString &title, const QString &message)
{
emit postGuiMessage(title, message);
}
void Logger::log(Log log)
{
QString msg;
-6
Ver Arquivo
@@ -46,15 +46,9 @@ public:
static Logger* instance();
static void destroy();
void postGuiLog(const QString& title, const QString& message);
void postOptionalGuiLog(const QString& title, const QString& message);
void postGuiMessage(const QString& title, const QString& message);
signals:
void newLog(const QString&);
void guiLog(const QString&, const QString&);
void guiMessage(const QString&, const QString&);
void optionalGuiLog(const QString&, const QString&);
protected:
Logger(QObject* parent=0);
-34
Ver Arquivo
@@ -1,34 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 <QNetworkRequest>
#include "mirall/mirallaccessmanager.h"
#include "mirall/utility.h"
namespace Mirall
{
MirallAccessManager::MirallAccessManager(QObject* parent)
: QNetworkAccessManager (parent)
{}
QNetworkReply* MirallAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
{
QNetworkRequest newRequest(request);
newRequest.setRawHeader( QByteArray("User-Agent"), Utility::userAgentString());
return QNetworkAccessManager::createRequest (op, newRequest, outgoingData);
}
} // ns Mirall
-35
Ver Arquivo
@@ -1,35 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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 MIRALL_ACCESS_MANAGER_H
#define MIRALL_ACCESS_MANAGER_H
#include <QNetworkAccessManager>
namespace Mirall
{
class MirallAccessManager : public QNetworkAccessManager
{
Q_OBJECT
public:
MirallAccessManager(QObject* parent = 0);
protected:
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0);
};
} // ns Mirall
#endif
+228 -299
Ver Arquivo
@@ -18,78 +18,24 @@
#include "mirall/owncloudinfo.h"
#include "mirall/owncloudtheme.h"
#include "mirall/theme.h"
#include "creds/abstractcredentials.h"
#include "creds/credentialsfactory.h"
#include "mirall/credentialstore.h"
#include <QtCore>
#include <QtGui>
#define DEFAULT_REMOTE_POLL_INTERVAL 30000 // default remote poll time in milliseconds
#define DEFAULT_MAX_LOG_LINES 20000
#define CA_CERTS_KEY QLatin1String("CaCertificates")
namespace Mirall {
static const char urlC[] = "url";
static const char authTypeC[] = "authType";
static const char caCertsKeyC[] = "CaCertificates";
static const char remotePollIntervalC[] = "remotePollInterval";
static const char forceSyncIntervalC[] = "forceSyncInterval";
static const char monoIconsC[] = "monoIcons";
static const char optionalDesktopNoficationsC[] = "optionalDesktopNotifications";
static const char skipUpdateCheckC[] = "skipUpdateCheck";
static const char geometryC[] = "geometry";
static const char proxyHostC[] = "Proxy/host";
static const char proxyTypeC[] = "Proxy/type";
static const char proxyPortC[] = "Proxy/port";
static const char proxyUserC[] = "Proxy/user";
static const char proxyPassC[] = "Proxy/pass";
static const char proxyNeedsAuthC[] = "Proxy/needsAuth";
static const char useUploadLimitC[] = "BWLimit/useUploadLimit";
static const char useDownloadLimitC[] = "BWLimit/useDownloadLimit";
static const char uploadLimitC[] = "BWLimit/uploadLimit";
static const char downloadLimitC[] = "BWLimit/downloadLimit";
static const char seenVersionC[] = "Updater/seenVersion";
static const char maxLogLinesC[] = "Logging/maxLogLines";
QString MirallConfigFile::_oCVersion;
QString MirallConfigFile::_confDir = QString::null;
bool MirallConfigFile::_askedUser = false;
QMap< QString, MirallConfigFile::SharedCreds > MirallConfigFile::credentialsPerConfig;
MirallConfigFile::MirallConfigFile( const QString& appendix, bool useOldConfig )
MirallConfigFile::MirallConfigFile( const QString& appendix )
:_customHandle(appendix)
{
if (useOldConfig && !appendix.isEmpty()) {
QString oldConfigFile = configFile();
_customHandle = appendix;
QString newConfigFile = configFile();
QFile::copy(oldConfigFile, newConfigFile);
} else {
_customHandle = appendix;
}
QSettings::setDefaultFormat(QSettings::IniFormat);
if (! credentialsPerConfig.contains(_customHandle)) {
QString con( _customHandle );
if( _customHandle.isEmpty() ) con = defaultConnection();
const QString config = configFile();
qDebug() << "Loading config: " << config;
QSettings settings(config, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( con );
QString type = settings.value( QLatin1String(authTypeC) ).toString();
qDebug() << "Getting credentials of type " << type << " for " << _customHandle;
credentialsPerConfig.insert(_customHandle, SharedCreds(CredentialsFactory::create (type)));
}
}
void MirallConfigFile::setConfDir(const QString &value)
@@ -103,99 +49,66 @@ void MirallConfigFile::setConfDir(const QString &value)
}
}
bool MirallConfigFile::optionalDesktopNotifications() const
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value(QLatin1String(optionalDesktopNoficationsC), true).toBool();
}
void MirallConfigFile::setOptionalDesktopNotifications(bool show)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(optionalDesktopNoficationsC), show);
settings.sync();
}
QString MirallConfigFile::seenVersion() const
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value(QLatin1String(seenVersionC)).toString();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup(QLatin1String("Updater"));
return settings.value(QLatin1String("seenVersion")).toString();
}
void MirallConfigFile::setSeenVersion(const QString &version)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(seenVersionC), version);
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup(QLatin1String("Updater"));
settings.setValue(QLatin1String("seenVersion"), version);
settings.sync();
}
void MirallConfigFile::saveGeometry(QWidget *w)
{
Q_ASSERT(!w->objectName().isNull());
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup(w->objectName());
settings.setValue(QLatin1String(geometryC), w->saveGeometry());
settings.sync();
}
void MirallConfigFile::restoreGeometry(QWidget *w)
{
w->restoreGeometry(getValue(geometryC, w->objectName()).toByteArray());
}
QString MirallConfigFile::configPath() const
{
if( _confDir.isEmpty() ) {
_confDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
}
QString dir = _confDir;
if( _confDir.isEmpty() )
_confDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
if( !dir.endsWith(QLatin1Char('/')) ) dir.append(QLatin1Char('/'));
return dir;
}
QString MirallConfigFile::excludeFile(Scope scope) const
QString MirallConfigFile::excludeFile() const
{
// prefer sync-exclude.lst, but if it does not exist, check for
// exclude.lst for compatibility reasons in the user writeable
// exclude.lst for compatibility reasonsin the user writeable
// directories.
const QString exclFile("sync-exclude.lst");
QFileInfo fi;
fi.setFile( configPath(), exclFile );
if (scope != SystemScope) {
fi.setFile( configPath(), exclFile );
if( ! fi.isReadable() ) {
fi.setFile( configPath(), QLatin1String("exclude.lst") );
}
if( ! fi.isReadable() ) {
fi.setFile( configPath(), exclFile );
}
if( ! fi.isReadable() ) {
fi.setFile( configPath(), QLatin1String("exclude.lst") );
}
if (scope != UserScope) {
// Check alternative places...
if( ! fi.isReadable() ) {
#ifdef Q_OS_WIN
fi.setFile( QApplication::applicationDirPath(), exclFile );
// Check alternative places...
if( ! fi.isReadable() ) {
#ifdef Q_OS_WIN32
fi.setFile( QApplication::applicationDirPath(), exclFile );
#endif
#ifdef Q_OS_UNIX
fi.setFile( QString("/etc/%1").arg(Theme::instance()->appName()), exclFile );
#ifdef Q_OS_LINUX
fi.setFile( QString("/etc/%1").arg(Theme::instance()->appName()), exclFile );
#endif
#ifdef Q_OS_MAC
// exec path is inside the bundle
fi.setFile( QApplication::applicationDirPath(),
QLatin1String("../Resources/") + exclFile );
// exec path is inside the bundle
fi.setFile( QApplication::applicationDirPath(),
QLatin1String("../Resources/") + exclFile );
#endif
}
}
qDebug() << " ==> returning exclude file path: " << fi.absoluteFilePath();
return fi.absoluteFilePath();
if( fi.isReadable() ) {
qDebug() << " ==> returning exclude file path: " << fi.absoluteFilePath();
return fi.absoluteFilePath();
}
qDebug() << "EMPTY exclude file path!";
return QString::null;
}
@@ -205,13 +118,13 @@ QString MirallConfigFile::configFile() const
if( qApp->applicationName().isEmpty() ) {
qApp->setApplicationName( Theme::instance()->appNameGUI() );
}
QString file = configPath() + Theme::instance()->configFileName();
QString dir = configPath() + Theme::instance()->configFileName();
if( !_customHandle.isEmpty() ) {
file.append( QLatin1Char('_'));
file.append( _customHandle );
qDebug() << __PRETTY_FUNCTION__ << " OO Custom config file in use: " << file;
dir.append( QLatin1Char('_'));
dir.append( _customHandle );
qDebug() << " OO Custom config file in use: " << dir;
}
return file;
return dir;
}
bool MirallConfigFile::exists()
@@ -230,92 +143,122 @@ bool MirallConfigFile::connectionExists( const QString& conn )
QString con = conn;
if( conn.isEmpty() ) con = defaultConnection();
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup(conn);
return settings.contains( QLatin1String(urlC) );
return settings.contains( QString::fromLatin1("%1/url").arg( conn ) );
}
void MirallConfigFile::writeOwncloudConfig( const QString& connection,
const QString& url,
AbstractCredentials* credentials)
const QString& user,
const QString& passwd )
{
const QString file = configFile();
qDebug() << "*** writing mirall config to " << file;
bool skipPwd = false; // can be refactored - remove it.
qDebug() << "*** writing mirall config to " << file << " Skippwd: " << skipPwd;
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup( connection );
settings.setValue( QLatin1String(urlC), url );
settings.setValue(QLatin1String(authTypeC), credentials->authType());
credentialsPerConfig.insert(_customHandle, SharedCreds(credentials));
settings.setValue( QLatin1String("url"), url );
settings.setValue( QLatin1String("user"), user );
#ifdef WITH_QTKEYCHAIN
// Password is stored to QtKeyChain now by default in CredentialStore
// The CredentialStore calls clearPasswordFromConfig after the creds
// were successfully wiritten to delete the passwd entry from config.
qDebug() << "Going to delete the password from settings file.";
#else
if( !skipPwd )
writePassword( passwd );
#endif
if( !skipPwd )
writePassword( passwd );
else
clearPasswordFromConfig(); // wipe the password.
settings.setValue( QLatin1String("nostoredpassword"), QVariant(skipPwd) );
settings.sync();
// check the perms, only read-write for the owner.
QFile::setPermissions( file, QFile::ReadOwner|QFile::WriteOwner );
// Store credentials temporar until the config is finalized.
//ownCloudInfo::instance()->setCredentials( user, passwd, _customHandle );
ownCloudInfo::instance()->setCredentials( user, passwd, _customHandle );
}
void MirallConfigFile::storeData(const QString& group, const QString& key, const QVariant& value)
// This method is called after the password was successfully stored into the
// QKeyChain in CredentialStore.
void MirallConfigFile::clearPasswordFromConfig( const QString& connection )
{
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
const QString file = configFile();
QString con( defaultConnection() );
if( !connection.isEmpty() )
con = connection;
settings.beginGroup(con);
settings.setValue(key, value);
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
settings.remove(QLatin1String("passwd"));
settings.remove(QLatin1String("password"));
settings.sync();
}
QVariant MirallConfigFile::retrieveData(const QString& group, const QString& key) const
bool MirallConfigFile::writePassword( const QString& passwd, const QString& connection )
{
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
const QString file = configFile();
QString pwd( passwd );
QString con( defaultConnection() );
if( !connection.isEmpty() )
con = connection;
settings.beginGroup(con);
return settings.value(key);
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
// store password into settings file.
settings.beginGroup( con );
QByteArray pwdba = pwd.toUtf8();
settings.setValue( QLatin1String("passwd"), QVariant(pwdba.toBase64()) );
settings.sync();
return true;
}
void MirallConfigFile::removeData(const QString& group, const QString& key)
// set the url, called from redirect handling.
void MirallConfigFile::setOwnCloudUrl( const QString& connection, const QString & url )
{
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
const QString file = configFile();
settings.beginGroup(con);
settings.remove(key);
}
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup( connection );
settings.setValue( QLatin1String("url"), url );
bool MirallConfigFile::dataExists(const QString& group, const QString& key) const
{
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup(con);
return settings.contains(key);
settings.sync();
}
QByteArray MirallConfigFile::caCerts( )
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value( QLatin1String(caCertsKeyC) ).toByteArray();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QByteArray certs = settings.value( CA_CERTS_KEY ).toByteArray();
return certs;
}
void MirallConfigFile::setCaCerts( const QByteArray & certs )
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
const QString file = configFile();
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.setValue( QLatin1String(caCertsKeyC), certs );
settings.setValue( CA_CERTS_KEY, certs );
settings.sync();
}
@@ -328,8 +271,7 @@ void MirallConfigFile::removeConnection( const QString& connection )
qDebug() << " removing the config file for connection " << con;
// Currently its just removing the entire config file
// TODO: Eh? Shouldn't it try to load a file under configFile() and set it to INI?
QSettings settings;
QSettings settings( configFile(), QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
settings.remove(QString::null); // removes all content from the group
@@ -340,22 +282,41 @@ void MirallConfigFile::removeConnection( const QString& connection )
* returns the configured owncloud url if its already configured, otherwise an empty
* string.
* The returned url always has a trailing hash.
* If webdav is true, the webdav-server url is returned.
*/
QString MirallConfigFile::ownCloudUrl( const QString& connection) const
QString MirallConfigFile::ownCloudUrl( const QString& connection, bool webdav ) const
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
QString url = settings.value( QLatin1String(urlC) ).toString();
QString url = settings.value( QLatin1String("url") ).toString();
if( ! url.isEmpty() ) {
if( ! url.endsWith(QLatin1Char('/'))) url.append(QLatin1String("/"));
if( webdav ) url.append( QLatin1String("remote.php/webdav/") );
}
return url;
qDebug() << "Returning configured owncloud url: " << url;
return url;
}
QString MirallConfigFile::ownCloudUser( const QString& connection ) const
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
QString user = settings.value( QLatin1String("user") ).toString();
// qDebug() << "Returning configured owncloud user: " << user;
return user;
}
int MirallConfigFile::remotePollInterval( const QString& connection ) const
@@ -363,11 +324,11 @@ int MirallConfigFile::remotePollInterval( const QString& connection ) const
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
int remoteInterval = settings.value( QLatin1String(remotePollIntervalC), DEFAULT_REMOTE_POLL_INTERVAL ).toInt();
int remoteInterval = settings.value( QLatin1String("remotePollInterval"), DEFAULT_REMOTE_POLL_INTERVAL ).toInt();
if( remoteInterval < 5000) {
qDebug() << "Remote Interval is less than 5 seconds, reverting to" << DEFAULT_REMOTE_POLL_INTERVAL;
remoteInterval = DEFAULT_REMOTE_POLL_INTERVAL;
@@ -384,29 +345,52 @@ void MirallConfigFile::setRemotePollInterval(int interval, const QString &connec
qDebug() << "Remote Poll interval of " << interval << " is below fife seconds.";
return;
}
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
settings.setValue(QLatin1String(remotePollIntervalC), interval );
settings.setValue("remotePollInterval", interval );
settings.sync();
}
quint64 MirallConfigFile::forceSyncInterval(const QString& connection) const
bool MirallConfigFile::passwordStorageAllowed( const QString& connection )
{
uint pollInterval = remotePollInterval(connection);
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
quint64 interval = settings.value( QLatin1String(forceSyncIntervalC), 10 * pollInterval ).toULongLong();
if( interval < pollInterval) {
qDebug() << "Force sync interval is less than the remote poll inteval, reverting to" << pollInterval;
interval = pollInterval;
bool skipPwd = settings.value( QLatin1String("nostoredpassword"), false ).toBool();
return !skipPwd;
}
QString MirallConfigFile::ownCloudPasswd( const QString& connection ) const
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
QByteArray pwdba = settings.value(QLatin1String("passwd")).toByteArray();
if( !pwdba.isEmpty() ) {
return QString::fromUtf8( QByteArray::fromBase64(pwdba) );
}
return interval;
// check the password entry, cleartext from before
// read it and convert to base64, delete the cleartext entry.
QString p = settings.value(QLatin1String("password")).toString();
if( ! p.isEmpty() ) {
// its there, save base64-encoded and delete.
pwdba = p.toUtf8();
settings.setValue( QLatin1String("passwd"), QVariant(pwdba.toBase64()) );
settings.remove( QLatin1String("password") );
settings.sync();
}
return p;
}
QString MirallConfigFile::ownCloudVersion() const
@@ -426,11 +410,11 @@ bool MirallConfigFile::ownCloudSkipUpdateCheck( const QString& connection ) cons
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
bool skipIt = settings.value( QLatin1String(skipUpdateCheckC), false ).toBool();
bool skipIt = settings.value( QLatin1String("skipUpdateCheck"), false ).toBool();
return skipIt;
}
@@ -440,27 +424,31 @@ void MirallConfigFile::setOwnCloudSkipUpdateCheck( bool skip, const QString& con
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
settings.setValue( QLatin1String(skipUpdateCheckC), QVariant(skip) );
settings.setValue( QLatin1String("skipUpdateCheck"), QVariant(skip) );
settings.sync();
}
int MirallConfigFile::maxLogLines() const
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value( QLatin1String(maxLogLinesC), DEFAULT_MAX_LOG_LINES ).toInt();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup(QLatin1String("Logging"));
int logLines = settings.value( QLatin1String("maxLogLines"), 20000 ).toInt();
return logLines;
}
void MirallConfigFile::setMaxLogLines( int lines )
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(maxLogLinesC), lines);
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup(QLatin1String("Logging"));
settings.setValue(QLatin1String("maxLogLines"), lines);
settings.sync();
}
@@ -487,8 +475,6 @@ void MirallConfigFile::acceptCustomConfig()
QString srcConfig = configFile(); // this considers the custom handle
credentialsPerConfig.insert(QString(), credentialsPerConfig[_customHandle]);
credentialsPerConfig.remove(_customHandle);
_customHandle.clear();
QString targetConfig = configFile();
QString targetBak = targetConfig + QLatin1String(".bak");
@@ -510,7 +496,18 @@ void MirallConfigFile::acceptCustomConfig()
}
QFile::remove( targetBak );
credentialsPerConfig[QString()]->persistForUrl(ownCloudUrl());
// inform the credential store about the password change.
QString url = ownCloudUrl();
QString user = ownCloudUser();
QString pwd = ownCloudPasswd();
bool allow = passwordStorageAllowed();
if( pwd.isEmpty() ) {
qDebug() << "Password is empty, skipping to write cred store.";
} else {
CredentialStore::instance()->setCredentials(url, user, pwd, allow);
CredentialStore::instance()->saveCredentials();
}
}
void MirallConfigFile::setProxyType(int proxyType,
@@ -519,129 +516,61 @@ void MirallConfigFile::setProxyType(int proxyType,
const QString& user,
const QString& pass)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup(QLatin1String("proxy"));
settings.setValue(QLatin1String(proxyTypeC), proxyType);
settings.setValue(QLatin1String("type"), proxyType);
if (proxyType == QNetworkProxy::HttpProxy ||
proxyType == QNetworkProxy::Socks5Proxy) {
settings.setValue(QLatin1String(proxyHostC), host);
settings.setValue(QLatin1String(proxyPortC), port);
settings.setValue(QLatin1String(proxyNeedsAuthC), needsAuth);
settings.setValue(QLatin1String(proxyUserC), user);
settings.setValue(QLatin1String(proxyPassC), pass.toUtf8().toBase64());
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();
}
QVariant MirallConfigFile::getValue(const QString& param, const QString& group,
const QVariant& defaultValue) const
QVariant MirallConfigFile::getValue(const QString& param, const QString& group) const
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
if (!group.isEmpty())
settings.beginGroup(group);
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup(group);
return settings.value(param, defaultValue);
}
void MirallConfigFile::setValue(const QString& key, const QVariant &value)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(key, value);
return settings.value(param);
}
int MirallConfigFile::proxyType() const
{
return getValue(QLatin1String(proxyTypeC)).toInt();
return getValue(QLatin1String("type"), QLatin1String("proxy")).toInt();
}
QString MirallConfigFile::proxyHostName() const
{
return getValue(QLatin1String(proxyHostC)).toString();
return getValue(QLatin1String("host"), QLatin1String("proxy")).toString();
}
int MirallConfigFile::proxyPort() const
{
return getValue(QLatin1String(proxyPortC)).toInt();
return getValue(QLatin1String("port"), QLatin1String("proxy")).toInt();
}
bool MirallConfigFile::proxyNeedsAuth() const
{
return getValue(QLatin1String(proxyNeedsAuthC)).toBool();
return getValue(QLatin1String("needsAuth"), QLatin1String("proxy")).toBool();
}
QString MirallConfigFile::proxyUser() const
{
return getValue(QLatin1String(proxyUserC)).toString();
return getValue(QLatin1String("user"), QLatin1String("proxy")).toString();
}
QString MirallConfigFile::proxyPassword() const
{
QByteArray pass = getValue(proxyPassC).toByteArray();
QByteArray pass = getValue(QLatin1String("pass"), QLatin1String("proxy")).toByteArray();
return QString::fromUtf8(QByteArray::fromBase64(pass));
}
int MirallConfigFile::useUploadLimit() const
{
return getValue(useUploadLimitC, QString::null, -1).toInt();
}
bool MirallConfigFile::useDownloadLimit() const
{
return getValue(useDownloadLimitC, QString::null, false).toBool();
}
void MirallConfigFile::setUseUploadLimit(int val)
{
setValue(useUploadLimitC, val);
}
void MirallConfigFile::setUseDownloadLimit(bool enable)
{
setValue(useDownloadLimitC, enable);
}
int MirallConfigFile::uploadLimit() const
{
return getValue(uploadLimitC, QString::null, 10).toInt();
}
int MirallConfigFile::downloadLimit() const
{
return getValue(downloadLimitC, QString::null, 80).toInt();
}
void MirallConfigFile::setUploadLimit(int kbytes)
{
setValue(uploadLimitC, kbytes);
}
void MirallConfigFile::setDownloadLimit(int kbytes)
{
setValue(downloadLimitC, kbytes);
}
bool MirallConfigFile::monoIcons() const
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value(QLatin1String(monoIconsC), false).toBool();
}
void MirallConfigFile::setMonoIcons(bool useMonoIcons)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(monoIconsC), useMonoIcons);
}
AbstractCredentials* MirallConfigFile::getCredentials() const
{
return credentialsPerConfig[_customHandle].data();
}
}
+27 -44
Ver Arquivo
@@ -15,26 +15,33 @@
#ifndef MIRALLCONFIGFILE_H
#define MIRALLCONFIGFILE_H
#include <QSharedPointer>
#include <QString>
#include <QVariant>
class QWidget;
class QVariant;
namespace Mirall {
class AbstractCredentials;
class MirallConfigFile
{
/* let only CredentialStore read the password from the file. All other classes
* should work with CredentialStore to get the credentials. */
friend class CredentialStore;
friend class ConnectionValidator;
public:
MirallConfigFile( const QString& appendix = QString(), bool useOldConfig = false );
MirallConfigFile( const QString& appendix = QString() );
enum Scope { UserScope, SystemScope };
// enum customMediaType {
// oCSetupTop, // ownCloud connect page
// oCSetupSide,
// oCSetupBottom,
// oCSetupFixUrl,
// oCSetupResultTop // ownCloud connect result page
// };
QString configPath() const;
QString configFile() const;
QString excludeFile(Scope scope) const;
QString excludeFile() const;
bool exists();
@@ -43,13 +50,15 @@ public:
void writeOwncloudConfig( const QString& connection,
const QString& url,
AbstractCredentials* credentials);
AbstractCredentials* getCredentials() const;
const QString& user,
const QString& passwd );
void removeConnection( const QString& connection = QString() );
QString ownCloudUrl( const QString& connection = QString() ) const;
QString ownCloudUser( const QString& connection = QString() ) const;
QString ownCloudUrl( const QString& connection = QString(), bool webdav = false ) const;
void setOwnCloudUrl(const QString &connection, const QString& );
// the certs do not depend on a connection.
QByteArray caCerts();
@@ -72,17 +81,11 @@ public:
/* Set poll interval. Value in microseconds has to be larger than 5000 */
void setRemotePollInterval(int interval, const QString& connection = QString() );
/* Force sync interval, in milliseconds */
quint64 forceSyncInterval(const QString &connection = QString()) const;
// Custom Config: accept the custom config to become the main one.
void acceptCustomConfig();
// Custom Config: remove the custom config file.
void cleanupCustomConfig();
bool monoIcons() const;
void setMonoIcons(bool);
// proxy settings
void setProxyType(int proxyType,
const QString& host = QString(),
@@ -97,46 +100,26 @@ public:
QString proxyUser() const;
QString proxyPassword() const;
/** 0: no limit, 1: manual, >0: automatic */
int useUploadLimit() const;
bool useDownloadLimit() const;
void setUseUploadLimit(int);
void setUseDownloadLimit(bool);
int uploadLimit() const;
int downloadLimit() const;
void setUploadLimit(int kbytes);
void setDownloadLimit(int kbytes);
static void setConfDir(const QString &value);
bool optionalDesktopNotifications() const;
void setOptionalDesktopNotifications(bool show);
QString seenVersion() const;
void setSeenVersion(const QString &version);
void saveGeometry(QWidget *w);
void restoreGeometry(QWidget *w);
protected:
void storeData(const QString& group, const QString& key, const QVariant& value);
QVariant retrieveData(const QString& group, const QString& key) const;
void removeData(const QString& group, const QString& key);
bool dataExists(const QString& group, const QString& key) const;
// these classes can only be access from CredentialStore as a friend class.
QString ownCloudPasswd( const QString& connection = QString() ) const;
void clearPasswordFromConfig( const QString& connect = QString() );
bool writePassword( const QString& passwd, const QString& connection = QString() );
private:
QVariant getValue(const QString& param, const QString& group = QString::null,
const QVariant& defaultValue = QVariant()) const;
void setValue(const QString& key, const QVariant &value);
QVariant getValue(const QString& param, const QString& group) const;
private:
typedef QSharedPointer< AbstractCredentials > SharedCreds;
static bool _askedUser;
static QString _oCVersion;
static QString _confDir;
static QMap< QString, SharedCreds > credentialsPerConfig;
QString _customHandle;
};
}
-161
Ver Arquivo
@@ -1,161 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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 "networksettings.h"
#include "ui_networksettings.h"
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/application.h"
#include "mirall/utility.h"
#include "mirall/mirallconfigfile.h"
#include <QNetworkProxy>
namespace Mirall {
NetworkSettings::NetworkSettings(QWidget *parent) :
QWidget(parent),
_ui(new Ui::NetworkSettings)
{
_ui->setupUi(this);
_ui->hostLineEdit->setPlaceholderText(tr("Hostname of proxy server"));
_ui->userLineEdit->setPlaceholderText(tr("Username for proxy server"));
_ui->passwordLineEdit->setPlaceholderText(tr("Password for proxy server"));
_ui->typeComboBox->addItem(tr("HTTP(S) proxy"), QNetworkProxy::HttpProxy);
_ui->typeComboBox->addItem(tr("SOCKS5 proxy"), QNetworkProxy::Socks5Proxy);
_ui->authRequiredcheckBox->setEnabled(true);
connect(_ui->manualProxyRadioButton, SIGNAL(toggled(bool)),
_ui->manualSettings, SLOT(setEnabled(bool)));
connect(_ui->manualProxyRadioButton, SIGNAL(toggled(bool)),
_ui->typeComboBox, SLOT(setEnabled(bool)));
connect(_ui->authRequiredcheckBox, SIGNAL(toggled(bool)),
_ui->authWidgets, SLOT(setEnabled(bool)));
loadProxySettings();
loadBWLimitSettings();
// proxy
connect(_ui->typeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(saveProxySettings()));
connect(_ui->proxyButtonGroup, SIGNAL(buttonClicked(int)), SLOT(saveProxySettings()));
connect(_ui->hostLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
connect(_ui->userLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
connect(_ui->passwordLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
connect(_ui->portSpinBox, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
connect(_ui->uploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
connect(_ui->noUploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
connect(_ui->autoUploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
connect(_ui->downloadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
connect(_ui->noDownloadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
connect(_ui->downloadSpinBox, SIGNAL(valueChanged(int)), SLOT(saveBWLimitSettings()));
connect(_ui->uploadSpinBox, SIGNAL(valueChanged(int)), SLOT(saveBWLimitSettings()));
}
NetworkSettings::~NetworkSettings()
{
delete _ui;
}
void NetworkSettings::loadProxySettings()
{
// load current proxy settings
Mirall::MirallConfigFile cfgFile;
int type = cfgFile.proxyType();
switch (type) {
case QNetworkProxy::NoProxy:
_ui->noProxyRadioButton->setChecked(true);
break;
case QNetworkProxy::DefaultProxy:
_ui->systemProxyRadioButton->setChecked(true);
break;
case QNetworkProxy::Socks5Proxy:
case QNetworkProxy::HttpProxy:
_ui->typeComboBox->setCurrentIndex(_ui->typeComboBox->findData(type));
_ui->manualProxyRadioButton->setChecked(true);
break;
default:
break;
}
_ui->hostLineEdit->setText(cfgFile.proxyHostName());
int port = cfgFile.proxyPort();
if (port == 0)
port = 8080;
_ui->portSpinBox->setValue(port);
if (!cfgFile.proxyUser().isEmpty())
{
_ui->authRequiredcheckBox->setChecked(true);
_ui->userLineEdit->setText(cfgFile.proxyUser());
_ui->passwordLineEdit->setText(cfgFile.proxyPassword());
}
}
void NetworkSettings::loadBWLimitSettings()
{
MirallConfigFile cfgFile;
_ui->downloadLimitRadioButton->setChecked(cfgFile.useDownloadLimit());
int uploadLimit = cfgFile.useUploadLimit();
if ( uploadLimit >= 1 ) {
_ui->uploadLimitRadioButton->setChecked(true);
} else if (uploadLimit == 0){
_ui->noDownloadLimitRadioButton->setChecked(true);
} else {
_ui->autoUploadLimitRadioButton->setChecked(true);
}
_ui->downloadSpinBox->setValue(cfgFile.downloadLimit());
_ui->uploadSpinBox->setValue(cfgFile.uploadLimit());
}
void NetworkSettings::saveProxySettings()
{
MirallConfigFile cfgFile;
if (_ui->noProxyRadioButton->isChecked()){
cfgFile.setProxyType(QNetworkProxy::NoProxy);
} else if (_ui->systemProxyRadioButton->isChecked()){
cfgFile.setProxyType(QNetworkProxy::DefaultProxy);
} else if (_ui->manualProxyRadioButton->isChecked()) {
int type = _ui->typeComboBox->itemData(_ui->typeComboBox->currentIndex()).toInt();
bool needsAuth = _ui->authRequiredcheckBox->isChecked();
QString user = _ui->userLineEdit->text();
QString pass = _ui->passwordLineEdit->text();
cfgFile.setProxyType(type, _ui->hostLineEdit->text(),
_ui->portSpinBox->value(), needsAuth, user, pass);
}
emit proxySettingsChanged();
}
void NetworkSettings::saveBWLimitSettings()
{
MirallConfigFile cfgFile;
cfgFile.setUseDownloadLimit(_ui->downloadLimitRadioButton->isChecked());
if (_ui->uploadLimitRadioButton->isChecked()) {
cfgFile.setUseUploadLimit(1);
} else if (_ui->noUploadLimitRadioButton->isChecked()) {
cfgFile.setUseUploadLimit(0);
} else if (_ui->autoUploadLimitRadioButton->isChecked()) {
cfgFile.setUseUploadLimit(-1);
}
cfgFile.setDownloadLimit(_ui->downloadSpinBox->value());
cfgFile.setUploadLimit(_ui->uploadSpinBox->value());
}
} // namespace Mirall
-50
Ver Arquivo
@@ -1,50 +0,0 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@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 MIRALL_NETWORKSETTINGS_H
#define MIRALL_NETWORKSETTINGS_H
#include <QWidget>
namespace Mirall {
namespace Ui {
class NetworkSettings;
}
class NetworkSettings : public QWidget
{
Q_OBJECT
public:
explicit NetworkSettings(QWidget *parent = 0);
~NetworkSettings();
signals:
void proxySettingsChanged();
private slots:
void saveProxySettings();
void saveBWLimitSettings();
private:
void loadProxySettings();
void loadBWLimitSettings();
Ui::NetworkSettings *_ui;
};
} // namespace Mirall
#endif // MIRALL_NETWORKSETTINGS_H
-371
Ver Arquivo
@@ -1,371 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Mirall::NetworkSettings</class>
<widget class="QWidget" name="Mirall::NetworkSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>518</width>
<height>384</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="proxyGroupBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Proxy Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="noProxyRadioButton">
<property name="text">
<string>No Proxy</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">proxyButtonGroup</string>
</attribute>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="systemProxyRadioButton">
<property name="text">
<string>Use system proxy</string>
</property>
<attribute name="buttonGroup">
<string notr="true">proxyButtonGroup</string>
</attribute>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="manualProxyRadioButton">
<property name="text">
<string>Specify proxy manually as</string>
</property>
<attribute name="buttonGroup">
<string notr="true">proxyButtonGroup</string>
</attribute>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="typeComboBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QWidget" name="manualSettings" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="rightMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="hostLabel">
<property name="text">
<string>Host</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="hostLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>:</string>
</property>
</widget>
</item>
<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>
</layout>
</item>
<item>
<widget class="QCheckBox" name="authRequiredcheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Proxy server requires authentication</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="authWidgets" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="userLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="passwordLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Download Bandwidth</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0">
<widget class="QRadioButton" name="downloadLimitRadioButton">
<property name="text">
<string>Limit to</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="downloadSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>9999</number>
</property>
<property name="value">
<number>80</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>KBytes/s</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>147</width>
<height>25</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="2">
<widget class="QRadioButton" name="noDownloadLimitRadioButton">
<property name="text">
<string>No Limit</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Upload Bandwidth</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0" colspan="2">
<widget class="QRadioButton" name="noUploadLimitRadioButton">
<property name="text">
<string>No Limit</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QRadioButton" name="autoUploadLimitRadioButton">
<property name="text">
<string>Limit automatically</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="uploadLimitRadioButton">
<property name="text">
<string>Limit to</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSpinBox" name="uploadSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>9999</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>KBytes/s</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<zorder>autoUploadLimitRadioButton</zorder>
<zorder>uploadLimitRadioButton</zorder>
<zorder>noUploadLimitRadioButton</zorder>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>downloadLimitRadioButton</sender>
<signal>toggled(bool)</signal>
<receiver>downloadSpinBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>73</x>
<y>69</y>
</hint>
<hint type="destinationlabel">
<x>131</x>
<y>78</y>
</hint>
</hints>
</connection>
<connection>
<sender>uploadLimitRadioButton</sender>
<signal>toggled(bool)</signal>
<receiver>uploadSpinBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>322</x>
<y>101</y>
</hint>
<hint type="destinationlabel">
<x>411</x>
<y>106</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="proxyButtonGroup"/>
</buttongroups>
</ui>
+532
Ver Arquivo
@@ -0,0 +1,532 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "mirall/owncloudfolder.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/owncloudinfo.h"
#include "mirall/credentialstore.h"
#include "mirall/logger.h"
#include "mirall/utility.h"
#include <csync.h>
#include <QDebug>
#include <QDir>
#include <QUrl>
#include <QMutexLocker>
#include <QThread>
#include <QStringList>
#include <QTextStream>
#include <QTimer>
#include <QNetworkProxy>
#include <QNetworkAccessManager>
#include <QNetworkProxyFactory>
#include <QMessageBox>
#include <QPushButton>
namespace Mirall {
void csyncLogCatcher(CSYNC *ctx,
int verbosity,
const char *function,
const char *buffer,
void *userdata)
{
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
}
static QString replaceScheme(const QString &urlStr)
{
QUrl url( urlStr );
if( url.scheme() == QLatin1String("http") ) {
url.setScheme( QLatin1String("owncloud") );
} else {
// connect SSL!
url.setScheme( QLatin1String("ownclouds") );
}
return url.toString();
}
ownCloudFolder::ownCloudFolder(const QString &alias,
const QString &mpath,
const QString &secondPath,
QObject *parent)
: Folder(alias, mpath, secondPath, parent)
, _thread(0)
, _csync(0)
, _csyncError(false)
, _csyncUnavail(false)
{
ServerActionNotifier *notifier = new ServerActionNotifier(this);
connect(notifier, SIGNAL(guiLog(QString,QString)), Logger::instance(), SIGNAL(guiLog(QString,QString)));
connect(this, SIGNAL(syncFinished(SyncResult)), notifier, SLOT(slotSyncFinished(SyncResult)));
qDebug() << "****** ownCloud folder using watcher *******";
// The folder interval is set in the folder parent class.
QString url = replaceScheme(secondPath);
QString localpath = path();
if( csync_create( &_csync_ctx, localpath.toUtf8().data(), url.toUtf8().data() ) < 0 ) {
qDebug() << "Unable to create csync-context!";
_csync_ctx = 0;
} else {
csync_set_log_callback( _csync_ctx, csyncLogCatcher );
csync_set_log_verbosity(_csync_ctx, 11);
MirallConfigFile cfgFile;
csync_set_config_dir( _csync_ctx, cfgFile.configPath().toUtf8() );
csync_enable_conflictcopys(_csync_ctx);
QString excludeList = cfgFile.excludeFile();
if( !excludeList.isEmpty() ) {
qDebug() << "==== added CSync exclude List: " << excludeList.toUtf8();
csync_add_exclude_list( _csync_ctx, excludeList.toUtf8() );
}
csync_set_auth_callback( _csync_ctx, getauth );
if( csync_init( _csync_ctx ) < 0 ) {
qDebug() << "Could not initialize csync!" << csync_get_error(_csync_ctx) << csync_get_error_string(_csync_ctx);
slotCSyncError(CSyncThread::csyncErrorToString(csync_get_error(_csync_ctx), csync_get_error_string(_csync_ctx)));
csync_destroy(_csync_ctx);
_csync_ctx = 0;
}
setProxy();
}
}
ownCloudFolder::~ownCloudFolder()
{
if( _thread ) {
_thread->quit();
csync_request_abort(_csync_ctx);
_thread->wait();
}
delete _csync;
// Destroy csync here.
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)
{
switch (type) {
case QNetworkProxy::NoProxy:
return "NoProxy";
case QNetworkProxy::DefaultProxy:
return "DefaultProxy";
case QNetworkProxy::Socks5Proxy:
return "Socks5Proxy";
case QNetworkProxy::HttpProxy:
return "HttpProxy";
case QNetworkProxy::HttpCachingProxy:
return "HttpCachingProxy";
case QNetworkProxy::FtpCachingProxy:
return "FtpCachingProxy";
default:
return "NoProxy";
}
}
int ownCloudFolder::getauth(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata
)
{
int re = 0;
QMutex mutex;
QString qPrompt = QString::fromLatin1( prompt ).trimmed();
QString user = CredentialStore::instance()->user();
QString pwd = CredentialStore::instance()->password();
if( qPrompt == QLatin1String("Enter your username:") ) {
// qDebug() << "OOO Username requested!";
QMutexLocker locker( &mutex );
qstrncpy( buf, user.toUtf8().constData(), len );
} else if( qPrompt == QLatin1String("Enter your password:") ) {
QMutexLocker locker( &mutex );
// qDebug() << "OOO Password requested!";
qstrncpy( buf, pwd.toUtf8().constData(), len );
} else {
if( qPrompt.startsWith( QLatin1String("There are problems with the SSL certificate:"))) {
// SSL is requested. If the program came here, the SSL check was done by mirall
// It needs to be checked if the chain is still equal to the one which
// was verified by the user.
QRegExp regexp("fingerprint: ([\\w\\d:]+)");
bool certOk = false;
int pos = 0;
// This is the set of certificates which QNAM accepted, so we should accept
// them as well
QList<QSslCertificate> certs = ownCloudInfo::instance()->certificateChain();
while (!certOk && (pos = regexp.indexIn(qPrompt, 1+pos)) != -1) {
QString neon_fingerprint = regexp.cap(1);
foreach( const QSslCertificate& c, certs ) {
QString verified_shasum = Utility::formatFingerprint(c.digest(QCryptographicHash::Sha1).toHex());
qDebug() << "SSL Fingerprint from neon: " << neon_fingerprint << " compared to verified: " << verified_shasum;
if( verified_shasum == neon_fingerprint ) {
certOk = true;
break;
}
}
}
// certOk = false; DEBUG setting, keep disabled!
if( !certOk ) { // Problem!
qstrcpy( buf, "no" );
re = -1;
} else {
qstrcpy( buf, "yes" ); // Certificate is fine!
}
} else {
qDebug() << "Unknown prompt: <" << prompt << ">";
re = -1;
}
}
return re;
}
bool ownCloudFolder::isBusy() const
{
return ( _thread && _thread->isRunning() );
}
QString ownCloudFolder::secondPath() const
{
QString re(Folder::secondPath());
MirallConfigFile cfg;
QString ocUrl = cfg.ownCloudUrl(QString::null, true);
if (ocUrl.endsWith(QLatin1Char('/')))
ocUrl.chop(1);
// qDebug() << "**** " << ocUrl << " <-> " << re;
if( re.startsWith( ocUrl ) ) {
re.remove( ocUrl );
}
return re;
}
void ownCloudFolder::startSync()
{
startSync( QStringList() );
}
void ownCloudFolder::startSync(const QStringList &pathList)
{
if (!_csync_ctx) {
qDebug() << Q_FUNC_INFO << "_csync_ctx is empty. probably because csync_init has failed.";
// the error should already be set
QMetaObject::invokeMethod(this, "slotCSyncFinished", Qt::QueuedConnection);
return;
}
if (_thread && _thread->isRunning()) {
qCritical() << "* ERROR csync is still running and new sync requested.";
return;
}
if (_thread)
_thread->quit();
delete _csync;
delete _thread;
_errors.clear();
_csyncError = false;
_csyncUnavail = false;
MirallConfigFile cfgFile;
_syncResult.clearErrors();
_syncResult.setStatus( SyncResult::SyncPrepare );
emit syncStateChange();
qDebug() << "*** Start syncing";
_thread = new QThread(this);
_csync = new CSyncThread( _csync_ctx );
_csync->moveToThread(_thread);
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");
connect( _csync, SIGNAL(treeWalkResult(const SyncFileItemVector&)),
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
connect(_csync, SIGNAL(started()), SLOT(slotCSyncStarted()), Qt::QueuedConnection);
connect(_csync, SIGNAL(finished()), SLOT(slotCSyncFinished()), Qt::QueuedConnection);
connect(_csync, SIGNAL(csyncError(QString)), SLOT(slotCSyncError(QString)), 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();
QMetaObject::invokeMethod(_csync, "startSync", Qt::QueuedConnection);
emit syncStarted();
}
void ownCloudFolder::slotCSyncStarted()
{
qDebug() << " * csync thread started";
_syncResult.setStatus(SyncResult::SyncRunning);
emit syncStateChange();
}
void ownCloudFolder::slotCSyncError(const QString& err)
{
_errors.append( err );
_csyncError = true;
}
void ownCloudFolder::slotCsyncUnavailable()
{
_csyncUnavail = true;
}
void ownCloudFolder::slotCSyncFinished()
{
qDebug() << "-> CSync Finished slot with error " << _csyncError;
if (_csyncError) {
_syncResult.setStatus(SyncResult::Error);
qDebug() << " ** error Strings: " << _errors;
_syncResult.setErrorStrings( _errors );
qDebug() << " * owncloud csync thread finished with error";
} else if (_csyncUnavail) {
_syncResult.setStatus(SyncResult::Unavailable);
} else {
_syncResult.setStatus(SyncResult::Success);
}
if( _thread && _thread->isRunning() ) {
_thread->quit();
}
emit syncFinished( _syncResult );
}
void ownCloudFolder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
{
_syncResult.setSyncFileItemVector(items);
}
void ownCloudFolder::slotTerminateSync()
{
qDebug() << "folder " << alias() << " Terminating!";
MirallConfigFile cfg;
QString configDir = cfg.configPath();
qDebug() << "csync's Config Dir: " << configDir;
if( _thread && _csync ) {
csync_request_abort(_csync_ctx);
_thread->quit();
_thread->wait();
_csync->deleteLater();
delete _thread;
_csync = 0;
_thread = 0;
csync_resume(_csync_ctx);
}
if( ! configDir.isEmpty() ) {
QFile file( configDir + QLatin1String("/lock"));
if( file.exists() ) {
qDebug() << "After termination, lock file exists and gets removed.";
file.remove();
}
}
_errors.append( tr("The CSync thread terminated.") );
_csyncError = true;
qDebug() << "-> CSync Terminated!";
slotCSyncFinished();
}
void ownCloudFolder::slotLocalPathChanged( const QString& dir )
{
QDir notifiedDir(dir);
QDir localPath( path() );
if( notifiedDir.absolutePath() == localPath.absolutePath() ) {
if( !localPath.exists() ) {
qDebug() << "XXXXXXX The sync folder root was removed!!";
if( _thread && _thread->isRunning() ) {
qDebug() << "CSync currently running, set wipe flag!!";
} else {
qDebug() << "CSync not running, wipe it now!!";
wipe();
}
qDebug() << "ALARM: The local path was DELETED!";
}
}
}
// This removes the csync File database if the sync folder definition is removed
// permanentely. This is needed to provide a clean startup again in case another
// local folder is synced to the same ownCloud.
// See http://bugs.owncloud.org/thebuggenie/owncloud/issues/oc-788
void ownCloudFolder::wipe()
{
QString stateDbFile = path()+QLatin1String(".csync_journal.db");
QFile file(stateDbFile);
if( file.exists() ) {
if( !file.remove()) {
qDebug() << "WRN: Failed to remove existing csync StateDB " << stateDbFile;
} else {
qDebug() << "wipe: Removed csync StateDB " << stateDbFile;
}
} else {
qDebug() << "WRN: statedb is empty, can not remove.";
}
// Check if the tmp database file also exists
QString ctmpName = path() + QLatin1String(".csync_journal.db.ctmp");
QFile ctmpFile( ctmpName );
if( ctmpFile.exists() ) {
ctmpFile.remove();
}
}
ServerActionNotifier::ServerActionNotifier(QObject *parent)
: QObject(parent)
{
}
void ServerActionNotifier::slotSyncFinished(const SyncResult &result)
{
SyncFileItemVector items = result.syncFileItemVector();
if (items.count() == 0)
return;
int newItems = 0;
int removedItems = 0;
int updatedItems = 0;
SyncFileItem firstItemNew;
SyncFileItem firstItemDeleted;
SyncFileItem firstItemUpdated;
foreach (const SyncFileItem &item, items) {
if (item._dir == SyncFileItem::Down) {
switch (item._instruction) {
case CSYNC_INSTRUCTION_NEW:
newItems++;
if (firstItemNew.isEmpty())
firstItemNew = item;
break;
case CSYNC_INSTRUCTION_REMOVE:
removedItems++;
if (firstItemDeleted.isEmpty())
firstItemDeleted = item;
break;
case CSYNC_INSTRUCTION_UPDATED:
updatedItems++;
if (firstItemUpdated.isEmpty())
firstItemUpdated = item;
break;
default:
// nothing.
break;
}
}
}
if (newItems > 0) {
QString file = QDir::toNativeSeparators(firstItemNew._file);
if (newItems == 1)
emit guiLog(tr("New file available"), tr("'%1' has been synced to this machine.").arg(file));
else
emit guiLog(tr("New files available"), tr("'%1' and %n other file(s) have been synced to this machine.",
"", newItems-1).arg(file));
}
if (removedItems > 0) {
QString file = QDir::toNativeSeparators(firstItemDeleted._file);
if (removedItems == 1)
emit guiLog(tr("File removed"), tr("'%1' has been removed.").arg(file));
else
emit guiLog(tr("Files removed"), tr("'%1' and %n other file(s) have been removed.",
"", removedItems-1).arg(file));
}
if (updatedItems > 0) {
QString file = QDir::toNativeSeparators(firstItemUpdated._file);
if (updatedItems == 1)
emit guiLog(tr("File updated"), tr("'%1' has been updated.").arg(file));
else
emit guiLog(tr("Files updated"), tr("'%1' and %n other file(s) have been updated.",
"", updatedItems-1).arg(file));
}
}
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
+116
Ver Arquivo
@@ -0,0 +1,116 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MIRALL_ownCloudFolder_H
#define MIRALL_ownCloudFolder_H
#include <QMutex>
#include <QThread>
#include <QStringList>
#include "mirall/folder.h"
#include "mirall/csyncthread.h"
class QProcess;
class QTimer;
namespace Mirall {
enum SyncFileStatus_s {
STATUS_NONE,
STATUS_EVAL,
STATUS_REMOVE,
STATUS_RENAME,
STATUS_NEW,
STATUS_CONFLICT,
STATUS_IGNORE,
STATUS_SYNC,
STATUS_STAT_ERROR,
STATUS_ERROR,
STATUS_UPDATED
};
typedef SyncFileStatus_s SyncFileStatus;
class ServerActionNotifier : public QObject
{
Q_OBJECT
public:
ServerActionNotifier(QObject *parent = 0);
public slots:
void slotSyncFinished(const SyncResult &result);
signals:
void guiLog(const QString&, const QString&);
void sendResults();
private:
};
class ownCloudFolder : public Folder
{
Q_OBJECT
public:
ownCloudFolder(const QString &alias,
const QString &path,
const QString &secondPath, QObject *parent = 0L);
virtual ~ownCloudFolder();
QString secondPath() const;
virtual bool isBusy() const;
virtual void startSync(const QStringList &pathList);
virtual void wipe();
/* get status about a singel file. */
SyncFileStatus fileStatus( const QString& );
void setProxy();
public slots:
void startSync();
void slotTerminateSync();
void slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool*);
protected slots:
void slotLocalPathChanged( const QString& );
void slotThreadTreeWalkResult(const SyncFileItemVector& );
private slots:
void slotCSyncStarted();
void slotCSyncError(const QString& );
void slotCsyncUnavailable();
void slotCSyncFinished();
private:
static int getauth(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata
);
const char* proxyTypeToCStr(QNetworkProxy::ProxyType type);
QString _secondPath;
QThread *_thread;
CSyncThread *_csync;
QStringList _errors;
bool _csyncError;
bool _csyncUnavail;
bool _wipeDb;
SyncFileItemVector _items;
CSYNC *_csync_ctx;
};
}
#endif
+221 -262
Ver Arquivo
@@ -15,19 +15,33 @@
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#include "mirall/utility.h"
#include "mirall/logger.h"
#include "creds/abstractcredentials.h"
#include <QtCore>
#include <QtGui>
#include <QAuthenticator>
#if QT46_IMPL
#include <QHttp>
#endif
#define DEFAULT_CONNECTION QLatin1String("default");
static const char WEBDAV_PATH[] = "remote.php/webdav/";
namespace Mirall
{
class oCCookieJar : public QNetworkCookieJar
{
public:
QList<QNetworkCookie> cookiesForUrl ( const QUrl & url ) const {
QList<QNetworkCookie> list;
return list;
}
};
ownCloudInfo *ownCloudInfo::_instance = 0;
ownCloudInfo* ownCloudInfo::instance()
@@ -48,16 +62,13 @@ ownCloudInfo* ownCloudInfo::instance()
ownCloudInfo::ownCloudInfo() :
QObject(0),
_manager(0),
_authAttempts(0),
_lastQuotaUsedBytes(0),
_lastQuotaTotalBytes(0)
_manager(0)
{
_connection = Theme::instance()->appName();
connect(this, SIGNAL(guiLog(QString,QString)),
Logger::instance(), SIGNAL(guiLog(QString,QString)));
// this will set credentials specific qnam
setCustomConfigHandle(QString());
setNetworkAccessManager( new QNetworkAccessManager( this ) );
}
void ownCloudInfo::setNetworkAccessManager( QNetworkAccessManager* qnam )
@@ -72,7 +83,18 @@ void ownCloudInfo::setNetworkAccessManager( QNetworkAccessManager* qnam )
connect( _manager, SIGNAL( sslErrors(QNetworkReply*, QList<QSslError>)),
this, SIGNAL(sslFailed(QNetworkReply*, QList<QSslError>)) );
// The authenticationRequired signal is not handled because the creds are set
// in the request header.
#if 0
connect( _manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
this, SLOT(slotAuthentication(QNetworkReply*,QAuthenticator*)));
#endif
// no cookie jar so far.
_manager->setCookieJar(new oCCookieJar);
_certsUntrusted = false;
}
ownCloudInfo::~ownCloudInfo()
@@ -84,8 +106,6 @@ void ownCloudInfo::setCustomConfigHandle( const QString& handle )
_configHandle = handle;
_authAttempts = 0; // allow a couple of tries again.
resetSSLUntrust();
MirallConfigFile cfg(_configHandle);
setNetworkAccessManager (cfg.getCredentials()->getQNAM());
}
bool ownCloudInfo::isConfigured()
@@ -96,32 +116,28 @@ bool ownCloudInfo::isConfigured()
QNetworkReply *ownCloudInfo::checkInstallation()
{
_redirectCount = 0;
MirallConfigFile cfgFile( _configHandle );
QUrl url ( cfgFile.ownCloudUrl( _connection ) + QLatin1String("status.php") );
/* No authentication required for this. */
return getRequest(url);
return getRequest( QLatin1String("status.php"), false );
}
QNetworkReply* ownCloudInfo::getWebDAVPath( const QString& path )
{
_redirectCount = 0;
QUrl url ( webdavUrl( _connection ) + path );
QNetworkReply *reply = getRequest(url);
_directories[reply] = path;
return reply;
return getRequest( path, true );
}
QNetworkReply* ownCloudInfo::getRequest( const QUrl& url )
QNetworkReply* ownCloudInfo::getRequest( const QString& path, bool webdav )
{
qDebug() << "Get Request to " << url;
qDebug() << "Get Request to " << path;
MirallConfigFile cfgFile( _configHandle );
QString url = cfgFile.ownCloudUrl( _connection, webdav ) + path;
QNetworkRequest request;
request.setUrl( url );
request.setUrl( QUrl( url ) );
setupHeaders( request, 0 );
QNetworkReply *reply = _manager->get( request );
connect( reply, SIGNAL(finished()), SLOT(slotReplyFinished()));
_directories[reply] = path;
if( !_configHandle.isEmpty() ) {
qDebug() << "Setting config handle " << _configHandle;
@@ -133,13 +149,87 @@ QNetworkReply* ownCloudInfo::getRequest( const QUrl& url )
return reply;
}
#if QT46_IMPL
QNetworkReply* ownCloudInfo::mkdirRequest( const QString& dir )
{
qDebug() << "OCInfo Making dir " << dir;
MirallConfigFile cfgFile( _configHandle );
QUrl url = QUrl( cfgFile.ownCloudUrl( _connection, true ) + dir );
QHttp::ConnectionMode conMode = QHttp::ConnectionModeHttp;
if (url.scheme() == "https")
conMode = QHttp::ConnectionModeHttps;
QHttp* qhttp = new QHttp(QString(url.encodedHost()), conMode, 0, this);
connect(qhttp, SIGNAL(requestStarted(int)), this,SLOT(qhttpRequestStarted(int)));
connect(qhttp, SIGNAL(requestFinished(int, bool)), this,SLOT(qhttpRequestFinished(int,bool)));
connect(qhttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(qhttpResponseHeaderReceived(QHttpResponseHeader)));
//connect(qhttp, SIGNAL(authenticationRequired(QString,quint16,QAuthenticator*)), this, SLOT(qhttpAuthenticationRequired(QString,quint16,QAuthenticator*)));
QHttpRequestHeader header("MKCOL", QString(url.encodedPath()), 1,1); /* header */
header.setValue("Host", QString(url.encodedHost()));
header.setValue("User-Agent", Utility::userAgentString());
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("Connection", "keep-alive");
header.setContentType("application/x-www-form-urlencoded"); //important
header.setContentLength(0);
QString con = _configHandle;
if( con.isEmpty() ) con = DEFAULT_CONNECTION;
if( _credentials.contains(con)) {
oCICredentials creds = _credentials.value(con);
QString concatenated = creds.user + QLatin1Char(':') + creds.passwd;
const QString b(QLatin1String("Basic "));
QByteArray data = b.toLocal8Bit() + concatenated.toLocal8Bit().toBase64();
header.setValue("Authorization", data);
qhttp->setUser( creds.user, creds.passwd );
}
int david = qhttp->request(header,0,0);
//////////////// connect(davinfo, SIGNAL(dataSendProgress(int,int)), this, SLOT(SendStatus(int, int)));
/////////////////connect(davinfo, SIGNAL(done(bool)), this,SLOT(DavWake(bool)));
//connect(_http, SIGNAL(requestFinished(int, bool)), this,SLOT(qhttpRequestFinished(int,bool)));
///////////connect(davinfo, SIGNAL(responseHeaderReceived(constQHttpResponseHeader &)), this, SLOT(RegisterBackHeader(constQHttpResponseHeader &)));
return NULL;
}
void ownCloudInfo::qhttpResponseHeaderReceived(const QHttpResponseHeader& header)
{
qDebug() << "Resp:" << header.toString();
if (header.statusCode() == 201)
emit webdavColCreated( QNetworkReply::NoError );
else
qDebug() << "http request failed" << header.toString();
}
void ownCloudInfo::qhttpRequestStarted(int id)
{
qDebug() << "QHttp based request started " << id;
}
void ownCloudInfo::qhttpRequestFinished(int id, bool success )
{
qDebug() << "HIT!";
QHttp* qhttp = qobject_cast<QHttp*>(sender());
if( success ) {
qDebug() << "QHttp based request successful";
} else {
qDebug() << "QHttp based request failed: " << qhttp->errorString();
}
}
#else
QNetworkReply* ownCloudInfo::mkdirRequest( const QString& dir )
{
qDebug() << "OCInfo Making dir " << dir;
_authAttempts = 0;
MirallConfigFile cfgFile( _configHandle );
QNetworkRequest req;
req.setUrl( QUrl( webdavUrl(_connection) + dir ) );
QNetworkReply *reply = davRequest("MKCOL", req, 0);
req.setUrl( QUrl( cfgFile.ownCloudUrl( _connection, true ) + dir ) );
QNetworkReply *reply = davRequest(QLatin1String("MKCOL"), req, 0);
// remember the confighandle used for this request
if( ! _configHandle.isEmpty() )
@@ -156,62 +246,6 @@ QNetworkReply* ownCloudInfo::mkdirRequest( const QString& dir )
return reply;
}
QNetworkReply* ownCloudInfo::getQuotaRequest( const QString& dir )
{
QNetworkRequest req;
req.setUrl( QUrl( webdavUrl(_connection) + dir ) );
req.setRawHeader("Depth", "0");
QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"
" <d:prop>\n"
" <d:quota-available-bytes/>\n"
" <d:quota-used-bytes/>\n"
" <d:getetag/>"
" </d:prop>\n"
"</d:propfind>\n");
QBuffer *buf = new QBuffer;
buf->setData(xml);
buf->open(QIODevice::ReadOnly);
QNetworkReply *reply = davRequest("PROPFIND", req, buf);
buf->setParent(reply);
if( reply->error() != QNetworkReply::NoError ) {
qDebug() << "getting quota: request network error: " << reply->errorString();
}
connect( reply, SIGNAL( finished()), SLOT(slotGetQuotaFinished()) );
connect( reply, SIGNAL( error(QNetworkReply::NetworkError)),
this, SLOT( slotError(QNetworkReply::NetworkError)));
return reply;
}
QNetworkReply* ownCloudInfo::getDirectoryListing( const QString& dir )
{
QNetworkRequest req;
req.setUrl( QUrl( webdavUrl(_connection) + dir ) );
req.setRawHeader("Depth", "1");
QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"
" <d:prop>\n"
" <d:resourcetype/>\n"
" </d:prop>\n"
"</d:propfind>\n");
QBuffer *buf = new QBuffer;
buf->setData(xml);
buf->open(QIODevice::ReadOnly);
QNetworkReply *reply = davRequest("PROPFIND", req, buf);
buf->setParent(reply);
if( reply->error() != QNetworkReply::NoError ) {
qDebug() << "getting quota: request network error: " << reply->errorString();
}
connect( reply, SIGNAL( finished()), SLOT(slotGetDirectoryListingFinished()) );
connect( reply, SIGNAL( error(QNetworkReply::NetworkError)),
this, SLOT( slotError(QNetworkReply::NetworkError)));
return reply;
}
void ownCloudInfo::slotMkdirFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
@@ -229,90 +263,47 @@ void ownCloudInfo::slotMkdirFinished()
reply->deleteLater();
}
#endif
void ownCloudInfo::slotGetQuotaFinished()
// FIXME: remove this later, once the new connection dialog has settled.
#if 0
void ownCloudInfo::slotAuthentication( QNetworkReply *reply, QAuthenticator *auth )
{
bool ok = false;
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if( !(auth && reply) ) return;
QString configHandle;
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 207) {
// Parse DAV response
QXmlStreamReader reader(reply);
reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));
// an empty config handle is ok for the default config.
if( _configHandleMap.contains(reply) ) {
configHandle = _configHandleMap[reply];
qDebug() << "Auth: Have a custom config handle: " << configHandle;
}
qint64 quotaUsedBytes = 0;
qint64 quotaAvailableBytes = 0;
QString etag;
qDebug() << "Auth request to me and I am " << this;
_authAttempts++;
MirallConfigFile cfgFile( configHandle );
qDebug() << "Authenticating request for " << reply->url();
if( reply->url().toString().startsWith( cfgFile.ownCloudUrl( _connection, true )) ) {
while (!reader.atEnd()) {
QXmlStreamReader::TokenType type = reader.readNext();
if (type == QXmlStreamReader::StartElement &&
reader.namespaceUri() == QLatin1String("DAV:")) {
QString name = reader.name().toString();
if (name == QLatin1String("quota-used-bytes")) {
quotaUsedBytes = reader.readElementText().toLongLong(&ok);
if (!ok) quotaUsedBytes = 0;
} else if (name == QLatin1String("quota-available-bytes")) {
quotaAvailableBytes = reader.readElementText().toLongLong(&ok);
if (!ok) quotaAvailableBytes = 0;
} else if (name == QLatin1String("getetag")) {
etag = reader.readElementText();
}
}
QString con = configHandle;
if( con.isEmpty() ) con = DEFAULT_CONNECTION;
if( _credentials.contains(con)) {
oCICredentials creds = _credentials.value(con);
auth->setUser( creds.user );
auth->setPassword( creds.passwd );
} else {
qDebug() << "Unable to get Credentials, not set!";
reply->close();
}
qint64 total = quotaUsedBytes + quotaAvailableBytes;
_lastQuotaTotalBytes = total;
_lastQuotaUsedBytes = quotaUsedBytes;
emit quotaUpdated(total, quotaUsedBytes);
_lastEtag = etag;
} else {
_lastQuotaTotalBytes = 0;
_lastQuotaUsedBytes = 0;
qDebug() << "WRN: attempt to authenticate to different url - attempt " <<_authAttempts;
}
reply->deleteLater();
}
void ownCloudInfo::slotGetDirectoryListingFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 207) {
// Parse DAV response
QXmlStreamReader reader(reply);
reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));
QStringList folders;
QString currentItem;
while (!reader.atEnd()) {
QXmlStreamReader::TokenType type = reader.readNext();
if (type == QXmlStreamReader::StartElement &&
reader.namespaceUri() == QLatin1String("DAV:")) {
QString name = reader.name().toString();
if (name == QLatin1String("href")) {
currentItem = reader.readElementText();
} else if (name == QLatin1String("collection") &&
!currentItem.isEmpty()) {
folders.append(currentItem);
currentItem.clear();
}
}
}
emit directoryListingUpdated(folders);
if( _authAttempts > 1) {
qDebug() << "Too many attempts to authenticate. Stop request.";
reply->close();
}
reply->deleteLater();
}
QList<QNetworkCookie> ownCloudInfo::getLastAuthCookies()
{
QUrl url = QUrl( webdavUrl(_connection));
QList<QNetworkCookie> cookies = _manager->cookieJar()->cookiesForUrl(url);
return cookies;
}
#endif
QString ownCloudInfo::configHandle(QNetworkReply *reply)
{
@@ -329,6 +320,20 @@ QList<QSslCertificate> ownCloudInfo::certificateChain() const
return _certificateChain;
}
QUrl ownCloudInfo::redirectUrl(const QUrl& possibleRedirectUrl,
const QUrl& oldRedirectUrl) const {
QUrl redirectUrl;
/*
* Check if the URL is empty and
* that we aren't being fooled into a infinite redirect loop.
*/
if(!possibleRedirectUrl.isEmpty() &&
possibleRedirectUrl != oldRedirectUrl) {
redirectUrl = possibleRedirectUrl;
}
return redirectUrl;
}
//
// There have been problems with the finish-signal coming from the networkmanager.
// To avoid that, the reply-signals were connected and the data is taken from the
@@ -349,17 +354,12 @@ void ownCloudInfo::slotReplyFinished()
}
// Detect redirect url
QUrl possibleRedirUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
QVariant possibleRedirUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
/* We'll deduct if the redirection is valid in the redirectUrl function */
_urlRedirectedTo = redirectUrl( possibleRedirUrl.toUrl(),
_urlRedirectedTo );
if (!possibleRedirUrl.isEmpty() && _redirectCount++ > 10) {
// Are we in a redirect loop
qDebug() << "Redirect loop while redirecting to" << possibleRedirUrl;
possibleRedirUrl.clear();
}
if(!possibleRedirUrl.isEmpty()) {
if(!_urlRedirectedTo.isEmpty()) {
QString configHandle;
qDebug() << "Redirected to " << possibleRedirUrl;
@@ -372,28 +372,24 @@ void ownCloudInfo::slotReplyFinished()
}
QString path = _directories[reply];
if (path.isEmpty()) {
path = QLatin1String("status.php");
} else {
path.prepend( QLatin1String(WEBDAV_PATH) );
}
qDebug() << "This path was redirected: " << path;
QString newUrl = possibleRedirUrl.toString();
if( !path.isEmpty() && newUrl.endsWith( path )) {
MirallConfigFile cfgFile( configHandle );
QString newUrl = _urlRedirectedTo.toString();
if( newUrl.endsWith( path )) {
// cut off the trailing path
newUrl.chop( path.length() );
_urlRedirectedTo = newUrl;
qDebug() << "Updated url to" << newUrl;
getRequest( possibleRedirUrl );
cfgFile.setOwnCloudUrl( _connection, newUrl );
qDebug() << "Update the config file url to " << newUrl;
getRequest( path, false ); // FIXME: Redirect for webdav!
reply->deleteLater();
return;
} else {
qDebug() << "WRN: Path is not part of the redirect URL. NO redirect.";
}
reply->deleteLater();
_directories.remove(reply);
_configHandleMap.remove(reply);
return;
}
_urlRedirectedTo.clear();
// TODO: check if this is always the correct encoding
const QString version = QString::fromUtf8( reply->readAll() );
@@ -443,8 +439,8 @@ void ownCloudInfo::slotReplyFinished()
// get version out
edition = val;
} else if(key == QLatin1String("installed")) {
// Silently ignoring "installed = true" information
} else {
// Silently ignoring "installed = true" information
} else {
qDebug() << "Unknown info from ownCloud status.php: "<< key << "=" << val;
}
}
@@ -459,13 +455,15 @@ void ownCloudInfo::slotReplyFinished()
QString dir(QLatin1String("unknown"));
if( _directories.contains(reply) ) {
dir = _directories[reply];
_directories.remove(reply);
}
emit ownCloudDirExists( dir, reply );
}
if( _configHandleMap.contains(reply)) {
_configHandleMap.remove(reply);
}
reply->deleteLater();
_directories.remove(reply);
_configHandleMap.remove(reply);
}
void ownCloudInfo::resetSSLUntrust()
@@ -520,11 +518,43 @@ void ownCloudInfo::slotError( QNetworkReply::NetworkError err)
}
}
void ownCloudInfo::setCredentials( const QString& user, const QString& passwd,
const QString& configHandle )
{
QString con( configHandle );
if( configHandle.isEmpty() )
con = DEFAULT_CONNECTION;
if( _credentials.contains(con) ) {
qDebug() << "Overwriting credentials for connection " << con;
}
oCICredentials creds;
creds.user = user;
creds.passwd = passwd;
creds.connection = con;
_credentials[con] = creds;
}
// ============================================================================
void ownCloudInfo::setupHeaders( QNetworkRequest & req, quint64 size )
{
QUrl url( req.url() );
MirallConfigFile cfgFile(_configHandle );
QUrl url( cfgFile.ownCloudUrl( QString::null, false ) );
qDebug() << "Setting up host header: " << url.host();
req.setRawHeader( QByteArray("Host"), url.host().toUtf8() );
req.setRawHeader( QByteArray("User-Agent"), Utility::userAgentString());
QString con = _configHandle;
if( con.isEmpty() ) con = DEFAULT_CONNECTION;
if( _credentials.contains(con)) {
oCICredentials creds = _credentials.value(con);
QString concatenated = creds.user + QLatin1Char(':') + creds.passwd;
const QString b(QLatin1String("Basic "));
QByteArray data = b.toUtf8() + concatenated.toUtf8().toBase64();
req.setRawHeader( QByteArray("Authorization"), data );
}
if (size) {
req.setHeader( QNetworkRequest::ContentLengthHeader, size);
@@ -532,89 +562,18 @@ void ownCloudInfo::setupHeaders( QNetworkRequest & req, quint64 size )
}
}
QNetworkReply* ownCloudInfo::davRequest(const QByteArray& reqVerb, QNetworkRequest& req, QIODevice *data)
#if QT46_IMPL
#else
QNetworkReply* ownCloudInfo::davRequest(const QString& reqVerb, QNetworkRequest& req, QByteArray *data)
{
setupHeaders(req, quint64(data ? data->size() : 0));
return _manager->sendCustomRequest(req, reqVerb, data );
}
QString ownCloudInfo::webdavUrl(const QString &connection)
{
QString url;
if (!_urlRedirectedTo.isEmpty()) {
url = _urlRedirectedTo.toString();
if( data ) {
QBuffer iobuf( data );
return _manager->sendCustomRequest(req, reqVerb.toUtf8(), &iobuf );
} else {
MirallConfigFile cfgFile(_configHandle );
url = cfgFile.ownCloudUrl( connection );
return _manager->sendCustomRequest(req, reqVerb.toUtf8(), 0 );
}
url.append( QLatin1String( WEBDAV_PATH ) );
if (!url.endsWith('/')) url.append('/');
return url;
}
#endif
}
RequestEtagJob::RequestEtagJob(const QString& dir, QObject* parent)
: QObject(parent)
{
QNetworkRequest req;
req.setUrl( QUrl( ownCloudInfo::instance()->webdavUrl(ownCloudInfo::instance()->_connection) + dir ) );
if (dir.isEmpty() || dir == "/") {
/* For the root directory, we need to query the etags of all the sub directories
* because, at the time I am writing this comment (Owncloud 5.0.9), the etag of the
* root directory is not updated when the sub directories changes */
req.setRawHeader("Depth", "1");
} else {
req.setRawHeader("Depth", "0");
}
QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"
" <d:prop>\n"
" <d:getetag/>"
" </d:prop>\n"
"</d:propfind>\n");
QBuffer *buf = new QBuffer;
buf->setData(xml);
buf->open(QIODevice::ReadOnly);
_reply = ownCloudInfo::instance()->davRequest("PROPFIND", req, buf);
buf->setParent(_reply);
if( _reply->error() != QNetworkReply::NoError ) {
qDebug() << "getting etag: request network error: " << _reply->errorString();
}
connect( _reply, SIGNAL( finished()), SLOT(slotFinished()) );
connect( _reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError()));
}
void RequestEtagJob::slotFinished()
{
if (_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 207) {
// Parse DAV response
QXmlStreamReader reader(_reply);
reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));
QString etag;
while (!reader.atEnd()) {
QXmlStreamReader::TokenType type = reader.readNext();
if (type == QXmlStreamReader::StartElement &&
reader.namespaceUri() == QLatin1String("DAV:")) {
QString name = reader.name().toString();
if (name == QLatin1String("getetag")) {
etag += reader.readElementText();
}
}
}
emit etagRetreived(etag);
}
_reply->deleteLater();
deleteLater();
}
void RequestEtagJob::slotError()
{
qDebug() << "RequestEtagJob Error: " << _reply->errorString();
_reply->deleteLater();
deleteLater();
}
} // ns Mirall
+37 -54
Ver Arquivo
@@ -18,9 +18,21 @@
#include <QObject>
#include <QtNetwork>
#if QT_VERSION >= 0x040700
#define QT46_IMPL 0
#else
#define QT46_IMPL 1
#endif
namespace Mirall
{
typedef struct {
QString user;
QString passwd;
QString connection;
} oCICredentials;
class ownCloudInfo : public QObject
{
Q_OBJECT
@@ -35,6 +47,12 @@ public:
*/
QNetworkReply* checkInstallation();
/**
* a general GET request to the ownCloud. If the second bool parameter is
* true, the WebDAV server is queried.
*/
QNetworkReply* getRequest( const QString&, bool );
/**
* convenience: GET request to the WebDAV server.
*/
@@ -69,16 +87,6 @@ public:
*/
QNetworkReply* mkdirRequest( const QString& );
/**
* Retrieve quota for a path. Provide a relative path.
*/
QNetworkReply* getQuotaRequest( const QString& );
/**
* provide collections in a directory via owncloud. Provide a relative path.
*/
QNetworkReply* getDirectoryListing( const QString& dir );
/**
* Use a custom ownCloud configuration file identified by handle
*/
@@ -96,17 +104,11 @@ public:
QList<QSslCertificate> certificateChain() const;
/**
* returns the owncloud webdav url.
* It may be different from the one in the config if there was a HTTP redirection
* The returned URL is guaranteed to end in a forward slash ('/')
* Store credentials for a given connection. Empty connection parameter
* means "default connection".
*/
QString webdavUrl(const QString& connection = QString());
qint64 lastQuotaUsedBytes() const { return _lastQuotaUsedBytes; }
qint64 lastQuotaTotalBytes() const { return _lastQuotaTotalBytes; }
QString lastEtag() const { return _lastEtag; }
QList<QNetworkCookie> getLastAuthCookies();
void setCredentials( const QString&, const QString&,
const QString& configHandle = QString::null );
signals:
// result signal with url- and version string.
@@ -117,29 +119,34 @@ signals:
void webdavColCreated( QNetworkReply::NetworkError );
void sslFailed( QNetworkReply *reply, QList<QSslError> errors );
void guiLog( const QString& title, const QString& content );
void quotaUpdated( qint64 total, qint64 quotaUsedBytes );
void directoryListingUpdated(const QStringList &directories);
public slots:
protected slots:
void slotReplyFinished( );
void slotError( QNetworkReply::NetworkError );
// void slotAuthentication( QNetworkReply*, QAuthenticator *);
#if QT46_IMPL
void qhttpRequestFinished(int id, bool success );
void qhttpRequestStarted(int id);
void qhttpResponseHeaderReceived(const QHttpResponseHeader& header);
// void qhttpAuthenticationRequired(const QString& hostname, quint16 port ,QAuthenticator* authenticator);
#else
void slotMkdirFinished();
void slotGetQuotaFinished();
void slotGetDirectoryListingFinished();
#endif
private:
explicit ownCloudInfo();
/**
* a general GET request to the ownCloud WebDAV.
*/
QNetworkReply* getRequest( const QUrl &url);
QNetworkReply* davRequest(const QByteArray&, QNetworkRequest&, QIODevice* );
QUrl redirectUrl(const QUrl&, const QUrl& ) const;
~ownCloudInfo();
void setupHeaders(QNetworkRequest &req, quint64 size );
#if QT46_IMPL
#else
QNetworkReply* davRequest(const QString&, QNetworkRequest&, QByteArray* );
#endif
static ownCloudInfo *_instance;
@@ -152,34 +159,10 @@ private:
QList<QSslCertificate> _certificateChain;
bool _certsUntrusted;
int _authAttempts;
QMap<QString, oCICredentials> _credentials;
QMutex _certChainMutex;
int _redirectCount;
qint64 _lastQuotaUsedBytes;
qint64 _lastQuotaTotalBytes;
QString _lastEtag;
friend class RequestEtagJob;
};
class RequestEtagJob : public QObject {
Q_OBJECT
QNetworkReply *_reply;
public:
explicit RequestEtagJob(const QString &dir , QObject* parent = 0);
private slots:
void slotFinished();
void slotError();
signals:
void etagRetreived(const QString &etag);
};
} // ns Mirall
#endif // OWNCLOUDINFO_H
+195 -297
Ver Arquivo
@@ -1,6 +1,5 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,44 +12,39 @@
* for more details.
*/
#include <QAbstractButton>
#include <QtCore>
#include <QProcess>
#include <QMessageBox>
#include <QDesktopServices>
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudwizard.h"
#include "mirall/owncloudsetupwizard.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/owncloudinfo.h"
#include "mirall/folderman.h"
#include "mirall/credentialstore.h"
#include "mirall/utility.h"
#include "mirall/mirallaccessmanager.h"
#include "creds/abstractcredentials.h"
#include "creds/dummycredentials.h"
namespace Mirall {
OwncloudSetupWizard::OwncloudSetupWizard(QObject* parent) :
class Theme;
OwncloudSetupWizard::OwncloudSetupWizard( FolderMan *folderMan, Theme *theme, QObject *parent ) :
QObject( parent ),
_ocWizard(new OwncloudWizard),
_mkdirRequestReply(),
_checkInstallationRequest(),
_checkRemoteFolderRequest(),
_configHandle(),
_remoteFolder()
_mkdirRequestReply(0),
_checkInstallationRequest(0),
_folderMan(folderMan)
{
connect( _ocWizard, SIGNAL(determineAuthType(const QString&)),
this, SLOT(slotDetermineAuthType(const QString&)));
_ocWizard = new OwncloudWizard();
connect( _ocWizard, SIGNAL(connectToOCUrl( const QString& ) ),
this, SLOT(slotConnectToOCUrl( const QString& )));
connect( _ocWizard, SIGNAL(createLocalAndRemoteFolders(QString, QString)),
this, SLOT(slotCreateLocalAndRemoteFolders(QString, QString)));
connect( _ocWizard, SIGNAL(finished(int)),this,SLOT(slotAssistantFinished(int)));
connect( _ocWizard, SIGNAL(clearPendingRequests()),
this, SLOT(slotClearPendingRequests()));
_ocWizard->setWindowTitle( tr("%1 Connection Wizard").arg( theme->appNameGUI() ) );
}
OwncloudSetupWizard::~OwncloudSetupWizard()
@@ -58,12 +52,8 @@ OwncloudSetupWizard::~OwncloudSetupWizard()
_ocWizard->deleteLater();
}
void OwncloudSetupWizard::runWizard(QObject* obj, const char* amember, QWidget *parent)
{
OwncloudSetupWizard *wiz = new OwncloudSetupWizard(parent);
connect( wiz, SIGNAL(ownCloudWizardDone(int)), obj, amember);
FolderMan::instance()->setSyncEnabled(false);
wiz->startWizard();
OwncloudWizard *OwncloudSetupWizard::wizard() {
return _ocWizard;
}
void OwncloudSetupWizard::startWizard()
@@ -72,10 +62,14 @@ void OwncloudSetupWizard::startWizard()
MirallConfigFile cfgFile;
// Fill the entry fields with existing values.
QString url = cfgFile.ownCloudUrl();
//QString user = cfgFile.ownCloudUser();
bool configExists = !( url.isEmpty()/* || user.isEmpty()*/ );
QString user = cfgFile.ownCloudUser();
bool configExists = !( url.isEmpty() || user.isEmpty() );
_ocWizard->setConfigExists( configExists );
if( !user.isEmpty() ) {
_ocWizard->setOCUser( user );
}
if( !url.isEmpty() ) {
_ocWizard->setOCUrl( url );
}
@@ -86,145 +80,103 @@ void OwncloudSetupWizard::startWizard()
QString localFolder = Theme::instance()->defaultClientFolder();
// if its a relative path, prepend with users home dir, otherwise use as absolute path
if( !QDir(localFolder).isAbsolute() ) {
localFolder = QDir::homePath() + QDir::separator() + localFolder;
if( !localFolder.startsWith(QLatin1Char('/')) ) {
localFolder = QDir::homePath() + QDir::separator() + Theme::instance()->defaultClientFolder();
}
_ocWizard->setProperty("localFolder", localFolder);
_ocWizard->setRemoteFolder(_remoteFolder);
_ocWizard->setStartId(WizardCommon::Page_ServerSetup);
_ocWizard->setStartId(OwncloudWizard::Page_oCSetup);
_ocWizard->restart();
// settings re-initialized in initPage must be set here after restart
_ocWizard->setMultipleFoldersExist(FolderMan::instance()->map().count() > 1);
_ocWizard->setMultipleFoldersExist(_folderMan->map().count() > 1);
_ocWizard->open();
_ocWizard->show();
_ocWizard->raise();
}
void OwncloudSetupWizard::slotDetermineAuthType(const QString& serverUrl)
// Method executed when the user ends the wizard, either with 'accept' or 'reject'.
// accept the custom config to be the main one if Accepted.
void OwncloudSetupWizard::slotAssistantFinished( int result )
{
QString url(serverUrl);
qDebug() << "Connect to url: " << url;
_ocWizard->setField(QLatin1String("OCUrl"), url );
_ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2 to determine authentication type...")
.arg( Theme::instance()->appNameGUI() ).arg(url) );
// write a temporary config.
QDateTime now = QDateTime::currentDateTime();
MirallConfigFile cfg( _configHandle );
// remove a possibly existing custom config.
if( ! _configHandle.isEmpty() ) {
// remove the old config file.
MirallConfigFile oldConfig( _configHandle );
oldConfig.cleanupCustomConfig();
}
_configHandle = now.toString(QLatin1String("MMddyyhhmmss"));
if( result == QDialog::Rejected ) {
// the old config remains valid. Remove the temporary one.
cfg.cleanupCustomConfig();
qDebug() << "Rejected the new config, use the old!";
} else if( result == QDialog::Accepted ) {
qDebug() << "Config Changes were accepted!";
MirallConfigFile cfgFile( _configHandle, true );
if( url.isEmpty() ) return;
if( !( url.startsWith(QLatin1String("https://")) || url.startsWith(QLatin1String("http://"))) ) {
qDebug() << "url does not start with a valid protocol, assuming https.";
url.prepend(QLatin1String("https://"));
// FIXME: give a hint about the auto completion
_ocWizard->setOCUrl(url);
}
cfgFile.writeOwncloudConfig( Theme::instance()->appName(),
url,
new DummyCredentials);
// go through all folders and remove the journals if the server changed.
MirallConfigFile prevCfg;
QUrl prevUrl( prevCfg.ownCloudUrl() );
QUrl newUrl( cfg.ownCloudUrl() );
ownCloudInfo* info = ownCloudInfo::instance();
info->setCustomConfigHandle( _configHandle );
if( info->isConfigured() ) {
// reset the SSL Untrust flag to let the SSL dialog appear again.
info->resetSSLUntrust();
connect(info, SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
SLOT(slotOwnCloudFoundAuth(QString,QString,QString,QString)));
connect(info, SIGNAL(noOwncloudFound(QNetworkReply*)),
SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*)));
_checkInstallationRequest = info->checkInstallation();
} else {
qDebug() << " ownCloud seems not to be configured, can not start test connect.";
}
}
bool urlHasChanged = (prevUrl.host() != newUrl.host() || prevUrl.path() != newUrl.path());
void OwncloudSetupWizard::slotOwnCloudFoundAuth( const QString& url, const QString& infoString, const QString& version, const QString& )
{
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFoundAuth(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*)));
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\">Successfully connected to %1: %2 version %3 (%4)</font><br/><br/>")
.arg( url ).arg(Theme::instance()->appNameGUI()).arg(infoString).arg(version));
MirallAccessManager* nm = new MirallAccessManager(this);
// TODO: We should get this path from owncloud info.
QNetworkReply* reply = nm->get (QNetworkRequest (url + "/remote.php/webdav/"));
connect (reply, SIGNAL(finished()),
this, SLOT(slotAuthCheckReplyFinished()));
nm->setProperty ("mirallRedirs", QVariant (0));
}
void OwncloudSetupWizard::slotAuthCheckReplyFinished()
{
QNetworkReply* reply = qobject_cast< QNetworkReply* > (sender ());
QUrl redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
QNetworkAccessManager* nm = reply->manager ();
const int redirCount = nm->property ("mirallRedirs").toInt();
if (redirCount > 10) {
redirection.clear ();
}
disconnect (reply, SIGNAL(finished()),
this, SLOT(slotAuthCheckReplyFinished()));
if ((reply->error () == QNetworkReply::AuthenticationRequiredError) || redirection.isEmpty()) {
reply->deleteLater();
nm->deleteLater();
_ocWizard->setAuthType (WizardCommon::HttpCreds);
} else if (redirection.toString().endsWith ("/remote.php/webdav/")) {
QNetworkReply* newReply = nm->get (QNetworkRequest(redirection));
connect (newReply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotAuthCheckReplyError(QNetworkReply::NetworkError)));
connect (newReply, SIGNAL(finished()),
this, SLOT(slotAuthCheckReplyFinished(QNetworkReply::NetworkError)));
reply->deleteLater();
nm->setProperty ("mirallRedirs", QVariant(redirCount + 1));
} else {
QRegExp shibbolethyWords ("SAML|wayf");
shibbolethyWords.setCaseSensitivity (Qt::CaseInsensitive);
if (redirection.toString ().contains (shibbolethyWords)) {
_ocWizard->setAuthType(WizardCommon::Shibboleth);
} else {
// TODO: Send an error.
// eh?
_ocWizard->setAuthType (WizardCommon::HttpCreds);
// 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.";
}
const QString localFolder = _ocWizard->localFolder();
bool acceptCfg = true;
if( urlHasChanged ) {
_folderMan->unloadAllFolders();
bool startFromScratch = _ocWizard->field( "OCSyncFromScratch" ).toBool();
if( startFromScratch ) {
// first try to rename (backup) the current local dir.
bool renameOk = false;
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.";
}
}
reply->deleteLater();
nm->deleteLater();
}
}
void OwncloudSetupWizard::slotNoOwnCloudFoundAuth( QNetworkReply *err )
{
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
// clear the custom config handle
_configHandle.clear();
ownCloudInfo::instance()->setCustomConfigHandle( QString::null );
_ocWizard->displayError(tr("Failed to connect to %1:<br/>%2").
arg(Theme::instance()->appNameGUI()).arg(err->errorString()));
// remove the config file again
MirallConfigFile cfgFile( _configHandle );
cfgFile.cleanupCustomConfig();
// notify others.
emit ownCloudWizardDone( result );
}
void OwncloudSetupWizard::slotConnectToOCUrl( const QString& url )
@@ -236,6 +188,23 @@ void OwncloudSetupWizard::slotConnectToOCUrl( const QString& url )
testOwnCloudConnect();
}
void OwncloudSetupWizard::slotClearPendingRequests()
{
qDebug() << "Pending request: " << _mkdirRequestReply;
if( _mkdirRequestReply && _mkdirRequestReply->isRunning() ) {
qDebug() << "ABORTing pending mkdir request.";
_mkdirRequestReply->abort();
}
if( _checkInstallationRequest && _checkInstallationRequest->isRunning() ) {
qDebug() << "ABORTing pending check installation request.";
_checkInstallationRequest->abort();
}
if( _checkRemoteFolderRequest && _checkRemoteFolderRequest->isRunning() ) {
qDebug() << "ABORTing pending remote folder check request.";
_checkRemoteFolderRequest->abort();
}
}
void OwncloudSetupWizard::testOwnCloudConnect()
{
// write a temporary config.
@@ -250,7 +219,7 @@ void OwncloudSetupWizard::testOwnCloudConnect()
_configHandle = now.toString(QLatin1String("MMddyyhhmmss"));
MirallConfigFile cfgFile( _configHandle, true );
MirallConfigFile cfgFile( _configHandle );
QString url = _ocWizard->field(QLatin1String("OCUrl")).toString();
if( url.isEmpty() ) return;
if( !( url.startsWith(QLatin1String("https://")) || url.startsWith(QLatin1String("http://"))) ) {
@@ -261,50 +230,75 @@ void OwncloudSetupWizard::testOwnCloudConnect()
}
cfgFile.writeOwncloudConfig( Theme::instance()->appName(),
url,
_ocWizard->getCredentials());
_ocWizard->field(QLatin1String("OCUser")).toString(),
_ocWizard->field(QLatin1String("OCPasswd")).toString() );
ownCloudInfo* info(ownCloudInfo::instance());
info->setCustomConfigHandle( _configHandle );
// If there is already a config, take its proxy config.
if( info->isConfigured() ) {
if( ownCloudInfo::instance()->isConfigured() ) {
MirallConfigFile prevCfg;
cfgFile.setProxyType( prevCfg.proxyType(), prevCfg.proxyHostName(), prevCfg.proxyPort(),
prevCfg.proxyNeedsAuth(), prevCfg.proxyUser(), prevCfg.proxyPassword() );
}
connect( info,SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
this,SLOT(slotConnectionCheck(QString,QNetworkReply*)));
qDebug() << "# checking for authentication settings.";
_checkRemoteFolderRequest = info->getWebDAVPath(_remoteFolder ); // this call needs to be authenticated.
// continue in slotConnectionCheck
}
void OwncloudSetupWizard::slotConnectionCheck(const QString&, QNetworkReply* reply)
{
// disconnect from ownCloud Info signals
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
this, SLOT(slotConnectionCheck(QString,QNetworkReply*)));
switch (reply->error()) {
case QNetworkReply::NoError:
case QNetworkReply::ContentNotFoundError:
_ocWizard->successfulStep();
break;
default:
_ocWizard->displayError(tr("Error: Wrong credentials."));
break;
// now start ownCloudInfo to check the connection.
ownCloudInfo* info = ownCloudInfo::instance();
info->setCustomConfigHandle( _configHandle );
if( info->isConfigured() ) {
// reset the SSL Untrust flag to let the SSL dialog appear again.
info->resetSSLUntrust();
connect(info, SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
connect(info, SIGNAL(noOwncloudFound(QNetworkReply*)),
SLOT(slotNoOwnCloudFound(QNetworkReply*)));
_checkInstallationRequest = info->checkInstallation();
} else {
qDebug() << " ownCloud seems not to be configured, can not start test connect.";
}
}
void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFolder, const QString& remoteFolder)
void OwncloudSetupWizard::slotOwnCloudFound( const QString& url, const QString& infoString, const QString& version, const QString& )
{
qDebug() << "Setup local sync folder for new oC connection " << localFolder;
const QDir fi( localFolder );
// FIXME: Show problems with local folder properly.
bool localFolderOk = true;
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\">Successfully connected to %1: %2 version %3 (%4)</font><br/><br/>")
.arg( url ).arg(Theme::instance()->appNameGUI()).arg(infoString).arg(version));
// enable the finish button.
_ocWizard->button( QWizard::FinishButton )->setEnabled( true );
// start the local folder creation
setupLocalSyncFolder();
}
void OwncloudSetupWizard::slotNoOwnCloudFound( QNetworkReply *err )
{
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
_ocWizard->displayError(tr("Failed to connect to %1:<br/>%2").
arg(Theme::instance()->appNameGUI()).arg(err->errorString()));
// remove the config file again
MirallConfigFile cfgFile( _configHandle );
cfgFile.cleanupCustomConfig();
finalizeSetup( false );
}
void OwncloudSetupWizard::setupLocalSyncFolder()
{
if( ! _folderMan ) return;
const QString localFolder = _ocWizard->property("localFolder").toString();
qDebug() << "Setup local sync folder for new oC connection " << localFolder;
QDir fi( localFolder );
// FIXME: Show problems with local folder properly.
bool localFolderOk = true;
if( fi.exists() ) {
// there is an existing local folder. If its non empty, it can only be synced if the
// ownCloud is newly created.
@@ -325,19 +319,18 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
}
if( localFolderOk ) {
checkRemoteFolder(remoteFolder);
checkRemoteFolder();
}
}
void OwncloudSetupWizard::checkRemoteFolder(const QString& remoteFolder)
void OwncloudSetupWizard::checkRemoteFolder()
{
ownCloudInfo* info(ownCloudInfo::instance());
connect( info,SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
connect( ownCloudInfo::instance(),SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
this,SLOT(slotAuthCheckReply(QString,QNetworkReply*)));
qDebug() << "# checking for existence of remote folder.";
info->setCustomConfigHandle(_configHandle);
_checkRemoteFolderRequest = info->getWebDAVPath(remoteFolder); // this call needs to be authenticated.
qDebug() << "# checking for authentication settings.";
ownCloudInfo::instance()->setCustomConfigHandle(_configHandle);
_checkRemoteFolderRequest = ownCloudInfo::instance()->getRequest(_remoteFolder, true ); // this call needs to be authenticated.
// continue in slotAuthCheckReply
}
@@ -353,12 +346,22 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep
if( errId == QNetworkReply::NoError ) {
qDebug() << "******** Remote folder found, all cool!";
} else if( errId == QNetworkReply::AuthenticationRequiredError ) { // returned if the user is wrong.
qDebug() << "******** Password is wrong!";
error = tr("The given credentials do not authenticate.");
ok = false;
} else if( errId == QNetworkReply::OperationCanceledError ) {
// the username was wrong and ownCloudInfo was closing the request after a couple of auth tries.
qDebug() << "******** Username or password is wrong!";
error = tr("Username or password is wrong!");
ok = false;
} else if( errId == QNetworkReply::ContentNotFoundError ) {
if( createRemoteFolder() ) {
return; // Finish here, the mkdir request will go on.
} else {
// FIXME try to create the remote folder!
if( !createRemoteFolder() ) {
error = tr("The remote folder could not be accessed!");
ok = false;
} else {
return; // Finish here, the mkdir request will go on.
}
} else {
error = tr("Error: %1").arg(reply->errorString());
@@ -367,6 +370,8 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep
if( !ok ) {
_ocWizard->displayError(error);
} else {
_ocWizard->setRemoteFolder( _remoteFolder );
}
finalizeSetup( ok );
@@ -377,11 +382,10 @@ bool OwncloudSetupWizard::createRemoteFolder()
if( _remoteFolder.isEmpty() ) return false;
_ocWizard->appendToConfigurationLog( tr("creating folder on ownCloud: %1" ).arg( _remoteFolder ));
ownCloudInfo* info(ownCloudInfo::instance());
connect(info, SIGNAL(webdavColCreated(QNetworkReply::NetworkError)),
connect(ownCloudInfo::instance(), SIGNAL(webdavColCreated(QNetworkReply::NetworkError)),
this, SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError)));
_mkdirRequestReply = info->mkdirRequest( _remoteFolder );
_mkdirRequestReply = ownCloudInfo::instance()->mkdirRequest( _remoteFolder );
return (_mkdirRequestReply != NULL);
}
@@ -436,119 +440,13 @@ void OwncloudSetupWizard::finalizeSetup( bool success )
+ tr("Successfully connected to %1!")
.arg(Theme::instance()->appNameGUI())
+ QLatin1String("</b></font></p>"));
_ocWizard->successfulStep();
} else {
_ocWizard->appendToConfigurationLog(QLatin1String("<p><font color=\"red\">")
+ tr("Connection to %1 could not be established. Please check again.")
.arg(Theme::instance()->appNameGUI())
+ QLatin1String("</font></p>"));
}
_ocWizard->successfullyConnected(success);
}
// Method executed when the user ends the wizard, either with 'accept' or 'reject'.
// accept the custom config to be the main one if Accepted.
void OwncloudSetupWizard::slotAssistantFinished( int result )
{
MirallConfigFile cfg( _configHandle );
FolderMan *folderMan = FolderMan::instance();
if( result == QDialog::Rejected ) {
// the old config remains valid. Remove the temporary one.
cfg.cleanupCustomConfig();
qDebug() << "Rejected the new config, use the old!";
} else if( result == QDialog::Accepted ) {
AbstractCredentials* credentials(_ocWizard->getCredentials());
qDebug() << "Config Changes were accepted!";
// go through all folders and remove the journals if the server changed.
MirallConfigFile prevCfg;
QUrl prevUrl( prevCfg.ownCloudUrl() );
QUrl newUrl( cfg.ownCloudUrl() );
AbstractCredentials* oldCredentials(prevCfg.getCredentials());
bool urlHasChanged = (prevUrl.host() != newUrl.host() ||
prevUrl.port() != newUrl.port() ||
prevUrl.path() != newUrl.path());
// if the user changed, its also a changed url.
if(credentials->changed(oldCredentials)) {
urlHasChanged = true;
qDebug() << "The User has changed, same as url change.";
}
const QString localFolder = _ocWizard->localFolder();
bool acceptCfg = true;
if( urlHasChanged ) {
// first terminate sync jobs.
folderMan->terminateSyncProcess();
folderMan->unloadAllFolders();
bool startFromScratch = _ocWizard->field( "OCSyncFromScratch" ).toBool();
if( startFromScratch ) {
// first try to rename (backup) the current local dir.
bool renameOk = false;
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(Theme::instance()->appName(),
localFolder, _remoteFolder );
_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.";
}
}
}
// clear the custom config handle
_configHandle.clear();
ownCloudInfo::instance()->setCustomConfigHandle( QString::null );
// notify others.
emit ownCloudWizardDone( result );
}
void OwncloudSetupWizard::slotClearPendingRequests()
{
qDebug() << "Pending request: " << _mkdirRequestReply;
if( _mkdirRequestReply && _mkdirRequestReply->isRunning() ) {
qDebug() << "ABORTing pending mkdir request.";
_mkdirRequestReply->abort();
}
if( _checkInstallationRequest && _checkInstallationRequest->isRunning() ) {
qDebug() << "ABORTing pending check installation request.";
_checkInstallationRequest->abort();
}
if( _checkRemoteFolderRequest && _checkRemoteFolderRequest->isRunning() ) {
qDebug() << "ABORTing pending remote folder check request.";
_checkRemoteFolderRequest->abort();
}
}
} // ns Mirall
+56 -29
Ver Arquivo
@@ -21,54 +21,81 @@
#include <QNetworkReply>
#include <QPointer>
#include "mirall/owncloudwizard.h"
#include "mirall/theme.h"
namespace Mirall {
class OwncloudWizard;
class SiteCopyFolder;
class SyncResult;
class ownCloudInfo;
class FolderMan;
class OwncloudSetupWizard : public QObject
{
Q_OBJECT
public:
/** Run the wizard */
static void runWizard(QObject *obj, const char* amember, QWidget *parent = 0 );
explicit OwncloudSetupWizard( FolderMan *folderMan = 0, Theme *theme = 0, QObject *parent = 0 );
signals:
// overall dialog close signal.
void ownCloudWizardDone( int );
private slots:
void slotDetermineAuthType(const QString&);
void slotOwnCloudFoundAuth(const QString&, const QString&, const QString&, const QString&);
void slotAuthCheckReplyFinished();
void slotNoOwnCloudFoundAuth(QNetworkReply*);
void slotConnectToOCUrl(const QString&);
void slotConnectionCheck(const QString&, QNetworkReply*);
void slotCreateLocalAndRemoteFolders(const QString&, const QString&);
void slotAuthCheckReply(const QString&, QNetworkReply*);
void slotCreateRemoteFolderFinished(QNetworkReply::NetworkError);
void slotAssistantFinished( int );
void slotClearPendingRequests();
private:
explicit OwncloudSetupWizard(QObject *parent = 0 );
~OwncloudSetupWizard();
/**
* @intro wether or not to show the intro wizard page
*/
void startWizard();
void testOwnCloudConnect();
void checkRemoteFolder(const QString& remoteFolder);
void installServer();
bool isBusy();
void writeOwncloudConfig();
/**
* returns the configured owncloud url if its already configured, otherwise an empty
* string.
*/
void setupLocalSyncFolder();
OwncloudWizard *wizard();
signals:
// issued if the oC Setup process (owncloud-admin) is finished.
void ownCloudSetupFinished( bool );
// overall dialog close signal.
void ownCloudWizardDone( int );
public slots:
protected slots:
// wizard dialog signals
void slotConnectToOCUrl( const QString& );
private slots:
void slotOwnCloudFound( const QString&, const QString&, const QString&, const QString& );
void slotNoOwnCloudFound( QNetworkReply* );
void slotCreateRemoteFolderFinished( QNetworkReply::NetworkError );
void slotAssistantFinished( int );
void slotClearPendingRequests();
void slotAuthCheckReply( const QString&, QNetworkReply * );
private:
bool createRemoteFolder();
void checkRemoteFolder();
void finalizeSetup( bool );
OwncloudWizard* _ocWizard;
/* Start a request to the newly installed ownCloud to check the connection */
void testOwnCloudConnect();
OwncloudWizard *_ocWizard;
QPointer<QNetworkReply> _mkdirRequestReply;
QPointer<QNetworkReply> _checkInstallationRequest;
QPointer<QNetworkReply> _checkRemoteFolderRequest;
QString _configHandle;
QString _remoteFolder;
FolderMan *_folderMan;
QString _configHandle;
QString _remoteFolder;
};
}
+11 -14
Ver Arquivo
@@ -52,28 +52,32 @@ QString ownCloudTheme::about() const
QString devString;
#ifdef GIT_SHA1
const QString githubPrefix(QLatin1String(
"https://github.com/owncloud/mirall/commit/"));
" https://github.com/owncloud/mirall/commit/"));
const QString gitSha1(QLatin1String(GIT_SHA1));
devString = QCoreApplication::translate("ownCloudTheme::about()",
"<p><small>Built from Git revision <a href=\"%1\">%2</a>"
" on %3, %4 using OCsync %5 and Qt %6.</small><p>")
" on %3, %4<br>using OCsync %5 and Qt %6.</small><p>")
.arg(githubPrefix+gitSha1).arg(gitSha1.left(6))
.arg(__DATE__).arg(__TIME__)
.arg(MIRALL_STRINGIFY(LIBCSYNC_VERSION))
.arg(QT_VERSION_STR);
#endif
return QCoreApplication::translate("ownCloudTheme::about()",
"<p>Version %2. "
"For more information visit <a href=\"%3\">%4</a></p>"
"<p><small>By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, ownCloud Inc. "
"Based on Mirall by Duncan Mac-Vicar P.</small></p>"
"<p><b>%1 Client Version %2</b></p>"
"<p><b>Authors</b>"
"<br><a href=\"mailto:freitag@owncloud.com\">"
"Klaas Freitag</a>, ownCloud, Inc."
"<br><a href=\"mailto:danimo@owncloud.com\">"
"Daniel Molkentin</a>, ownCloud, Inc."
"<br><br>Based on Mirall by Duncan Mac-Vicar P.</p>"
"<p>For more information visit <a href=\"%3\">%4</a>.</p>"
"%7"
)
.arg(appName())
.arg(MIRALL_STRINGIFY(MIRALL_VERSION))
.arg("http://" MIRALL_STRINGIFY(APPLICATION_DOMAIN))
.arg(MIRALL_STRINGIFY(APPLICATION_DOMAIN))
.arg(devString);
}
QIcon ownCloudTheme::trayFolderIcon( const QString& ) const
@@ -105,11 +109,6 @@ QVariant ownCloudTheme::customMedia(Theme::CustomMediaType type)
}
}
QString ownCloudTheme::helpUrl() const
{
return QString::fromLatin1("http://doc.owncloud.org/desktop/%1.%2/").arg(MIRALL_VERSION_MAJOR).arg(MIRALL_VERSION_MINOR);
}
QColor ownCloudTheme::wizardHeaderBackgroundColor() const
{
return QColor("#1d2d42");
@@ -125,7 +124,5 @@ QPixmap ownCloudTheme::wizardHeaderLogo() const
return QPixmap(":/mirall/theme/colored/wizard_logo.png");
}
}
-2
Ver Arquivo
@@ -21,7 +21,6 @@ namespace Mirall {
class ownCloudTheme : public Theme
{
Q_OBJECT
public:
ownCloudTheme();
@@ -36,7 +35,6 @@ public:
QIcon applicationIcon() const;
QVariant customMedia(CustomMediaType type);
QString helpUrl() const;
QColor wizardHeaderBackgroundColor() const;
QColor wizardHeaderTitleColor() const;
+626
Ver Arquivo
@@ -0,0 +1,626 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "mirall/owncloudwizard.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#include "QProgressIndicator.h"
#include <QtCore>
#include <QtGui>
#include <stdlib.h>
namespace Mirall
{
void setupCustomMedia( QVariant variant, QLabel *label )
{
if( !label ) return;
QPixmap pix = variant.value<QPixmap>();
if( !pix.isNull() ) {
label->setPixmap(pix);
label->setAlignment( Qt::AlignTop | Qt::AlignRight );
label->setVisible(true);
} else {
QString str = variant.toString();
if( !str.isEmpty() ) {
label->setText( str );
label->setTextFormat( Qt::RichText );
label->setVisible(true);
label->setOpenExternalLinks(true);
}
}
}
// ======================================================================
OwncloudSetupPage::OwncloudSetupPage()
{
_ui.setupUi(this);
Theme *theme = Theme::instance();
setTitle( tr("<font color=\"%1\" size=\"5\">Connect to %2</font>")
.arg(theme->wizardHeaderTitleColor().name()).arg( theme->appNameGUI()));
setSubTitle( tr("<font color=\"%1\">Enter user credentials</font>")
.arg(theme->wizardHeaderTitleColor().name()));
registerField( QLatin1String("OCUrl"), _ui.leUrl );
registerField( QLatin1String("OCUser"), _ui.leUsername );
registerField( QLatin1String("OCPasswd"), _ui.lePassword);
registerField( QLatin1String("OCSyncFromScratch"), _ui.cbSyncFromScratch);
_ui.errorLabel->setVisible(true);
_ui.advancedBox->setVisible(false);
_progressIndi = new QProgressIndicator;
_ui.resultLayout->addWidget( _progressIndi );
_progressIndi->setVisible(false);
_ui.resultLayout->setEnabled(false);
// Error label
QString style = QLatin1String("border: 1px solid #eed3d7; border-radius: 5px; padding: 3px;"
"background-color: #f2dede; color: #b94a48;");
_ui.errorLabel->setStyleSheet( style );
_ui.errorLabel->setWordWrap(true);
_ui.errorLabel->setVisible(false);
_checking = false;
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()
{
delete _progressIndi;
}
void OwncloudSetupPage::slotToggleAdvanced(int state)
{
_ui.advancedBox->setVisible( state == Qt::Checked );
slotHandleUserInput();
QSize size = wizard()->sizeHint();
// need to substract header for some reason
size -= QSize(0, 63);
wizard()->setMinimumSize(size);
wizard()->resize(size);
}
void OwncloudSetupPage::setOCUser( const QString & user )
{
_ocUser = user;
_ui.leUsername->setText(user);
}
void OwncloudSetupPage::setServerUrl( const QString& newUrl )
{
_oCUrl = newUrl;
if( _oCUrl.isEmpty() ) {
_ui.leUrl->clear();
return;
}
_ui.leUrl->setText( _oCUrl );
}
void OwncloudSetupPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->hide();
_ui.bottomLabel->hide();
Theme *theme = Theme::instance();
QVariant variant = theme->customMedia( Theme::oCSetupTop );
if( !variant.isNull() ) {
setupCustomMedia( variant, _ui.topLabel );
}
variant = theme->customMedia( Theme::oCSetupBottom );
setupCustomMedia( variant, _ui.bottomLabel );
QString fixUrl = theme->overrideServerUrl();
if( !fixUrl.isEmpty() ) {
_ui.label_2->hide();
setServerUrl( fixUrl );
_ui.leUrl->setEnabled( false );
_ui.leUrl->hide();
}
}
void OwncloudSetupPage::slotUserChanged(const QString& user )
{
slotHandleUserInput();
}
// slot hit from textChanged of the url entry field.
void OwncloudSetupPage::slotUrlChanged(const QString& ocUrl)
{
slotHandleUserInput();
#if 0
QString url = ocUrl;
bool visible = false;
if (url.startsWith(QLatin1String("https://"))) {
_ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-high.png"));
_ui.urlLabel->setToolTip(tr("This url is secure. You can use it."));
visible = true;
}
if (url.startsWith(QLatin1String("http://"))) {
_ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-low.png"));
_ui.urlLabel->setToolTip(tr("This url is NOT secure. You should not use it."));
visible = true;
}
#endif
}
bool OwncloudSetupPage::isComplete() const
{
if( _ui.leUrl->text().isEmpty() ) return false;
if( _checking ) return false;
return !( _ui.lePassword->text().isEmpty() || _ui.leUsername->text().isEmpty() );
}
void OwncloudSetupPage::initializePage()
{
_connected = 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
{
return OwncloudWizard::Page_Result;
}
QString OwncloudSetupPage::url() const
{
QString url = _ui.leUrl->text().simplified();
return url;
}
QString OwncloudSetupPage::localFolder() const
{
QString folder = wizard()->property("localFolder").toString();
return folder;
}
void OwncloudSetupPage::setConnected( bool comp )
{
_connected = comp;
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
bool OwncloudSetupPage::validatePage()
{
bool re = false;
if( ! _connected) {
setErrorString(QString::null);
_checking = true;
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(true);
_progressIndi->startAnimation();
emit completeChanged();
emit connectToOCUrl( url() );
return false;
} else {
// connecting is running
stopSpinner();
_checking = false;
emit completeChanged();
return true;
}
}
void OwncloudSetupPage::setErrorString( const QString& err )
{
if( err.isEmpty()) {
_ui.errorLabel->setVisible(false);
} else {
_ui.errorLabel->setVisible(true);
_ui.errorLabel->setText(err);
}
_checking = false;
emit completeChanged();
stopSpinner();
}
void OwncloudSetupPage::stopSpinner()
{
_ui.resultLayout->setEnabled(false);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
OwncloudSetupPage::SyncMode OwncloudSetupPage::syncMode()
{
return BoxMode;
}
void OwncloudSetupPage::setRemoteFolder( const QString& remoteFolder )
{
if( !remoteFolder.isEmpty() ) {
_remoteFolder = remoteFolder;
}
}
void OwncloudSetupPage::setMultipleFoldersExist(bool exist)
{
_multipleFoldersExist = exist;
}
void OwncloudSetupPage::slotSelectFolder()
{
QString dir = QFileDialog::getExistingDirectory(0, tr("Local Sync Folder"), QDir::homePath());
if( !dir.isEmpty() ) {
_ui.pbSelectLocalFolder->setText(dir);
wizard()->setProperty("localFolder", dir);
slotHandleUserInput();
}
}
OwncloudSetupPage::SyncMode OwncloudWizard::syncMode()
{
return _setupPage->syncMode();
return OwncloudSetupPage::BoxMode;
}
void OwncloudWizard::setMultipleFoldersExist(bool exist)
{
_setupPage->setMultipleFoldersExist(exist);
}
void OwncloudSetupPage::setConfigExists( bool config )
{
_configExists = config;
if (config == true) {
setSubTitle( tr("<font color=\"%1\">Change your user credentials</font>")
.arg(Theme::instance()->wizardHeaderTitleColor().name()));
}
}
// ======================================================================
OwncloudWizardResultPage::OwncloudWizardResultPage()
{
_ui.setupUi(this);
// no fields to register.
Theme *theme = Theme::instance();
setTitle( tr("<font color=\"%1\" size=\"5\">Everything set up!</font>")
.arg(theme->wizardHeaderTitleColor().name()));
// required to show header in QWizard's modern style
setSubTitle( QLatin1String(" ") );
_ui.pbOpenLocal->setText("Open local folder");
_ui.pbOpenServer->setText(tr("Open %1").arg(Theme::instance()->appNameGUI()));
_ui.pbOpenLocal->setIcon(QIcon(":/mirall/resources/folder-sync.png"));
_ui.pbOpenLocal->setText(tr("Open Local Folder"));
_ui.pbOpenLocal->setIconSize(QSize(48, 48));
connect(_ui.pbOpenLocal, SIGNAL(clicked()), SLOT(slotOpenLocal()));
_ui.pbOpenLocal->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
QIcon appIcon = theme->applicationIcon();
_ui.pbOpenServer->setIcon(appIcon.pixmap(48));
_ui.pbOpenServer->setText(tr("Open %1").arg(theme->appNameGUI()));
_ui.pbOpenServer->setIconSize(QSize(48, 48));
_ui.pbOpenServer->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
connect(_ui.pbOpenServer, SIGNAL(clicked()), SLOT(slotOpenServer()));
setupCustomization();
}
OwncloudWizardResultPage::~OwncloudWizardResultPage()
{
}
void OwncloudWizardResultPage::setComplete(bool complete)
{
_complete = complete;
emit completeChanged();
}
bool OwncloudWizardResultPage::isComplete() const
{
return _complete;
}
void OwncloudWizardResultPage::initializePage()
{
const QString localFolder = wizard()->property("localFolder").toString();
QString text;
if( _remoteFolder == QLatin1String("/") || _remoteFolder.isEmpty() ) {
text = tr("Your entire account is synced to the local folder <i>%1</i>")
.arg(QDir::toNativeSeparators(localFolder));
} else {
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 );
}
void OwncloudWizardResultPage::setRemoteFolder(const QString &remoteFolder)
{
_remoteFolder = remoteFolder;
}
void OwncloudWizardResultPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->setText( QString::null );
_ui.topLabel->hide();
QVariant variant = Theme::instance()->customMedia( Theme::oCSetupResultTop );
setupCustomMedia( variant, _ui.topLabel );
}
// ======================================================================
/**
* Folder wizard itself
*/
OwncloudWizard::OwncloudWizard(QWidget *parent)
: QWizard(parent),
_configExists(false)
{
_setupPage = new OwncloudSetupPage;
_resultPage = new OwncloudWizardResultPage;
setPage(Page_oCSetup, _setupPage );
setPage(Page_Result, _resultPage );
// note: start Id is set by the calling class depending on if the
// welcome text is to be shown or not.
setWizardStyle( QWizard::ModernStyle );
connect( this, SIGNAL(currentIdChanged(int)), SLOT(slotCurrentPageChanged(int)));
connect( _setupPage, SIGNAL(connectToOCUrl(QString)), SIGNAL(connectToOCUrl(QString)));
Theme *theme = Theme::instance();
setWizardStyle(QWizard::ModernStyle);
setPixmap( QWizard::BannerPixmap, theme->wizardHeaderBanner() );
setPixmap( QWizard::LogoPixmap, theme->wizardHeaderLogo() );
setOption( QWizard::NoBackButtonOnStartPage );
setOption( QWizard::NoBackButtonOnLastPage );
setOption( QWizard::NoCancelButton );
setTitleFormat(Qt::RichText);
setSubTitleFormat(Qt::RichText);
}
QString OwncloudWizard::localFolder() const
{
return(_setupPage->localFolder());
}
QString OwncloudWizard::ocUrl() const
{
QString url = field("OCUrl").toString().simplified();
return url;
}
void OwncloudWizard::enableFinishOnResultWidget(bool enable)
{
_resultPage->setComplete(enable);
}
void OwncloudWizard::setRemoteFolder( const QString& remoteFolder )
{
_setupPage->setRemoteFolder( remoteFolder );
_resultPage->setRemoteFolder( remoteFolder );
}
void OwncloudWizard::showConnectInfo( const QString& msg )
{
if( _setupPage ) {
_setupPage->setErrorString( msg );
}
}
void OwncloudWizard::successfullyConnected(bool enable)
{
_setupPage->setConnected( enable );
if( enable ) {
next();
}
}
void OwncloudWizard::slotCurrentPageChanged( int id )
{
qDebug() << "Current Wizard page changed to " << id;
if( id == Page_oCSetup ) {
setButtonText( QWizard::NextButton, tr("Connect...") );
emit clearPendingRequests();
_setupPage->initializePage();
}
if( id == Page_Result ) {
appendToConfigurationLog( QString::null );
}
}
void OwncloudWizard::displayError( const QString& msg )
{
_setupPage->setErrorString( msg );
}
void OwncloudWizard::appendToConfigurationLog( const QString& msg, LogType type )
{
_setupLog << msg;
qDebug() << "Setup-Log: " << msg;
}
void OwncloudWizard::setOCUrl( const QString& url )
{
_setupPage->setServerUrl( url );
}
void OwncloudWizard::setOCUser( const QString& user )
{
_oCUser = user;
_setupPage->setOCUser( user );
}
void OwncloudWizard::setConfigExists( bool config )
{
_configExists = config;
_setupPage->setConfigExists( config );
}
bool OwncloudWizard::configExists()
{
return _configExists;
}
void OwncloudWizardResultPage::slotOpenLocal()
{
const QString localFolder = wizard()->property("localFolder").toString();
QDesktopServices::openUrl(QUrl::fromLocalFile(localFolder));
}
void OwncloudWizardResultPage::slotOpenServer()
{
QUrl url = field("OCUrl").toUrl();
qDebug() << Q_FUNC_INFO << url;
QDesktopServices::openUrl(url);
}
} // end namespace
+191
Ver Arquivo
@@ -0,0 +1,191 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MIRALL_OWNCLOUDWIZARD_H
#define MIRALL_OWNCLOUDWIZARD_H
#include <QWizard>
#include "ui_owncloudsetuppage_ng.h"
#include "ui_owncloudwizardresultpage.h"
class QLabel;
class QVariant;
class QProgressIndicator;
namespace Mirall {
class OwncloudSetupPage;
class OwncloudWizardResultPage;
class OwncloudSetupPage: public QWizardPage
{
Q_OBJECT
public:
OwncloudSetupPage();
~OwncloudSetupPage();
enum SyncMode {
SelectiveMode,
BoxMode
};
virtual bool isComplete() const;
virtual void initializePage();
virtual int nextId() const;
void setServerUrl( const QString& );
void setOCUser( const QString& );
void setAllowPasswordStorage( bool );
bool validatePage();
QString url() const;
QString localFolder() const;
void setConnected(bool complete);
void setRemoteFolder( const QString& remoteFolder);
void setMultipleFoldersExist( bool exist );
SyncMode syncMode();
public slots:
void setErrorString( const QString& );
void setConfigExists( bool );
void stopSpinner();
protected slots:
void slotUrlChanged(const QString&);
void slotUserChanged(const QString&);
void setupCustomization();
void slotToggleAdvanced(int state);
void slotSelectFolder();
signals:
void connectToOCUrl( const QString& );
protected:
void updateFoldersInfo();
private slots:
void slotHandleUserInput();
private:
bool urlHasChanged();
Ui_OwncloudSetupPage _ui;
QString _oCUrl;
QString _ocUser;
bool _connected;
bool _checking;
bool _configExists;
bool _multipleFoldersExist;
QProgressIndicator *_progressIndi;
QButtonGroup *_selectiveSyncButtons;
QString _remoteFolder;
};
class OwncloudWizard: public QWizard
{
Q_OBJECT
public:
enum {
Page_oCSetup,
Page_Result
};
enum LogType {
LogPlain,
LogParagraph
};
OwncloudWizard(QWidget *parent = 0);
void setOCUrl( const QString& );
void setOCUser( const QString& );
void setupCustomMedia( QVariant, QLabel* );
QString ocUrl() const;
QString localFolder() const;
void enableFinishOnResultWidget(bool enable);
void displayError( const QString& );
OwncloudSetupPage::SyncMode syncMode();
void setMultipleFoldersExist( bool );
void setConfigExists( bool );
bool configExists();
public slots:
void setRemoteFolder( const QString& );
void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph );
void slotCurrentPageChanged( int );
void showConnectInfo( const QString& );
void successfullyConnected(bool);
signals:
void clearPendingRequests();
void connectToOCUrl( const QString& );
private:
OwncloudSetupPage *_setupPage;
OwncloudWizardResultPage *_resultPage;
QString _configFile;
QString _oCUser;
QStringList _setupLog;
bool _configExists;
};
/**
* page to ask for the type of Owncloud to connect to
*/
/**
* page to display the install result
*/
class OwncloudWizardResultPage : public QWizardPage
{
Q_OBJECT
public:
OwncloudWizardResultPage();
~OwncloudWizardResultPage();
bool isComplete() const;
void initializePage();
void setRemoteFolder( const QString& remoteFolder);
public slots:
void setComplete(bool complete);
protected slots:
void slotOpenLocal();
void slotOpenServer();
protected:
void setupCustomization();
private:
QString _localFolder;
QString _remoteFolder;
bool _complete;
Ui_OwncloudWizardResultPage _ui;
};
} // ns Mirall
#endif
-186
Ver Arquivo
@@ -1,186 +0,0 @@
/*
* 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 "progressdispatcher.h"
#include <QObject>
#include <QMetaType>
#include <QDebug>
namespace Mirall {
ProgressDispatcher* ProgressDispatcher::_instance = 0;
QString Progress::asResultString( Kind kind )
{
QString re;
switch(kind) {
case Download:
case EndDownload:
re = QObject::tr("Download");
break;
case Upload:
re = QObject::tr("Upload");
break;
case Context:
re = QObject::tr("Context");
break;
case Inactive:
re = QObject::tr("Inactive");
break;
case StartDownload:
re = QObject::tr("Download");
break;
case StartUpload:
case EndUpload:
re = QObject::tr("Upload");
break;
case StartSync:
re = QObject::tr("Start");
break;
case EndSync:
re = QObject::tr("Finished");
break;
case StartDelete:
re = QObject::tr("For deletion");
break;
case EndDelete:
re = QObject::tr("deleted");
break;
default:
Q_ASSERT(false);
}
return re;
}
QString Progress::asActionString( Kind kind )
{
QString re;
switch(kind) {
case Download:
re = QObject::tr("downloading");
break;
case Upload:
re = QObject::tr("uploading");
break;
case Context:
re = QObject::tr("Context");
break;
case Inactive:
re = QObject::tr("inactive");
break;
case StartDownload:
re = QObject::tr("downloading");
break;
case StartUpload:
re = QObject::tr("uploading");
break;
case EndDownload:
re = QObject::tr("downloading");
break;
case EndUpload:
re = QObject::tr("uploading");
break;
case StartSync:
re = QObject::tr("starting");
break;
case EndSync:
re = QObject::tr("finished");
break;
case StartDelete:
re = QObject::tr("delete");
break;
case EndDelete:
re = QObject::tr("deleted");
break;
default:
Q_ASSERT(false);
}
return re;
}
ProgressDispatcher* ProgressDispatcher::instance() {
if (!_instance) {
_instance = new ProgressDispatcher();
}
return _instance;
}
ProgressDispatcher::ProgressDispatcher(QObject *parent) :
QObject(parent),
_problemQueueSize(50)
{
}
ProgressDispatcher::~ProgressDispatcher()
{
}
QList<Progress::Info> ProgressDispatcher::recentChangedItems(int count)
{
if( count > 0 ) {
return _recentChanges.mid(0, count);
}
return _recentChanges;
}
QList<Progress::SyncProblem> ProgressDispatcher::recentProblems(int count)
{
if( count > 0 ) {
return _recentProblems.mid(0, count);
}
return _recentProblems;
}
void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress::Info& progress)
{
if( folder.isEmpty() ) {
return;
}
Progress::Info newProgress = progress;
if( newProgress.kind == Progress::Error ) {
Progress::SyncProblem err;
err.folder = folder;
err.current_file = newProgress.current_file;
err.error_message = QString::fromLocal8Bit( (const char*)newProgress.file_size );
err.error_code = newProgress.file_size;
err.timestamp = QTime::currentTime();
_recentProblems.enqueue( err );
if( _recentProblems.size() > _problemQueueSize ) {
_recentProblems.dequeue();
}
emit progressSyncProblem( folder, err );
} else {
if( newProgress.kind == Progress::StartSync ) {
_recentProblems.clear();
}
if( newProgress.kind == Progress::EndSync ) {
newProgress.overall_current_bytes = newProgress.overall_transmission_size;
newProgress.current_file_no = newProgress.overall_file_count;
}
if( newProgress.kind == Progress::EndDownload || newProgress.kind == Progress::EndUpload ||
newProgress.kind == Progress::EndDelete ) {
_recentChanges.enqueue(newProgress);
}
emit progressInfo( folder, newProgress );
}
}
}
-121
Ver Arquivo
@@ -1,121 +0,0 @@
/*
* 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 PROGRESSDISPATCHER_H
#define PROGRESSDISPATCHER_H
#include <QObject>
#include <QHash>
#include <QTime>
#include <QQueue>
namespace Mirall {
/**
* @brief The FolderScheduler class schedules folders for sync
*/
class Progress
{
public:
typedef enum {
Invalid,
StartSync,
Download,
Upload,
Context,
Inactive,
StartDownload,
StartUpload,
EndDownload,
EndUpload,
EndSync,
StartDelete,
EndDelete,
Error
} Kind;
typedef struct {
Kind kind;
QString folder;
QString current_file;
qint64 file_size;
qint64 current_file_bytes;
qint64 overall_file_count;
qint64 current_file_no;
qint64 overall_transmission_size;
qint64 overall_current_bytes;
QTime timestamp;
} Info;
typedef struct {
QString folder;
QString current_file;
QString error_message;
int error_code;
QTime timestamp;
} SyncProblem;
static QString asActionString( Kind );
static QString asResultString( Kind );
};
/**
* @file progressdispatcher.h
* @brief A singleton class to provide sync progress information to other gui classes.
*
* How to use the ProgressDispatcher:
* Just connect to the two signals either to progress for every individual file
* or the overall sync progress.
*
*/
class ProgressDispatcher : public QObject
{
Q_OBJECT
friend class Folder; // only allow Folder class to access the setting slots.
public:
static ProgressDispatcher* instance();
~ProgressDispatcher();
QList<Progress::Info> recentChangedItems(int count);
QList<Progress::SyncProblem> recentProblems(int count);
signals:
/**
@brief Signals the progress of data transmission.
@param[out] folder The folder which is being processed
@param[out] newProgress A struct with all progress info.
*/
void progressInfo( const QString& folder, const Progress::Info& progress );
void progressSyncProblem( const QString& folder, const Progress::SyncProblem& problem );
protected:
void setProgressInfo(const QString &folder, const Progress::Info& progress);
private:
ProgressDispatcher(QObject* parent = 0);
const int _problemQueueSize;
QQueue<Progress::Info> _recentChanges;
QQueue<Progress::SyncProblem> _recentProblems;
static ProgressDispatcher* _instance;
};
}
#endif // PROGRESSDISPATCHER_H

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais