Compare commits
139 Commits
v1.4.0-bet
...
v1.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ce09713b6 | ||
|
|
4fa6faf608 | ||
|
|
a24ae13d9c | ||
|
|
64dd0d1b45 | ||
|
|
da63b1223c | ||
|
|
36f32c2aef | ||
|
|
063acadc3b | ||
|
|
81c720c05b | ||
|
|
edcdcb945a | ||
|
|
5df6430bb2 | ||
|
|
9a0096d07c | ||
|
|
25d33d6057 | ||
|
|
ab4c6247c7 | ||
|
|
1b69dbb38b | ||
|
|
bfdd488b00 | ||
|
|
54c8809bf4 | ||
|
|
0873665bec | ||
|
|
02b3033ca3 | ||
|
|
a27c8ad90c | ||
|
|
18a58f73de | ||
|
|
d1451a3c90 | ||
|
|
0bef47b2f3 | ||
|
|
ccc05d6658 | ||
|
|
c15de69156 | ||
|
|
8bfb44fd28 | ||
|
|
79d3b84fad | ||
|
|
b97701586e | ||
|
|
b120345fe7 | ||
|
|
ec5c65a530 | ||
|
|
77e7a1fa8d | ||
|
|
f6d45b68ef | ||
|
|
24d76a0d75 | ||
|
|
c3326efe94 | ||
|
|
c0e056bb84 | ||
|
|
8a7df36701 | ||
|
|
39ec6b1bb2 | ||
|
|
30b2406533 | ||
|
|
076d5dda0e | ||
|
|
e78eab46ff | ||
|
|
19a08f8d5e | ||
|
|
c6319117fd | ||
|
|
4c10ed4ada | ||
|
|
b0ab3ca80b | ||
|
|
9f89a2fe76 | ||
|
|
e386bfb550 | ||
|
|
0189a3f1bd | ||
|
|
d3a333e03c | ||
|
|
04d3e282fb | ||
|
|
4be5f970d5 | ||
|
|
31ceff181e | ||
|
|
42abf4101c | ||
|
|
f09cae74fb | ||
|
|
13a6393ec5 | ||
|
|
ace57f9dd4 | ||
|
|
e5117a98c9 | ||
|
|
c1f7af7e6f | ||
|
|
b4c116e2a2 | ||
|
|
a19a960b5e | ||
|
|
29d2094626 | ||
|
|
c3b82e6818 | ||
|
|
1a7c89326b | ||
|
|
3a1f04ac2d | ||
|
|
2c8e95a0f4 | ||
|
|
a9d94ef732 | ||
|
|
2756d17873 | ||
|
|
34d7f84fc2 | ||
|
|
cea9b389bf | ||
|
|
71b1e881d8 | ||
|
|
7ba47e9d44 | ||
|
|
be48cb646c | ||
|
|
47eb5ff1d9 | ||
|
|
b608f5a670 | ||
|
|
e81dc34c4e | ||
|
|
1603e627a3 | ||
|
|
bf978b3e0f | ||
|
|
0fdaf33288 | ||
|
|
367c4153c1 | ||
|
|
395c673a24 | ||
|
|
22de23c651 | ||
|
|
23926d2461 | ||
|
|
c03f31b6ba | ||
|
|
a1060a8538 | ||
|
|
24251bc223 | ||
|
|
f78749d2cd | ||
|
|
0995377d39 | ||
|
|
b9228e64ff | ||
|
|
c4084de716 | ||
|
|
3c667918e7 | ||
|
|
e55745cbcf | ||
|
|
e01ce20431 | ||
|
|
dce8cb83d9 | ||
|
|
8dc956c55b | ||
|
|
6c77921a32 | ||
|
|
55e4748f06 | ||
|
|
5ff9e02517 | ||
|
|
7f7ebc36f5 | ||
|
|
0e5bfc03ce | ||
|
|
b309d333a6 | ||
|
|
ee439382ed | ||
|
|
192212c682 | ||
|
|
148bdfdcd6 | ||
|
|
066c0ba189 | ||
|
|
9651f1cddf | ||
|
|
5feb9b0806 | ||
|
|
44b9ee19e7 | ||
|
|
cc16d19bc4 | ||
|
|
b96c2de2b7 | ||
|
|
f882b80708 | ||
|
|
4d7c014b23 | ||
|
|
1f274699e5 | ||
|
|
697e355f07 | ||
|
|
e89bdfc422 | ||
|
|
c2cc9e62a7 | ||
|
|
1f2ae0d061 | ||
|
|
91a39588c6 | ||
|
|
a642f86d5b | ||
|
|
00cf290574 | ||
|
|
b59952b539 | ||
|
|
88b4ff9809 | ||
|
|
ddd0965a82 | ||
|
|
0a9491ff46 | ||
|
|
32b44e3d87 | ||
|
|
268004b4ff | ||
|
|
6c0f6ae62e | ||
|
|
094f2bb540 | ||
|
|
f4da7f1fb0 | ||
|
|
b058185d3b | ||
|
|
eecb981736 | ||
|
|
46b870e260 | ||
|
|
1ffab7337d | ||
|
|
82fb8c49cf | ||
|
|
ff2d59d32f | ||
|
|
0ced165b3e | ||
|
|
d3378c131a | ||
|
|
0300a85295 | ||
|
|
60a116f3e0 | ||
|
|
ff4d2d488f | ||
|
|
b0852b4cf5 | ||
|
|
c047b4d4de |
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.gitmodules
|
||||
*build*/
|
||||
*flymake*
|
||||
CMakeLists.txt.user*
|
||||
|
||||
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "doc/ocdoc"]
|
||||
path = doc/ocdoc
|
||||
url = https://github.com/owncloud/documentation
|
||||
@@ -13,12 +13,16 @@ else ()
|
||||
include ( ${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake )
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED APPLICATION_SHORTNAME)
|
||||
set ( APPLICATION_SHORTNAME ${APPLICATION_NAME} )
|
||||
endif()
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/VERSION.cmake)
|
||||
configure_file( ${CMAKE_SOURCE_DIR}/src/mirall/version.h.in "${CMAKE_CURRENT_BINARY_DIR}/src/mirall/version.h" )
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/src/mirall/")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(DefineInstallationPaths)
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
|
||||
@@ -34,10 +38,8 @@ if (${GIT_SHA1} STREQUAL "GITDIR-NOTFOUND")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
## stupid, we should upstream this
|
||||
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr" AND NOT CMAKE_INSTALL_SYSCONFDIR)
|
||||
set(CMAKE_INSTALL_SYSCONFDIR "/etc")
|
||||
endif()
|
||||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||
set(DATADIR ${DATA_INSTALL_DIR})
|
||||
|
||||
#####
|
||||
## handle BUILD_OWNCLOUD_OSX_BUNDLE
|
||||
@@ -83,25 +85,6 @@ set(USE_INOTIFY ${INOTIFY_FOUND})
|
||||
|
||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
set(CPACK_SOURCE_IGNORE_FILES
|
||||
# hidden files
|
||||
"/\\\\..+$"
|
||||
# temporary files
|
||||
"\\\\.swp$"
|
||||
# backup files
|
||||
"~$"
|
||||
# others
|
||||
"\\\\.#"
|
||||
"/#"
|
||||
"/build/"
|
||||
"/_build/"
|
||||
# used before
|
||||
"\\\\.o$"
|
||||
"\\\\.lo$"
|
||||
"\\\\.la$"
|
||||
"Makefile\\\\.in$"
|
||||
)
|
||||
|
||||
include(OwnCloudCPack.cmake)
|
||||
|
||||
add_definitions(-DUNICODE)
|
||||
@@ -123,5 +106,5 @@ endif(UNIT_TESTING)
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
configure_file(sync-exclude.lst ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/sync-exclude.lst COPYONLY)
|
||||
else()
|
||||
install( FILES sync-exclude.lst DESTINATION ${CMAKE_INSTALL_SYSCONFDIR} )
|
||||
install( FILES sync-exclude.lst DESTINATION ${SYSCONFDIR}/${APPLICATION_SHORTNAME} )
|
||||
endif()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 1.4.0beta1 (release 2013-08-08 ), csync 0.81.0 required
|
||||
version 1.4.0 (release 2013-09-04 ), csync 0.90.0 required
|
||||
|
||||
* New Scheduler: Only sync when there are actual changes in the server
|
||||
* Add a Settings Dialog, move Proxy Settings there
|
||||
@@ -19,6 +19,9 @@ version 1.4.0beta1 (release 2013-08-08 ), csync 0.81.0 required
|
||||
* Add an editor for ingore patterns
|
||||
* ALlow to flag certain ignore patterns as discardable
|
||||
* Ensure to ship with all valid translations
|
||||
* Progress Dialog now preserves the last syncned items across sync runs
|
||||
* Split Setup Wizard into multiple pages again
|
||||
* Implement "--logfile -" to log to stdout
|
||||
* Add preliminary support for Shibboleth authentication
|
||||
* Linux: Provide more icon sizes
|
||||
* Linux: Do not trigger notifier on ignored files
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
set( APPLICATION_SHORTNAME "owncloud" )
|
||||
set( APPLICATION_NAME "ownCloud" )
|
||||
set( APPLICATION_EXECUTABLE "owncloud" )
|
||||
set( APPLICATION_DOMAIN "owncloud.com" )
|
||||
set( APPLICATION_VENDOR "ownCloud, Inc" )
|
||||
set( THEME_CLASS "ownCloudTheme" )
|
||||
#set( APPLICATION_SHORTNAME ${APPLICATION_NAME} )
|
||||
set( APPLICATION_EXECUTABLE "owncloud" )
|
||||
set( APPLICATION_DOMAIN "owncloud.com" )
|
||||
set( APPLICATION_VENDOR "ownCloud, Inc" )
|
||||
set( THEME_CLASS "ownCloudTheme" )
|
||||
set( APPLICATION_REV_DOMAIN "com.owncloud.desktopclient" )
|
||||
set( WIN_SETUP_BITMAP_PATH "${CMAKE_SOURCE_DIR}/admin/win/nsi" )
|
||||
# set( THEME_INCLUDE "${OEM_THEME_DIR}/mytheme.h" )
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set( VERSION_MAJOR 1 )
|
||||
set( VERSION_MINOR 4 )
|
||||
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 )
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ mount="/Volumes/$(basename $src_dmg|cut -d"-" -f1)"
|
||||
|
||||
test -e $tmp_dmg && rm -rf $tmp_dmg
|
||||
hdiutil convert $src_dmg -format UDRW -o $tmp_dmg
|
||||
open $tmp_dmg
|
||||
sleep 12s
|
||||
hdiutil attach $tmp_dmg
|
||||
pushd $mount
|
||||
codesign -s "$identity" $mount/*.app
|
||||
popd
|
||||
|
||||
108
cmake/modules/DefineInstallationPaths.cmake
Normal file
@@ -0,0 +1,108 @@
|
||||
if (UNIX)
|
||||
# Suffix for Linux
|
||||
SET(LIB_SUFFIX
|
||||
CACHE STRING "Define suffix of directory name (32/64)"
|
||||
)
|
||||
|
||||
SET(EXEC_INSTALL_PREFIX
|
||||
"${CMAKE_INSTALL_PREFIX}"
|
||||
CACHE PATH "Base directory for executables and libraries"
|
||||
)
|
||||
SET(SHARE_INSTALL_PREFIX
|
||||
"${CMAKE_INSTALL_PREFIX}/share"
|
||||
CACHE PATH "Base directory for files which go to share/"
|
||||
)
|
||||
SET(DATA_INSTALL_PREFIX
|
||||
"${SHARE_INSTALL_PREFIX}/${APPLICATION_SHORT_NAME}"
|
||||
CACHE PATH "The parent directory where applications can install their data")
|
||||
|
||||
# The following are directories where stuff will be installed to
|
||||
SET(BIN_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/bin"
|
||||
CACHE PATH "The ${APPLICATION_SHORT_NAME} binary install dir (default prefix/bin)"
|
||||
)
|
||||
SET(SBIN_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/sbin"
|
||||
CACHE PATH "The ${APPLICATION_SHORT_NAME} sbin install dir (default prefix/sbin)"
|
||||
)
|
||||
SET(LIB_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)"
|
||||
)
|
||||
SET(LIBEXEC_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/libexec"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)"
|
||||
)
|
||||
SET(PLUGIN_INSTALL_DIR
|
||||
"${LIB_INSTALL_DIR}/${APPLICATION_SHORT_NAME}"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_SHORT_NAME})"
|
||||
)
|
||||
SET(INCLUDE_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/include"
|
||||
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
|
||||
)
|
||||
|
||||
SET(DATA_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}"
|
||||
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_SHORT_NAME})"
|
||||
)
|
||||
SET(HTML_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}/doc/HTML"
|
||||
CACHE PATH "The HTML install dir for documentation (default data/doc/html)"
|
||||
)
|
||||
SET(ICON_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}/icons"
|
||||
CACHE PATH "The icon install dir (default data/icons/)"
|
||||
)
|
||||
SET(SOUND_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}/sounds"
|
||||
CACHE PATH "The install dir for sound files (default data/sounds)"
|
||||
)
|
||||
|
||||
SET(LOCALE_INSTALL_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/locale"
|
||||
CACHE PATH "The install dir for translations (default prefix/share/locale)"
|
||||
)
|
||||
|
||||
SET(XDG_APPS_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/applications/"
|
||||
CACHE PATH "The XDG apps dir"
|
||||
)
|
||||
SET(XDG_DIRECTORY_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/desktop-directories"
|
||||
CACHE PATH "The XDG directory"
|
||||
)
|
||||
|
||||
IF(NOT "${EXEC_INSTALL_PREFIX}" STREQUAL "/usr")
|
||||
SET(SYSCONFDIR_INSTALL_PREFIX "${EXEC_INSTALL_PREFIX}")
|
||||
endif()
|
||||
|
||||
SET(SYSCONF_INSTALL_DIR
|
||||
"${SYSCONFDIR_INSTALL_PREFIX}/etc"
|
||||
CACHE PATH "The ${APPLICATION_SHORT_NAME} sysconfig install dir (default prefix/etc)"
|
||||
)
|
||||
SET(MAN_INSTALL_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/man"
|
||||
CACHE PATH "The ${APPLICATION_SHORT_NAME} man install dir (default prefix/man)"
|
||||
)
|
||||
SET(INFO_INSTALL_DIR
|
||||
"${SHARE_INSTALL_PREFIX}/info"
|
||||
CACHE PATH "The ${APPLICATION_SHORT_NAME} info install dir (default prefix/info)"
|
||||
)
|
||||
endif (UNIX)
|
||||
|
||||
if (WIN32)
|
||||
# Same same
|
||||
set(SHARE_INSTALL_PREFIX "share" CACHE PATH "-")
|
||||
set(BIN_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
|
||||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
|
||||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
|
||||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
|
||||
set(SYSCONF_INSTALL_DIR "config" CACHE PATH "-")
|
||||
set(MAN_INSTALL_DIR "man" CACHE PATH "-")
|
||||
endif (WIN32)
|
||||
@@ -1,6 +1,6 @@
|
||||
;ownCloud installer script.
|
||||
|
||||
!define APPLICATION_SHORTNAME "@APPLICATION_SHORTNAME@"
|
||||
!define APPLICATION_SHORTNAME "@APPLICATION_EXECUTABLE@"
|
||||
!define APPLICATION_NAME "@APPLICATION_NAME@"
|
||||
!define APPLICATION_VENDOR "@APPLICATION_VENDOR@"
|
||||
!define APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@.exe"
|
||||
|
||||
@@ -8,4 +8,10 @@
|
||||
#cmakedefine APPLICATION_DOMAIN @APPLICATION_DOMAIN@
|
||||
#cmakedefine THEME_CLASS @THEME_CLASS@
|
||||
#cmakedefine THEME_INCLUDE @THEME_INCLUDE@
|
||||
|
||||
#cmakedefine APPLICATION_NAME "@APPLICATION_NAME@"
|
||||
#cmakedefine APPLICATION_SHORTNAME "@APPLICATION_SHORTNAME@"
|
||||
|
||||
#cmakedefine SYSCONFDIR "@SYSCONFDIR@"
|
||||
#cmakedefine DATADIR "@DATADIR@"
|
||||
#endif
|
||||
|
||||
@@ -22,12 +22,17 @@ if(SPHINX_FOUND)
|
||||
add_custom_target(doc DEPENDS doc-html doc-man COMMENT "Building documentation...")
|
||||
endif(WITH_DOC)
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ocdoc")
|
||||
add_dependencies(doc doc-html-org)
|
||||
add_dependencies(doc doc-html-com)
|
||||
endif()
|
||||
|
||||
if(PDFLATEX_FOUND)
|
||||
# if this still fails on Debian/Ubuntu, run
|
||||
# apt-get install texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended
|
||||
add_custom_target(doc-latex ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b latex
|
||||
-d ${SPHINX_CACHE_DIR}
|
||||
-d ${SPHINX_CACHE_DIR}/latex
|
||||
-D latex_logo=${LATEX_LOGO}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_PDF_DIR} )
|
||||
@@ -41,7 +46,7 @@ if(SPHINX_FOUND)
|
||||
if (EXISTS ${QT_QCOLLECTIONGENERATOR_EXECUTABLE})
|
||||
add_custom_target( doc-qch-sphinx ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b qthelp
|
||||
-d ${SPHINX_CACHE_DIR}
|
||||
-d ${SPHINX_CACHE_DIR}/qthelp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_QCH_DIR} )
|
||||
add_custom_target( doc-qch ${QT_QCOLLECTIONGENERATOR_EXECUTABLE}
|
||||
@@ -54,12 +59,24 @@ if(SPHINX_FOUND)
|
||||
endif()
|
||||
add_custom_target( doc-html ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b html
|
||||
-d ${SPHINX_CACHE_DIR}
|
||||
-d ${SPHINX_CACHE_DIR}/html
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_HTML_DIR} )
|
||||
${SPHINX_HTML_DIR}/unthemed )
|
||||
add_custom_target( doc-html-org ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b html
|
||||
-d ${SPHINX_CACHE_DIR}/html
|
||||
-D html_theme=owncloud_org
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_HTML_DIR}/org )
|
||||
add_custom_target( doc-html-com ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b html
|
||||
-d ${SPHINX_CACHE_DIR}/html
|
||||
-D html_theme=owncloud_com
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_HTML_DIR}/com )
|
||||
add_custom_target( doc-man ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b man
|
||||
-d ${SPHINX_CACHE_DIR}
|
||||
-d ${SPHINX_CACHE_DIR}/man
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_MAN_DIR} )
|
||||
|
||||
@@ -71,7 +88,7 @@ if(SPHINX_FOUND)
|
||||
add_custom_target( doc-chm-sphinx ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b htmlhelp
|
||||
-D html_theme=basic
|
||||
-d ${SPHINX_CACHE_DIR}
|
||||
-d ${SPHINX_CACHE_DIR}/htmlhelp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_HTMLHELP_DIR} )
|
||||
add_custom_target( doc-chm pushd ${SPHINX_HTMLHELP_DIR}; ${MSHTML_COMPILER} *.hhp; popd
|
||||
|
||||
37
doc/accountsetup.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Setting up an Account
|
||||
=====================
|
||||
|
||||
If no account has been configured, ownCloud Client will automatically assist
|
||||
you in connecting to your ownCloud Server after the application has been
|
||||
started.
|
||||
|
||||
As a first step, specify the URL to your Server, just
|
||||
like you would when you open your ownCloud instance inside a browser.
|
||||
|
||||
.. image:: images/wizard_url.png
|
||||
:scale: 50 %
|
||||
|
||||
.. note:: Make sure to use ``https://`` if the server supports it. Otherwise,
|
||||
your password and all data will be transferred to the server unencrypted.
|
||||
This makes it easy for third parties to intercept your communication, and
|
||||
getting hold of your password!
|
||||
|
||||
Next, you are prompted for your username and password. Again, use the same
|
||||
credentials that you would use to log on via the web interface.
|
||||
|
||||
.. image:: images/wizard_user.png
|
||||
:scale: 50 %
|
||||
|
||||
Finally, choose the folder that ownCloud Client is supposed to sync the
|
||||
contents of your ownCloud account with. By default, this is a folder
|
||||
called `ownCloud`, which will reside in your home directory.
|
||||
|
||||
.. image:: images/wizard_targetfolder.png
|
||||
:scale: 50 %
|
||||
|
||||
After pressing `Connect`, ownCloud Client will commence with the syncing
|
||||
process. The next screen will give you the opportunity to review your
|
||||
settings:
|
||||
|
||||
.. image:: images/wizard_overview.png
|
||||
:scale: 50 %
|
||||
14
doc/advancedusage.rst
Normal file
@@ -0,0 +1,14 @@
|
||||
Advanced Usage
|
||||
==============
|
||||
|
||||
.. index:: Advanced Usage
|
||||
|
||||
Options
|
||||
-------
|
||||
.. index:: command line switches, command line, options, parameters
|
||||
.. include:: options.rst
|
||||
|
||||
Config File
|
||||
-----------
|
||||
.. index:: config file
|
||||
.. include:: conffile.rst
|
||||
@@ -1,5 +1,6 @@
|
||||
Architecture
|
||||
============
|
||||
Appendix B: Architecture
|
||||
========================
|
||||
|
||||
.. index:: architecture
|
||||
|
||||
The ownCloud project provides desktop sync clients to synchronize the
|
||||
@@ -11,11 +12,10 @@ csync was written to synchronize with ownCloud’s built-in WebDAV server.
|
||||
|
||||
The ownCloud sync client is based on a tool called mirall initially written by
|
||||
Duncan Mac Vicar. Later Klaas Freitag joined the project and enhanced it to work
|
||||
with ownCloud server. Both mirall and ownCloud Client (oCC) build from the same
|
||||
source, currently hosted in the ownCloud source repo on gitorious.
|
||||
with ownCloud server.
|
||||
|
||||
oCC is written in C++ using the `Qt Framework`_. As a result oCC runs on the
|
||||
three important platforms Linux, Windows and MacOS.
|
||||
ownCloud Client is written in C++ using the `Qt Framework`_. As a result, the
|
||||
ownCloud Client runs on the three important platforms Linux, Windows and MacOS.
|
||||
|
||||
.. _csync: http://www.csync.org
|
||||
.. _`Qt Framework`: http://www.qt-project.org
|
||||
@@ -23,8 +23,8 @@ three important platforms Linux, Windows and MacOS.
|
||||
The Sync Process
|
||||
----------------
|
||||
|
||||
First it is important to recall what syncing is. Syncing tries to keep the files
|
||||
on both repositories the same. That means if a file is added to one repository
|
||||
First it is important to recall what syncing is: It tries to keep the files
|
||||
on two repositories the same. That means if a file is added to one repository
|
||||
it is going to be copied to the other repository. If a file is changed on one
|
||||
repository, the change is propagated to the other repository. Also, if a file
|
||||
is deleted on one side, it is deleted on the other. As a matter of fact, in
|
||||
@@ -34,10 +34,10 @@ 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.
|
||||
The ownCloud Client 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
|
||||
------------------------
|
||||
@@ -62,16 +62,18 @@ 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. 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.
|
||||
.. note:: ownCloud Client 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.
|
||||
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.
|
||||
|
||||
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
|
||||
@@ -105,7 +107,8 @@ are involved and one of them is not in sync with NTP time.
|
||||
.. _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
|
||||
@@ -118,25 +121,41 @@ 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.
|
||||
In case a file has changed on both, the local and the remote repository since
|
||||
the last sync run, it can not easily be decided which version of the file is
|
||||
the one that should be used. However, changes to any side must not be lost.
|
||||
|
||||
That is called a **conflict case**. 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.
|
||||
|
||||
|
||||
.. _ignored-files-label:
|
||||
|
||||
Ignored Files
|
||||
-------------
|
||||
|
||||
ownCloud Client will refuse to sync the following files:
|
||||
|
||||
* Files matched by one of the pattern in :ref:`ignoredFilesEditor-label`
|
||||
* Files containing characters that do not work on certain file systems.
|
||||
Currently, these characters are: `\, :, ?, *, ", >, <, |`
|
||||
* Files starting in ``.csync_journal.db`` (reserved for journalling)
|
||||
|
||||
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 client stores the ETag number in a per-directory database,
|
||||
called the journal. It is a hidden file right in the directory
|
||||
to be synced.
|
||||
|
||||
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.
|
||||
If the journal database gets removed, ownCloud Client'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 with NTP time
|
||||
before restarting the client after a database removal.
|
||||
|
||||
Pressing ``F5`` in the Account Settings Dialog that allows to "reset" the
|
||||
journal. That can be used to recreate the journal database. Use this only
|
||||
if advised to do so by the developer or support staff.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
Building the Client
|
||||
===================
|
||||
.. _building-label:
|
||||
|
||||
Appendix A: Building the Client
|
||||
===============================
|
||||
|
||||
This section explains how to build the ownCloud Client from source
|
||||
for all major platforms. You should read this section if you want
|
||||
|
||||
@@ -28,7 +28,7 @@ import sys, os
|
||||
extensions = ['sphinx.ext.todo']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
#templates_path = ['templates']
|
||||
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
@@ -95,7 +95,7 @@ pygments_style = 'sphinx'
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = ['themes']
|
||||
html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/themes']
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
@@ -120,7 +120,7 @@ html_short_title = "Client Manual"
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
#html_static_path = ['static']
|
||||
html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
|
||||
@@ -4,8 +4,8 @@ Glossary
|
||||
.. glossary::
|
||||
:sorted:
|
||||
|
||||
ownCloud Sync Client
|
||||
ownCloud Client
|
||||
oCC
|
||||
Name of the official ownCloud syncing client for desktop, which runs on
|
||||
Windows, Mac OS X and Linux. It is based Mirall, and uses the CSync
|
||||
sync engine for synchronization with the ownCloud server.
|
||||
@@ -23,6 +23,7 @@ Glossary
|
||||
exist in the client directory.
|
||||
|
||||
unique id
|
||||
ETag
|
||||
ID assigned to every file starting with ownCloud server 4.5 and submitted
|
||||
via the HTTP ``Etag``. Used to check if files on client and server have
|
||||
changed.
|
||||
|
||||
|
Before Width: | Height: | Size: 45 KiB |
BIN
doc/images/icon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
doc/images/ignored_files_editor.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
doc/images/menu.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
doc/images/settings_account.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
doc/images/settings_general.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
doc/images/settings_network.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
doc/images/sync_protocol.png
Normal file
|
After Width: | Height: | Size: 168 KiB |
BIN
doc/images/wizard_overview.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
doc/images/wizard_targetfolder.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
doc/images/wizard_url.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
doc/images/wizard_user.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
@@ -6,8 +6,11 @@ Contents
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
install
|
||||
usage
|
||||
introduction
|
||||
accountsetup
|
||||
visualtour
|
||||
advancedusage
|
||||
|
||||
building
|
||||
architecture
|
||||
troubleshooting
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
The latest version of ownCloud client can be obtained at
|
||||
http://owncloud.org/sync-clients/.
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
||||
ownCloud client for Windows is provided as a NSIS-based setup file for
|
||||
machine-wide install.
|
||||
|
||||
Mac OS X
|
||||
--------
|
||||
|
||||
Installing the ownCloud client on your Mac follows the normal app installation
|
||||
pattern:
|
||||
|
||||
1. Download the installation file Click ownCloud-x.y.z.dmg, a window with the
|
||||
2. ownCloud icon opens In that window, drag the ownCloud application into the
|
||||
3. ‘Applications’ folder on the right hand side From ‘Applications’, choose
|
||||
ownCloud
|
||||
|
||||
Linux
|
||||
------
|
||||
|
||||
The ownCloud client is provided as in a convenient repository for a wide range
|
||||
of popular Linux distributions. If you want to build the sources instead.
|
||||
|
||||
Supported distributions are CentOS/RHEL, Fedora, SLES, openSUSE, Ubuntu and
|
||||
Debian.
|
||||
|
||||
To support other distributions, a source build is required.
|
||||
37
doc/introduction.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
This is the documentation for the ownCloud Sync Client, also referred to as
|
||||
the ownCloud Client.
|
||||
|
||||
The ownCloud Sync Client is a desktop program you install on your computer.
|
||||
Specify one ore more directories on the local machine to sync your ownCloud
|
||||
server, and always have your latest files wherever you are. Make a change to the
|
||||
files on one computer, it will flow across the others using these desktop sync
|
||||
clients.
|
||||
|
||||
ownCloud Client is available for Windows, Mac OS X and various Linux
|
||||
distributions. See below for details on how to obtain the Client.
|
||||
|
||||
Obtaining the Client
|
||||
--------------------
|
||||
|
||||
The latest version of the ownCloud Client can be obtained at
|
||||
http://owncloud.org/sync-clients/.
|
||||
|
||||
ownCloud client for **Windows** is provided as a NSIS-based setup file for
|
||||
machine-wide install. Installing the ownCloud client on **Mac OS** follows
|
||||
the normal app bundle installation pattern:
|
||||
|
||||
1. Download the installation file: Click ``ownCloud-x.y.z.dmg``, a window with
|
||||
the ownCloud icon opens.
|
||||
2. In that window, drag the ownCloud application into the ``Applications``
|
||||
folder.
|
||||
3. On the right hand side From ``Applications``, choose ``ownCloud``.
|
||||
|
||||
The ownCloud Client is also provided as in a convenient repository for a wide
|
||||
range of popular **Linux distributions**. If you want to build the sources
|
||||
instead.
|
||||
|
||||
Supported distributions are Fedora, openSUSE, Ubuntu and Debian.
|
||||
To support other distributions, a is required, see :ref:`building-label`
|
||||
1
doc/ocdoc
Submodule
@@ -15,9 +15,6 @@ ownCloud Client supports the following command line switches:
|
||||
``--logflush``
|
||||
flush the log file after every write.
|
||||
|
||||
``--monoicons``
|
||||
Use black/white pictograms for systray.
|
||||
|
||||
``--confdir`` `<dirname>`
|
||||
Use the given configuration directory.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Troubleshooting
|
||||
===============
|
||||
Appendix C: Troubleshooting
|
||||
===========================
|
||||
|
||||
If the client fails to start syncing it basically can have two
|
||||
basic reasons: Either the server setup has a problem or the client
|
||||
@@ -55,6 +55,12 @@ ownCloud is not shared with other syncing apps.
|
||||
not be attempted. In the worst case, doing so can result in data
|
||||
loss.
|
||||
|
||||
If some files do not get take a look at the sync protocol. Some files are
|
||||
automatically automatically being ignored because they are system files,
|
||||
others get ignored because their file name contains characters that cannot
|
||||
be represented on certain file systems. See :ref:`_ignored-files-label` for
|
||||
details.
|
||||
|
||||
If you are operating your own server and use the local storage backend (the
|
||||
default), make sure that ownCloud has exclusive access to the directory.
|
||||
|
||||
@@ -65,13 +71,15 @@ If you are using a different backend, you can try to exclude a bug in the
|
||||
backend by reverting to the local backend.
|
||||
|
||||
Logfiles
|
||||
========
|
||||
--------
|
||||
|
||||
Doing effective debugging requires to provide as much as relevant logs as
|
||||
possible. The log output can help you with tracking down problem, and if you
|
||||
report a bug, you're advised to include the output.
|
||||
|
||||
:Client Logfile:
|
||||
Client Logfile
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Start the client with ``--logwindow``. That opens a window providing a view
|
||||
on the current log. It provides a Save button to let you save the log to a
|
||||
file.
|
||||
@@ -97,11 +105,14 @@ given expiry period.
|
||||
|
||||
For example, for a long running test where you intend to keep the log data of the
|
||||
last two days, this would be the command line:
|
||||
|
||||
```
|
||||
owncloud --logdir /tmp/owncloud_logs --logexpire 48
|
||||
```
|
||||
|
||||
:ownCloud server Logfile:
|
||||
ownCloud server Logfile
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ownCloud server maintains an ownCloud specific logfile as well. It can and
|
||||
must be enabled through the ownCloud Administration page. There you can adjust
|
||||
the loglevel. It is advisable to set it to a verbose level like ``Debug`` or
|
||||
@@ -110,7 +121,9 @@ the loglevel. It is advisable to set it to a verbose level like ``Debug`` or
|
||||
The logfile can be viewed either in the web interface or can be found in the
|
||||
filesystem in the ownCloud server data dir.
|
||||
|
||||
:Webserver Logfiles:
|
||||
Webserver Logfiles
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Also, please take a look at your webservers error log file to check if there
|
||||
are problems. For Apache on Linux, the error logs usually can be found at
|
||||
``/var/log/apache2``. A file called ``error_log`` shows errors like PHP code
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
Usage
|
||||
=====
|
||||
.. index:: usage, client sync usage
|
||||
|
||||
To start ownCloud Client, click on the desktop icon or start it from the
|
||||
application menu. In the system tray, an ownCloud icon appears.
|
||||
|
||||
.. index:: start application
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
ownCloud is represented by an icon in the Desktop's system tray, also known
|
||||
as notification area.
|
||||
|
||||
The clients menu is accessed with a right click (Windows, Linux) or left click
|
||||
(Mac OS).
|
||||
|
||||
The status of the current sync can be observed in the Status dialog, available
|
||||
trough the ``Open status...`` option. On Windows, a left click on the tray icon
|
||||
also opens the status dialog.
|
||||
|
||||
.. note:: Until the intial setup has finished, the Connection Wizard will be
|
||||
shown instead when left-clicking on Windows.
|
||||
|
||||
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
|
||||
-------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
Options
|
||||
-------
|
||||
.. index:: command line switches, command line, options, parameters
|
||||
.. include:: options.rst
|
||||
|
||||
Config File
|
||||
-----------
|
||||
.. index:: config file
|
||||
.. include:: conffile.rst
|
||||
178
doc/visualtour.rst
Normal file
@@ -0,0 +1,178 @@
|
||||
Visual Tour
|
||||
===========
|
||||
|
||||
.. index:: visual tour, usage
|
||||
|
||||
ownCloud Client stays in the background, and is visible as an
|
||||
icon in your system tray (Windows, KDE), status bar (Mac OS X)
|
||||
or notification area (Ubuntu), like so:
|
||||
|
||||
.. image:: images/icon.png
|
||||
|
||||
If a setup is still required, it will open the setup. Otherwise, the
|
||||
main menu is opened, which provides several options and displays
|
||||
progress information:
|
||||
|
||||
.. image:: images/menu.png
|
||||
|
||||
Here is an explanation of the individual items in the menu:
|
||||
|
||||
* ``Open ownCloud in browser``: Opens the ownCloud web interface
|
||||
* ``Open folder 'ownCloud'``: Opens the local folder. If you have
|
||||
defined multiple sync targets, you should see multiple entries
|
||||
here.
|
||||
* **Disk space indicator**: Shows how much space is used up on the server.
|
||||
* Operation indicator: Shows the status of the current sync process, or
|
||||
``Up to date`` if server and client are in sync.
|
||||
* **Recent Changes**: shows the last six files modified by sync operations,
|
||||
and provides access to the Sync Protocol, which lists all changes
|
||||
since the last restart of ownCloud Client.
|
||||
* ``Settings...``: provides access to the settings menu.
|
||||
* ``Help``: Opens a browser to display this help.
|
||||
* ``Quit ownCloud``: Quits ownCloud, ending a currently running sync run.
|
||||
|
||||
The settings dialog is split up in three categories: ``Account Settings``,
|
||||
``General Settings`` and ``Network Settings``:
|
||||
|
||||
Account Settings
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. index:: account settings, user, password, Server URL
|
||||
|
||||
The ``Account Settings`` tab provides an executive summary about the synced
|
||||
folders in your account and allows to modify them. It also provides a more
|
||||
detailed report about the storage usage. Finally, it allows to change
|
||||
the files that ownCloud Client should ignore (for details, see the
|
||||
``Ignored Files Editor`` section below), and to modify various aspects
|
||||
of the current account settings, such as user name, password and server URL.
|
||||
|
||||
.. image:: images/settings_account.png
|
||||
:scale: 50 %
|
||||
|
||||
General Settings
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. index:: general settings, auto start, startup, desktop notifications
|
||||
|
||||
The tab provides several useful options:
|
||||
|
||||
.. image:: images/settings_general.png
|
||||
:scale: 50 %
|
||||
|
||||
* **Launch on System Startup**: This option is automatically activated
|
||||
once a user has conimaged his account. Unchecking the box will cause
|
||||
ownCloud client to not launch on startup for a particular user.
|
||||
* **Show Desktop Nofications**: Do not show bubble notifications whenever
|
||||
a set of sync operations has been performed.
|
||||
* **Use Monochrome Icons**: Use less obstrusive icons. Especially useful
|
||||
on Mac OS.
|
||||
|
||||
The acout menu provides information about authors as well as detailed
|
||||
information about the build conditions. Those are particularly valuable
|
||||
when filing a bug report.
|
||||
|
||||
Network Settings
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. index:: proxy settings, SOCKS, bandwith, throttling, limiting
|
||||
|
||||
This tab consollidates ``Proxy Settings`` and ``Bandwith Limiting``:
|
||||
|
||||
.. image:: images/settings_network.png
|
||||
:scale: 50 %
|
||||
|
||||
Proxy Settings
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
* ``No Proxy``: Check this if ownCloud Client should circumvent the default
|
||||
proxy conimaged on the system.
|
||||
* ``Use system proxy``: Default, will follow the systems proxy settings.
|
||||
On Linux, this will only pick up the value of the variable ``http_proxy``.
|
||||
* ``Specify proxy manually as``: Allows to specify custom proxy settings.
|
||||
If you require to go through a HTTP(S) proxy server such as Squid or Microsoft
|
||||
Forefront TMG, pick ``HTTP(S)``. ``SOCKSv5`` on the other hand is particulary
|
||||
useful in special company LAN setups, or in combination with the OpenSSH
|
||||
dynamic application level forwarding feature (see ``ssh -D``).
|
||||
* ``Host``: Enter the host name or IP address of your proxy server, followed
|
||||
by the port number. HTTP proxies usually listen on Ports 8080 (default) or
|
||||
3128. SOCKS server usually listen on port 1080.
|
||||
* ``Proxy Server requires authentication``: Should be checked if the proxy
|
||||
server does not allow anonymous usage. If you check this option, you must
|
||||
provide username and password in the fields below, or ownless Cloud will no
|
||||
longer be able to connect successfully.
|
||||
|
||||
Bandwidth Limiting
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``Download Bandwidth`` (i.e. the bandwidth available for data flowing
|
||||
from the ownCloud Server to the client) can be either ``Unlimited``
|
||||
(the default), or limited to a custom value, specified in bytes
|
||||
|
||||
The ``Upload Bandwith`` (i.e. the bandwith available for data flowing
|
||||
from the ownCloud Client to the server) additionally has the option
|
||||
to ``Limit automatically``: When this option is checked, the ownCloud
|
||||
Client will surrender available upstream bandwith to other applications.
|
||||
Use this option if you expirience problems with real time communication,
|
||||
such as Skype or other VoIP software, in conjunction with ownCloud Client.
|
||||
This is commonly the case with asymmetric internet connection, such as
|
||||
certain DSL lines with very limited upstream capacity.
|
||||
|
||||
ownCloud Client will pick up changes immediately, but ongoing operations
|
||||
will finish using the old settings.
|
||||
|
||||
The Sync Protocol
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. index:: sync protocol
|
||||
|
||||
The ``Sync Protocol`` window, which can be invoked from either from the main
|
||||
menu (``Recent Changes`` -> ``Details...``) or the ``Account Settings``
|
||||
(``Info`` button), will provide you with an in-depth summary of the recent
|
||||
sync activity. It will also show files that have not been synched (ignored
|
||||
files). Those are ignored either because they are listed in the ignored
|
||||
files list (see ``Ignored Files Editor`` section below), or because they
|
||||
cannot be synced in a cross-platform manner because they contain special
|
||||
characters that cannot be stored on certain file systems.
|
||||
|
||||
.. image:: images/sync_protocol.png
|
||||
:scale: 50 %
|
||||
|
||||
.. _ignoredFilesEditor-label:
|
||||
|
||||
The Ignored Files Editor
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. index:: ignored files, exclude files, pattern
|
||||
|
||||
The ignored files editor allows adding patterns for files or directories
|
||||
that should be excluded from the sync process. Next to normal characters,
|
||||
wildcards can be used to match an arbitrary number of characters, designated
|
||||
by an asterisk (``*``) or a single character, designated by a question mark
|
||||
(``?``).
|
||||
|
||||
Global defaults cannot be directly modified within the editor. Hovering
|
||||
with the mouse will reveal the location of the global exclude definition
|
||||
file.
|
||||
|
||||
In addition to this list, ownCloud Client always excludes files with
|
||||
characters that cannot be synched down to other file systems,
|
||||
see :ref:`ignored-files-label`.
|
||||
|
||||
.. note:: Modifying the global exclude definition file might render the
|
||||
client unusable or cause undesired behavior.
|
||||
|
||||
.. note:: Custom entries are currently not validated for syntactical
|
||||
correctness by the editor, but might fail to load correctly.
|
||||
|
||||
.. image:: images/ignored_files_editor.png
|
||||
:scale: 50%
|
||||
|
||||
Examples:
|
||||
^^^^^^^^^
|
||||
+-----------+------------------------------+
|
||||
| Pattern | Matches |
|
||||
+===========+==============================+
|
||||
| ``~$*`` | ``~$foo``, ``~$example.doc`` |
|
||||
+-----------+------------------------------+
|
||||
| ``fl?p`` | ``flip``, ``flap`` |
|
||||
+-----------+------------------------------+
|
||||
@@ -4,4 +4,5 @@ Type=Application
|
||||
Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_SHORTNAME@
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing
|
||||
|
||||
@@ -11,7 +11,7 @@ else()
|
||||
set(theme_dir ${CMAKE_CURRENT_SOURCE_DIR}/../theme)
|
||||
endif()
|
||||
|
||||
set(synclib_NAME ${APPLICATION_SHORTNAME}sync)
|
||||
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
|
||||
|
||||
set(mirall_UI
|
||||
mirall/folderwizardsourcepage.ui
|
||||
@@ -22,7 +22,6 @@ mirall/generalsettings.ui
|
||||
mirall/networksettings.ui
|
||||
mirall/accountsettings.ui
|
||||
mirall/ignorelisteditor.ui
|
||||
mirall/fileitemdialog.ui
|
||||
mirall/itemprogressdialog.ui
|
||||
wizard/owncloudsetupnocredspage.ui
|
||||
wizard/owncloudhttpcredspage.ui
|
||||
@@ -169,8 +168,8 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
)
|
||||
if(NOT WIN32)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_SHORTNAME}.desktop)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_SHORTNAME}.desktop DESTINATION share/applications )
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop DESTINATION share/applications )
|
||||
endif()
|
||||
else()
|
||||
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
|
||||
@@ -193,7 +192,6 @@ set(mirall_SRCS
|
||||
mirall/occinfo.cpp
|
||||
mirall/sslerrordialog.cpp
|
||||
mirall/logbrowser.cpp
|
||||
mirall/fileitemdialog.cpp
|
||||
mirall/settingsdialog.cpp
|
||||
mirall/generalsettings.cpp
|
||||
mirall/networksettings.cpp
|
||||
@@ -218,7 +216,6 @@ set(mirall_HEADERS
|
||||
mirall/updatedetector.h
|
||||
mirall/sslerrordialog.h
|
||||
mirall/logbrowser.h
|
||||
mirall/fileitemdialog.h
|
||||
mirall/settingsdialog.h
|
||||
mirall/generalsettings.h
|
||||
mirall/networksettings.h
|
||||
@@ -257,7 +254,7 @@ set( final_src
|
||||
include( AddAppIconMacro )
|
||||
set(ownCloud_old ${ownCloud})
|
||||
|
||||
kde4_add_app_icon( ownCloud "${theme_dir}/colored/${APPLICATION_SHORTNAME}-icon*.png")
|
||||
kde4_add_app_icon( ownCloud "${theme_dir}/colored/${APPLICATION_EXECUTABLE}-icon*.png")
|
||||
list(APPEND final_src ${ownCloud})
|
||||
set(ownCloud ${ownCloud_old})
|
||||
|
||||
@@ -265,16 +262,15 @@ 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" )
|
||||
file( GLOB _icons "${theme_dir}/colored/${APPLICATION_EXECUTABLE}-icon-*.png" )
|
||||
foreach( _file ${_icons} )
|
||||
string( REPLACE "${theme_dir}/colored/${APPLICATION_SHORTNAME}-icon-" "" _res ${_file} )
|
||||
string( REPLACE "${theme_dir}/colored/${APPLICATION_EXECUTABLE}-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 )
|
||||
install( FILES ${_file} RENAME ${APPLICATION_EXECUTABLE}.png DESTINATION ${DATADIR}/icons/hicolor/${_res}x${_res}/apps )
|
||||
endforeach( _file )
|
||||
endif(NOT WIN32)
|
||||
|
||||
install(FILES ${mirall_I18N} DESTINATION share/${APPLICATION_SHORTNAME}/i18n)
|
||||
install(FILES ${mirall_I18N} DESTINATION share/${APPLICATION_EXECUTABLE}/i18n)
|
||||
|
||||
# we may not add MACOSX_BUNDLE here, if not building one
|
||||
|
||||
|
||||
16
src/main.cpp
@@ -23,7 +23,12 @@ int main(int argc, char **argv)
|
||||
|
||||
Mirall::Application app(argc, argv);
|
||||
app.initialize();
|
||||
|
||||
|
||||
if( app.giveHelp() ) {
|
||||
app.showHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if the application is already running, notify it.
|
||||
if( app.isRunning() ) {
|
||||
QStringList args = app.arguments();
|
||||
@@ -34,7 +39,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable() && qgetenv("DESKTOP_SESSION") != "ubuntu") {
|
||||
QMessageBox::critical(0, qApp->translate("main.cpp", "System Tray not available"),
|
||||
qApp->translate("main.cpp", "%1 requires on a working system tray. "
|
||||
"If you are running XFCE, please follow "
|
||||
@@ -43,11 +48,6 @@ int main(int argc, char **argv)
|
||||
.arg(Mirall::Theme::instance()->appNameGUI()));
|
||||
}
|
||||
}
|
||||
// if help requested, show on command line and exit.
|
||||
if( ! app.giveHelp() ) {
|
||||
return app.exec();
|
||||
} else {
|
||||
app.showHelp();
|
||||
}
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#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"
|
||||
@@ -34,9 +33,21 @@
|
||||
#include <QDesktopServices>
|
||||
#include <QListWidgetItem>
|
||||
#include <QMessageBox>
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
static const char progressBarStyleC[] =
|
||||
"QProgressBar {"
|
||||
"border: 1px solid grey;"
|
||||
"border-radius: 5px;"
|
||||
"text-align: center;"
|
||||
"}"
|
||||
"QProgressBar::chunk {"
|
||||
"background-color: %1; width: 1px;"
|
||||
"}";
|
||||
|
||||
AccountSettings::AccountSettings(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::AccountSettings),
|
||||
@@ -47,6 +58,7 @@ AccountSettings::AccountSettings(QWidget *parent) :
|
||||
_model = new FolderStatusModel;
|
||||
_model->setParent(this);
|
||||
FolderStatusDelegate *delegate = new FolderStatusDelegate;
|
||||
delegate->setParent(this);
|
||||
|
||||
ui->_folderList->setItemDelegate( delegate );
|
||||
ui->_folderList->setModel( _model );
|
||||
@@ -54,13 +66,16 @@ AccountSettings::AccountSettings(QWidget *parent) :
|
||||
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);
|
||||
|
||||
QAction *resetFolderAction = new QAction(this);
|
||||
resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5));
|
||||
connect(resetFolderAction, SIGNAL(triggered()), SLOT(slotResetCurrentFolder()));
|
||||
addAction(resetFolderAction);
|
||||
|
||||
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()));
|
||||
@@ -70,6 +85,8 @@ AccountSettings::AccountSettings(QWidget *parent) :
|
||||
connect(ui->_folderList, SIGNAL(clicked(QModelIndex)), SLOT(slotFolderActivated(QModelIndex)));
|
||||
connect(ui->_folderList, SIGNAL(doubleClicked(QModelIndex)),SLOT(slotDoubleClicked(QModelIndex)));
|
||||
|
||||
QColor color = palette().highlight().color();
|
||||
ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));
|
||||
ownCloudInfo *ocInfo = ownCloudInfo::instance();
|
||||
slotUpdateQuota(ocInfo->lastQuotaTotalBytes(), ocInfo->lastQuotaUsedBytes());
|
||||
connect(ocInfo, SIGNAL(quotaUpdated(qint64,qint64)), SLOT(slotUpdateQuota(qint64,qint64)));
|
||||
@@ -86,8 +103,6 @@ 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 );
|
||||
|
||||
@@ -140,6 +155,7 @@ void AccountSettings::slotFolderWizardAccepted()
|
||||
folderMan->slotScheduleAllFolders();
|
||||
emit folderChanged();
|
||||
}
|
||||
buttonsSetEnabled();
|
||||
}
|
||||
|
||||
void AccountSettings::slotFolderWizardRejected()
|
||||
@@ -185,7 +201,6 @@ void AccountSettings::buttonsSetEnabled()
|
||||
bool isSelected = selected.isValid();
|
||||
|
||||
ui->_ButtonEnable->setEnabled(isSelected);
|
||||
ui->_ButtonReset->setEnabled(isSelected);
|
||||
ui->_ButtonRemove->setEnabled(isSelected);
|
||||
ui->_ButtonInfo->setEnabled(isSelected);
|
||||
}
|
||||
@@ -207,7 +222,11 @@ void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f )
|
||||
SyncResult res = f->syncResult();
|
||||
SyncResult::Status status = res.status();
|
||||
|
||||
QString errors = res.errorStrings().join(QLatin1String("<br/>"));
|
||||
QStringList errorList = res.errorStrings();
|
||||
QString errors;
|
||||
if( ! errorList.isEmpty() ) {
|
||||
errors = res.errorStrings().join(QLatin1String("<br/>"));
|
||||
}
|
||||
|
||||
Theme *theme = Theme::instance();
|
||||
item->setData( theme->statusHeaderText( status ), Qt::ToolTipRole );
|
||||
@@ -219,6 +238,12 @@ void AccountSettings::folderToModelItem( QStandardItem *item, Folder *f )
|
||||
item->setData( theme->statusHeaderText( status ), FolderStatusDelegate::FolderStatus );
|
||||
item->setData( errors, FolderStatusDelegate::FolderErrorMsg );
|
||||
|
||||
if( errors.isEmpty() && (status == SyncResult::Error ||
|
||||
status == SyncResult::SetupError ||
|
||||
status == SyncResult::Unavailable )) {
|
||||
item->setData( theme->statusHeaderText(status), FolderStatusDelegate::FolderErrorMsg);
|
||||
}
|
||||
|
||||
bool ongoing = false;
|
||||
item->setData( QVariant(res.warnCount()), FolderStatusDelegate::WarningCount );
|
||||
if( status == SyncResult::SyncRunning ) {
|
||||
@@ -260,8 +285,10 @@ void AccountSettings::slotResetCurrentFolder()
|
||||
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),
|
||||
"<p><b>Note:</b> This function is designed for maintenance purposes only. "
|
||||
"No files will be removed, but this can cause significant data traffic and "
|
||||
"take several minutes or hours to complete, depending on the size of the folder. "
|
||||
"Only use this option if advised by your administrator.</p>").arg(alias),
|
||||
QMessageBox::Yes|QMessageBox::No );
|
||||
if( ret == QMessageBox::Yes ) {
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
@@ -307,9 +334,10 @@ void AccountSettings::setFolderList( const Folder::Map &folders )
|
||||
slotAddFolder( f );
|
||||
}
|
||||
|
||||
QModelIndex idx = _model->index(0, 0);
|
||||
if (idx.isValid())
|
||||
QModelIndex idx = _model->index(0, 0);
|
||||
if (idx.isValid()) {
|
||||
ui->_folderList->setCurrentIndex(idx);
|
||||
}
|
||||
buttonsSetEnabled();
|
||||
|
||||
}
|
||||
@@ -352,7 +380,7 @@ void AccountSettings::slotEnableCurrentFolder()
|
||||
|
||||
// this sets the folder status to disabled but does not interrupt it.
|
||||
Folder *f = folderMan->folder( alias );
|
||||
if( f && !folderEnabled ) {
|
||||
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"),
|
||||
@@ -395,11 +423,6 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
|
||||
item = _model->item( ++row );
|
||||
}
|
||||
|
||||
#if 0
|
||||
if( !_fileItemDialog.isNull() && _fileItemDialog->isVisible() ) {
|
||||
_fileItemDialog->setSyncResult( FolderMan::instance()->syncResult(folder) );
|
||||
}
|
||||
#endif
|
||||
if( item ) {
|
||||
folderToModelItem( item, folder );
|
||||
} else {
|
||||
@@ -425,7 +448,9 @@ void AccountSettings::slotOCInfo( const QString& url, const QString& versionStr,
|
||||
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) );
|
||||
QUrl safeUrl(url);
|
||||
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
|
||||
ui->connectLabel->setText( tr("Connected to <a href=\"%1\">%2</a>.").arg(url, safeUrl.toString()) );
|
||||
ui->connectLabel->setToolTip( tr("Version: %1 (%2)").arg(versionStr).arg(version));
|
||||
ui->_ButtonAdd->setEnabled(true);
|
||||
|
||||
@@ -534,6 +559,15 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
||||
// stay with the previous kind-string for Context.
|
||||
if( progress.kind != Progress::Context ) {
|
||||
_kindContext = Progress::asActionString(progress.kind);
|
||||
} else {
|
||||
if( _kindContext.isEmpty() ) {
|
||||
// empty kind context means that the dialog was opened after the action
|
||||
// was started.
|
||||
Progress::Kind kind = ProgressDispatcher::instance()->currentFolderContext(progress.folder);
|
||||
if( kind != Progress::Invalid ) {
|
||||
_kindContext = Progress::asActionString(kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
QString kindString = _kindContext;
|
||||
|
||||
@@ -637,13 +671,23 @@ void AccountSettings::slotHideProgress()
|
||||
|
||||
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));
|
||||
if( total > 0 ) {
|
||||
ui->quotaProgressBar->setVisible(true);
|
||||
ui->quotaInfoLabel->setVisible(true);
|
||||
ui->quotaProgressBar->setEnabled(true);
|
||||
// workaround the label only accepting ints (which may be only 32 bit wide)
|
||||
ui->quotaProgressBar->setMaximum(100);
|
||||
int qVal = qRound(used/(double)total * 100);
|
||||
if( qVal > 100 ) qVal = 100;
|
||||
ui->quotaProgressBar->setValue(qVal);
|
||||
QString usedStr = Utility::octetsToString(used);
|
||||
QString totalStr = Utility::octetsToString(total);
|
||||
ui->quotaLabel->setText(tr("%1 of %2 in use.").arg(usedStr, totalStr));
|
||||
} else {
|
||||
ui->quotaProgressBar->setVisible(false);
|
||||
ui->quotaInfoLabel->setVisible(false);
|
||||
ui->quotaLabel->setText(tr("Currently there is no storage usage information available."));
|
||||
}
|
||||
}
|
||||
|
||||
void AccountSettings::slotIgnoreFilesEditor()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>607</width>
|
||||
<height>385</height>
|
||||
<height>382</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -30,16 +30,6 @@
|
||||
</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">
|
||||
@@ -71,7 +61,7 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="_ButtonAdd">
|
||||
<property name="text">
|
||||
<string>Add Sync...</string>
|
||||
<string>Add Folder...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -82,19 +72,6 @@
|
||||
</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">
|
||||
@@ -102,13 +79,6 @@
|
||||
</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">
|
||||
@@ -161,7 +131,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="quotaInfoLabel">
|
||||
<property name="text">
|
||||
<string><b>Note:</b> Some folders, including network mounted or shared folders, might have different limits.</string>
|
||||
</property>
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mirall/application.h"
|
||||
#include "mirall/systray.h"
|
||||
#include "mirall/folder.h"
|
||||
@@ -81,8 +83,7 @@ static const char optionsC[] =
|
||||
QString applicationTrPath()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
// FIXME - proper path!
|
||||
return QString::fromLatin1("/usr/share/%1/i18n/").arg(Theme::instance()->appName());
|
||||
return QString::fromLatin1(DATADIR"/i18n/");
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
return QApplication::applicationDirPath()+QLatin1String("/../Resources/Translations"); // path defaults to app dir.
|
||||
@@ -113,11 +114,12 @@ Application::Application(int &argc, char **argv) :
|
||||
setWindowIcon( _theme->applicationIcon() );
|
||||
|
||||
parseOptions(arguments());
|
||||
setupTranslations();
|
||||
setupLogBrowser();
|
||||
//no need to waste time;
|
||||
if ( _helpOnly ) return;
|
||||
|
||||
setupLogBrowser();
|
||||
setupTranslations();
|
||||
|
||||
connect( this, SIGNAL(messageReceived(QString)), SLOT(slotParseOptions(QString)));
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString)),
|
||||
this, SLOT(slotShowTrayMessage(QString,QString)));
|
||||
@@ -182,6 +184,11 @@ Application::Application(int &argc, char **argv) :
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
if (_settingsDialog) {
|
||||
delete _settingsDialog.data();
|
||||
}
|
||||
|
||||
delete _logBrowser;
|
||||
delete _tray; // needed, see ctor
|
||||
|
||||
qDebug() << "* Mirall shutdown";
|
||||
@@ -329,7 +336,7 @@ void Application::setupActions()
|
||||
QObject::connect(_actionSettings, SIGNAL(triggered(bool)), SLOT(slotSettings()));
|
||||
_actionHelp = new QAction(tr("Help"), this);
|
||||
QObject::connect(_actionHelp, SIGNAL(triggered(bool)), SLOT(slotHelp()));
|
||||
_actionQuit = new QAction(tr("Quit"), this);
|
||||
_actionQuit = new QAction(tr("Quit %1").arg(_theme->appNameGUI()), this);
|
||||
QObject::connect(_actionQuit, SIGNAL(triggered(bool)), SLOT(quit()));
|
||||
}
|
||||
|
||||
@@ -362,7 +369,7 @@ void Application::setupContextMenu()
|
||||
_recentActionsMenu->addAction(_actionRecent);
|
||||
} else {
|
||||
_contextMenu = new QMenu();
|
||||
_recentActionsMenu = _contextMenu->addMenu(tr("Recent Changes..."));
|
||||
_recentActionsMenu = _contextMenu->addMenu(tr("Recent Changes"));
|
||||
// this must be called only once after creating the context menu, or
|
||||
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
||||
_tray->setContextMenu(_contextMenu);
|
||||
@@ -379,7 +386,7 @@ void Application::setupContextMenu()
|
||||
Folder *folder = folderMan->map().value(li.first());
|
||||
if( folder ) {
|
||||
// if there is singleFolder mode, a generic open action is displayed.
|
||||
QAction *action = new QAction( tr("Open local folder '%1'").arg(_theme->appNameGUI()), this);
|
||||
QAction *action = new QAction( tr("Open %1 folder").arg(_theme->appNameGUI()), this);
|
||||
connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map()));
|
||||
_folderOpenActionMapper->setMapping( action, folder->alias() );
|
||||
|
||||
@@ -407,7 +414,9 @@ void Application::setupContextMenu()
|
||||
_contextMenu->addMenu(_recentActionsMenu);
|
||||
_contextMenu->addSeparator();
|
||||
_contextMenu->addAction(_actionSettings);
|
||||
_contextMenu->addAction(_actionHelp);
|
||||
if (!_theme->helpUrl().isEmpty()) {
|
||||
_contextMenu->addAction(_actionHelp);
|
||||
}
|
||||
_contextMenu->addSeparator();
|
||||
|
||||
_contextMenu->addAction(_actionQuit);
|
||||
@@ -418,8 +427,8 @@ void Application::setupLogBrowser()
|
||||
// might be called from second instance
|
||||
if (!_logBrowser) {
|
||||
// init the log browser.
|
||||
_logBrowser = new LogBrowser;
|
||||
qInstallMsgHandler( mirallLogCatcher );
|
||||
_logBrowser = new LogBrowser;
|
||||
// ## TODO: allow new log name maybe?
|
||||
if (!_logDirectory.isEmpty()) {
|
||||
enterNextLogFile();
|
||||
@@ -510,6 +519,9 @@ void Application::slotSetupProxy()
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
FolderMan::instance()->setDirtyProxy(true);
|
||||
FolderMan::instance()->slotScheduleAllFolders();
|
||||
}
|
||||
|
||||
void Application::slotRefreshQuotaDisplay( qint64 total, qint64 used )
|
||||
@@ -522,7 +534,7 @@ void Application::slotRefreshQuotaDisplay( qint64 total, qint64 used )
|
||||
double percent = used/(double)total*100;
|
||||
QString percentFormatted = Utility::compactFormatDouble(percent, 1);
|
||||
QString totalFormatted = Utility::octetsToString(total);
|
||||
_actionQuota->setText(tr("%1% of %2 used").arg(percentFormatted).arg(totalFormatted));
|
||||
_actionQuota->setText(tr("%1% of %2 in use").arg(percentFormatted).arg(totalFormatted));
|
||||
}
|
||||
|
||||
void Application::slotUseMonoIconsChanged(bool)
|
||||
@@ -551,9 +563,9 @@ void Application::rebuildRecentMenus()
|
||||
_recentActionsMenu->addAction(tr("No items synced recently"));
|
||||
} else {
|
||||
QListIterator<Progress::Info> i(progressInfoList);
|
||||
i.toBack();
|
||||
while(i.hasPrevious()) {
|
||||
Progress::Info info = i.previous();
|
||||
|
||||
while(i.hasNext()) {
|
||||
Progress::Info info = i.next();
|
||||
QString kindStr = Progress::asResultString(info.kind);
|
||||
QString timeStr = info.timestamp.toString("hh:mm");
|
||||
|
||||
@@ -594,7 +606,7 @@ void Application::slotUpdateProgress(const QString &folder, const Progress::Info
|
||||
|
||||
void Application::slotDisplayIdle()
|
||||
{
|
||||
_actionStatus->setText(tr("In Sync"));
|
||||
_actionStatus->setText(tr("Up to date"));
|
||||
}
|
||||
|
||||
void Application::slotHelp()
|
||||
|
||||
@@ -140,19 +140,19 @@ QString CSyncThread::csyncErrorToString( CSYNC_ERROR_CODE err, const char *errSt
|
||||
errStr = tr("A HTTP transmission error happened.");
|
||||
break;
|
||||
case CSYNC_ERR_PERM:
|
||||
errStr = tr("CSync failed due to not handled permission deniend.");
|
||||
errStr = tr("CSync: Permission deniend.");
|
||||
break;
|
||||
case CSYNC_ERR_NOT_FOUND:
|
||||
errStr = tr("CSync failed to find a specific file.");
|
||||
errStr = tr("CSync: File not found.");
|
||||
break;
|
||||
case CSYNC_ERR_EXISTS:
|
||||
errStr = tr("CSync tried to create a directory that already exists.");
|
||||
errStr = tr("CSync: Directory already exists.");
|
||||
break;
|
||||
case CSYNC_ERR_NOSPC:
|
||||
errStr = tr("CSync: No space on %1 server available.").arg(Theme::instance()->appNameGUI());
|
||||
errStr = tr("CSync: No space left on %1 server.").arg(Theme::instance()->appNameGUI());
|
||||
break;
|
||||
case CSYNC_ERR_UNSPEC:
|
||||
errStr = tr("CSync unspecified error.");
|
||||
errStr = tr("CSync: unspecified error.");
|
||||
|
||||
default:
|
||||
errStr = tr("An internal error number %1 happend.").arg( (int) err );
|
||||
@@ -187,7 +187,9 @@ int CSyncThread::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
item._file = QString::fromUtf8( file->path );
|
||||
item._instruction = file->instruction;
|
||||
item._dir = SyncFileItem::None;
|
||||
|
||||
if(file->error_string) {
|
||||
item._errorString = QString::fromUtf8(file->error_string);
|
||||
}
|
||||
SyncFileItem::Direction dir;
|
||||
|
||||
int re = 0;
|
||||
@@ -257,7 +259,7 @@ int CSyncThread::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
|
||||
int CSyncThread::treewalkError(TREE_WALK_FILE* file)
|
||||
{
|
||||
SyncFileItem item;
|
||||
SyncFileItem item; // only used for search.
|
||||
item._file= QString::fromUtf8(file->path);
|
||||
int indx = _syncedItems.indexOf(item);
|
||||
|
||||
@@ -269,6 +271,7 @@ int CSyncThread::treewalkError(TREE_WALK_FILE* file)
|
||||
file->instruction == CSYNC_INSTRUCTION_ERROR) ) {
|
||||
_mutex.lock();
|
||||
_syncedItems[indx]._instruction = file->instruction;
|
||||
_syncedItems[indx]._errorString = QString::fromUtf8(file->error_string);
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
@@ -335,14 +338,14 @@ void CSyncThread::startSync()
|
||||
|
||||
int downloadLimit = 0;
|
||||
if (cfg.useDownloadLimit()) {
|
||||
downloadLimit = cfg.downloadLimit();
|
||||
downloadLimit = cfg.downloadLimit() * 1000;
|
||||
}
|
||||
csync_set_module_property(_csync_ctx, "bandwidth_limit_download", &downloadLimit);
|
||||
|
||||
int uploadLimit = -75; // 75%
|
||||
int useUpLimit = cfg.useUploadLimit();
|
||||
if ( useUpLimit >= 1) {
|
||||
uploadLimit = cfg.uploadLimit();
|
||||
uploadLimit = cfg.uploadLimit() * 1000;
|
||||
} else if (useUpLimit == 0) {
|
||||
uploadLimit = 0;
|
||||
}
|
||||
@@ -494,7 +497,7 @@ void CSyncThread::cb_progress( CSYNC_PROGRESS *progress, void *userdata )
|
||||
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();
|
||||
pInfo.timestamp = QDateTime::currentDateTime();
|
||||
|
||||
// Connect to something in folder!
|
||||
thread->transmissionProgress( pInfo );
|
||||
|
||||
@@ -1,309 +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/fileitemdialog.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
|
||||
#define TYPE_DELETED 4
|
||||
#define TYPE_ERROR 5
|
||||
#define TYPE_RENAME 6
|
||||
#define TYPE_IGNORE 7
|
||||
|
||||
#define FILE_TYPE 100
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
FileItemDialog::FileItemDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
_ui(new Ui::FileItemDialog)
|
||||
{
|
||||
_ui->setupUi(this);
|
||||
connect(_ui->_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 );
|
||||
|
||||
_ui->_treeWidget->setColumnWidth(0, 480);
|
||||
_timer.setInterval(1000);
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotSetFolderMessage()));
|
||||
|
||||
QPushButton *copyBtn = _ui->_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;
|
||||
|
||||
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;
|
||||
default:
|
||||
folderMessage = tr( "Undefined Error State." );
|
||||
}
|
||||
|
||||
_folderMessage = folderMessage;
|
||||
_lastSyncTime = result.syncTime();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
slotSetFolderMessage();
|
||||
if( syncStatus == SyncResult::SyncRunning ) {
|
||||
_timer.stop();
|
||||
} else {
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
setSyncFileItems( result.syncFileItemVector() );
|
||||
|
||||
}
|
||||
|
||||
void FileItemDialog::slotSetFolderMessage()
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
int secs = _lastSyncTime.secsTo(now);
|
||||
|
||||
if (secs < 60)
|
||||
_ui->_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));
|
||||
}
|
||||
|
||||
void FileItemDialog::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);
|
||||
Logger::instance()->postGuiLog(tr("Copied to clipboard"), tr("The sync protocol has been copied to the clipboard."));
|
||||
}
|
||||
|
||||
void FileItemDialog::accept()
|
||||
{
|
||||
_timer.stop();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void FileItemDialog::setSyncFileItems( const SyncFileItemVector& list )
|
||||
{
|
||||
_ui->_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->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||
_ui->_treeWidget->addTopLevelItem(_syncedFileItem);
|
||||
|
||||
strings.clear();
|
||||
strings.append(tr("New Files"));
|
||||
_newFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_NEW );
|
||||
_newFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||
_ui->_treeWidget->addTopLevelItem(_newFileItem);
|
||||
|
||||
strings.clear();
|
||||
strings.append(tr("Deleted Files"));
|
||||
_deletedFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_DELETED );
|
||||
_deletedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||
_ui->_treeWidget->addTopLevelItem(_deletedFileItem);
|
||||
|
||||
strings.clear();
|
||||
strings.append(tr("Renamed Files"));
|
||||
_renamedFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_RENAME);
|
||||
_renamedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||
_ui->_treeWidget->addTopLevelItem(_renamedFileItem);
|
||||
|
||||
strings.clear();
|
||||
strings.append(tr("Ignored Files"));
|
||||
_ignoredFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_IGNORE);
|
||||
_ignoredFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||
_ui->_treeWidget->addTopLevelItem(_renamedFileItem);
|
||||
|
||||
strings.clear();
|
||||
strings.append(tr("Errors"));
|
||||
_errorFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_ERROR );
|
||||
_errorFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||
_ui->_treeWidget->addTopLevelItem(_errorFileItem);
|
||||
|
||||
strings.clear();
|
||||
strings.append(tr("Conflicts"));
|
||||
_conflictFileItem = new QTreeWidgetItem( _ui->_treeWidget, strings, TYPE_CONFLICT);
|
||||
_conflictFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||
_ui->_treeWidget->addTopLevelItem(_conflictFileItem);
|
||||
|
||||
QList<QTreeWidgetItem*> syncedItems;
|
||||
QList<QTreeWidgetItem*> renamedItems;
|
||||
QList<QTreeWidgetItem*> newItems;
|
||||
QList<QTreeWidgetItem*> deletedItems;
|
||||
QList<QTreeWidgetItem*> ignoredItems;
|
||||
QList<QTreeWidgetItem*> conflictItems;
|
||||
QList<QTreeWidgetItem*> errorItems;
|
||||
|
||||
quint64 overall_files = 0;
|
||||
|
||||
foreach( SyncFileItem item, list ) {
|
||||
overall_files++;
|
||||
|
||||
QString dir;
|
||||
QStringList str( item._file );
|
||||
if( item._dir == SyncFileItem::Up ) dir = tr("Uploaded");
|
||||
if( item._dir == SyncFileItem::Down ) dir = tr("Downloaded");
|
||||
str << dir;
|
||||
|
||||
switch( item._instruction ) {
|
||||
case CSYNC_INSTRUCTION_NONE:
|
||||
// do nothing.
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_EVAL:
|
||||
// should not happen
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_REMOVE:
|
||||
case CSYNC_INSTRUCTION_DELETED:
|
||||
deletedItems.append( new QTreeWidgetItem(_deletedFileItem, str, FILE_TYPE) );
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_RENAME:
|
||||
renamedItems.append( new QTreeWidgetItem(_renamedFileItem, str, FILE_TYPE) );
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_NEW:
|
||||
newItems.append( new QTreeWidgetItem(_newFileItem, str, FILE_TYPE) );
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_CONFLICT:
|
||||
conflictItems.append( new QTreeWidgetItem(_conflictFileItem, str, FILE_TYPE) );
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_IGNORE:
|
||||
ignoredItems.append( new QTreeWidgetItem(_ignoredFileItem, str, FILE_TYPE) );
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_SYNC:
|
||||
case CSYNC_INSTRUCTION_UPDATED:
|
||||
syncedItems.append( new QTreeWidgetItem(_syncedFileItem, str, FILE_TYPE) );
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_STAT_ERROR:
|
||||
case CSYNC_INSTRUCTION_ERROR:
|
||||
errorItems.append( new QTreeWidgetItem(_errorFileItem, str, FILE_TYPE) );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
formatHeaderItem( _syncedFileItem, syncedItems );
|
||||
formatHeaderItem( _newFileItem, newItems );
|
||||
formatHeaderItem( _deletedFileItem, deletedItems );
|
||||
formatHeaderItem( _renamedFileItem, renamedItems );
|
||||
formatHeaderItem( _errorFileItem, errorItems );
|
||||
formatHeaderItem( _conflictFileItem, conflictItems );
|
||||
formatHeaderItem( _ignoredFileItem, ignoredItems );
|
||||
|
||||
}
|
||||
|
||||
void FileItemDialog::formatHeaderItem( QTreeWidgetItem *header, const QList<QTreeWidgetItem*>& list )
|
||||
{
|
||||
if( !header ) return;
|
||||
|
||||
header->addChildren( list );
|
||||
int count = list.count();
|
||||
#if LEAVE_THAT_TO_DESIGNERS
|
||||
QColor col("#adc5d3");
|
||||
header->setBackgroundColor(0, col);
|
||||
header->setBackgroundColor(1, col);
|
||||
#endif
|
||||
header->setText(1, QString::number( count ));
|
||||
if( count ) {
|
||||
QFont font;
|
||||
font.setWeight( QFont::Bold );
|
||||
header->setFont(0, font);
|
||||
header->setFont(1, font);
|
||||
header->setExpanded(true);
|
||||
} else {
|
||||
header->setExpanded(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +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 <QTimer>
|
||||
|
||||
#include "mirall/syncfileitem.h"
|
||||
|
||||
#include "ui_fileitemdialog.h"
|
||||
|
||||
namespace Mirall {
|
||||
class SyncResult;
|
||||
|
||||
namespace Ui {
|
||||
class FileItemDialog;
|
||||
}
|
||||
|
||||
class FileItemDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FileItemDialog(QWidget *parent = 0);
|
||||
~FileItemDialog();
|
||||
void setSyncResult( const SyncResult& );
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
|
||||
protected slots:
|
||||
void slotSetFolderMessage();
|
||||
void copyToClipboard();
|
||||
|
||||
private:
|
||||
void setSyncFileItems( const SyncFileItemVector& list );
|
||||
void formatHeaderItem( QTreeWidgetItem *, const QList<QTreeWidgetItem*>& );
|
||||
|
||||
QTreeWidgetItem *_newFileItem;
|
||||
QTreeWidgetItem *_syncedFileItem;
|
||||
QTreeWidgetItem *_deletedFileItem;
|
||||
QTreeWidgetItem *_renamedFileItem;
|
||||
QTreeWidgetItem *_errorFileItem;
|
||||
QTreeWidgetItem *_conflictFileItem;
|
||||
QTreeWidgetItem *_ignoredFileItem;
|
||||
|
||||
QString _folderMessage;
|
||||
QDateTime _lastSyncTime;
|
||||
QTimer _timer;
|
||||
Ui::FileItemDialog *_ui;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // FILEITEMDIALOG_H
|
||||
@@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Mirall::FileItemDialog</class>
|
||||
<widget class="QWidget" name="Mirall::FileItemDialog">
|
||||
<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>2</number>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">2</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>
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "mirall/logger.h"
|
||||
#include "mirall/owncloudinfo.h"
|
||||
#include "mirall/utility.h"
|
||||
#include "folderman.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
|
||||
#include <QDebug>
|
||||
@@ -69,10 +70,6 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP
|
||||
|
||||
_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();
|
||||
|
||||
@@ -208,7 +205,7 @@ void Folder::setSyncEnabled( bool doit )
|
||||
_syncResult.clearErrors();
|
||||
evaluateSync( QStringList() );
|
||||
} else {
|
||||
// disable folder. Done through the _enabled-flag set above
|
||||
_pollTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,28 +233,37 @@ 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)";
|
||||
_watcher->clearPendingEvents();
|
||||
qDebug() << "* Polling" << alias() << "for changes. (time since next sync:" << (_timeSinceLastSync.elapsed() / 1000) << "s)";
|
||||
|
||||
if (quint64(_timeSinceLastSync.elapsed()) > MirallConfigFile().forceSyncInterval()) {
|
||||
qDebug() << "* Force Sync now";
|
||||
evaluateSync(QStringList());
|
||||
} else {
|
||||
RequestEtagJob* job = new RequestEtagJob(secondPath(), this);
|
||||
// check if the etag is different
|
||||
QObject::connect(new RequestEtagJob(secondPath(), this), SIGNAL(etagRetreived(QString)),
|
||||
this, SLOT(etagRetreived(QString)));
|
||||
QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
||||
QObject::connect(job, SIGNAL(networkError()), this, SLOT(slotNetworkUnavailable()));
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::etagRetreived(const QString& etag)
|
||||
{
|
||||
qDebug() << "* Compare etag " << etag << " with previous etag " << _lastEtag;
|
||||
qDebug() << "* Compare etag with previous etag: " << (_lastEtag != etag);
|
||||
|
||||
// re-enable sync if it was disabled because network was down
|
||||
FolderMan::instance()->setSyncEnabled(true);
|
||||
|
||||
if (_lastEtag != etag) {
|
||||
_lastEtag = etag;
|
||||
evaluateSync(QStringList());
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::slotNetworkUnavailable()
|
||||
{
|
||||
_syncResult.setStatus(SyncResult::Unavailable);
|
||||
emit syncStateChange();
|
||||
}
|
||||
|
||||
void Folder::slotChanged(const QStringList &pathList)
|
||||
{
|
||||
@@ -265,14 +271,95 @@ void Folder::slotChanged(const QStringList &pathList)
|
||||
evaluateSync(pathList);
|
||||
}
|
||||
|
||||
void Folder::slotSyncFinished(const SyncResult &result)
|
||||
void Folder::bubbleUpSyncResult()
|
||||
{
|
||||
_watcher->setEventsEnabledDelayed(2000);
|
||||
_pollTimer.start();
|
||||
_timeSinceLastSync.restart();
|
||||
// count new, removed and updated items
|
||||
int newItems = 0;
|
||||
int removedItems = 0;
|
||||
int updatedItems = 0;
|
||||
int ignoredItems = 0;
|
||||
|
||||
qDebug() << "OO folder slotSyncFinished: result: " << int(result.status());
|
||||
emit syncStateChange();
|
||||
SyncFileItem firstItemNew;
|
||||
SyncFileItem firstItemDeleted;
|
||||
SyncFileItem firstItemUpdated;
|
||||
|
||||
Logger *logger = Logger::instance();
|
||||
|
||||
foreach (const SyncFileItem &item, _syncResult.syncFileItemVector() ) {
|
||||
if( item._instruction == CSYNC_INSTRUCTION_ERROR ) {
|
||||
slotCSyncError( tr("File %1: %2").arg(item._file).arg(item._errorString) );
|
||||
logger->postGuiLog(tr("File %1").arg(item._file), item._errorString);
|
||||
|
||||
} else {
|
||||
if (item._dir == SyncFileItem::Down) {
|
||||
switch (item._instruction) {
|
||||
case CSYNC_INSTRUCTION_NEW:
|
||||
newItems++;
|
||||
if (firstItemNew.isEmpty())
|
||||
firstItemNew = item;
|
||||
|
||||
if (item._type == SyncFileItem::Directory) {
|
||||
_watcher->addPath(path() + item._file);
|
||||
}
|
||||
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_REMOVE:
|
||||
removedItems++;
|
||||
if (firstItemDeleted.isEmpty())
|
||||
firstItemDeleted = item;
|
||||
|
||||
if (item._type == SyncFileItem::Directory) {
|
||||
_watcher->removePath(path() + item._file);
|
||||
}
|
||||
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_UPDATED:
|
||||
updatedItems++;
|
||||
if (firstItemUpdated.isEmpty())
|
||||
firstItemUpdated = item;
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_ERROR:
|
||||
qDebug() << "Got Instruction ERROR. " << _syncResult.errorString();
|
||||
break;
|
||||
default:
|
||||
// nothing.
|
||||
break;
|
||||
}
|
||||
} else if( item._dir == SyncFileItem::None ) { // ignored files counting.
|
||||
if( item._instruction == CSYNC_INSTRUCTION_IGNORE ) {
|
||||
ignoredItems++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_syncResult.setWarnCount(ignoredItems);
|
||||
|
||||
qDebug() << "OO folder slotSyncFinished: result: " << int(_syncResult.status());
|
||||
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::slotLocalPathChanged( const QString& dir )
|
||||
@@ -411,6 +498,8 @@ void Folder::setProxy()
|
||||
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() );
|
||||
|
||||
FolderMan::instance()->setDirtyProxy(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,6 +538,8 @@ void Folder::startSync(const QStringList &pathList)
|
||||
QMetaObject::invokeMethod(this, "slotCSyncFinished", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
} else if (FolderMan::instance()->isDirtyProxy()) {
|
||||
setProxy();
|
||||
}
|
||||
|
||||
if (_thread && _thread->isRunning()) {
|
||||
@@ -522,10 +613,14 @@ void Folder::slotCsyncUnavailable()
|
||||
void Folder::slotCSyncFinished()
|
||||
{
|
||||
qDebug() << "-> CSync Finished slot with error " << _csyncError;
|
||||
_watcher->setEventsEnabledDelayed(2000);
|
||||
_pollTimer.start();
|
||||
_timeSinceLastSync.restart();
|
||||
|
||||
bubbleUpSyncResult();
|
||||
|
||||
if (_csyncError) {
|
||||
_syncResult.setStatus(SyncResult::Error);
|
||||
|
||||
qDebug() << " ** error Strings: " << _errors;
|
||||
_syncResult.setErrorStrings( _errors );
|
||||
qDebug() << " * owncloud csync thread finished with error";
|
||||
@@ -541,6 +636,7 @@ void Folder::slotCSyncFinished()
|
||||
if( _thread && _thread->isRunning() ) {
|
||||
_thread->quit();
|
||||
}
|
||||
emit syncStateChange();
|
||||
ownCloudInfo::instance()->getQuotaRequest("/");
|
||||
emit syncFinished( _syncResult );
|
||||
}
|
||||
@@ -573,79 +669,6 @@ void Folder::slotTransmissionProgress(const Progress::Info& progress)
|
||||
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 ?
|
||||
|
||||
@@ -53,17 +53,6 @@ typedef enum SyncFileStatus_s {
|
||||
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
|
||||
@@ -140,7 +129,6 @@ signals:
|
||||
void scheduleToSync( const QString& );
|
||||
|
||||
public slots:
|
||||
void slotSyncFinished(const SyncResult &);
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -172,6 +160,7 @@ private slots:
|
||||
|
||||
void slotPollTimerTimeout();
|
||||
void etagRetreived(const QString &);
|
||||
void slotNetworkUnavailable();
|
||||
|
||||
/**
|
||||
* Triggered by a file system watcher on the local sync dir
|
||||
@@ -189,6 +178,8 @@ protected:
|
||||
void setProxy();
|
||||
const char* proxyTypeToCStr(QNetworkProxy::ProxyType type);
|
||||
|
||||
void bubbleUpSyncResult();
|
||||
|
||||
/**
|
||||
* Starts a sync (calling startSync)
|
||||
* if the policies allow for it
|
||||
|
||||
@@ -37,7 +37,8 @@ FolderMan* FolderMan::_instance = 0;
|
||||
|
||||
FolderMan::FolderMan(QObject *parent) :
|
||||
QObject(parent),
|
||||
_syncEnabled( true )
|
||||
_syncEnabled( true ),
|
||||
_dirtyProxy( true )
|
||||
{
|
||||
// if QDir::mkpath would not be so stupid, I would not need to have this
|
||||
// duplication of folderConfigPath() here
|
||||
@@ -355,6 +356,10 @@ void FolderMan::slotScheduleSync( const QString& alias )
|
||||
|
||||
void FolderMan::setSyncEnabled( bool enabled )
|
||||
{
|
||||
if (!_syncEnabled && enabled && !_scheduleQueue.isEmpty()) {
|
||||
// We have things in our queue that were waiting the the connection to go back on.
|
||||
QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync()));
|
||||
}
|
||||
_syncEnabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,9 @@ public slots:
|
||||
|
||||
void slotScheduleAllFolders();
|
||||
|
||||
bool isDirtyProxy() { return _dirtyProxy; }
|
||||
void setDirtyProxy(bool value = true) { _dirtyProxy = value; }
|
||||
|
||||
private slots:
|
||||
// slot to add a folder to the syncing queue
|
||||
void slotScheduleSync( const QString & );
|
||||
@@ -136,6 +139,7 @@ private:
|
||||
QString _currentSyncFolder;
|
||||
bool _syncEnabled;
|
||||
QQueue<QString> _scheduleQueue;
|
||||
bool _dirtyProxy; // If the proxy need to be re-configured
|
||||
|
||||
explicit FolderMan(QObject *parent = 0);
|
||||
static FolderMan *_instance;
|
||||
|
||||
@@ -212,6 +212,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
|
||||
int h = iconRect.bottom();
|
||||
if( !errorText.isEmpty() ) {
|
||||
h += aliasMargin;
|
||||
QRect errorRect = localPathRect;
|
||||
errorRect.setLeft( iconRect.left());
|
||||
errorRect.setTop( h );
|
||||
@@ -222,10 +223,6 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
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;
|
||||
@@ -246,7 +243,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
// 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 barHeight = qMax(fileNameTextHeight, aliasFm.height()+2); ;
|
||||
int overallWidth = option.rect.width()-2*aliasMargin;
|
||||
|
||||
painter->save();
|
||||
@@ -263,6 +260,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
pBRect.setWidth( overallWidth - progressTextWidth - margin );
|
||||
|
||||
QStyleOptionProgressBarV2 pBarOpt;
|
||||
|
||||
pBarOpt.state = option.state | QStyle::State_Horizontal;
|
||||
pBarOpt.minimum = 0;
|
||||
pBarOpt.maximum = 100;
|
||||
@@ -283,6 +281,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
|
||||
QString elidedText = progressFm.elidedText(overallString, Qt::ElideLeft, overallProgressRect.width());
|
||||
painter->drawText( overallProgressRect, Qt::AlignRight+Qt::AlignVCenter, elidedText);
|
||||
// painter->drawRect(overallProgressRect);
|
||||
|
||||
// Individual File Progress
|
||||
QRect fileRect;
|
||||
|
||||
@@ -172,5 +172,16 @@ void FolderWatcher::changeDetected(const QString& f)
|
||||
setProcessTimer();
|
||||
}
|
||||
|
||||
void FolderWatcher::addPath(const QString &path )
|
||||
{
|
||||
_d->addPath(path);
|
||||
}
|
||||
|
||||
void FolderWatcher::removePath(const QString &path )
|
||||
{
|
||||
_d->removePath(path);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Mirall
|
||||
|
||||
|
||||
@@ -88,6 +88,15 @@ public:
|
||||
void setEventInterval(int seconds);
|
||||
|
||||
QStringList ignores() const;
|
||||
|
||||
/**
|
||||
* Not all backends are recursive by default.
|
||||
* Those need to be notified when a directory is added or removed while the watcher is disabled.
|
||||
* This is a no-op for backend that are recursive
|
||||
*/
|
||||
void addPath(const QString&);
|
||||
void removePath(const QString&);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Enabled or disables folderChanged() events.
|
||||
|
||||
@@ -50,8 +50,7 @@ void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
|
||||
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"
|
||||
emit _parent->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."));
|
||||
}
|
||||
@@ -119,9 +118,8 @@ void FolderWatcherPrivate::slotINotifyEvent(int mask, int /*cookie*/, const QStr
|
||||
}
|
||||
else if (mask & IN_DELETE) {
|
||||
//qDebug() << cookie << " DELETE: " << path;
|
||||
if ( QFileInfo(path).isDir() && _inotify->directories().contains(path) ) {
|
||||
qDebug() << "(-) Watcher:" << path;
|
||||
_inotify->removePath(path);
|
||||
if ( QFileInfo(path).isDir() ) {
|
||||
removePath(path);
|
||||
}
|
||||
}
|
||||
else if (mask & IN_CLOSE_WRITE) {
|
||||
@@ -160,4 +158,13 @@ void FolderWatcherPrivate::slotINotifyEvent(int mask, int /*cookie*/, const QStr
|
||||
_parent->setProcessTimer();
|
||||
}
|
||||
|
||||
void FolderWatcherPrivate::removePath(const QString &path )
|
||||
{
|
||||
if (_inotify->directories().contains(path) ) {
|
||||
qDebug() << "(-) Watcher:" << path;
|
||||
_inotify->removePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Mirall
|
||||
|
||||
@@ -26,6 +26,8 @@ class FolderWatcherPrivate : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FolderWatcherPrivate(FolderWatcher *p);
|
||||
void addPath(const QString &path) { slotAddFolderRecursive(path); }
|
||||
void removePath(const QString &);
|
||||
signals:
|
||||
void error(const QString& error);
|
||||
private slots:
|
||||
|
||||
@@ -31,6 +31,9 @@ public:
|
||||
FolderWatcherPrivate(FolderWatcher *p);
|
||||
~FolderWatcherPrivate();
|
||||
|
||||
void addPath(const QString &) {}
|
||||
void removePath(const QString &) {}
|
||||
|
||||
void startWatching();
|
||||
void doNotifyParent();
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ class FolderWatcherPrivate : public QObject {
|
||||
public:
|
||||
FolderWatcherPrivate(FolderWatcher *p);
|
||||
~FolderWatcherPrivate();
|
||||
|
||||
void addPath(const QString &) {}
|
||||
void removePath(const QString &) {}
|
||||
|
||||
private:
|
||||
FolderWatcher *_parent;
|
||||
WatcherThread *_thread;
|
||||
|
||||
@@ -358,10 +358,9 @@ FolderWizard::FolderWizard( QWidget *parent )
|
||||
setPage(Page_Target, _folderWizardTargetPage );
|
||||
}
|
||||
|
||||
setWindowTitle( tr( "%1 Folder Wizard" ).arg( Theme::instance()->appNameGUI() ) );
|
||||
#ifdef Q_WS_MAC
|
||||
setWizardStyle( QWizard::ModernStyle );
|
||||
#endif
|
||||
setWindowTitle( tr("Add Folder") );
|
||||
setOptions(QWizard::CancelButtonOnLeft);
|
||||
setButtonText(QWizard::FinishButton, tr("Add Folder"));
|
||||
}
|
||||
|
||||
FolderWizard::~FolderWizard()
|
||||
|
||||
@@ -7,29 +7,30 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>423</width>
|
||||
<height>226</height>
|
||||
<height>155</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sync Directory</string>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>349</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Pick a local folder on your computer to sync:</string>
|
||||
<string>Pick a local folder on your computer to sync</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
@@ -66,7 +67,7 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="warnLabel">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
@@ -152,19 +153,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>349</width>
|
||||
<height>83</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
||||
@@ -7,102 +7,14 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>520</width>
|
||||
<height>367</height>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Synchronization Target</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_17">
|
||||
<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>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Select a destination folder</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<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>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<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 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>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QFrame" name="warnFrame">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
@@ -213,7 +125,64 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Select a destination folder</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<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>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<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 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>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -221,7 +190,7 @@
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>102</height>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
|
||||
#include <QNetworkProxy>
|
||||
#include <QDir>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
@@ -49,6 +50,13 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
|
||||
|
||||
// misc
|
||||
connect(_ui->monoIconsCheckBox, SIGNAL(toggled(bool)), SLOT(saveMiscSettings()));
|
||||
|
||||
// OEM themes are not obliged to ship mono icons, so there
|
||||
// is no point in offering an option
|
||||
QString themeDir = QString::fromLatin1(":/mirall/theme/%1/")
|
||||
.arg(Theme::instance()->systrayIconFlavor(true));
|
||||
_ui->monoIconsCheckBox->setVisible(QDir(themeDir).exists());
|
||||
|
||||
}
|
||||
|
||||
GeneralSettings::~GeneralSettings()
|
||||
|
||||
@@ -101,7 +101,14 @@ void IgnoreListEditor::slotUpdateLocalIgnoreList()
|
||||
|
||||
void IgnoreListEditor::slotAddPattern()
|
||||
{
|
||||
QString pattern = QInputDialog::getText(this, tr("Add Ignore Pattern"), tr("Add a new ignore pattern:"));
|
||||
bool okClicked;
|
||||
QString pattern = QInputDialog::getText(this, tr("Add Ignore Pattern"),
|
||||
tr("Add a new ignore pattern:"),
|
||||
QLineEdit::Normal, QString(), &okClicked);
|
||||
|
||||
if (!okClicked || pattern.isEmpty())
|
||||
return;
|
||||
|
||||
QListWidgetItem *item = new QListWidgetItem;
|
||||
setupItemFlags(item);
|
||||
if (pattern.startsWith("]")) {
|
||||
|
||||
@@ -23,16 +23,6 @@
|
||||
|
||||
#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) :
|
||||
@@ -50,14 +40,16 @@ ItemProgressDialog::ItemProgressDialog(Application*, QWidget *parent) :
|
||||
this, SLOT(slotProgressErrors(const QString&, const Progress::SyncProblem&)));
|
||||
|
||||
QStringList header;
|
||||
header << tr("Folder/Time");
|
||||
header << tr("Time");
|
||||
header << tr("File");
|
||||
header << tr("Folder");
|
||||
header << tr("Action");
|
||||
header << tr("Size");
|
||||
|
||||
_ui->_treeWidget->setHeaderLabels( header );
|
||||
|
||||
_ui->_treeWidget->setColumnWidth(1, 180);
|
||||
_ui->_treeWidget->setColumnCount(5);
|
||||
_ui->_treeWidget->setRootIsDecorated(false);
|
||||
|
||||
connect(this, SIGNAL(guiLog(QString,QString)), Logger::instance(), SIGNAL(guiLog(QString,QString)));
|
||||
|
||||
@@ -70,51 +62,25 @@ ItemProgressDialog::ItemProgressDialog(Application*, QWidget *parent) :
|
||||
|
||||
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() ) {
|
||||
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));
|
||||
QStringList errors = result.errorStrings();
|
||||
int cnt = errors.size();
|
||||
bool appendDots = false;
|
||||
if( cnt > 3 ) {
|
||||
cnt = 3;
|
||||
appendDots = true;
|
||||
}
|
||||
|
||||
for( int i = 0; i < cnt; i++) {
|
||||
errStr.append(QString("%1<br/>").arg(errors.at(i)));
|
||||
}
|
||||
if( appendDots ) {
|
||||
errStr.append(QString("..."));
|
||||
}
|
||||
_ui->_errorLabel->setText(errStr);
|
||||
} else {
|
||||
_ui->_errorLabel->setText(QString::null);
|
||||
@@ -127,44 +93,70 @@ 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();
|
||||
QDateTime dt = QDateTime::currentDateTime();
|
||||
|
||||
for (i = items.begin(); i != items.end(); ++i) {
|
||||
const SyncFileItem& item = *i;
|
||||
QString errMsg;
|
||||
if( item._instruction == CSYNC_INSTRUCTION_IGNORE ) {
|
||||
QString tooltip;
|
||||
// handle ignored files here.
|
||||
|
||||
if( item._instruction == CSYNC_INSTRUCTION_IGNORE
|
||||
|| item._instruction == CSYNC_INSTRUCTION_CONFLICT ) {
|
||||
QStringList columns;
|
||||
QString timeStr = QTime::currentTime().toString("hh:mm");
|
||||
QString timeStr = timeString(dt);
|
||||
QString longTimeStr = timeString(dt, QLocale::LongFormat);
|
||||
|
||||
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.");
|
||||
columns << folder;
|
||||
if( item._instruction == CSYNC_INSTRUCTION_IGNORE) {
|
||||
if( item._type == SyncFileItem::SoftLink ) {
|
||||
errMsg = tr("Soft Link ignored");
|
||||
tooltip = tr("Softlinks break the semantics of synchronization.\nPlease do not "
|
||||
"use them in synced directories");
|
||||
} else {
|
||||
QString obj = tr("file");
|
||||
if( item._type == SyncFileItem::Directory ) {
|
||||
obj = tr("directory");
|
||||
}
|
||||
tooltip = tr("The %1 was ignored because it is listed in the clients ignore list\n"
|
||||
"or the %1 name contains characters that are not syncable\nin a cross platform "
|
||||
"environment").arg(obj);
|
||||
errMsg = tr("Item ignored");
|
||||
if( item._errorString == QLatin1String("File listed on ignore list.") ) {
|
||||
errMsg = tr("%1 on ignore list").arg(obj);
|
||||
tooltip = tr("The %1 was skipped because it is listed on the clients\n"
|
||||
"list of names to ignore").arg(obj);
|
||||
} else if( item._errorString == QLatin1String("File contains invalid characters.") ) {
|
||||
errMsg = tr("Invalid characters");
|
||||
tooltip = tr("The %1 name contains one or more invalid characters which break\n"
|
||||
"syncing in a cross platform environment").arg(obj);
|
||||
}
|
||||
}
|
||||
} else if( item._instruction == CSYNC_INSTRUCTION_CONFLICT ) {
|
||||
errMsg = tr("Conflict file.");
|
||||
tooltip = tr("The file was changed on server and local repository and as a result it\n"
|
||||
"created a so called conflict. The local change is copied to the conflict\n"
|
||||
"file while the file from the server side is available under the original\n"
|
||||
"name");
|
||||
} else {
|
||||
errMsg = tr("Ignored.");
|
||||
Q_ASSERT(!"unhandled instruction.");
|
||||
}
|
||||
columns << errMsg;
|
||||
|
||||
QTreeWidgetItem *twitem = new QTreeWidgetItem(folderItem, columns);
|
||||
QTreeWidgetItem *twitem = new QTreeWidgetItem(columns);
|
||||
twitem->setData(0, ErrorIndicatorRole, QVariant(true) );
|
||||
twitem->setToolTip(0, longTimeStr);
|
||||
twitem->setToolTip(3, tooltip);
|
||||
twitem->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Problem, true));
|
||||
_ui->_treeWidget->insertTopLevelItem(0, twitem);
|
||||
|
||||
Q_UNUSED(twitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +170,6 @@ void ItemProgressDialog::setupList()
|
||||
bool haveSyncResult = false;
|
||||
|
||||
foreach( Folder *f, map.values() ) {
|
||||
findFolderItem(f->alias());
|
||||
if( f->syncResult().syncTime() > dt ) {
|
||||
dt = f->syncResult().syncTime();
|
||||
lastResult = f->syncResult();
|
||||
@@ -204,11 +195,6 @@ void ItemProgressDialog::setupList()
|
||||
slotProgressErrors(prob.folder, prob);
|
||||
folderHash[prob.folder] = 1;
|
||||
}
|
||||
|
||||
foreach( const QString& folder, folderHash.keys() ) {
|
||||
decorateFolderItem(folder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ItemProgressDialog::~ItemProgressDialog()
|
||||
@@ -223,22 +209,22 @@ void ItemProgressDialog::copyToClipboard()
|
||||
|
||||
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;
|
||||
}
|
||||
QTreeWidgetItem *child = _ui->_treeWidget->topLevelItem(i);
|
||||
// time stamp
|
||||
ts << left << qSetFieldWidth(10)
|
||||
<< child->data(0,Qt::DisplayRole).toString()
|
||||
// file name
|
||||
<< qSetFieldWidth(64)
|
||||
<< child->data(1,Qt::DisplayRole).toString()
|
||||
<< qSetFieldWidth(0) << ' '
|
||||
// action
|
||||
<< qSetFieldWidth(15)
|
||||
<< child->data(3, Qt::DisplayRole).toString()
|
||||
// size
|
||||
<< qSetFieldWidth(10)
|
||||
<< child->data(4, Qt::DisplayRole).toString()
|
||||
<< qSetFieldWidth(0)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
QApplication::clipboard()->setText(text);
|
||||
@@ -250,107 +236,76 @@ void ItemProgressDialog::accept()
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void ItemProgressDialog::decorateFolderItem( const QString& folder )
|
||||
void ItemProgressDialog::cleanErrors( const QString& /* folder */ ) // FIXME: Use the folder to detect which errors can be deleted.
|
||||
{
|
||||
QTreeWidgetItem *folderItem = findFolderItem(folder);
|
||||
if( ! folderItem ) return;
|
||||
int errorCnt = 0;
|
||||
_problemCounter = 0;
|
||||
QList<QTreeWidgetItem*> wipeList;
|
||||
|
||||
int childCnt = folderItem->childCount();
|
||||
for( int cnt = 0; cnt < childCnt; cnt++ ) {
|
||||
bool isErrorItem = folderItem->child(cnt)->data(0, ErrorIndicatorRole).toBool();
|
||||
if( isErrorItem ) {
|
||||
errorCnt++;
|
||||
int itemCnt = _ui->_treeWidget->topLevelItemCount();
|
||||
|
||||
for( int cnt = 0; cnt < itemCnt; cnt++ ) {
|
||||
QTreeWidgetItem *item = _ui->_treeWidget->topLevelItem(cnt);
|
||||
bool isErrorItem = item->data(0, ErrorIndicatorRole).toBool();
|
||||
if( isErrorItem ) {
|
||||
wipeList.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
qDeleteAll(wipeList.begin(), wipeList.end());
|
||||
}
|
||||
|
||||
QTreeWidgetItem *ItemProgressDialog::createFolderItem(const QString& folder)
|
||||
QString ItemProgressDialog::timeString(QDateTime dt, QLocale::FormatType format) const
|
||||
{
|
||||
QStringList strings;
|
||||
strings.append(folder);
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem( _ui->_treeWidget, strings );
|
||||
item->setFirstColumnSpanned(true);
|
||||
item->setExpanded(true);
|
||||
return item;
|
||||
}
|
||||
QLocale loc = QLocale::system();
|
||||
QString timeStr;
|
||||
QDate today = QDate::currentDate();
|
||||
|
||||
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));
|
||||
if( format == QLocale::NarrowFormat ) {
|
||||
if( dt.date().day() == today.day() ) {
|
||||
timeStr = loc.toString(dt.time(), QLocale::NarrowFormat);
|
||||
} else {
|
||||
timeStr = loc.toString(dt, QLocale::NarrowFormat);
|
||||
}
|
||||
} else {
|
||||
timeStr = loc.toString(dt, format);
|
||||
}
|
||||
}
|
||||
qDeleteAll(wipeList.begin(), wipeList.end());
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
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");
|
||||
QString timeStr = timeString(problem.timestamp);
|
||||
QString longTimeStr = timeString(problem.timestamp, QLocale::LongFormat);
|
||||
|
||||
columns << timeStr;
|
||||
columns << problem.current_file;
|
||||
columns << folder;
|
||||
QString errMsg = tr("Problem: %1").arg(problem.error_message);
|
||||
#if 0
|
||||
if( problem.error_code == 507 ) {
|
||||
errMsg = tr("No more storage space available on server.");
|
||||
}
|
||||
#endif
|
||||
columns << errMsg;
|
||||
// FIXME: Show the error code if available.
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(folderItem, columns);
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(columns);
|
||||
item->setData(0, ErrorIndicatorRole, QVariant(true) );
|
||||
item->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Problem, true));
|
||||
|
||||
// Maybe we should not set the error icon for all problems but distinguish
|
||||
// by error_code. A quota problem is considered an error, others might not??
|
||||
item->setIcon(0, Theme::instance()->syncStateIcon(SyncResult::Error, true));
|
||||
item->setToolTip(0, longTimeStr);
|
||||
_ui->_treeWidget->insertTopLevelItem(0, item);
|
||||
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 );
|
||||
// decorateFolderItem( folder );
|
||||
}
|
||||
|
||||
// Ingore other events than finishing an individual up- or download.
|
||||
@@ -359,14 +314,18 @@ void ItemProgressDialog::slotProgressInfo( const QString& folder, const Progress
|
||||
}
|
||||
|
||||
QStringList columns;
|
||||
QString timeStr = progress.timestamp.toString("hh:mm");
|
||||
QString timeStr = timeString(progress.timestamp);
|
||||
QString longTimeStr = timeString(progress.timestamp, QLocale::LongFormat);
|
||||
|
||||
columns << timeStr;
|
||||
columns << progress.current_file;
|
||||
columns << progress.folder;
|
||||
columns << Progress::asResultString(progress.kind);
|
||||
columns << Utility::octetsToString( progress.file_size );
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(folderItem, columns);
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(columns);
|
||||
item->setToolTip(0, longTimeStr);
|
||||
_ui->_treeWidget->insertTopLevelItem(0, item);
|
||||
Q_UNUSED(item);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDateTime>
|
||||
#include <QLocale>
|
||||
|
||||
#include "mirall/progressdispatcher.h"
|
||||
|
||||
#include "ui_fileitemdialog.h"
|
||||
#include "ui_itemprogressdialog.h"
|
||||
|
||||
namespace Mirall {
|
||||
class SyncResult;
|
||||
@@ -54,12 +55,9 @@ signals:
|
||||
|
||||
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 );
|
||||
QString timeString(QDateTime dt, QLocale::FormatType format = QLocale::NarrowFormat) const;
|
||||
|
||||
QHash<QString, QTreeWidgetItem*> _folderItems;
|
||||
const int ErrorIndicatorRole;
|
||||
Ui::ItemProgressDialog *_ui;
|
||||
int _problemCounter;
|
||||
|
||||
@@ -39,9 +39,6 @@
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
@@ -67,13 +64,6 @@
|
||||
</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">
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include <QAction>
|
||||
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
#include "mirall/logger.h"
|
||||
@@ -45,11 +46,6 @@ LogWidget::LogWidget(QWidget *parent)
|
||||
font.setFamily(QLatin1String("Courier New"));
|
||||
font.setFixedPitch(true);
|
||||
document()->setDefaultFont( font );
|
||||
|
||||
MirallConfigFile cfg;
|
||||
int lines = cfg.maxLogLines();
|
||||
// qDebug() << "# ## Have " << lines << " Loglines!";
|
||||
document()->setMaximumBlockCount( lines );
|
||||
}
|
||||
|
||||
// ==============================================================================
|
||||
@@ -57,8 +53,7 @@ LogWidget::LogWidget(QWidget *parent)
|
||||
LogBrowser::LogBrowser(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
_logWidget( new LogWidget(parent) ),
|
||||
_doFileFlush(false),
|
||||
_logstream(0)
|
||||
_doFileFlush(false)
|
||||
{
|
||||
setObjectName("LogBrowser"); // for save/restoreGeometry()
|
||||
setWindowTitle(tr("Log Output"));
|
||||
@@ -118,12 +113,23 @@ 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);
|
||||
|
||||
QAction *showLogWindow = new QAction(this);
|
||||
showLogWindow->setShortcut(QKeySequence("F12"));
|
||||
connect(showLogWindow, SIGNAL(triggered()), SLOT(close()));
|
||||
addAction(showLogWindow);
|
||||
|
||||
MirallConfigFile cfg;
|
||||
cfg.restoreGeometry(this);
|
||||
int lines = cfg.maxLogLines();
|
||||
// qDebug() << "# ## Have " << lines << " Loglines!";
|
||||
_logWidget->document()->setMaximumBlockCount( lines );
|
||||
|
||||
}
|
||||
|
||||
LogBrowser::~LogBrowser()
|
||||
{
|
||||
MirallConfigFile cfg;
|
||||
cfg.saveGeometry(this);
|
||||
}
|
||||
|
||||
void LogBrowser::slotNewLog( const QString& msg )
|
||||
@@ -143,9 +149,16 @@ void LogBrowser::setLogFile( const QString & name, bool flush )
|
||||
if( _logstream ) {
|
||||
_logFile.close();
|
||||
}
|
||||
_logFile.setFileName( name );
|
||||
|
||||
if(!_logFile.open(QIODevice::WriteOnly)) {
|
||||
bool openSucceeded = false;
|
||||
if (name == QLatin1String("-")) {
|
||||
openSucceeded = _logFile.open(1, QIODevice::WriteOnly);
|
||||
} else {
|
||||
_logFile.setFileName( name );
|
||||
openSucceeded = _logFile.open(QIODevice::WriteOnly);
|
||||
}
|
||||
|
||||
if(!openSucceeded) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Error"),
|
||||
@@ -216,11 +229,4 @@ void LogBrowser::slotClearLog()
|
||||
_logWidget->clear();
|
||||
}
|
||||
|
||||
void LogBrowser::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
MirallConfigFile cfg;
|
||||
cfg.saveGeometry(this);
|
||||
QWidget::closeEvent(event);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -47,9 +47,6 @@ public:
|
||||
|
||||
void setLogFile(const QString& , bool );
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
protected slots:
|
||||
void slotNewLog( const QString &msg );
|
||||
void slotFind();
|
||||
|
||||
@@ -94,12 +94,20 @@ MirallConfigFile::MirallConfigFile( const QString& appendix, bool useOldConfig )
|
||||
|
||||
void MirallConfigFile::setConfDir(const QString &value)
|
||||
{
|
||||
if( value.isEmpty() ) return;
|
||||
QString dirPath = value;
|
||||
if( dirPath.isEmpty() ) return;
|
||||
|
||||
QFileInfo fi(value);
|
||||
QFileInfo fi(dirPath);
|
||||
if ( !fi.exists() && !fi.isAbsolute() ) {
|
||||
QDir::current().mkdir(dirPath);
|
||||
QDir dir = QDir::current();
|
||||
dir.cd(dirPath);
|
||||
fi.setFile(dir.path());
|
||||
}
|
||||
if( fi.exists() && fi.isDir() ) {
|
||||
qDebug() << "** Using custom config dir " << value;
|
||||
_confDir=value;
|
||||
dirPath = fi.absoluteFilePath();
|
||||
qDebug() << "** Using custom config dir " << dirPath;
|
||||
_confDir=dirPath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +193,7 @@ QString MirallConfigFile::excludeFile(Scope scope) const
|
||||
fi.setFile( QApplication::applicationDirPath(), exclFile );
|
||||
#endif
|
||||
#ifdef Q_OS_UNIX
|
||||
fi.setFile( QString("/etc/%1").arg(Theme::instance()->appName()), exclFile );
|
||||
fi.setFile( QString( SYSCONFDIR "/%1").arg(Theme::instance()->appName()), exclFile );
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
// exec path is inside the bundle
|
||||
@@ -587,7 +595,7 @@ QString MirallConfigFile::proxyPassword() const
|
||||
|
||||
int MirallConfigFile::useUploadLimit() const
|
||||
{
|
||||
return getValue(useUploadLimitC, QString::null, -1).toInt();
|
||||
return getValue(useUploadLimitC, QString::null, 0).toInt();
|
||||
}
|
||||
|
||||
bool MirallConfigFile::useDownloadLimit() const
|
||||
|
||||
@@ -102,6 +102,7 @@ public:
|
||||
bool useDownloadLimit() const;
|
||||
void setUseUploadLimit(int);
|
||||
void setUseDownloadLimit(bool);
|
||||
/** in kbyte/s */
|
||||
int uploadLimit() const;
|
||||
int downloadLimit() const;
|
||||
void setUploadLimit(int kbytes);
|
||||
|
||||
@@ -113,7 +113,7 @@ void NetworkSettings::loadBWLimitSettings()
|
||||
if ( uploadLimit >= 1 ) {
|
||||
_ui->uploadLimitRadioButton->setChecked(true);
|
||||
} else if (uploadLimit == 0){
|
||||
_ui->noDownloadLimitRadioButton->setChecked(true);
|
||||
_ui->noUploadLimitRadioButton->setChecked(true);
|
||||
} else {
|
||||
_ui->autoUploadLimitRadioButton->setChecked(true);
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="noDownloadLimitRadioButton">
|
||||
<property name="text">
|
||||
<string>No Limit</string>
|
||||
<string>No limit</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
@@ -254,6 +254,12 @@
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Upload Bandwidth</string>
|
||||
</property>
|
||||
@@ -261,7 +267,7 @@
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="noUploadLimitRadioButton">
|
||||
<property name="text">
|
||||
<string>No Limit</string>
|
||||
<string>No limit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -138,7 +138,10 @@ QNetworkReply* ownCloudInfo::mkdirRequest( const QString& dir )
|
||||
qDebug() << "OCInfo Making dir " << dir;
|
||||
_authAttempts = 0;
|
||||
QNetworkRequest req;
|
||||
req.setUrl( QUrl( webdavUrl(_connection) + dir ) );
|
||||
QUrl url = QUrl(webdavUrl(_connection));
|
||||
url.setEncodedPath(url.encodedPath()+QUrl::toPercentEncoding(dir, "/"));
|
||||
|
||||
req.setUrl( url );
|
||||
QNetworkReply *reply = davRequest("MKCOL", req, 0);
|
||||
|
||||
// remember the confighandle used for this request
|
||||
@@ -234,8 +237,9 @@ void ownCloudInfo::slotGetQuotaFinished()
|
||||
{
|
||||
bool ok = false;
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
|
||||
int http_result_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 207) {
|
||||
if (http_result_code == 207) {
|
||||
// Parse DAV response
|
||||
QXmlStreamReader reader(reply);
|
||||
reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));
|
||||
@@ -268,6 +272,7 @@ void ownCloudInfo::slotGetQuotaFinished()
|
||||
emit quotaUpdated(total, quotaUsedBytes);
|
||||
_lastEtag = etag;
|
||||
} else {
|
||||
qDebug() << "Quota request *not* successful, http result code is " << http_result_code;
|
||||
_lastQuotaTotalBytes = 0;
|
||||
_lastQuotaUsedBytes = 0;
|
||||
}
|
||||
@@ -296,7 +301,7 @@ void ownCloudInfo::slotGetDirectoryListingFinished()
|
||||
currentItem = reader.readElementText();
|
||||
} else if (name == QLatin1String("collection") &&
|
||||
!currentItem.isEmpty()) {
|
||||
folders.append(currentItem);
|
||||
folders.append(QUrl::fromEncoded(currentItem.toLatin1()).path());
|
||||
currentItem.clear();
|
||||
}
|
||||
}
|
||||
@@ -585,6 +590,8 @@ RequestEtagJob::RequestEtagJob(const QString& dir, QObject* parent)
|
||||
connect( _reply, SIGNAL( finished()), SLOT(slotFinished()) );
|
||||
connect( _reply, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||
this, SLOT(slotError()));
|
||||
connect( _reply, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||
ownCloudInfo::instance(), SLOT(slotError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
||||
void RequestEtagJob::slotFinished()
|
||||
@@ -615,6 +622,7 @@ void RequestEtagJob::slotError()
|
||||
qDebug() << "RequestEtagJob Error: " << _reply->errorString();
|
||||
_reply->deleteLater();
|
||||
deleteLater();
|
||||
emit networkError();
|
||||
}
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -178,6 +178,7 @@ private slots:
|
||||
|
||||
signals:
|
||||
void etagRetreived(const QString &etag);
|
||||
void networkError();
|
||||
};
|
||||
|
||||
} // ns Mirall
|
||||
|
||||
@@ -47,8 +47,11 @@ OwncloudSetupWizard::OwncloudSetupWizard(QObject* parent) :
|
||||
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)));
|
||||
|
||||
/* basicSetupFinished might be called from a reply from the network.
|
||||
slotAssistantFinished might destroy the temporary QNetworkAccessManager.
|
||||
Therefore Qt::QueuedConnection is required */
|
||||
connect( _ocWizard, SIGNAL(basicSetupFinished(int)),
|
||||
this, SLOT(slotAssistantFinished(int)), Qt::QueuedConnection);
|
||||
connect( _ocWizard, SIGNAL(clearPendingRequests()),
|
||||
this, SLOT(slotClearPendingRequests()));
|
||||
}
|
||||
@@ -241,15 +244,10 @@ void OwncloudSetupWizard::testOwnCloudConnect()
|
||||
// write a temporary config.
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
|
||||
// remove a possibly existing custom config.
|
||||
if( ! _configHandle.isEmpty() ) {
|
||||
// remove the old config file.
|
||||
MirallConfigFile oldConfig( _configHandle );
|
||||
oldConfig.cleanupCustomConfig();
|
||||
if( _configHandle.isEmpty() ) {
|
||||
_configHandle = now.toString(QLatin1String("MMddyyhhmmss"));
|
||||
}
|
||||
|
||||
_configHandle = now.toString(QLatin1String("MMddyyhhmmss"));
|
||||
|
||||
MirallConfigFile cfgFile( _configHandle, true );
|
||||
QString url = _ocWizard->field(QLatin1String("OCUrl")).toString();
|
||||
if( url.isEmpty() ) return;
|
||||
@@ -484,8 +482,6 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
||||
// 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.
|
||||
@@ -505,10 +501,6 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 ) {
|
||||
@@ -524,6 +516,11 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
||||
qDebug() << "User interrupted change of configuration.";
|
||||
}
|
||||
}
|
||||
|
||||
// save the user credentials and afterwards clear the cred store.
|
||||
if( acceptCfg ) {
|
||||
cfg.acceptCustomConfig();
|
||||
}
|
||||
}
|
||||
|
||||
// clear the custom config handle
|
||||
|
||||
@@ -33,15 +33,6 @@ ownCloudTheme::ownCloudTheme()
|
||||
// qDebug() << " ** running ownCloud theme!";
|
||||
}
|
||||
|
||||
QString ownCloudTheme::appName() const
|
||||
{
|
||||
/* If this is changed, existing configs are not found any more
|
||||
* because the value is used by QDesktopServices to find the config
|
||||
* file. Be aware.
|
||||
*/
|
||||
return QLatin1String("ownCloud");
|
||||
}
|
||||
|
||||
QString ownCloudTheme::configFileName() const
|
||||
{
|
||||
return QLatin1String("owncloud.cfg");
|
||||
@@ -65,7 +56,7 @@ QString ownCloudTheme::about() const
|
||||
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. "
|
||||
"<p><small>By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, ownCloud Inc.<br>"
|
||||
"Based on Mirall by Duncan Mac-Vicar P.</small></p>"
|
||||
"%7"
|
||||
)
|
||||
|
||||
@@ -25,7 +25,6 @@ class ownCloudTheme : public Theme
|
||||
public:
|
||||
ownCloudTheme();
|
||||
|
||||
virtual QString appName() const;
|
||||
QString configFileName() const;
|
||||
QString about() const;
|
||||
QPixmap splashScreen() const;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <QObject>
|
||||
#include <QMetaType>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
@@ -28,35 +28,35 @@ QString Progress::asResultString( Kind kind )
|
||||
switch(kind) {
|
||||
case Download:
|
||||
case EndDownload:
|
||||
re = QObject::tr("Download");
|
||||
re = QCoreApplication::translate( "progress", "Download");
|
||||
break;
|
||||
case Upload:
|
||||
re = QObject::tr("Upload");
|
||||
re = QCoreApplication::translate( "progress", "Upload");
|
||||
break;
|
||||
case Context:
|
||||
re = QObject::tr("Context");
|
||||
re = QCoreApplication::translate( "progress", "Context" );
|
||||
break;
|
||||
case Inactive:
|
||||
re = QObject::tr("Inactive");
|
||||
re = QCoreApplication::translate( "progress", "Inactive");
|
||||
break;
|
||||
case StartDownload:
|
||||
re = QObject::tr("Download");
|
||||
re = QCoreApplication::translate( "progress", "Download");
|
||||
break;
|
||||
case StartUpload:
|
||||
case EndUpload:
|
||||
re = QObject::tr("Upload");
|
||||
re = QCoreApplication::translate( "progress", "Upload");
|
||||
break;
|
||||
case StartSync:
|
||||
re = QObject::tr("Start");
|
||||
re = QCoreApplication::translate( "progress", "Start");
|
||||
break;
|
||||
case EndSync:
|
||||
re = QObject::tr("Finished");
|
||||
re = QCoreApplication::translate( "progress", "Finished");
|
||||
break;
|
||||
case StartDelete:
|
||||
re = QObject::tr("For deletion");
|
||||
re = QCoreApplication::translate( "progress", "For deletion");
|
||||
break;
|
||||
case EndDelete:
|
||||
re = QObject::tr("deleted");
|
||||
re = QCoreApplication::translate( "progress", "deleted");
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
@@ -71,40 +71,40 @@ QString Progress::asActionString( Kind kind )
|
||||
|
||||
switch(kind) {
|
||||
case Download:
|
||||
re = QObject::tr("downloading");
|
||||
re = QCoreApplication::translate( "progress", "downloading");
|
||||
break;
|
||||
case Upload:
|
||||
re = QObject::tr("uploading");
|
||||
re = QCoreApplication::translate( "progress", "uploading");
|
||||
break;
|
||||
case Context:
|
||||
re = QObject::tr("Context");
|
||||
re = QCoreApplication::translate( "progress", "Context");
|
||||
break;
|
||||
case Inactive:
|
||||
re = QObject::tr("inactive");
|
||||
re = QCoreApplication::translate( "progress", "inactive");
|
||||
break;
|
||||
case StartDownload:
|
||||
re = QObject::tr("downloading");
|
||||
re = QCoreApplication::translate( "progress", "downloading");
|
||||
break;
|
||||
case StartUpload:
|
||||
re = QObject::tr("uploading");
|
||||
re = QCoreApplication::translate( "progress", "uploading");
|
||||
break;
|
||||
case EndDownload:
|
||||
re = QObject::tr("downloading");
|
||||
re = QCoreApplication::translate( "progress", "downloading");
|
||||
break;
|
||||
case EndUpload:
|
||||
re = QObject::tr("uploading");
|
||||
re = QCoreApplication::translate( "progress", "uploading");
|
||||
break;
|
||||
case StartSync:
|
||||
re = QObject::tr("starting");
|
||||
re = QCoreApplication::translate( "progress", "starting");
|
||||
break;
|
||||
case EndSync:
|
||||
re = QObject::tr("finished");
|
||||
re = QCoreApplication::translate( "progress", "finished");
|
||||
break;
|
||||
case StartDelete:
|
||||
re = QObject::tr("delete");
|
||||
re = QCoreApplication::translate( "progress", "delete");
|
||||
break;
|
||||
case EndDelete:
|
||||
re = QObject::tr("deleted");
|
||||
re = QCoreApplication::translate( "progress", "deleted");
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
@@ -121,7 +121,7 @@ ProgressDispatcher* ProgressDispatcher::instance() {
|
||||
|
||||
ProgressDispatcher::ProgressDispatcher(QObject *parent) :
|
||||
QObject(parent),
|
||||
_problemQueueSize(50)
|
||||
_QueueSize(50)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -158,13 +158,14 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress::
|
||||
Progress::SyncProblem err;
|
||||
err.folder = folder;
|
||||
err.current_file = newProgress.current_file;
|
||||
// its really
|
||||
err.error_message = QString::fromLocal8Bit( (const char*)newProgress.file_size );
|
||||
err.error_code = newProgress.file_size;
|
||||
err.timestamp = QTime::currentTime();
|
||||
err.error_code = newProgress.current_file_bytes;
|
||||
err.timestamp = QDateTime::currentDateTime();
|
||||
|
||||
_recentProblems.enqueue( err );
|
||||
if( _recentProblems.size() > _problemQueueSize ) {
|
||||
_recentProblems.dequeue();
|
||||
_recentProblems.prepend( err );
|
||||
if( _recentProblems.size() > _QueueSize ) {
|
||||
_recentProblems.removeLast();
|
||||
}
|
||||
emit progressSyncProblem( folder, err );
|
||||
} else {
|
||||
@@ -174,13 +175,32 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const Progress::
|
||||
if( newProgress.kind == Progress::EndSync ) {
|
||||
newProgress.overall_current_bytes = newProgress.overall_transmission_size;
|
||||
newProgress.current_file_no = newProgress.overall_file_count;
|
||||
_currentAction.remove(newProgress.folder);
|
||||
}
|
||||
if( newProgress.kind == Progress::EndDownload || newProgress.kind == Progress::EndUpload ||
|
||||
if( newProgress.kind == Progress::EndDownload ||
|
||||
newProgress.kind == Progress::EndUpload ||
|
||||
newProgress.kind == Progress::EndDelete ) {
|
||||
_recentChanges.enqueue(newProgress);
|
||||
_recentChanges.prepend(newProgress);
|
||||
if( _recentChanges.size() > _QueueSize ) {
|
||||
_recentChanges.removeLast();
|
||||
}
|
||||
}
|
||||
// store the last real action to help clients that start during
|
||||
// the Context-phase of an upload or download.
|
||||
if( newProgress.kind != Progress::Context ) {
|
||||
_currentAction[folder] = newProgress.kind;
|
||||
}
|
||||
|
||||
emit progressInfo( folder, newProgress );
|
||||
}
|
||||
}
|
||||
|
||||
Progress::Kind ProgressDispatcher::currentFolderContext( const QString& folder )
|
||||
{
|
||||
if( _currentAction.contains(folder)) {
|
||||
return _currentAction[folder];
|
||||
}
|
||||
return Progress::Invalid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,9 +25,8 @@ namespace Mirall {
|
||||
/**
|
||||
* @brief The FolderScheduler class schedules folders for sync
|
||||
*/
|
||||
class Progress
|
||||
namespace Progress
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
Invalid,
|
||||
StartSync,
|
||||
@@ -57,7 +56,7 @@ public:
|
||||
qint64 overall_transmission_size;
|
||||
qint64 overall_current_bytes;
|
||||
|
||||
QTime timestamp;
|
||||
QDateTime timestamp;
|
||||
|
||||
} Info;
|
||||
|
||||
@@ -66,12 +65,12 @@ public:
|
||||
QString current_file;
|
||||
QString error_message;
|
||||
int error_code;
|
||||
QTime timestamp;
|
||||
QDateTime timestamp;
|
||||
} SyncProblem;
|
||||
|
||||
static QString asActionString( Kind );
|
||||
static QString asResultString( Kind );
|
||||
};
|
||||
QString asActionString( Kind );
|
||||
QString asResultString( Kind );
|
||||
}
|
||||
|
||||
/**
|
||||
* @file progressdispatcher.h
|
||||
@@ -93,6 +92,8 @@ public:
|
||||
|
||||
QList<Progress::Info> recentChangedItems(int count);
|
||||
QList<Progress::SyncProblem> recentProblems(int count);
|
||||
|
||||
Progress::Kind currentFolderContext( const QString& folder );
|
||||
signals:
|
||||
/**
|
||||
@brief Signals the progress of data transmission.
|
||||
@@ -110,10 +111,11 @@ protected:
|
||||
|
||||
private:
|
||||
ProgressDispatcher(QObject* parent = 0);
|
||||
const int _problemQueueSize;
|
||||
QQueue<Progress::Info> _recentChanges;
|
||||
QQueue<Progress::SyncProblem> _recentProblems;
|
||||
const int _QueueSize;
|
||||
QList<Progress::Info> _recentChanges;
|
||||
QList<Progress::SyncProblem> _recentProblems;
|
||||
|
||||
QHash<QString, Progress::Kind> _currentAction;
|
||||
static ProgressDispatcher* _instance;
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,11 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
|
||||
_ui->setupUi(this);
|
||||
setObjectName("Settings"); // required as group for saveGeometry call
|
||||
|
||||
setWindowTitle(tr("%1 Settings").arg(Theme::instance()->appNameGUI()));
|
||||
setWindowTitle(tr("%1").arg(Theme::instance()->appNameGUI()));
|
||||
|
||||
_accountSettings = new AccountSettings(this);
|
||||
addAccount(tr("Account"), _accountSettings);
|
||||
slotUpdateAccountState();
|
||||
|
||||
QIcon generalIcon(QLatin1String(":/mirall/resources/settings.png"));
|
||||
QListWidgetItem *general = new QListWidgetItem(generalIcon, tr("General"), _ui->labelWidget);
|
||||
@@ -62,18 +66,12 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
|
||||
NetworkSettings *networkSettings = new NetworkSettings;
|
||||
_ui->stack->addWidget(networkSettings);
|
||||
connect(networkSettings, SIGNAL(proxySettingsChanged()), app, SLOT(slotSetupProxy()));
|
||||
connect(networkSettings, SIGNAL(proxySettingsChanged()), FolderMan::instance(), SLOT(slotScheduleAllFolders()));
|
||||
|
||||
//connect(generalSettings, SIGNAL(resizeToSizeHint()), SLOT(resizeToSizeHint()));
|
||||
|
||||
_accountSettings = new AccountSettings(this);
|
||||
addAccount(tr("Account"), _accountSettings);
|
||||
slotUpdateAccountState();
|
||||
|
||||
connect( app, SIGNAL(folderStateChanged(Folder*)), _accountSettings, SLOT(slotUpdateFolderState(Folder*)));
|
||||
connect( app, SIGNAL(folderStateChanged(Folder*)), SLOT(slotUpdateAccountState()));
|
||||
|
||||
connect( _accountSettings, SIGNAL(addASync()), app, SLOT(slotFolderAdded()) );
|
||||
connect( _accountSettings, SIGNAL(folderChanged()), app, SLOT(slotFoldersChanged()));
|
||||
connect( _accountSettings, SIGNAL(openFolderAlias(const QString&)),
|
||||
app, SLOT(slotFolderOpenAction(QString)));
|
||||
@@ -84,7 +82,7 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
|
||||
connect( ProgressDispatcher::instance(), SIGNAL(progressSyncProblem(QString,Progress::SyncProblem)),
|
||||
_accountSettings, SLOT(slotProgressProblem(QString,Progress::SyncProblem)) );
|
||||
|
||||
_ui->labelWidget->setCurrentRow(_ui->labelWidget->row(general));
|
||||
_ui->labelWidget->setCurrentRow(_ui->labelWidget->row(_accountItem));
|
||||
|
||||
connect(_ui->labelWidget, SIGNAL(currentRowChanged(int)),
|
||||
_ui->stack, SLOT(setCurrentIndex(int)));
|
||||
@@ -92,12 +90,20 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
|
||||
QPushButton *closeButton = _ui->buttonBox->button(QDialogButtonBox::Close);
|
||||
connect(closeButton, SIGNAL(pressed()), SLOT(accept()));
|
||||
|
||||
QAction *showLogWindow = new QAction(this);
|
||||
showLogWindow->setShortcut(QKeySequence("F12"));
|
||||
connect(showLogWindow, SIGNAL(triggered()), app, SLOT(slotOpenLogBrowser()));
|
||||
addAction(showLogWindow);
|
||||
|
||||
MirallConfigFile cfg;
|
||||
cfg.restoreGeometry(this);
|
||||
}
|
||||
|
||||
SettingsDialog::~SettingsDialog()
|
||||
{
|
||||
MirallConfigFile cfg;
|
||||
cfg.saveGeometry(this);
|
||||
|
||||
delete _ui;
|
||||
}
|
||||
|
||||
@@ -110,13 +116,6 @@ void SettingsDialog::addAccount(const QString &title, QWidget *widget)
|
||||
|
||||
}
|
||||
|
||||
void SettingsDialog::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
MirallConfigFile cfg;
|
||||
cfg.saveGeometry(this);
|
||||
QWidget::closeEvent(event);
|
||||
}
|
||||
|
||||
void SettingsDialog::slotUpdateAccountState()
|
||||
{
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
|
||||
@@ -41,9 +41,6 @@ public:
|
||||
|
||||
void addAccount(const QString &title, QWidget *widget);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
protected slots:
|
||||
void slotUpdateAccountState();
|
||||
|
||||
|
||||
@@ -6,15 +6,24 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>704</width>
|
||||
<height>299</height>
|
||||
<width>693</width>
|
||||
<height>457</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
// variables
|
||||
QString _file;
|
||||
QString _renameTarget;
|
||||
QString _errorString;
|
||||
csync_instructions_e _instruction;
|
||||
Direction _dir;
|
||||
Type _type;
|
||||
|
||||
@@ -45,35 +45,45 @@ QString Theme::statusHeaderText( SyncResult::Status status ) const
|
||||
|
||||
switch( status ) {
|
||||
case SyncResult::Undefined:
|
||||
resultStr = QObject::tr("Status undefined");
|
||||
resultStr = QCoreApplication::translate("theme", "Status undefined");
|
||||
break;
|
||||
case SyncResult::NotYetStarted:
|
||||
resultStr = QObject::tr("Waiting to start sync");
|
||||
resultStr = QCoreApplication::translate("theme", "Waiting to start sync");
|
||||
break;
|
||||
case SyncResult::SyncRunning:
|
||||
resultStr = QObject::tr("Sync is running");
|
||||
resultStr = QCoreApplication::translate("theme", "Sync is running");
|
||||
break;
|
||||
case SyncResult::Success:
|
||||
resultStr = QObject::tr("Sync Success");
|
||||
resultStr = QCoreApplication::translate("theme", "Sync Success");
|
||||
break;
|
||||
case SyncResult::Problem:
|
||||
resultStr = QObject::tr("Sync Success, problems with individual files.");
|
||||
resultStr = QCoreApplication::translate("theme", "Sync Success, problems with individual files.");
|
||||
break;
|
||||
case SyncResult::Error:
|
||||
resultStr = QObject::tr("Sync Error - Click info button for details.");
|
||||
resultStr = QCoreApplication::translate("theme", "Sync Error - Click info button for details.");
|
||||
break;
|
||||
case SyncResult::SetupError:
|
||||
resultStr = QObject::tr( "Setup Error" );
|
||||
resultStr = QCoreApplication::translate("theme", "Setup Error" );
|
||||
break;
|
||||
default:
|
||||
resultStr = QObject::tr("Status undefined");
|
||||
case SyncResult::Unavailable:
|
||||
resultStr = QCoreApplication::translate("theme", "The server is currently unavailable" );
|
||||
break;
|
||||
case SyncResult::SyncPrepare:
|
||||
resultStr = QCoreApplication::translate("theme", "Preparing to sync" );
|
||||
break;
|
||||
|
||||
}
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
QString Theme::appNameGUI() const
|
||||
{
|
||||
return appName();
|
||||
return QLatin1String(APPLICATION_NAME);
|
||||
}
|
||||
|
||||
QString Theme::appName() const
|
||||
{
|
||||
return QLatin1String(APPLICATION_SHORTNAME);
|
||||
}
|
||||
|
||||
QString Theme::version() const
|
||||
@@ -94,12 +104,8 @@ QIcon Theme::trayFolderIcon( const QString& backend ) const
|
||||
QIcon Theme::themeIcon( const QString& name, bool sysTray ) const
|
||||
{
|
||||
QString flavor;
|
||||
if (sysTray && _mono) {
|
||||
#ifdef Q_OS_MAC
|
||||
flavor = QLatin1String("black");
|
||||
#else
|
||||
flavor = QLatin1String("white");
|
||||
#endif
|
||||
if (sysTray) {
|
||||
flavor = systrayIconFlavor(_mono);
|
||||
} else {
|
||||
flavor = QLatin1String("colored");
|
||||
}
|
||||
@@ -158,6 +164,21 @@ QString Theme::defaultClientFolder() const
|
||||
return appName();
|
||||
}
|
||||
|
||||
QString Theme::systrayIconFlavor(bool mono) const
|
||||
{
|
||||
QString flavor;
|
||||
if (mono) {
|
||||
#ifdef Q_OS_MAC
|
||||
flavor = QLatin1String("black");
|
||||
#else
|
||||
flavor = QLatin1String("white");
|
||||
#endif
|
||||
} else {
|
||||
flavor = QLatin1String("colored");
|
||||
}
|
||||
return flavor;
|
||||
}
|
||||
|
||||
void Theme::setSystrayUseMonoIcons(bool mono)
|
||||
{
|
||||
_mono = mono;
|
||||
|
||||
@@ -48,7 +48,8 @@ public:
|
||||
* Use and redefine this if the human readable name contains spaces,
|
||||
* special chars and such.
|
||||
*
|
||||
* By default, appName() is returned.
|
||||
* By default, the name is derived from the APPLICATION_NAME
|
||||
* cmake variable.
|
||||
*
|
||||
* @return QString with human readable app name.
|
||||
*/
|
||||
@@ -61,9 +62,16 @@ public:
|
||||
* it is used for config files etc. If you need a more sophisticated
|
||||
* name in the GUI, redefine appNameGUI.
|
||||
*
|
||||
* By default, the name is derived from the APPLICATION_SHORTNAME
|
||||
* cmake variable, and should be the same. This method is only
|
||||
* reimplementable for legacy reasons.
|
||||
*
|
||||
* Warning: Do not modify this value, as many things, e.g. settings
|
||||
* depend on it! You most likely want to modify \ref appNameGUI().
|
||||
*
|
||||
* @return QString with app name.
|
||||
*/
|
||||
virtual QString appName() const = 0;
|
||||
virtual QString appName() const;
|
||||
|
||||
/**
|
||||
* @brief configFileName
|
||||
@@ -119,6 +127,8 @@ public:
|
||||
*/
|
||||
virtual QString enforcedLocale() const { return QString::null; }
|
||||
|
||||
/** colored, white or black */
|
||||
QString systrayIconFlavor(bool mono) const;
|
||||
|
||||
/**
|
||||
* Override to use a string or a custom image name.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QSettings>
|
||||
#include <QTextStream>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
@@ -102,31 +103,30 @@ void Utility::setupFavLink(const QString &folder)
|
||||
|
||||
QString Utility::octetsToString( qint64 octets )
|
||||
{
|
||||
static const qint64 kb = 1024;
|
||||
static const qint64 mb = 1024 * kb;
|
||||
static const qint64 gb = 1024 * mb;
|
||||
static const qint64 tb = 1024 * gb;
|
||||
static const qint64 kb = 1000;
|
||||
static const qint64 mb = 1000 * kb;
|
||||
static const qint64 gb = 1000 * mb;
|
||||
static const qint64 tb = 1000 * gb;
|
||||
|
||||
QString s;
|
||||
qreal value = octets;
|
||||
if (octets >= tb) {
|
||||
if (octets < 10*tb) {
|
||||
return compactFormatDouble(qreal(octets)/qreal(tb), 1, QLatin1String("TB"));
|
||||
}
|
||||
return QString::number(qRound64(qreal(octets)/qreal(tb))) + QLatin1String(" TB");
|
||||
s = QCoreApplication::translate("Utility", "%L1 TB");
|
||||
value /= tb;
|
||||
} else if (octets >= gb) {
|
||||
if (octets < 10*gb) {
|
||||
return compactFormatDouble(qreal(octets)/qreal(gb), 1, QLatin1String("GB"));
|
||||
}
|
||||
return QString::number(qRound64(qreal(octets)/qreal(gb))) + QLatin1String(" GB");
|
||||
s = QCoreApplication::translate("Utility", "%L1 GB");
|
||||
value /= gb;
|
||||
} else if (octets >= mb) {
|
||||
if (octets < 10*mb) {
|
||||
return compactFormatDouble(qreal(octets)/qreal(mb), 1, QLatin1String("MB"));
|
||||
}
|
||||
return QString::number(qRound64(qreal(octets)/qreal(mb))) + QLatin1String(" MB");
|
||||
s = QCoreApplication::translate("Utility", "%L1 MB");
|
||||
value /= mb;
|
||||
} else if (octets >= kb) {
|
||||
return QString::number(qRound64(qreal(octets)/qreal(kb))) + QLatin1String(" KB");
|
||||
} else {
|
||||
return QString::number(octets) + QLatin1String(" bytes");
|
||||
s = QCoreApplication::translate("Utility", "%L1 kB");
|
||||
value /= kb;
|
||||
} else {
|
||||
s = QCoreApplication::translate("Utility", "%L1 B");
|
||||
}
|
||||
|
||||
return (value > 9.95) ? s.arg(qRound(value)) : s.arg(value, 0, 'g', 2);
|
||||
}
|
||||
|
||||
// Qtified version of get_platforms() in csync_owncloud.c
|
||||
@@ -284,16 +284,24 @@ void Utility::setLaunchOnStartup(const QString &appName, const QString& guiName,
|
||||
qDebug() << "Could not create autostart directory";
|
||||
return;
|
||||
}
|
||||
QSettings desktopFile(desktopFileLocation, QSettings::IniFormat);
|
||||
desktopFile.beginGroup("Desktop Entry");
|
||||
desktopFile.setValue(QLatin1String("Name"), guiName);
|
||||
desktopFile.setValue(QLatin1String("GenericName"), QLatin1String("File Synchronizer"));
|
||||
desktopFile.setValue(QLatin1String("Exec"), QCoreApplication::applicationFilePath());
|
||||
desktopFile.setValue(QLatin1String("Terminal"), false);
|
||||
desktopFile.setValue(QLatin1String("Icon"), appName);
|
||||
desktopFile.setValue(QLatin1String("Categories"), QLatin1String("Network"));
|
||||
desktopFile.setValue(QLatin1String("StartupNotify"), false);
|
||||
desktopFile.endGroup();
|
||||
QFile iniFile(desktopFileLocation);
|
||||
if (!iniFile.open(QIODevice::WriteOnly)) {
|
||||
qDebug() << "Could not write auto start entry" << desktopFileLocation;
|
||||
return;
|
||||
}
|
||||
QTextStream ts(&iniFile);
|
||||
ts.setCodec("UTF-8");
|
||||
ts << QLatin1String("[Desktop Entry]") << endl
|
||||
<< QLatin1String("Name=") << guiName << endl
|
||||
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer") << endl
|
||||
<< QLatin1String("Exec=") << QCoreApplication::applicationFilePath() << endl
|
||||
<< QLatin1String("Terminal=") << "false" << endl
|
||||
<< QLatin1String("Icon=") << appName << endl
|
||||
<< QLatin1String("Categories=") << QLatin1String("Network") << endl
|
||||
<< QLatin1String("Type=") << QLatin1String("Application") << endl
|
||||
<< QLatin1String("StartupNotify=") << "false" << endl
|
||||
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true" << endl
|
||||
;
|
||||
} else {
|
||||
if (!QFile::remove(desktopFileLocation)) {
|
||||
qDebug() << "Could not remove autostart desktop file";
|
||||
|
||||
@@ -54,6 +54,7 @@ OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage()
|
||||
setupCustomization();
|
||||
|
||||
connect( _ui.pbSelectLocalFolder, SIGNAL(clicked()), SLOT(slotSelectFolder()));
|
||||
setButtonText(QWizard::NextButton, tr("Connect..."));
|
||||
}
|
||||
|
||||
void OwncloudAdvancedSetupPage::setupCustomization()
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>821</width>
|
||||
<height>647</height>
|
||||
<width>484</width>
|
||||
<height>342</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -34,6 +34,9 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -108,6 +108,12 @@
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
@@ -121,7 +127,6 @@
|
||||
<zorder>horizontalSpacer</zorder>
|
||||
<zorder>verticalSpacer</zorder>
|
||||
<zorder>horizontalSpacer_2</zorder>
|
||||
<zorder>horizontalLayoutWidget</zorder>
|
||||
<zorder>topLabel</zorder>
|
||||
<zorder>bottomLabel</zorder>
|
||||
</widget>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>478</width>
|
||||
<height>461</height>
|
||||
<width>525</width>
|
||||
<height>193</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -34,11 +34,30 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Server &Address</string>
|
||||
@@ -48,7 +67,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item>
|
||||
<widget class="Utils::FancyLineEdit" name="leUrl">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
@@ -64,6 +83,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -46,11 +46,13 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
|
||||
_setupLog(),
|
||||
_configExists(false)
|
||||
{
|
||||
setPage(WizardCommon::Page_ServerSetup, _setupPage );
|
||||
setPage(WizardCommon::Page_ServerSetup, _setupPage);
|
||||
setPage(WizardCommon::Page_HttpCreds, _httpCredsPage);
|
||||
setPage(WizardCommon::Page_ShibbolethCreds, _shibbolethCredsPage);
|
||||
setPage(WizardCommon::Page_AdvancedSetup, _advancedSetupPage);
|
||||
setPage(WizardCommon::Page_Result, _resultPage );
|
||||
setPage(WizardCommon::Page_Result, _resultPage);
|
||||
|
||||
connect(this, SIGNAL(finished(int)), SIGNAL(basicSetupFinished(int)));
|
||||
|
||||
// note: start Id is set by the calling class depending on if the
|
||||
// welcome text is to be shown or not.
|
||||
@@ -145,12 +147,13 @@ void OwncloudWizard::slotCurrentPageChanged( int id )
|
||||
qDebug() << "Current Wizard page changed to " << id;
|
||||
|
||||
if( id == WizardCommon::Page_ServerSetup ) {
|
||||
setButtonText( QWizard::NextButton, tr("Connect...") );
|
||||
emit clearPendingRequests();
|
||||
_setupPage->initializePage();
|
||||
}
|
||||
|
||||
if( id == WizardCommon::Page_Result ) {
|
||||
disconnect(this, SIGNAL(finished(int)), this, SIGNAL(basicSetupFinished(int)));
|
||||
emit basicSetupFinished(QDialog::Accepted);
|
||||
appendToConfigurationLog( QString::null );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ signals:
|
||||
void determineAuthType(const QString&);
|
||||
void connectToOCUrl( const QString& );
|
||||
void createLocalAndRemoteFolders(const QString&, const QString&);
|
||||
// make sure to connect to this, rather than finished(int)!!
|
||||
void basicSetupFinished( int );
|
||||
|
||||
private:
|
||||
OwncloudSetupPage* _setupPage;
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
*.filepart
|
||||
*~
|
||||
*.bak
|
||||
*.part
|
||||
*.crdownload
|
||||
|
||||
@@ -17,12 +16,9 @@ csync_journal.db.ctmp
|
||||
desktop.ini
|
||||
|
||||
*.kate-swp
|
||||
*.aux
|
||||
*.nav
|
||||
*.out
|
||||
*.toc
|
||||
|
||||
*_conflict-*
|
||||
]*.~*
|
||||
|
||||
].TemporaryItems
|
||||
].Trashes
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/../src)
|
||||
include(owncloud_add_test.cmake)
|
||||
|
||||
owncloud_add_test(First)
|
||||
owncloud_add_test(Utility)
|
||||
|
||||
@@ -10,10 +10,10 @@ macro(owncloud_add_test test_class)
|
||||
add_executable(${OWNCLOUD_TEST_CLASS}Test test${OWNCLOUD_TEST_CLASS_LOWERCASE}.cpp ${${OWNCLOUD_TEST_CLASS}_MOCS})
|
||||
|
||||
target_link_libraries(${OWNCLOUD_TEST_CLASS}Test
|
||||
|
||||
${APPLICATION_EXECUTABLE}sync
|
||||
${QT_QTTEST_LIBRARY}
|
||||
${QT_QTCORE_LIBRARY}
|
||||
)
|
||||
|
||||
add_test(NAME ${OWNCLOUD_TEST_CLASS}Test COMMAND ${OWNCLOUD_TEST_CLASS}Test)
|
||||
endmacro()
|
||||
endmacro()
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
This software is in the public domain, furnished "as is", without technical
|
||||
support, and with no warranty, express or implied, as to its usefulness for
|
||||
any purpose.
|
||||
*/
|
||||
|
||||
#ifndef MIRALL_TESTFIRST_H
|
||||
#define MIRALL_TESTFIRST_H
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
|
||||
class TestFirst : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void testTheFirstThing()
|
||||
{
|
||||
QVERIFY( true );
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
76
test/testutility.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
This software is in the public domain, furnished "as is", without technical
|
||||
support, and with no warranty, express or implied, as to its usefulness for
|
||||
any purpose.
|
||||
*/
|
||||
|
||||
#ifndef MIRALL_TESTUTILITY_H
|
||||
#define MIRALL_TESTUTILITY_H
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
#include "mirall/utility.h"
|
||||
|
||||
using namespace Mirall::Utility;
|
||||
|
||||
class TestUtility : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void testFormatFingerprint()
|
||||
{
|
||||
QVERIFY2(formatFingerprint("68ac906495480a3404beee4874ed853a037a7a8f")
|
||||
== "68:ac:90:64:95:48:0a:34:04:be:ee:48:74:ed:85:3a:03:7a:7a:8f",
|
||||
"Utility::formatFingerprint() is broken");
|
||||
}
|
||||
void testOctetsToString()
|
||||
{
|
||||
QCOMPARE(octetsToString(999) , QString("999 B"));
|
||||
QCOMPARE(octetsToString(1000) , QString("1 kB"));
|
||||
QCOMPARE(octetsToString(1010) , QString("1 kB"));
|
||||
QCOMPARE(octetsToString(1110) , QString("1.1 kB"));
|
||||
|
||||
QCOMPARE(octetsToString(9110) , QString("9.1 kB"));
|
||||
QCOMPARE(octetsToString(9910) , QString("9.9 kB"));
|
||||
QCOMPARE(octetsToString(9999) , QString("10 kB"));
|
||||
|
||||
QCOMPARE(octetsToString(123456) , QString("123 kB"));
|
||||
QCOMPARE(octetsToString(1234567) , QString("1.2 MB"));
|
||||
QCOMPARE(octetsToString(12345678) , QString("12 MB"));
|
||||
QCOMPARE(octetsToString(123456789) , QString("123 MB"));
|
||||
QCOMPARE(octetsToString(1000LL*1000*1000 * 5) , QString("5 GB"));
|
||||
|
||||
QCOMPARE(octetsToString(1), QString("1 B"));
|
||||
QCOMPARE(octetsToString(2), QString("2 B"));
|
||||
QCOMPARE(octetsToString(1024), QString("1 kB"));
|
||||
QCOMPARE(octetsToString(1024*1024), QString("1 MB"));
|
||||
QCOMPARE(octetsToString(1024LL*1024*1024), QString("1.1 GB"));
|
||||
QCOMPARE(octetsToString(1024LL*1024*1024*1024), QString("1.1 TB"));
|
||||
}
|
||||
|
||||
void testLaunchOnStartup()
|
||||
{
|
||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||
QString postfix = QString::number(qrand());
|
||||
|
||||
const QString appName = QString::fromLatin1("testLaunchOnStartup.%1").arg(postfix);
|
||||
const QString guiName = "LaunchOnStartup GUI Name";
|
||||
|
||||
QVERIFY(hasLaunchOnStartup(appName) == false);
|
||||
setLaunchOnStartup(appName, guiName, true);
|
||||
QVERIFY(hasLaunchOnStartup(appName) == true);
|
||||
setLaunchOnStartup(appName, guiName, false);
|
||||
QVERIFY(hasLaunchOnStartup(appName) == false);
|
||||
}
|
||||
|
||||
void testToCSyncScheme()
|
||||
{
|
||||
QVERIFY(toCSyncScheme("http://example.com/owncloud/") ==
|
||||
"owncloud://example.com/owncloud/");
|
||||
QVERIFY(toCSyncScheme("https://example.com/owncloud/") ==
|
||||
"ownclouds://example.com/owncloud/");
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||