Compare commits
347 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee080222d8 | ||
|
|
c7aaa3ab28 | ||
|
|
fcde01fd4c | ||
|
|
83be334ee8 | ||
|
|
819f76c2b9 | ||
|
|
783b16676f | ||
|
|
aa6160ab62 | ||
|
|
8bae06802b | ||
|
|
a20f572448 | ||
|
|
f74aa1e9a6 | ||
|
|
86525570aa | ||
|
|
d11ce781d0 | ||
|
|
be5a50a000 | ||
|
|
7309a894bc | ||
|
|
310f29d3fd | ||
|
|
07db03d6bc | ||
|
|
d68c4b379f | ||
|
|
396a12dfde | ||
|
|
c79f4f91a8 | ||
|
|
bec2f7c9b9 | ||
|
|
d4c8cad0e2 | ||
|
|
0ad2bd4b91 | ||
|
|
dcc8f9fa6c | ||
|
|
d7a93c74aa | ||
|
|
408547611b | ||
|
|
a8f0e79046 | ||
|
|
3e45147497 | ||
|
|
48310d3f5e | ||
|
|
1831a975eb | ||
|
|
a766a44bcf | ||
|
|
287f1c55ff | ||
|
|
1c6523bcec | ||
|
|
337c6d3e4e | ||
|
|
4a57957420 | ||
|
|
c633302f31 | ||
|
|
db95e7291d | ||
|
|
ae54c27805 | ||
|
|
284285d441 | ||
|
|
2554a67cc7 | ||
|
|
e2cccd8615 | ||
|
|
948a98a871 | ||
|
|
b50d201154 | ||
|
|
25a3ceb94d | ||
|
|
c514fe371a | ||
|
|
9169c70efe | ||
|
|
3c07cea229 | ||
|
|
d3f51c611f | ||
|
|
21123bb029 | ||
|
|
fb8d11650c | ||
|
|
2c250050d5 | ||
|
|
e9b3cbf3f7 | ||
|
|
d31a6e6179 | ||
|
|
26d8c213b0 | ||
|
|
bcb9491f6a | ||
|
|
9d2c3ebad3 | ||
|
|
ad063b0634 | ||
|
|
8765538458 | ||
|
|
dd4aa14a8c | ||
|
|
99814539eb | ||
|
|
dbec98ff48 | ||
|
|
e2e14f2184 | ||
|
|
e85291c4ba | ||
|
|
58a5405343 | ||
|
|
4ba85311da | ||
|
|
3cf7003101 | ||
|
|
ae558a5889 | ||
|
|
0b0b762c6c | ||
|
|
55a4fd752d | ||
|
|
136b699106 | ||
|
|
fd83bf2089 | ||
|
|
75f075feb0 | ||
|
|
817039ddf3 | ||
|
|
6d6deaf6c4 | ||
|
|
9c63b89bac | ||
|
|
2a6e084219 | ||
|
|
ec120cd64c | ||
|
|
a9173b1aa1 | ||
|
|
89f7f75af2 | ||
|
|
8809ac0c4a | ||
|
|
7a03164a9a | ||
|
|
406254cd04 | ||
|
|
f01eeed9d0 | ||
|
|
5b6439e29d | ||
|
|
38954c2193 | ||
|
|
5954fb280c | ||
|
|
8e63652fb3 | ||
|
|
365dfd5380 | ||
|
|
1c70fb3ba4 | ||
|
|
e5af8e87b3 | ||
|
|
bfbec24f43 | ||
|
|
8dd97a358a | ||
|
|
7290afc6fe | ||
|
|
2ba20369ea | ||
|
|
804aef6548 | ||
|
|
85f49b6af4 | ||
|
|
68afc6011d | ||
|
|
524ffcd0e1 | ||
|
|
a7303205b4 | ||
|
|
8a06b2d136 | ||
|
|
7ba8a55fa5 | ||
|
|
ee7dc8e1c5 | ||
|
|
3556f90d68 | ||
|
|
6d984b505d | ||
|
|
8d9336f9f4 | ||
|
|
2b5e694181 | ||
|
|
aa983e4966 | ||
|
|
424b3a9dfc | ||
|
|
5a3bc7af9a | ||
|
|
4501ec10dc | ||
|
|
699ae176df | ||
|
|
9297b3b850 | ||
|
|
cac5f81388 | ||
|
|
28af8068e9 | ||
|
|
a1d64af7b1 | ||
|
|
edbb79b79c | ||
|
|
a000a7b52e | ||
|
|
0a427541d6 | ||
|
|
1c297c56a2 | ||
|
|
6f9bbc431d | ||
|
|
f62626e3eb | ||
|
|
28fcd75494 | ||
|
|
39a89e8fc7 | ||
|
|
38a8096732 | ||
|
|
d358c839ce | ||
|
|
17901e7bc7 | ||
|
|
0ea16c04cc | ||
|
|
f1e0cd1c9c | ||
|
|
e1f404a011 | ||
|
|
69715d2182 | ||
|
|
0285213140 | ||
|
|
1a907f23f0 | ||
|
|
1296be71ed | ||
|
|
0ebcdbbb3f | ||
|
|
891ced0fca | ||
|
|
6276bb3873 | ||
|
|
dbb0cbaff8 | ||
|
|
cfa777260c | ||
|
|
66fc273db6 | ||
|
|
9c9e377cf4 | ||
|
|
f75eb24bfe | ||
|
|
a617a04295 | ||
|
|
dc16f277ce | ||
|
|
07258deaaf | ||
|
|
7b53e0f953 | ||
|
|
2ac764bd1a | ||
|
|
82d2851a6b | ||
|
|
7a3be71452 | ||
|
|
977a513ee5 | ||
|
|
22cbebb7a7 | ||
|
|
72b2e6778a | ||
|
|
08babbf38d | ||
|
|
2ae5ae6962 | ||
|
|
fa6331a40a | ||
|
|
cece465947 | ||
|
|
3f97047abc | ||
|
|
b6d5213880 | ||
|
|
0bcb65db29 | ||
|
|
7734656ae3 | ||
|
|
c14e17e271 | ||
|
|
1f4ea2c60e | ||
|
|
edb4ff6b98 | ||
|
|
279bb47ab4 | ||
|
|
7ef92748ea | ||
|
|
0e6e614318 | ||
|
|
a5b6c3add7 | ||
|
|
fd30d8b0d1 | ||
|
|
5944acf8a6 | ||
|
|
58ace7c774 | ||
|
|
a07444412b | ||
|
|
339f59a4e8 | ||
|
|
4beb9b3efc | ||
|
|
a04cf32a69 | ||
|
|
746c0359d2 | ||
|
|
854852959c | ||
|
|
1e1751e451 | ||
|
|
7cd0179adc | ||
|
|
c0543cdbaf | ||
|
|
d681066dc2 | ||
|
|
b81939bff5 | ||
|
|
f8685c97f1 | ||
|
|
11e06c33db | ||
|
|
c0f2f5bcaa | ||
|
|
bfee6402a6 | ||
|
|
4fac62560e | ||
|
|
d780055b0e | ||
|
|
3f5c53425b | ||
|
|
08f90ce3a6 | ||
|
|
6ee70a852a | ||
|
|
4908dbdee8 | ||
|
|
a6573c21e7 | ||
|
|
aca965f111 | ||
|
|
01a8ab7bf0 | ||
|
|
5dbd987df3 | ||
|
|
e37fc8c6e5 | ||
|
|
7614776e10 | ||
|
|
4ea4c70443 | ||
|
|
ec1946a9ff | ||
|
|
e0332deffc | ||
|
|
afe6caf406 | ||
|
|
1385aab65d | ||
|
|
862a9d938c | ||
|
|
80108727c4 | ||
|
|
84e3d6278d | ||
|
|
a1bf324f47 | ||
|
|
1b8f7059e3 | ||
|
|
b9fe6f2aed | ||
|
|
7794480da0 | ||
|
|
0171b8b998 | ||
|
|
915764cc52 | ||
|
|
381aa701ce | ||
|
|
76653fcedb | ||
|
|
dd0cfec225 | ||
|
|
67b64e0816 | ||
|
|
7552f5e5da | ||
|
|
9af862b455 | ||
|
|
f26f7646ba | ||
|
|
0f36dc03c4 | ||
|
|
36b385ed54 | ||
|
|
5e3f2cf25a | ||
|
|
8b0cfab2b2 | ||
|
|
f678629734 | ||
|
|
635cb4dc7c | ||
|
|
87df74e4d0 | ||
|
|
45c82a2746 | ||
|
|
d3c55c2b7c | ||
|
|
bc3938daa7 | ||
|
|
4d4b509ac3 | ||
|
|
304b484529 | ||
|
|
7025d612c1 | ||
|
|
2eb9406611 | ||
|
|
07034daffe | ||
|
|
dca8ecb929 | ||
|
|
dd2eecec42 | ||
|
|
72ba4213d5 | ||
|
|
11dbacab60 | ||
|
|
4caca2ce1a | ||
|
|
90e39e34e9 | ||
|
|
9a7171068d | ||
|
|
bb2a3590ad | ||
|
|
280dd205d9 | ||
|
|
2a722644b2 | ||
|
|
de69bb9448 | ||
|
|
5c495265f4 | ||
|
|
9cdf2d8150 | ||
|
|
6af1a52305 | ||
|
|
703002bafa | ||
|
|
8104e4bde9 | ||
|
|
763dbfc397 | ||
|
|
e0645b4b63 | ||
|
|
f714759ec7 | ||
|
|
8168e9cca1 | ||
|
|
be470b71ea | ||
|
|
216f39e9bc | ||
|
|
486c4481d8 | ||
|
|
6a154c139f | ||
|
|
d559ac513e | ||
|
|
c2c89c6c6b | ||
|
|
af76c77b18 | ||
|
|
c4be5107df | ||
|
|
c13218d647 | ||
|
|
4ce55a44ba | ||
|
|
905891683b | ||
|
|
f4019f5a5a | ||
|
|
b7aec51ed8 | ||
|
|
e6b9c16d04 | ||
|
|
488943aaa0 | ||
|
|
c3f6153f94 | ||
|
|
87aa3d7c60 | ||
|
|
144a2832b9 | ||
|
|
26c01cefa7 | ||
|
|
91b58bdb3f | ||
|
|
b97d9a4fa9 | ||
|
|
83a1663750 | ||
|
|
76f571f9a9 | ||
|
|
8c53f6ff49 | ||
|
|
08ab13dc4b | ||
|
|
aac9b770fc | ||
|
|
552d979039 | ||
|
|
30494eee75 | ||
|
|
eb0782ec90 | ||
|
|
c6edde1365 | ||
|
|
5c918a486c | ||
|
|
6e3b5e075a | ||
|
|
8b8d78f456 | ||
|
|
3cb2e74d12 | ||
|
|
41082c5e81 | ||
|
|
e939c6f91a | ||
|
|
5da634ed70 | ||
|
|
bee3605275 | ||
|
|
243567bdbb | ||
|
|
52b22b3c58 | ||
|
|
edfefabcf8 | ||
|
|
9c627782d4 | ||
|
|
cb1a9aef3c | ||
|
|
ba9f46ef49 | ||
|
|
5502087017 | ||
|
|
5510135084 | ||
|
|
ddecca47fd | ||
|
|
1eabdee253 | ||
|
|
029535bcea | ||
|
|
4ef89abac7 | ||
|
|
8af257a4cd | ||
|
|
a124dcd4e8 | ||
|
|
fbae2d7330 | ||
|
|
f296fad4bb | ||
|
|
e2d8105f0d | ||
|
|
287c073f00 | ||
|
|
ff1706c729 | ||
|
|
138a060df2 | ||
|
|
6678beadab | ||
|
|
09793fcd59 | ||
|
|
cab503bb2b | ||
|
|
f20db6bbc1 | ||
|
|
d50d4d1a6f | ||
|
|
59b722f663 | ||
|
|
b65fd11a36 | ||
|
|
36c9a29a7b | ||
|
|
6ba098d26d | ||
|
|
fbf25c1529 | ||
|
|
214261e764 | ||
|
|
b74cfcfec5 | ||
|
|
bc67756ff6 | ||
|
|
eccd12923b | ||
|
|
8f9ad524c2 | ||
|
|
5d958a4c07 | ||
|
|
22128781be | ||
|
|
34dcff4ce2 | ||
|
|
bcbdfdd7ab | ||
|
|
ee0125eff6 | ||
|
|
e6409b09a3 | ||
|
|
9c015de00b | ||
|
|
3a04778f97 | ||
|
|
53aea61184 | ||
|
|
b424247daf | ||
|
|
097be61c9f | ||
|
|
b349caeab1 | ||
|
|
593636f135 | ||
|
|
70ea325c75 | ||
|
|
1a9a9cb402 | ||
|
|
9d05a53c89 | ||
|
|
56794e8d7c | ||
|
|
2b2eb853fc | ||
|
|
bf2181f111 | ||
|
|
bd0882ccd5 | ||
|
|
0c2564df86 | ||
|
|
591b71cf18 | ||
|
|
76e9687d6f |
@@ -4,8 +4,8 @@ project(mirall)
|
|||||||
set(PACKAGE "mirall")
|
set(PACKAGE "mirall")
|
||||||
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
|
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
|
||||||
|
|
||||||
if ( EXISTS ${CMAKE_SOURCE_DIR}/OEM.cmake )
|
if ( DEFINED OEM_THEME_DIR AND EXISTS ${OEM_THEME_DIR}/OEM.cmake )
|
||||||
include ( ${CMAKE_SOURCE_DIR}/OEM.cmake )
|
include ( ${OEM_THEME_DIR}/OEM.cmake )
|
||||||
else ()
|
else ()
|
||||||
include ( ${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake )
|
include ( ${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake )
|
||||||
endif()
|
endif()
|
||||||
@@ -15,6 +15,22 @@ configure_file( ${CMAKE_SOURCE_DIR}/src/mirall/version.h.in "${CMAKE_CURRENT_BIN
|
|||||||
include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}/src/mirall/")
|
include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}/src/mirall/")
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
include(GetGitRevisionDescription)
|
||||||
|
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||||
|
|
||||||
|
# if we cannot get it from git, directly try .tag (packages)
|
||||||
|
# this will work if the tar balls have been properly created
|
||||||
|
# via git-archive.
|
||||||
|
if (${GIT_SHA1} STREQUAL "GITDIR-NOTFOUND")
|
||||||
|
file(READ ${CMAKE_SOURCE_DIR}/.tag sha1_candidate)
|
||||||
|
string(REPLACE "\n" "" sha1_candidate ${sha1_candidate})
|
||||||
|
if (NOT ${sha1_candidate} STREQUAL "$Format:%H$")
|
||||||
|
message("${sha1_candidate}")
|
||||||
|
set (GIT_SHA1 "${sha1_candidate}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
## stupid, we should upstream this
|
## stupid, we should upstream this
|
||||||
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr" AND NOT CMAKE_INSTALL_SYSCONFDIR)
|
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr" AND NOT CMAKE_INSTALL_SYSCONFDIR)
|
||||||
set(CMAKE_INSTALL_SYSCONFDIR "/etc")
|
set(CMAKE_INSTALL_SYSCONFDIR "/etc")
|
||||||
@@ -37,13 +53,20 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
#####
|
#####
|
||||||
|
|
||||||
|
#### find libs
|
||||||
find_package(Qt4 4.6.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest REQUIRED )
|
find_package(Qt4 4.6.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest REQUIRED )
|
||||||
find_package(Csync)
|
find_package(Csync)
|
||||||
|
if(UNIX)
|
||||||
|
find_package(INotify REQUIRED)
|
||||||
|
else()
|
||||||
find_package(INotify)
|
find_package(INotify)
|
||||||
|
endif()
|
||||||
find_package(Sphinx)
|
find_package(Sphinx)
|
||||||
find_package(PdfLatex)
|
find_package(PdfLatex)
|
||||||
|
find_package(QtKeychain)
|
||||||
|
|
||||||
set(WITH_CSYNC CSYNC_FOUND)
|
set(WITH_CSYNC CSYNC_FOUND)
|
||||||
|
set(WITH_QTKEYCHAIN ${QTKEYCHAIN_FOUND})
|
||||||
set(USE_INOTIFY ${INOTIFY_FOUND})
|
set(USE_INOTIFY ${INOTIFY_FOUND})
|
||||||
|
|
||||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|||||||
48
CONTRIBUTING.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
## Submitting Desktop Client issues
|
||||||
|
|
||||||
|
If you have questions about how to use the ownCloud Desktop Client, please
|
||||||
|
direct these to the [mailing list][mailinglist] or our [forum][forum].
|
||||||
|
We are also available on [IRC][irc].
|
||||||
|
|
||||||
|
### Guidelines
|
||||||
|
* Report the issue using our [template][template], it includes all the
|
||||||
|
informations we need to track down the issue.
|
||||||
|
* This repository is *only* for issues within the ownCloud desktop client.
|
||||||
|
Issues in other compontents should be reported in their own repositores:
|
||||||
|
- [ownCloud server](https://github.com/owncloud/core/issues)
|
||||||
|
- [ownCloud apps](https://github.com/owncloud/apps/issues) (e.g. Calendar,
|
||||||
|
Contacts...)
|
||||||
|
- [Android client](https://github.com/owncloud/android/issues)
|
||||||
|
- [iOS client](https://github.com/owncloud/ios-issues/issues)
|
||||||
|
* Search the existing issues first, it's likely that your issue was already
|
||||||
|
reported.
|
||||||
|
|
||||||
|
If your issue appears to be a bug, and hasn't been reported, open a new issue.
|
||||||
|
|
||||||
|
Help us to maximize the effort we can spend fixing issues and adding new
|
||||||
|
features, by not reporting duplicate issues.
|
||||||
|
|
||||||
|
[template]: https://raw.github.com/owncloud/mirall/master/issue_template.md
|
||||||
|
[mailinglist]: https://mail.kde.org/mailman/listinfo/owncloud
|
||||||
|
[forum]: http://forum.owncloud.org/
|
||||||
|
[irc]: http://webchat.freenode.net/?channels=owncloud&uio=d4
|
||||||
|
|
||||||
|
## Contributing to Source Code
|
||||||
|
|
||||||
|
Thanks for wanting to contribute source code to ownCloud. That's great!
|
||||||
|
|
||||||
|
Before we're able to merge your code to mirall, you need to sign
|
||||||
|
our [Contributor Agreement][agreement].
|
||||||
|
|
||||||
|
Please read the [Desktop Client Manual][mirallman] and the [Developer
|
||||||
|
Manuals][devmanual] to get useful infos like how to create your first
|
||||||
|
application or how to test the ownCloud code with phpunit.
|
||||||
|
|
||||||
|
[agreement]: http://owncloud.org/about/contributor-agreement/
|
||||||
|
[devmanual]: http://owncloud.org/dev/
|
||||||
|
[mirallman]: http://doc.owncloud.org/desktop/1.1/
|
||||||
|
|
||||||
|
## Translations
|
||||||
|
Please submit translations via [Transifex][transifex].
|
||||||
|
|
||||||
|
[transifex]: https://www.transifex.com/projects/p/owncloud/
|
||||||
@@ -9,9 +9,10 @@ endif(CPACK_GENERATOR MATCHES "NSIS")
|
|||||||
|
|
||||||
set( CMAKE_SOURCE_DIR @CMAKE_SOURCE_DIR@ )
|
set( CMAKE_SOURCE_DIR @CMAKE_SOURCE_DIR@ )
|
||||||
set( CMAKE_BINARY_DIR @CMAKE_BINARY_DIR@ )
|
set( CMAKE_BINARY_DIR @CMAKE_BINARY_DIR@ )
|
||||||
|
set( OEM_THEME_DIR @OEM_THEME_DIR@ )
|
||||||
|
|
||||||
if ( EXISTS "${CMAKE_SOURCE_DIR}/OEM.cmake" )
|
if ( DEFINED OEM_THEME_DIR AND EXISTS ${OEM_THEME_DIR}/OEM.cmake )
|
||||||
include ( "${CMAKE_SOURCE_DIR}/OEM.cmake" )
|
include ( ${OEM_THEME_DIR}/OEM.cmake )
|
||||||
else ()
|
else ()
|
||||||
include ( "${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake" )
|
include ( "${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake" )
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
95
ChangeLog
@@ -1,6 +1,70 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
=========
|
=========
|
||||||
version 1.1.2 (release 2012-11- ), csync 0.60.2 required
|
|
||||||
|
version 1.2.4 (release 2013-04-11 ), csync 0.70.6 required
|
||||||
|
* [Fixes] Clarify string in folder wizard
|
||||||
|
* [Fixes] Fixed some valgrind warnings
|
||||||
|
* [Fixes] Ensure that only one sync thread can ever run
|
||||||
|
* [Fixes] Fix default config storage path
|
||||||
|
* [Fixes] Skip folders with no absolute path
|
||||||
|
* [Fixes] Allow setting the configuration directory on command line
|
||||||
|
|
||||||
|
version 1.2.3 (release 2013-04-02 ), csync 0.70.5 required
|
||||||
|
|
||||||
|
* [Fixes] Unbreak self-signed certificate handling
|
||||||
|
|
||||||
|
version 1.2.2 (release 2013-04-02 ), csync 0.70.5 required
|
||||||
|
|
||||||
|
* [Fixes] Do not crash when local file tree contains symlinks
|
||||||
|
* [Fixes] Correctly handle locked files on Windows
|
||||||
|
* [Fixes] Display errors in all members of the SSL chain
|
||||||
|
* [Fixes] Enable Accessibility features on Windows
|
||||||
|
* [Fixes] Make setupFavLink work properly on Mac OS
|
||||||
|
* [Fixes] Ignore temporary files created by MS Office
|
||||||
|
* [Gui] Support Nautilus in setupFavLink
|
||||||
|
|
||||||
|
version 1.2.1 (release 2013-02-26 ), csync 0.70.4 required
|
||||||
|
* [Fixes] Leave configured folders on configuration changes.
|
||||||
|
* [Fixes] Do not allow to finish the setup dialog if connection can't be established.
|
||||||
|
* [Fixes] Better handling of credentials in setup dialog.
|
||||||
|
* [Fixes] Do not leak fd's to /dev/null when using gnutls
|
||||||
|
* [Fixes] Stop sync scheduling when configuration wizard starts.
|
||||||
|
* [Fixes] Clear pending network requests when stepping back in config wizard.
|
||||||
|
* [Fixes] User password dialog asynchronous issues.
|
||||||
|
* [Fixes] Make folderman starting and stoping the scheduling.
|
||||||
|
* [Fixes] Various minor fixes and cleanups.
|
||||||
|
* [Fixes] Crash on pausing sync
|
||||||
|
* [Fixes] Stale lock file after pausing sync
|
||||||
|
* [App] Load translations from app dir or bundle as well.
|
||||||
|
* [Platform] Build fixes and simplifications, ie. build only one lib.
|
||||||
|
* [Platform] Added some getter/setters for configuration values.
|
||||||
|
* [Platform] Added man pages.
|
||||||
|
* [Platform] Simplified/fixed credential store usage and custom configs.
|
||||||
|
* [Platform] Added soname version to libowncloudsync.
|
||||||
|
* [Platform] Pull in Qt translations
|
||||||
|
* [Gui] Make sync result popups less annoyingq
|
||||||
|
* [Gui] Fix for result popup
|
||||||
|
|
||||||
|
version 1.2.0 (release 2013-01-24 ), csync 0.70.2 required
|
||||||
|
* [GUI] New status dialog to show a detailed list of synced files.
|
||||||
|
* [GUI] New tray notifications about synced files.
|
||||||
|
* [GUI] New platform specific icon set.
|
||||||
|
* [App] Using cross platform QtKeychain library to store credentials crypted.
|
||||||
|
* [App] Use cross platform notification for changes in the local file system rather than regular poll.
|
||||||
|
* [Fixes] Improved SSL Certificate handling and SSL fixes troughout syncing.
|
||||||
|
* [Fixes] Fixed proxy authentication.
|
||||||
|
* [Fixes] Allow brackets in folder name alias.
|
||||||
|
* [Fixes] Lots of other minor fixes.
|
||||||
|
* [Platform] cmake fixes.
|
||||||
|
* [Platform] Improved, more detailed error reporting.
|
||||||
|
|
||||||
|
version 1.1.4 (release 2012-12-19 ), csync 0.60.4 required
|
||||||
|
* No changes to mirall, only csync fixes.
|
||||||
|
|
||||||
|
version 1.1.3 (release 2012-11-30 ), csync 0.60.3 required
|
||||||
|
* No changes to mirall, only csync fixes.
|
||||||
|
|
||||||
|
version 1.1.2 (release 2012-11-26 ), csync 0.60.2 required
|
||||||
* [Fixes] Allow to properly cancel the password dialog.
|
* [Fixes] Allow to properly cancel the password dialog.
|
||||||
* [Fixes] Share folder name correctly percent encoded with old Qt
|
* [Fixes] Share folder name correctly percent encoded with old Qt
|
||||||
4.6 builds ie. Debian.
|
4.6 builds ie. Debian.
|
||||||
@@ -18,23 +82,19 @@ version 1.1.2 (release 2012-11- ), csync 0.60.2 required
|
|||||||
* [Platform] Fix Mac building
|
* [Platform] Fix Mac building
|
||||||
|
|
||||||
version 1.1.1 (release 2012-10-18), csync 0.60.1 required
|
version 1.1.1 (release 2012-10-18), csync 0.60.1 required
|
||||||
* [GUI] Allow changing folder name in single folder mode
|
* [GUI] Allow changing folder name in single folder mode
|
||||||
* [GUI] Windows: Add license to installer
|
* [GUI] Windows: Add license to installer
|
||||||
* [GUI] owncloud --logwindow will bring up the log window
|
* [GUI] owncloud --logwindow will bring up the log window
|
||||||
in an already running instance
|
in an already running instance
|
||||||
* [Fixes] Make sure SSL errors are always handled
|
* [Fixes] Make sure SSL errors are always handled
|
||||||
* [Fixes] Allow special characters in folder alias
|
* [Fixes] Allow special characters in folder alias
|
||||||
* [Fixes] Proper workaround for Menu bug in Ubuntu
|
* [Fixes] Proper workaround for Menu bug in Ubuntu
|
||||||
* [Fixes] csync: Fix improper memory cleanup which could
|
* [Fixes] csync: Fix improper memory cleanup which could
|
||||||
cause memory leaks and crashes
|
cause memory leaks and crashes
|
||||||
* [Fixes] csync: Fix memory leak
|
* [Fixes] csync: Fix memory leak
|
||||||
* [Fixes] csync: Allow single quote (') in file names
|
* [Fixes] csync: Allow single quote (') in file names
|
||||||
* [Fixes] csync: Remove stray temporary files
|
* [Fixes] csync: Remove stray temporary files
|
||||||
|
|
||||||
version 1.1.0 (release 2012-10-10), csync 0.60.0 required
|
|
||||||
* [GUI] Added an about dialog
|
|
||||||
* [GUI] Improved themeing capabilities of the client.
|
|
||||||
* [GUI] Minor fixes in folder assistant.
|
|
||||||
* [GUI] Reworked tray context menu.
|
* [GUI] Reworked tray context menu.
|
||||||
* [GUI] Users can now sync the server root folder.
|
* [GUI] Users can now sync the server root folder.
|
||||||
* [Fixes] Proxy support: now supports Proxy Auto-Configuration (PAC)
|
* [Fixes] Proxy support: now supports Proxy Auto-Configuration (PAC)
|
||||||
@@ -53,7 +113,7 @@ version 1.1.0 (release 2012-10-10), csync 0.60.0 required
|
|||||||
* [Platform] csync conf file and database were moved to the users app data
|
* [Platform] csync conf file and database were moved to the users app data
|
||||||
directory, away from the .csync dir.
|
directory, away from the .csync dir.
|
||||||
* Renamed exclude.lst to sync-exclude.lst and moved it to
|
* Renamed exclude.lst to sync-exclude.lst and moved it to
|
||||||
/etc/appName()/ for more clean packaging. From the user path,
|
/etc/appName()/ for more clean packaging. From the user path,
|
||||||
still exclude.lst is read if sync-exclude.lst is not existing.
|
still exclude.lst is read if sync-exclude.lst is not existing.
|
||||||
* Placed custom.ini with customization options to /etc/appName()
|
* Placed custom.ini with customization options to /etc/appName()
|
||||||
|
|
||||||
@@ -62,7 +122,7 @@ version 1.0.5 (release 2012-08-14), csync 0.50.8 required
|
|||||||
|
|
||||||
version 1.0.4 (release 2012-08-10), csync 0.50.8 required
|
version 1.0.4 (release 2012-08-10), csync 0.50.8 required
|
||||||
* [APP] ownCloud is now a single instance app, can not start twice any more.
|
* [APP] ownCloud is now a single instance app, can not start twice any more.
|
||||||
* [APP] Proxy support
|
* [APP] Proxy support
|
||||||
* [APP] Handle HTTP redirection correctly, note new url.
|
* [APP] Handle HTTP redirection correctly, note new url.
|
||||||
* [APP] More relaxed handling of read only directories in the sync paths.
|
* [APP] More relaxed handling of read only directories in the sync paths.
|
||||||
* [APP] Started to split off a library with sync functionality, eg for KDE
|
* [APP] Started to split off a library with sync functionality, eg for KDE
|
||||||
@@ -73,13 +133,13 @@ version 1.0.4 (release 2012-08-10), csync 0.50.8 required
|
|||||||
* [GUI] Removed Log Window Button, log available through command line.
|
* [GUI] Removed Log Window Button, log available through command line.
|
||||||
* [GUI] Proxy configuration dialog added.
|
* [GUI] Proxy configuration dialog added.
|
||||||
* [GUI] Added Translations to languages Slovenian, Polish, Catalan,
|
* [GUI] Added Translations to languages Slovenian, Polish, Catalan,
|
||||||
Portuguese (Brazil), German, Greek, Spanish, Czech, Italian, Slovak,
|
Portuguese (Brazil), German, Greek, Spanish, Czech, Italian, Slovak,
|
||||||
French, Russian, Japanese, Swedish, Portuguese (Portugal)
|
French, Russian, Japanese, Swedish, Portuguese (Portugal)
|
||||||
all with translation rate >90%.
|
all with translation rate >90%.
|
||||||
* [Fixes] Loading of self signed certs into Networkmanager (#oc-843)
|
* [Fixes] Loading of self signed certs into Networkmanager (#oc-843)
|
||||||
* [Fixes] Win32: Handle SSL dll loading correctly.
|
* [Fixes] Win32: Handle SSL dll loading correctly.
|
||||||
* [Fixes] Many other small fixes and improvements.
|
* [Fixes] Many other small fixes and improvements.
|
||||||
|
|
||||||
version 1.0.3 (release 2012-06-19), csync 0.50.7 required
|
version 1.0.3 (release 2012-06-19), csync 0.50.7 required
|
||||||
* [GUI] Added a log window which catches the logging if required and
|
* [GUI] Added a log window which catches the logging if required and
|
||||||
allows to save for information.
|
allows to save for information.
|
||||||
@@ -88,7 +148,7 @@ version 1.0.3 (release 2012-06-19), csync 0.50.7 required
|
|||||||
* [Fixes] Do not use csync database files from a sync before.
|
* [Fixes] Do not use csync database files from a sync before.
|
||||||
* [Fixes] In Connection wizard, write the final config onyl if
|
* [Fixes] In Connection wizard, write the final config onyl if
|
||||||
the user really accepted. Also remove the former database.
|
the user really accepted. Also remove the former database.
|
||||||
* [Fixes] More user expected behaviour deletion of sync folder local
|
* [Fixes] More user expected behaviour deletion of sync folder local
|
||||||
and remote.
|
and remote.
|
||||||
* [Fixes] Allow special characters in the sync directory names
|
* [Fixes] Allow special characters in the sync directory names
|
||||||
* [Fixes] Win32: Fixed directory removal with special character dirs.
|
* [Fixes] Win32: Fixed directory removal with special character dirs.
|
||||||
@@ -129,4 +189,3 @@ version 1.0.1 (release 2012-04-18), csync 0.50.5 required
|
|||||||
* [Platform] MacOSX Bundle creation added
|
* [Platform] MacOSX Bundle creation added
|
||||||
* [Platform] Enabled ranslations on Windows.
|
* [Platform] Enabled ranslations on Windows.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
set( APPLICATION_SHORTNAME "owncloud" )
|
set( APPLICATION_SHORTNAME "owncloud" )
|
||||||
set( APPLICATION_NAME "ownCloud" )
|
set( APPLICATION_NAME "ownCloud" )
|
||||||
set( APPLICATION_EXECUTABLE "owncloud" )
|
set( APPLICATION_EXECUTABLE "owncloud" )
|
||||||
set( APPLICATION_DOMAIN "owncloud.org" )
|
set( APPLICATION_DOMAIN "owncloud.com" )
|
||||||
set( APPLICATION_VENDOR "ownCloud.org" )
|
set( APPLICATION_VENDOR "ownCloud, Inc" )
|
||||||
set( THEME_CLASS "ownCloudTheme" )
|
set( THEME_CLASS "ownCloudTheme" )
|
||||||
set( APPLICATION_REV_DOMAIN "org.owncloud.desktopclient" )
|
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" )
|
||||||
|
# set( APPLICATION_LICENSE "${OEM_THEME_DIR}/license.txt )
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ include( InstallRequiredSystemLibraries )
|
|||||||
|
|
||||||
set( CPACK_PACKAGE_CONTACT "Dominik Schmidt <domme@tomahawk-player.org>" )
|
set( CPACK_PACKAGE_CONTACT "Dominik Schmidt <domme@tomahawk-player.org>" )
|
||||||
|
|
||||||
if ( EXISTS "${CMAKE_SOURCE_DIR}/OEM.cmake" )
|
if ( DEFINED OEM_THEME_DIR AND EXISTS ${OEM_THEME_DIR}/OEM.cmake )
|
||||||
include ( "${CMAKE_SOURCE_DIR}/OEM.cmake" )
|
include ( "${OEM_THEME_DIR}/OEM.cmake" )
|
||||||
else ()
|
else ()
|
||||||
include ( "${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake" )
|
include ( "${CMAKE_SOURCE_DIR}/OWNCLOUD.cmake" )
|
||||||
endif()
|
endif()
|
||||||
@@ -45,12 +45,12 @@ if(WIN32)
|
|||||||
# CPACK_INCLUDE_TOPLEVEL_DIRECTORY Controls whether CPack adds a top-level directory, usually of the form ProjectName-Version-OS, to the top of package tree. 0 to disable, 1 to enable
|
# CPACK_INCLUDE_TOPLEVEL_DIRECTORY Controls whether CPack adds a top-level directory, usually of the form ProjectName-Version-OS, to the top of package tree. 0 to disable, 1 to enable
|
||||||
# CPACK_INSTALL_CMAKE_PROJECTS List of four values: Build directory, Project Name, Project Component, Directory in the package /home/andy/vtk/CMake-bin;CMake;ALL;/
|
# CPACK_INSTALL_CMAKE_PROJECTS List of four values: Build directory, Project Name, Project Component, Directory in the package /home/andy/vtk/CMake-bin;CMake;ALL;/
|
||||||
set( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md" ) # File used as a description of a project /path/to/project/ReadMe.txt
|
set( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md" ) # File used as a description of a project /path/to/project/ReadMe.txt
|
||||||
set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "ownCloud Syncing Client" ) # Description summary of a project
|
set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "${APPLICATION_NAME} Syncing Client" ) # Description summary of a project
|
||||||
# CPACK_PACKAGE_EXECUTABLES List of pairs of executables and labels. Used by the NSIS generator to create Start Menu shortcuts. ccmake;CMake
|
# CPACK_PACKAGE_EXECUTABLES List of pairs of executables and labels. Used by the NSIS generator to create Start Menu shortcuts. ccmake;CMake
|
||||||
set( CPACK_PACKAGE_INSTALL_DIRECTORY ${APPLICATION_NAME} ) # Installation directory on the target system -> C:\Program Files\fellody
|
set( CPACK_PACKAGE_INSTALL_DIRECTORY ${APPLICATION_NAME} ) # Installation directory on the target system -> C:\Program Files\fellody
|
||||||
set( CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${APPLICATION_NAME} ) # Registry key used when installing this project CMake 2.5.0
|
set( CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${APPLICATION_NAME} ) # Registry key used when installing this project CMake 2.5.0
|
||||||
set( CPACK_PACKAGE_NAME ${APPLICATION_NAME} ) # Package name, defaults to the project name
|
set( CPACK_PACKAGE_NAME ${APPLICATION_NAME} ) # Package name, defaults to the project name
|
||||||
set( CPACK_PACKAGE_VENDOR "http://owncloud.com" ) # Package vendor name
|
set( CPACK_PACKAGE_VENDOR "http://${APPLICATION_DOMAIN}" ) # Package vendor name
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# set( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt" ) # License file for the project, used by the STGZ, NSIS, and PackageMaker generators. /home/andy/vtk/CMake/Copyright.txt
|
# set( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt" ) # License file for the project, used by the STGZ, NSIS, and PackageMaker generators. /home/andy/vtk/CMake/Copyright.txt
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
set( VERSION_MAJOR 1 )
|
set( VERSION_MAJOR 1 )
|
||||||
set( VERSION_MINOR 1 )
|
set( VERSION_MINOR 2 )
|
||||||
set( VERSION_PATCH 2 )
|
set( VERSION_PATCH 4 )
|
||||||
set( VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}rc )
|
set( VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${VERSION_SUFFIX})
|
||||||
|
set( SOVERSION 0 )
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ mount="/Volumes/$(basename $src_dmg|cut -d"-" -f1)"
|
|||||||
test -e $tmp_dmg && rm -rf $tmp_dmg
|
test -e $tmp_dmg && rm -rf $tmp_dmg
|
||||||
hdiutil convert $src_dmg -format UDRW -o $tmp_dmg
|
hdiutil convert $src_dmg -format UDRW -o $tmp_dmg
|
||||||
open $tmp_dmg
|
open $tmp_dmg
|
||||||
sleep 2s
|
sleep 12s
|
||||||
pushd $mount
|
pushd $mount
|
||||||
codesign -s "$identity" $mount/*.app
|
codesign -s "$identity" $mount/*.app
|
||||||
popd
|
popd
|
||||||
|
|||||||
@@ -32,3 +32,7 @@ SET(QT_MOC_EXECUTABLE ${MINGW_PREFIX}-moc)
|
|||||||
SET(QT_RCC_EXECUTABLE ${MINGW_PREFIX}-rcc)
|
SET(QT_RCC_EXECUTABLE ${MINGW_PREFIX}-rcc)
|
||||||
SET(QT_UIC_EXECUTABLE ${MINGW_PREFIX}-uic)
|
SET(QT_UIC_EXECUTABLE ${MINGW_PREFIX}-uic)
|
||||||
SET(QT_LRELEASE_EXECUTABLE ${MINGW_PREFIX}-lrelease)
|
SET(QT_LRELEASE_EXECUTABLE ${MINGW_PREFIX}-lrelease)
|
||||||
|
|
||||||
|
# neon config
|
||||||
|
SET(NEON_CONFIG_EXECUTABLE ${CMAKE_FIND_ROOT_PATH}/bin/neon-config)
|
||||||
|
# /usr/i686-w64-mingw32/sys-root/mingw/bin/neon-config
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
@@ -1,28 +1,28 @@
|
|||||||
IF(EXISTS "${CMAKE_SOURCE_DIR}/../csync/src/csync.h")
|
|
||||||
SET(CSYNC_INCLUDE_PATH ${CMAKE_SOURCE_DIR}/../csync/src/)
|
|
||||||
ELSE()
|
|
||||||
FIND_PATH(CSYNC_INCLUDE_PATH NAMES csync.h HINTS $ENV{CSYNC_DIR} )
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF( DEFINED CSYNC_LIBRARY_PATH AND DEFINED CSYNC_INCLUDE_PATH )
|
IF( DEFINED CSYNC_BUILD_PATH )
|
||||||
IF( WIN32 )
|
SET(CSYNC_LIBRARY_PATH ${CSYNC_BUILD_PATH})
|
||||||
SET(CSYNC_LIBRARY ${CSYNC_LIBRARY_PATH}/src/libocsync.dll)
|
SET(CSYNC_BINARY_DIR ${CSYNC_BUILD_PATH})
|
||||||
ELSEIF ( APPLE )
|
|
||||||
SET(CSYNC_LIBRARY ${CSYNC_LIBRARY_PATH}/src/libocsync.dylib)
|
IF(WIN32)
|
||||||
|
SET(CSYNC_LIBRARY ${CSYNC_BUILD_PATH}/src/libocsync.dll)
|
||||||
|
ELSEIF( APPLE )
|
||||||
|
SET(CSYNC_LIBRARY ${CSYNC_BUILD_PATH}/src/libocsync.dylib)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(CSYNC_LIBRARY ${CSYNC_LIBRARY_PATH}/src/libocsync.so)
|
SET(CSYNC_LIBRARY ${CSYNC_BUILD_PATH}/src/libocsync.so)
|
||||||
ENDIF( )
|
ENDIF()
|
||||||
SET(CSYNC_BINARY_DIR ${CSYNC_LIBRARY_PATH})
|
|
||||||
ELSE()
|
ELSE()
|
||||||
FIND_LIBRARY(CSYNC_LIBRARY NAMES ocsync HINTS $ENV{CSYNC_DIR})
|
FIND_LIBRARY(CSYNC_LIBRARY NAMES ocsync HINTS $ENV{CSYNC_DIR})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF(NOT DEFINED CSYNC_INCLUDE_PATH)
|
||||||
|
FIND_PATH(CSYNC_INCLUDE_PATH NAMES csync.h HINTS $ENV{CSYNC_DIR} )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET(CSYNC_INCLUDE_DIR ${CSYNC_INCLUDE_PATH})
|
SET(CSYNC_INCLUDE_DIR ${CSYNC_INCLUDE_PATH})
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set CSYNC_FOUND to TRUE if
|
# handle the QUIETLY and REQUIRED arguments and set CSYNC_FOUND to TRUE if
|
||||||
# all listed variables are TRUE
|
# all listed variables are TRUE
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Csync DEFAULT_MSG
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Csync DEFAULT_MSG CSYNC_LIBRARY CSYNC_INCLUDE_PATH)
|
||||||
CSYNC_LIBRARY CSYNC_INCLUDE_PATH)
|
|
||||||
|
|
||||||
MARK_AS_ADVANCED( CSYNC_INCLUDE_PATH CSYNC_LIBRARY )
|
MARK_AS_ADVANCED( CSYNC_INCLUDE_PATH CSYNC_LIBRARY )
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
# also defined, but not for general use are
|
# also defined, but not for general use are
|
||||||
# INOTIFY_LIBRARY, where to find the inotify library.
|
# INOTIFY_LIBRARY, where to find the inotify library.
|
||||||
|
|
||||||
find_path(INOTIFY_INCLUDE_DIR sys/inotify.h)
|
find_path(INOTIFY_INCLUDE_DIR sys/inotify.h
|
||||||
|
HINTS /usr/include/${CMAKE_LIBRARY_ARCHITECTURE})
|
||||||
mark_as_advanced(INOTIFY_INCLUDE_DIR)
|
mark_as_advanced(INOTIFY_INCLUDE_DIR)
|
||||||
|
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set INOTIFY_FOUND to TRUE if
|
|
||||||
# all listed variables are TRUE
|
# all listed variables are TRUE
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set INOTIFY_FOUND to TRUE if
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(INOTIFY DEFAULT_MSG INOTIFY_INCLUDE_DIR)
|
find_package_handle_standard_args(INOTIFY DEFAULT_MSG INOTIFY_INCLUDE_DIR)
|
||||||
|
|
||||||
|
|||||||
18
cmake/modules/FindQtKeychain.cmake
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# - Try to find QtKeyChain
|
||||||
|
# Once done this will define
|
||||||
|
# QTKEYCHAIN_FOUND - System has QtKeyChain
|
||||||
|
# QTKEYCHAIN_INCLUDE_DIRS - The QtKeyChain include directories
|
||||||
|
# QTKEYCHAIN_LIBRARIES - The libraries needed to use QtKeyChain
|
||||||
|
# QTKEYCHAIN_DEFINITIONS - Compiler switches required for using LibXml2
|
||||||
|
|
||||||
|
find_path(QTKEYCHAIN_INCLUDE_DIR qtkeychain/keychain.h)
|
||||||
|
|
||||||
|
find_library(QTKEYCHAIN_LIBRARY NAMES libqtkeychain qtkeychain)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set QTKEYCHAIN_FOUND to TRUE
|
||||||
|
# if all listed variables are TRUE
|
||||||
|
find_package_handle_standard_args(QtKeyChain DEFAULT_MSG
|
||||||
|
QTKEYCHAIN_LIBRARY QTKEYCHAIN_INCLUDE_DIR)
|
||||||
|
|
||||||
|
mark_as_advanced(QTKEYCHAIN_INCLUDE_DIR QTKEYCHAIN_LIBRARY )
|
||||||
123
cmake/modules/GetGitRevisionDescription.cmake
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# - Returns a version string from Git
|
||||||
|
#
|
||||||
|
# These functions force a re-configure on each git commit so that you can
|
||||||
|
# trust the values of the variables in your build system.
|
||||||
|
#
|
||||||
|
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the refspec and sha hash of the current head revision
|
||||||
|
#
|
||||||
|
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the source tree, and adjusting
|
||||||
|
# the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
|
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe --exact-match on the source tree,
|
||||||
|
# and adjusting the output so that it tests false if there was no exact
|
||||||
|
# matching tag.
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright Iowa State University 2009-2010.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
if(__get_git_revision_description)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(__get_git_revision_description YES)
|
||||||
|
|
||||||
|
# We must run the following at "include" time, not at function call time,
|
||||||
|
# to find the path to this module rather than the path to a calling list file
|
||||||
|
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||||
|
|
||||||
|
function(get_git_head_revision _refspecvar _hashvar)
|
||||||
|
set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||||
|
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||||
|
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||||
|
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||||
|
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||||
|
# We have reached the root directory, we are not in git
|
||||||
|
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||||
|
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||||
|
endwhile()
|
||||||
|
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||||
|
if(NOT EXISTS "${GIT_DATA}")
|
||||||
|
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||||
|
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||||
|
|
||||||
|
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||||
|
"${GIT_DATA}/grabRef.cmake"
|
||||||
|
@ONLY)
|
||||||
|
include("${GIT_DATA}/grabRef.cmake")
|
||||||
|
|
||||||
|
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||||
|
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# TODO sanitize
|
||||||
|
#if((${ARGN}" MATCHES "&&") OR
|
||||||
|
# (ARGN MATCHES "||") OR
|
||||||
|
# (ARGN MATCHES "\\;"))
|
||||||
|
# message("Please report the following error to the project!")
|
||||||
|
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||||
|
|
||||||
|
execute_process(COMMAND
|
||||||
|
"${GIT_EXECUTABLE}"
|
||||||
|
describe
|
||||||
|
${hash}
|
||||||
|
${ARGN}
|
||||||
|
WORKING_DIRECTORY
|
||||||
|
"${CMAKE_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE
|
||||||
|
res
|
||||||
|
OUTPUT_VARIABLE
|
||||||
|
out
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var} "${out}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_get_exact_tag _var)
|
||||||
|
git_describe(out --exact-match ${ARGN})
|
||||||
|
set(${_var} "${out}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
38
cmake/modules/GetGitRevisionDescription.cmake.in
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#
|
||||||
|
# Internal file for GetGitRevisionDescription.cmake
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright Iowa State University 2009-2010.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
set(HEAD_HASH)
|
||||||
|
|
||||||
|
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||||
|
|
||||||
|
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||||
|
if(HEAD_CONTENTS MATCHES "ref")
|
||||||
|
# named branch
|
||||||
|
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||||
|
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||||
|
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
|
||||||
|
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
set(HEAD_HASH "${HEAD_REF}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# detached HEAD
|
||||||
|
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HEAD_HASH)
|
||||||
|
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||||
|
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||||
|
endif()
|
||||||
@@ -6,9 +6,7 @@
|
|||||||
!define APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@.exe"
|
!define APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@.exe"
|
||||||
!define APPLICATION_DOMAIN "@APPLICATION_DOMAIN@"
|
!define APPLICATION_DOMAIN "@APPLICATION_DOMAIN@"
|
||||||
!define APPLICATION_LICENSE "@APPLICATION_LICENSE@"
|
!define APPLICATION_LICENSE "@APPLICATION_LICENSE@"
|
||||||
|
!define WIN_SETUP_BITMAP_PATH "@WIN_SETUP_BITMAP_PATH@"
|
||||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.${APPLICATION_DOMAIN}"
|
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------------------
|
;-----------------------------------------------------------------------------
|
||||||
; Some installer script options (comment-out options not required)
|
; Some installer script options (comment-out options not required)
|
||||||
@@ -33,9 +31,11 @@
|
|||||||
!endif
|
!endif
|
||||||
!define MING_BIN "${MING_PATH}/bin"
|
!define MING_BIN "${MING_PATH}/bin"
|
||||||
!define MING_LIB "${MING_PATH}/lib"
|
!define MING_LIB "${MING_PATH}/lib"
|
||||||
|
!define MING_SHARE "${MING_PATH}/share"
|
||||||
!define BUILD_PATH "@CMAKE_BINARY_DIR@"
|
!define BUILD_PATH "@CMAKE_BINARY_DIR@"
|
||||||
!define SOURCE_PATH "@CMAKE_SOURCE_DIR@"
|
!define SOURCE_PATH "@CMAKE_SOURCE_DIR@"
|
||||||
!define QT_DLL_PATH "${MING_BIN}"
|
!define QT_DLL_PATH "${MING_BIN}"
|
||||||
|
!define ACCESSIBLE_DLL_PATH "${MING_LIB}/qt4/plugins/accessible"
|
||||||
!define SQLITE_DLL_PATH "${MING_LIB}/qt4/plugins/sqldrivers"
|
!define SQLITE_DLL_PATH "${MING_LIB}/qt4/plugins/sqldrivers"
|
||||||
!define IMAGEFORMATS_DLL_PATH "${MING_LIB}/qt4/plugins/imageformats"
|
!define IMAGEFORMATS_DLL_PATH "${MING_LIB}/qt4/plugins/imageformats"
|
||||||
|
|
||||||
@@ -63,7 +63,6 @@
|
|||||||
; Initial installer setup and definitions.
|
; Initial installer setup and definitions.
|
||||||
;-----------------------------------------------------------------------------
|
;-----------------------------------------------------------------------------
|
||||||
Name "@CPACK_NSIS_PACKAGE_NAME@"
|
Name "@CPACK_NSIS_PACKAGE_NAME@"
|
||||||
Caption "${APPLICATION_NAME} Setup"
|
|
||||||
BrandingText "${APPLICATION_NAME} ${VERSION} -- ${BUILD_TIME}"
|
BrandingText "${APPLICATION_NAME} ${VERSION} -- ${BUILD_TIME}"
|
||||||
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
|
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
|
||||||
InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||||
@@ -103,14 +102,12 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
|||||||
!define MUI_ABORTWARNING
|
!define MUI_ABORTWARNING
|
||||||
!define MUI_ICON ${NSI_PATH}\installer.ico
|
!define MUI_ICON ${NSI_PATH}\installer.ico
|
||||||
!define MUI_UNICON ${NSI_PATH}\installer.ico
|
!define MUI_UNICON ${NSI_PATH}\installer.ico
|
||||||
!define MUI_WELCOMEFINISHPAGE_BITMAP ${NSI_PATH}\welcome_${APPLICATION_SHORTNAME}.bmp
|
!define MUI_WELCOMEFINISHPAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/welcome.bmp
|
||||||
!define MUI_WELCOMEPAGE_TITLE "Welcome to the @CPACK_PACKAGE_NAME@ ${VERSION} Setup Wizard"
|
|
||||||
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation.$\r$\n$\r$\n$_CLICK"
|
|
||||||
!define MUI_HEADERIMAGE
|
!define MUI_HEADERIMAGE
|
||||||
!define MUI_HEADERIMAGE_BITMAP ${NSI_PATH}\page_header_${APPLICATION_SHORTNAME}.bmp
|
!define MUI_HEADERIMAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/page_header.bmp
|
||||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||||
!define MUI_FINISHPAGE_TITLE "@CPACK_PACKAGE_NAME@ Setup Completed"
|
!define MUI_FINISHPAGE_LINK "www.${APPLICATION_DOMAIN}"
|
||||||
!define MUI_FINISHPAGE_LINK "Click here to visit the @CPACK_PACKAGE_NAME@ website."
|
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.${APPLICATION_DOMAIN}"
|
||||||
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
|
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
|
||||||
!ifdef OPTION_FINISHPAGE_RELEASE_NOTES
|
!ifdef OPTION_FINISHPAGE_RELEASE_NOTES
|
||||||
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
||||||
@@ -128,7 +125,7 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
|||||||
;-----------------------------------------------------------------------------
|
;-----------------------------------------------------------------------------
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
!ifdef OPTION_LICENSE_AGREEMENT
|
!ifdef OPTION_LICENSE_AGREEMENT
|
||||||
!insertmacro MUI_PAGE_LICENSE "${source_path}/${APPLICATION_LICENSE}"
|
!insertmacro MUI_PAGE_LICENSE "${APPLICATION_LICENSE}"
|
||||||
!endif
|
!endif
|
||||||
Page custom PageReinstall PageLeaveReinstall
|
Page custom PageReinstall PageLeaveReinstall
|
||||||
!insertmacro MUI_PAGE_COMPONENTS
|
!insertmacro MUI_PAGE_COMPONENTS
|
||||||
@@ -287,22 +284,83 @@ Section "${APPLICATION_NAME}" SEC_OWNCLOUD
|
|||||||
;Main executable.
|
;Main executable.
|
||||||
File "${BUILD_PATH}\bin\${APPLICATION_EXECUTABLE}"
|
File "${BUILD_PATH}\bin\${APPLICATION_EXECUTABLE}"
|
||||||
File "${BUILD_PATH}\src\libowncloudsync.dll"
|
File "${BUILD_PATH}\src\libowncloudsync.dll"
|
||||||
|
|
||||||
File "${BUILD_PATH}\src\mirall_ca.qm"
|
File "${BUILD_PATH}\src\mirall_ca.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_cs_CZ.qm"
|
File "${BUILD_PATH}\src\mirall_cs_CZ.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_da.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_de.qm"
|
File "${BUILD_PATH}\src\mirall_de.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_el.qm"
|
File "${BUILD_PATH}\src\mirall_el.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_en.qm"
|
File "${BUILD_PATH}\src\mirall_en.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_eo.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_es.qm"
|
File "${BUILD_PATH}\src\mirall_es.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_es_AR.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_et_EE.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_eu.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_fa.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_fi_FI.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_fr.qm"
|
File "${BUILD_PATH}\src\mirall_fr.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_gl.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_he.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_hr.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_hu_HU.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_it.qm"
|
File "${BUILD_PATH}\src\mirall_it.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_ja_JP.qm"
|
File "${BUILD_PATH}\src\mirall_ja_JP.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_ko.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_lb.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_lt_LT.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_lv.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_mk.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_ms_MY.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_nb_NO.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_nl.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_oc.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_pl.qm"
|
File "${BUILD_PATH}\src\mirall_pl.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_pt_BR.qm"
|
File "${BUILD_PATH}\src\mirall_pt_BR.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_pt_PT.qm"
|
File "${BUILD_PATH}\src\mirall_pt_PT.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_ro.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_ru.qm"
|
File "${BUILD_PATH}\src\mirall_ru.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_ru_RU.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_si_LK.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_sk_SK.qm"
|
File "${BUILD_PATH}\src\mirall_sk_SK.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_sl.qm"
|
File "${BUILD_PATH}\src\mirall_sl.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_sr@latin.qm"
|
||||||
File "${BUILD_PATH}\src\mirall_sv.qm"
|
File "${BUILD_PATH}\src\mirall_sv.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_ta_LK.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_th_TH.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_tr.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_uk.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_vi.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_zh_CN.qm"
|
||||||
|
File "${BUILD_PATH}\src\mirall_zh_TW.qm"
|
||||||
|
|
||||||
|
#File "${MING_SHARE}\qt4\translations\qt_ar.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_cs.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_da.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_de.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_es.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_fa.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_fr.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_gl.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_he.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_hu.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_ja.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_ko.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_lt.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_pl.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_pt.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_ru.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_sk.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_sl.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_sv.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_uk.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_zh_CN.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_zh_TW.qm"
|
||||||
|
File "${MING_SHARE}\qt4\translations\qt_zh_TW.qm"
|
||||||
|
|
||||||
|
File "${MING_SHARE}\qt4\translations\qtkeychain_de.qm"
|
||||||
|
|
||||||
|
SetOutPath "$INSTDIR\accessible"
|
||||||
|
File "${ACCESSIBLE_DLL_PATH}\qtaccessiblewidgets4.dll"
|
||||||
|
|
||||||
SetOutPath "$INSTDIR\modules"
|
SetOutPath "$INSTDIR\modules"
|
||||||
; FIXME: fix installation dir of module, currently needs manual copying to
|
; FIXME: fix installation dir of module, currently needs manual copying to
|
||||||
@@ -324,6 +382,9 @@ Section "${APPLICATION_NAME}" SEC_OWNCLOUD
|
|||||||
File "${QT_DLL_PATH}\QtNetwork4.dll"
|
File "${QT_DLL_PATH}\QtNetwork4.dll"
|
||||||
File "${QT_DLL_PATH}\QtXml4.dll"
|
File "${QT_DLL_PATH}\QtXml4.dll"
|
||||||
|
|
||||||
|
;QtKeyChain stuff
|
||||||
|
File "${MING_BIN}\libqtkeychain.dll"
|
||||||
|
|
||||||
File "${CSYNC_LIBRARY_DIR}/libocsync.dll"
|
File "${CSYNC_LIBRARY_DIR}/libocsync.dll"
|
||||||
File "${MING_BIN}\libsqlite3-0.dll"
|
File "${MING_BIN}\libsqlite3-0.dll"
|
||||||
File "${MING_BIN}\libiniparser.dll"
|
File "${MING_BIN}\libiniparser.dll"
|
||||||
@@ -331,14 +392,10 @@ Section "${APPLICATION_NAME}" SEC_OWNCLOUD
|
|||||||
File "${MING_BIN}\libpng15-15.dll"
|
File "${MING_BIN}\libpng15-15.dll"
|
||||||
|
|
||||||
; ownCloud plugin
|
; ownCloud plugin
|
||||||
File "${MING_BIN}\libgcrypt-11.dll"
|
|
||||||
File "${MING_BIN}\libgnutls-26.dll"
|
|
||||||
File "${MING_BIN}\libgpg-error-0.dll"
|
|
||||||
File "${MING_BIN}\libintl-8.dll"
|
File "${MING_BIN}\libintl-8.dll"
|
||||||
File "${MING_BIN}\libneon-27.dll"
|
File "${MING_BIN}\libneon-27.dll"
|
||||||
File "${MING_BIN}\libproxy.dll"
|
File "${MING_BIN}\libproxy.dll"
|
||||||
File "${MING_BIN}\libmodman.dll"
|
File "${MING_BIN}\libmodman.dll"
|
||||||
File "${MING_BIN}\libtasn1-3.dll"
|
|
||||||
File "${MING_BIN}\libxml2-2.dll"
|
File "${MING_BIN}\libxml2-2.dll"
|
||||||
|
|
||||||
;MinGW stuff
|
;MinGW stuff
|
||||||
@@ -349,11 +406,10 @@ Section "${APPLICATION_NAME}" SEC_OWNCLOUD
|
|||||||
;File "${MING_BIN}\libpng15-15.dll"
|
;File "${MING_BIN}\libpng15-15.dll"
|
||||||
;File "${MING_BIN}\libjpeg-8.dll"
|
;File "${MING_BIN}\libjpeg-8.dll"
|
||||||
File "${MING_BIN}\zlib1.dll"
|
File "${MING_BIN}\zlib1.dll"
|
||||||
File "${MING_BIN}\libcrypto-8.dll"
|
File "${MING_BIN}\libcrypto-10.dll"
|
||||||
File "${MING_BIN}\libssl-8.dll"
|
File "${MING_BIN}\libssl-10.dll"
|
||||||
|
|
||||||
; CSync configs
|
; CSync configs
|
||||||
File "${CSYNC_CONFIG_DIR}/ocsync.conf"
|
|
||||||
File "${SOURCE_PATH}/sync-exclude.lst"
|
File "${SOURCE_PATH}/sync-exclude.lst"
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#cmakedefine USE_INOTIFY 1
|
#cmakedefine USE_INOTIFY 1
|
||||||
#cmakedefine WITH_CSYNC 1
|
#cmakedefine WITH_CSYNC 1
|
||||||
|
#cmakedefine WITH_QTKEYCHAIN 1
|
||||||
|
|
||||||
|
#cmakedefine GIT_SHA1 "@GIT_SHA1@"
|
||||||
|
#cmakedefine APPLICATION_DOMAIN @APPLICATION_DOMAIN@
|
||||||
#cmakedefine THEME_CLASS @THEME_CLASS@
|
#cmakedefine THEME_CLASS @THEME_CLASS@
|
||||||
|
#cmakedefine THEME_INCLUDE @THEME_INCLUDE@
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,20 +9,34 @@ if(SPHINX_FOUND)
|
|||||||
set(SPHINX_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/qthelp")
|
set(SPHINX_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/qthelp")
|
||||||
set(SPHINX_HTMLHELP_DIR "${CMAKE_CURRENT_BINARY_DIR}/htmlhelp")
|
set(SPHINX_HTMLHELP_DIR "${CMAKE_CURRENT_BINARY_DIR}/htmlhelp")
|
||||||
set(MSHTML_COMPILER wine 'C:\\Program Files\\HTML Help Workshop\\hhc.exe')
|
set(MSHTML_COMPILER wine 'C:\\Program Files\\HTML Help Workshop\\hhc.exe')
|
||||||
|
# assets
|
||||||
|
set(LATEX_LOGO "${CMAKE_CURRENT_SOURCE_DIR}/logo-blue.pdf")
|
||||||
|
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" conf.py @ONLY)
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" conf.py @ONLY)
|
||||||
add_custom_target(doc DEPENDS doc-html doc-man COMMENT "Building documentation...")
|
|
||||||
|
if(WITH_DOC)
|
||||||
|
add_custom_target(doc ALL DEPENDS doc-html doc-man COMMENT "Building documentation...")
|
||||||
|
install(DIRECTORY ${SPHINX_HTML_DIR} DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
install(DIRECTORY ${SPHINX_MAN_DIR} DESTINATION ${CMAKE_INSTALL_MANDIR})
|
||||||
|
else(WITH_DOC)
|
||||||
|
add_custom_target(doc DEPENDS doc-html doc-man COMMENT "Building documentation...")
|
||||||
|
endif(WITH_DOC)
|
||||||
|
|
||||||
if(PDFLATEX_FOUND)
|
if(PDFLATEX_FOUND)
|
||||||
# if this still fails on Debian/Ubuntu, run
|
# if this still fails on Debian/Ubuntu, run
|
||||||
# apt-get install texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended
|
# apt-get install texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended
|
||||||
add_custom_target(doc-latex ${SPHINX_EXECUTABLE}
|
add_custom_target(doc-latex ${SPHINX_EXECUTABLE}
|
||||||
-q -c . -b latex
|
-q -c . -b latex
|
||||||
-d ${SPHINX_CACHE_DIR}
|
-d ${SPHINX_CACHE_DIR}
|
||||||
|
-D latex_logo=${LATEX_LOGO}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${SPHINX_PDF_DIR} )
|
${SPHINX_PDF_DIR} )
|
||||||
add_custom_target(doc-pdf make -C ${SPHINX_PDF_DIR} all-pdf
|
add_custom_target(doc-pdf make -C ${SPHINX_PDF_DIR} all-pdf
|
||||||
DEPENDS doc-latex )
|
DEPENDS doc-latex )
|
||||||
add_dependencies(doc doc-pdf)
|
add_dependencies(doc doc-pdf)
|
||||||
|
if (WITH_DOC)
|
||||||
|
install(DIRECTORY ${SPHINX_PDF_DIR} DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
endif (WITH_DOC)
|
||||||
endif(PDFLATEX_FOUND)
|
endif(PDFLATEX_FOUND)
|
||||||
if (EXISTS ${QT_QCOLLECTIONGENERATOR_EXECUTABLE})
|
if (EXISTS ${QT_QCOLLECTIONGENERATOR_EXECUTABLE})
|
||||||
add_custom_target( doc-qch-sphinx ${SPHINX_EXECUTABLE}
|
add_custom_target( doc-qch-sphinx ${SPHINX_EXECUTABLE}
|
||||||
@@ -34,6 +48,9 @@ if(SPHINX_FOUND)
|
|||||||
${SPHINX_QCH_DIR}/*.qhcp
|
${SPHINX_QCH_DIR}/*.qhcp
|
||||||
DEPENDS doc-qch-sphinx )
|
DEPENDS doc-qch-sphinx )
|
||||||
add_dependencies(doc doc-qch)
|
add_dependencies(doc doc-qch)
|
||||||
|
if (WITH_DOC)
|
||||||
|
install(DIRECTORY ${SPHINX_QCH_DIR} DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
endif (WITH_DOC)
|
||||||
endif()
|
endif()
|
||||||
add_custom_target( doc-html ${SPHINX_EXECUTABLE}
|
add_custom_target( doc-html ${SPHINX_EXECUTABLE}
|
||||||
-q -c . -b html
|
-q -c . -b html
|
||||||
@@ -45,6 +62,7 @@ if(SPHINX_FOUND)
|
|||||||
-d ${SPHINX_CACHE_DIR}
|
-d ${SPHINX_CACHE_DIR}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${SPHINX_MAN_DIR} )
|
${SPHINX_MAN_DIR} )
|
||||||
|
|
||||||
## Building CHM files requires HTML Help Workshop. Since it requires wine
|
## Building CHM files requires HTML Help Workshop. Since it requires wine
|
||||||
## with special dependencies, it's impossible to write a cmake check for it.
|
## with special dependencies, it's impossible to write a cmake check for it.
|
||||||
## This is why doc-chm is not a dependency for doc. Instead, run
|
## This is why doc-chm is not a dependency for doc. Instead, run
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
Adding 3rd-Party Branding
|
|
||||||
=========================
|
|
||||||
|
|
||||||
The ownCloud Client supports theming in the setup assistant dialog in both the
|
|
||||||
account setting and the result window. These customizations do not require a
|
|
||||||
recompile of the client.
|
|
||||||
|
|
||||||
The dialogs have places where custom content can be inserted. Please take a look
|
|
||||||
on the screenshot below. For example the connection wizard has the two green
|
|
||||||
rectangles as well as the area at the bottom with the black line and the red
|
|
||||||
text.
|
|
||||||
|
|
||||||
The content places can be altered by a file called ``custom.ini`` which contains
|
|
||||||
content for the specific places in the dialogs.
|
|
||||||
|
|
||||||
On windows, the custom.ini has to be stored at
|
|
||||||
|
|
||||||
+-----------------+------------------------------------------------------------+
|
|
||||||
| OS | Path |
|
|
||||||
+=================+============================================================+
|
|
||||||
| Windows (64 bit)| ``%ProgramFiles(x86)%\ownCloud\custom.ini`` |
|
|
||||||
+-----------------+------------------------------------------------------------+
|
|
||||||
| Windows (32 bit)| ``%ProgramFiles%\ownCloud\custom.ini`` |
|
|
||||||
+-----------------+------------------------------------------------------------+
|
|
||||||
| Mac OS | ``owncloud.app/Contents/Resources/custom.ini`` |
|
|
||||||
+-----------------+------------------------------------------------------------+
|
|
||||||
| Linux | ``/etc/ownCloud/custom.ini`` |
|
|
||||||
+-----------------+------------------------------------------------------------+
|
|
||||||
|
|
||||||
The config file needs to be in a usual `Windows INI file format`_.
|
|
||||||
|
|
||||||
Under the group definition [GUICustomize] the following keys can be set:
|
|
||||||
|
|
||||||
* ``oCSetupTop``: The top area of the connect wizard, account page.
|
|
||||||
* ``oCSetupSide``: The side area of the connect wizard, account page.
|
|
||||||
* ``ocSetupBottom``: The bottom area of the connect wizard, account page
|
|
||||||
* ``oCSetupResultTop``: The top area of the connect wizard result page.
|
|
||||||
* ``oCSetupFixUrl``: A fixed url to the ownCloud instance. If this is set, the
|
|
||||||
user can not access the url entry field and it is hidden.
|
|
||||||
|
|
||||||
The keys can be set to either an image file or a `rich text`_ snippet, which
|
|
||||||
must be enclosed with double quotes. Image files must be addressed by the
|
|
||||||
complete file name. On windows, the pathes should be noted with slashes
|
|
||||||
instead of backslashes. Instead of absolute file pathes, you can use
|
|
||||||
the ``%RESOURCES`` placeholder (note the single ``%``!).
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
%RESOURCES/custom/myimage_top.png
|
|
||||||
|
|
||||||
.. note:: ``%RESOURCES`` is currently undefined on Linux, it points to the
|
|
||||||
directory location of ``custom.ini`` on all other platforms.
|
|
||||||
|
|
||||||
Example
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
A config file ``custom.ini`` like this::
|
|
||||||
|
|
||||||
[GUICustomize]
|
|
||||||
oCSetupTop=/home/kf/owncloud.com/topimg.png
|
|
||||||
oCSetupSide=/home/kf/owncloud.com/sideimg.png
|
|
||||||
oCSetupBottom="
|
|
||||||
<hr />
|
|
||||||
The Power of now: ownCloud Client
|
|
||||||
|
|
||||||
This nice ownCloud Client was presented by <a
|
|
||||||
href="http://owncloud.com">ownCloud Inc.</a>
|
|
||||||
"
|
|
||||||
oCSetupResultTop=/home/kf/owncloud.com/topimg.png
|
|
||||||
|
|
||||||
will produce this setup dialog:
|
|
||||||
|
|
||||||
.. figure:: images/branding_setup.png
|
|
||||||
|
|
||||||
Setup Dialog Customization
|
|
||||||
|
|
||||||
Packaging remarks
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
While you do not need to rebuild the client, you will need to repackage
|
|
||||||
the client on your own. This also means you will have to resign those
|
|
||||||
packages with your own signing key.
|
|
||||||
|
|
||||||
.. _`Windows INI file format`: http://en.wikipedia.org/wiki/INI_file
|
|
||||||
.. _`rich text`: http://qt-project.org/doc/qt-5.0/richtext-html-subset.html
|
|
||||||
|
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ Mac OS X
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
Follow the `generic build instructions`_.
|
Follow the `generic build instructions`_.
|
||||||
|
|
||||||
You can install the missing dependencies via MacPorts_ or Homebrew_.
|
You can install the missing dependencies via MacPorts_ or Homebrew_.
|
||||||
This is only needed on the build machine, since non-standard libs
|
This is only needed on the build machine, since non-standard libs
|
||||||
will be deployed in the app bundle.
|
will be deployed in the app bundle.
|
||||||
@@ -33,7 +33,7 @@ build system. If you are using Homebrew_, you can just add it::
|
|||||||
brew install iniparser
|
brew install iniparser
|
||||||
|
|
||||||
Otherwise, you need to copy the header and lib files to
|
Otherwise, you need to copy the header and lib files to
|
||||||
``/usr/local/include`` and ``/usr/local/lib`` respectively.
|
``/usr/local/include`` and ``/usr/local/lib`` respectively.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
You should not call ``make install`` at any time, since the product of the
|
You should not call ``make install`` at any time, since the product of the
|
||||||
@@ -51,22 +51,33 @@ if you do not have it installed already.
|
|||||||
In order to cross-compile, the following repositories need to be added
|
In order to cross-compile, the following repositories need to be added
|
||||||
via YaST or ``zypper ar`` (adjust when using openSUSE 12.2)::
|
via YaST or ``zypper ar`` (adjust when using openSUSE 12.2)::
|
||||||
|
|
||||||
http://download.opensuse.org/repositories/isv:/ownCloud:/devel:/mingw:/win32/openSUSE_12.1/isv:ownCloud:devel:mingw:win32.repo
|
http://download.opensuse.org/repositories/isv:/ownCloud:/devel:/mingw:/win32/openSUSE_12.1/
|
||||||
http://download.opensuse.org/repositories/windows:/mingw/openSUSE_12.1/windows:mingw.repo
|
http://download.opensuse.org/repositories/windows:/mingw/openSUSE_12.1/
|
||||||
http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_12.1/windows:mingw:win32.repo
|
http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_12.1/
|
||||||
|
|
||||||
Next, install the cross-compiler packages and the cross-compiled dependencies::
|
Next, install the cross-compiler packages and the cross-compiled dependencies::
|
||||||
|
|
||||||
zypper si -d mingw32-csync
|
zypper si -d mingw32-csync
|
||||||
zypper install kdewin-png2ico mingw32-libqt4 mingw32-libqt4-devel
|
zypper install kdewin-png2ico mingw32-libqt4 mingw32-libqt4-devel \
|
||||||
mingw32-libgcrypt mingw32-libgnutls mingw32-gnutls \
|
mingw32-libgcrypt mingw32-libgnutls mingw32-libneon \
|
||||||
mingw32-libneon mingw32-libbeecrypt mingw32-libopenssl \
|
mingw32-libbeecrypt mingw32-libopenssl mingw32-openssl \
|
||||||
mingw32-openssl
|
mingw32-libpng-devel mingw32-libsqlite mingw32-qtkeychain \
|
||||||
|
mingw32-qtkeychain-devel mingw32-iniparser mingw32-dlfcn
|
||||||
|
|
||||||
For the installer, the NSIS installer packages are also required::
|
For the installer, the NSIS installer package is also required::
|
||||||
|
|
||||||
zypper install mingw32-cross-nsis mingw32-cross-nsis-plugin-processes \
|
zypper install mingw32-cross-nsis
|
||||||
mingw32-cross-nsis-plugin-uac
|
|
||||||
|
.. Usually, the following would be needed as well, but due to a bug in mingw, they
|
||||||
|
will currently not build properly from source.
|
||||||
|
|
||||||
|
mingw32-cross-nsis-plugin-processes mingw32-cross-nsis-plugin-uac
|
||||||
|
|
||||||
|
You will also need to manually download and install the following files with
|
||||||
|
``rpm -ivh <package>`` (They will also work with OpenSUSE 12.2)::
|
||||||
|
|
||||||
|
http://pmbs.links2linux.org/download/mingw:/32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-processes-0-1.1.x86_64.rpm
|
||||||
|
http://pmbs.links2linux.org/download/mingw:/32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-uac-0-3.1.x86_64.rpm
|
||||||
|
|
||||||
Now, follow the `generic build instructions`_, but pay attention to
|
Now, follow the `generic build instructions`_, but pay attention to
|
||||||
the following differences:
|
the following differences:
|
||||||
@@ -111,33 +122,39 @@ Next, make sure to check out the 'dav' branch in the newly checked out
|
|||||||
cd ocsync
|
cd ocsync
|
||||||
git checkout dav
|
git checkout dav
|
||||||
|
|
||||||
The first package to buidld is CSync::
|
The first package to build is CSync::
|
||||||
|
|
||||||
cd ocsync-build
|
cd ocsync-build
|
||||||
cmake -DCMAKE_BUILD_TYPE="Debug" -DLOG_TO_CALLBACK=ON -DWITH_LOG4C=OFF ../ocsync
|
cmake -DCMAKE_BUILD_TYPE="Debug" ../ocsync
|
||||||
make
|
make
|
||||||
|
|
||||||
You probably have to satisfy some dependencies. Make sure to install all the
|
You probably have to satisfy some dependencies. Make sure to install all the
|
||||||
needed development packages. You will need ``iniparser``, ``sqlite3`` as well as
|
needed development packages. You will need ``iniparser``, ``sqlite3`` as well as
|
||||||
``neon`` for the ownCloud module. ``libssh`` and ``libsmbclient`` are optional
|
``neon`` for the ownCloud module. Take special care about ``neon``. If that is
|
||||||
and not required for the client to work. If you want to install the client, run
|
missing, the cmake run will succeed but silently not build the ownCloud module.
|
||||||
``make install`` as a final step.
|
``libssh`` and ``libsmbclient`` are optional and not required for the client
|
||||||
|
to work. If you want to install the client, run ``make install`` as a final step.
|
||||||
|
|
||||||
Next, we build mirall::
|
Next, we build mirall::
|
||||||
|
|
||||||
cd ../mirall-build
|
cd ../mirall-build
|
||||||
cmake -DCMAKE_BUILD_TYPE="Debug" ../mirall \
|
cmake -DCMAKE_BUILD_TYPE="Debug" ../mirall \
|
||||||
-DCSYNC_LIBRARY_PATH=../ocsync-build \
|
-DCSYNC_BUILD_PATH=/path/to/ocsync-build \
|
||||||
-DCSYNC_INCLUDE_PATH=../ocsync/src
|
-DCSYNC_INCLUDE_PATH=/path/to/ocsync/src
|
||||||
|
|
||||||
If this succeeds, call ``make``. The owncloud binary should appear in the
|
Note that it is important to use absolute pathes for the include- and library
|
||||||
``bin`` directory. You can also run ``make install`` to install the client to
|
directories. If this succeeds, call ``make``. The owncloud binary should appear
|
||||||
|
in the ``bin`` directory. You can also run ``make install`` to install the client to
|
||||||
``/usr/local/bin``.
|
``/usr/local/bin``.
|
||||||
|
|
||||||
To build in installer (requires the mingw32-cross-nsis packages)::
|
To build in installer (requires the mingw32-cross-nsis packages)::
|
||||||
|
|
||||||
make package
|
make package
|
||||||
|
|
||||||
|
Known cmake parameters:
|
||||||
|
|
||||||
|
* WITH_DOC=TRUE: create doc and manpages via running ``make``; also adds install statements to be able to install it via ``make install``.
|
||||||
|
|
||||||
.. _`ownCloud repository from OBS`: http://software.opensuse.org/download/package?project=isv:ownCloud:devel&package=owncloud-client
|
.. _`ownCloud repository from OBS`: http://software.opensuse.org/download/package?project=isv:ownCloud:devel&package=owncloud-client
|
||||||
.. _CSync: http://www.csync.org
|
.. _CSync: http://www.csync.org
|
||||||
.. _`Client Download Page`: http://owncloud.org/sync-clients/
|
.. _`Client Download Page`: http://owncloud.org/sync-clients/
|
||||||
|
|||||||
@@ -213,12 +213,14 @@ latex_documents = [
|
|||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
('index', 'owncloud', u'ownCloud Client Manual',
|
('owncloud.1', 'owncloud', u'File synchronisation desktop utility.',
|
||||||
|
[u'The ownCloud developers'], 1),
|
||||||
|
('mirall.1', 'mirall', u'File synchronisation desktop utility.',
|
||||||
[u'The ownCloud developers'], 1)
|
[u'The ownCloud developers'], 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
#man_show_urls = False
|
man_show_urls = True
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output ------------------------------------------------
|
# -- Options for Texinfo output ------------------------------------------------
|
||||||
|
|||||||
31
doc/conffile.rst
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
ownCloud Client reads a configuration file.
|
||||||
|
|
||||||
|
On Linux it can be found in:
|
||||||
|
``$HOME/.local/share/data/ownCloud/owncloud.cfg``
|
||||||
|
|
||||||
|
On Windows it can be found in:
|
||||||
|
``%LOCALAPPDATA%\ownCloud\owncloud.cfg``
|
||||||
|
|
||||||
|
On Mac it can be found in:
|
||||||
|
``$HOME/Library/Application Support/ownCloud``
|
||||||
|
|
||||||
|
|
||||||
|
It contains settings in the ini file format known from Windows.
|
||||||
|
|
||||||
|
.. note:: Changes here should be done carefully as wrong settings can cause disfunctionality.
|
||||||
|
|
||||||
|
.. note:: Changes may be overwritten by using ownCloud's configuration dialog.
|
||||||
|
|
||||||
|
.. note:: The new version is less precise in this regard.
|
||||||
|
|
||||||
|
These are config settings that may be changed:
|
||||||
|
|
||||||
|
``remotePollinterval`` (default: ``30000``)
|
||||||
|
Poll time for the remote repository in milliseconds
|
||||||
|
|
||||||
|
``maxLogLines`` (default: ``20000``)
|
||||||
|
Maximum count of log lines shown in the log window
|
||||||
|
|
||||||
|
``remotePollinterval``
|
||||||
|
The frequency used for polling for remote changes on the ownCloud Server.
|
||||||
|
|
||||||
@@ -1,10 +1,4 @@
|
|||||||
.. ownCloud Documentation documentation master file, created by
|
.. _contents:
|
||||||
sphinx-quickstart on Mon Oct 22 23:16:40 2012.
|
|
||||||
You can adapt this file completely to your liking, but it should at least
|
|
||||||
contain the root `toctree` directive.
|
|
||||||
|
|
||||||
ownCloud Desktop Client
|
|
||||||
***********************
|
|
||||||
|
|
||||||
Contents
|
Contents
|
||||||
========
|
========
|
||||||
@@ -15,7 +9,6 @@ Contents
|
|||||||
install
|
install
|
||||||
usage
|
usage
|
||||||
building
|
building
|
||||||
branding
|
|
||||||
architecture
|
architecture
|
||||||
troubleshooting
|
troubleshooting
|
||||||
glossary
|
glossary
|
||||||
|
|||||||
BIN
doc/logo-blue.pdf
Normal file
38
doc/mirall.1.rst
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
mirall(1)
|
||||||
|
---------
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
========
|
||||||
|
|
||||||
|
*mirall* [`OPTIONS`...]
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
===========
|
||||||
|
|
||||||
|
mirall is a file synchronisation desktop utility.
|
||||||
|
It synchronizes files on your local machine with an ownCloud Server. If you
|
||||||
|
make a change to the files on one computer, it will flow across the others
|
||||||
|
using this desktop sync clients.
|
||||||
|
|
||||||
|
Normally you start the client by click on the desktop icon or start from the
|
||||||
|
application menu. After starting an ownCloud icon appears in the system tray.
|
||||||
|
|
||||||
|
Options
|
||||||
|
=======
|
||||||
|
.. include:: options.rst
|
||||||
|
|
||||||
|
Config File
|
||||||
|
===========
|
||||||
|
.. include:: conffile.rst
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
====
|
||||||
|
|
||||||
|
Please report bugs at https://github.com/owncloud/core/issues.
|
||||||
|
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
========
|
||||||
|
`csync(1)`, `mirall(1)`
|
||||||
|
|
||||||
15
doc/options.rst
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
ownCloud Client supports the following command line switches:
|
||||||
|
|
||||||
|
``--logwindow``
|
||||||
|
open a window to show log output at startup.
|
||||||
|
|
||||||
|
``--logfile`` `<filename>`
|
||||||
|
write log output to file.
|
||||||
|
|
||||||
|
``--flushlog``
|
||||||
|
flush the log file after every write.
|
||||||
|
|
||||||
|
``--monoicons``
|
||||||
|
Use black/white pictograms for systray.
|
||||||
|
|
||||||
|
|
||||||
37
doc/owncloud.1.rst
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
owncloud(1)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
========
|
||||||
|
*owncloud* [`OPTIONS`...]
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
===========
|
||||||
|
owncloud is a file synchronisation desktop utility it is based on mirall.
|
||||||
|
It synchronizes files on your local machine with an ownCloud Server. If you
|
||||||
|
make a change to the files on one computer, it will flow across the others
|
||||||
|
using this desktop sync clients.
|
||||||
|
|
||||||
|
Normally you start the client by click on the desktop icon or start from the
|
||||||
|
application menu. After starting an ownCloud icon appears in the system tray.
|
||||||
|
|
||||||
|
Options
|
||||||
|
=======
|
||||||
|
.. include:: options.rst
|
||||||
|
|
||||||
|
Config File
|
||||||
|
===========
|
||||||
|
.. include:: conffile.rst
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
====
|
||||||
|
|
||||||
|
Please report bugs at https://github.com/owncloud/core/issues.
|
||||||
|
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
========
|
||||||
|
`csync(1)`, `mirall(1)`
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ Troubleshooting
|
|||||||
Verify that you can log on to ownClouds WebDAV server. Assuming your ownCloud
|
Verify that you can log on to ownClouds WebDAV server. Assuming your ownCloud
|
||||||
instance is installed at ``http://yourserver.com/owncloud``, type
|
instance is installed at ``http://yourserver.com/owncloud``, type
|
||||||
``http://yourserver.com/owncloud/remote.php/webdav`` into your browsers
|
``http://yourserver.com/owncloud/remote.php/webdav`` into your browsers
|
||||||
address bar.
|
address bar.
|
||||||
|
|
||||||
If you are not prompted to enter your user name and password, please verify
|
If you are not prompted to enter your user name and password, please verify
|
||||||
that your server installation is working correctly.
|
that your server installation is working correctly.
|
||||||
@@ -14,6 +14,13 @@ Troubleshooting
|
|||||||
your provided are correct, please ensure that your authentication backend
|
your provided are correct, please ensure that your authentication backend
|
||||||
is configured properly.
|
is configured properly.
|
||||||
|
|
||||||
|
A more sophisticated test is to use a WebDAV command line client and log
|
||||||
|
into the ownCloud WebDAV server, such as a little app called cadaver, available
|
||||||
|
on Linux. I can be used to further verify that the WebDAV server is running
|
||||||
|
properly, for example by performing PROPFIND calls:
|
||||||
|
|
||||||
|
``propget .`` called within cadaver will return some properties of the current
|
||||||
|
directory and thus be a successful WebDAV connect.
|
||||||
|
|
||||||
:The desktop client fails for an unknown reason:
|
:The desktop client fails for an unknown reason:
|
||||||
Start the client with ``--logwindow``. You can also open a log window for an
|
Start the client with ``--logwindow``. You can also open a log window for an
|
||||||
@@ -26,3 +33,10 @@ Troubleshooting
|
|||||||
|
|
||||||
The log output can help you with tracking down problem, and if you report
|
The log output can help you with tracking down problem, and if you report
|
||||||
a bug, it's useful to include the output.
|
a bug, it's useful to include the output.
|
||||||
|
|
||||||
|
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
|
||||||
|
problems. A file called ``access_log`` usually records all requests handled
|
||||||
|
by the server. More information about the apache logging can be found at
|
||||||
|
``http://httpd.apache.org/docs/current/logs.html``.
|
||||||
@@ -13,54 +13,12 @@ connections as well as pausing a sync connection.
|
|||||||
|
|
||||||
A right click on the tray icon gives other configuration options.
|
A right click on the tray icon gives other configuration options.
|
||||||
|
|
||||||
|
Options
|
||||||
Command line switches
|
-------
|
||||||
---------------------
|
|
||||||
.. index:: command line switches, command line, options, parameters
|
.. index:: command line switches, command line, options, parameters
|
||||||
|
.. include:: options.rst
|
||||||
|
|
||||||
ownCloud Client supports the following command line switches:
|
|
||||||
|
|
||||||
+--------------------------+------------------------------------------------+
|
|
||||||
| Switch | Action |
|
|
||||||
+==========================+================================================+
|
|
||||||
| ``--logwindow`` | open a window to show log output at startup. |
|
|
||||||
+--------------------------+------------------------------------------------+
|
|
||||||
| ``--logfile <filename>`` | write log output to file. |
|
|
||||||
+--------------------------+------------------------------------------------+
|
|
||||||
| ``--flushlog`` | flush the log file after every write. |
|
|
||||||
+--------------------------+------------------------------------------------+
|
|
||||||
|
|
||||||
Config File
|
Config File
|
||||||
-----------
|
-----------
|
||||||
.. index:: config file
|
.. index:: config file
|
||||||
|
.. include:: conffile.rst
|
||||||
ownCloud Client reads a configuration file which on Linux can be found at ``$HOME/.local/share/data/ownCloud/owncloud.cfg``
|
|
||||||
.. todo:: Windows, Mac?
|
|
||||||
It contains settings in the ini file format known from Windows.
|
|
||||||
|
|
||||||
.. note:: Changes here should be done carefully as wrong settings can cause disfunctionality.
|
|
||||||
|
|
||||||
|
|
||||||
These are config settings that may be changed:
|
|
||||||
|
|
||||||
+---------------------------+-----------+--------------+-----------+-----------------------------------------------------+
|
|
||||||
| Setting | Data Type | Unit | Default | Description |
|
|
||||||
+===========================+===========+==============+===========+=====================================================+
|
|
||||||
| ``remotePollinterval`` | integer | milliseconds | ``30000`` | Poll time for the remote repository |
|
|
||||||
+---------------------------+-----------+--------------+-----------+-----------------------------------------------------+
|
|
||||||
| ``localPollinterval`` | integer | milliseconds | ``10000`` | Poll time for local repository |
|
|
||||||
+---------------------------+-----------+--------------+-----------+-----------------------------------------------------+
|
|
||||||
| ``PollTimerExceedFactor`` | integer | n/a | ``10`` | Poll Timer Exceed Factor |
|
|
||||||
+---------------------------+-----------+--------------+-----------+-----------------------------------------------------+
|
|
||||||
| ``maxLogLines`` | integer | lines | ``20000`` | Maximum count of log lines shown in the log window |
|
|
||||||
+---------------------------+-----------+--------------+-----------+-----------------------------------------------------+
|
|
||||||
|
|
||||||
* ``remotePollinterval`` is for systems which have notify for local file system changes (Linux only currently)
|
|
||||||
this is the frequency it polls for remote changes. The following two values are ignored.
|
|
||||||
|
|
||||||
* ``localPollinterval`` is for systems which poll the local file system (currently Win and Mac) this is the
|
|
||||||
frequency they poll locally. The ``remotePollInterval`` is ignored on these systems.
|
|
||||||
|
|
||||||
* ``PollTimerExceedFactor`` sets the exceed factor is the factor after which a remote poll is done. That means the effective
|
|
||||||
frequency for remote poll is ``localPollInterval * pollTimerExceedFactor``.
|
|
||||||
|
|||||||
48
issue_template.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
### Expected behaviour
|
||||||
|
Tell us what should happen
|
||||||
|
|
||||||
|
### Actual behaviour
|
||||||
|
Tell us what happens instead
|
||||||
|
|
||||||
|
### Steps to reproduce
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
### Server configuration
|
||||||
|
Operating system:
|
||||||
|
|
||||||
|
Web server:
|
||||||
|
|
||||||
|
Database:
|
||||||
|
|
||||||
|
PHP version:
|
||||||
|
|
||||||
|
ownCloud version:
|
||||||
|
|
||||||
|
### Client configuration
|
||||||
|
Client version:
|
||||||
|
|
||||||
|
Operating system:
|
||||||
|
|
||||||
|
OS language:
|
||||||
|
|
||||||
|
Installation path of client:
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
#### output of `owncloud --logwindow` or `owncloud --logfile log.txt`
|
||||||
|
```
|
||||||
|
Insert your log output here
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Web server error log
|
||||||
|
```
|
||||||
|
Insert your webserver log here
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ownCloud log (data/owncloud.log)
|
||||||
|
```
|
||||||
|
Insert your ownCloud log here
|
||||||
|
```
|
||||||
|
|
||||||
7
mirall.desktop.in
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Categories=Utility;X-SuSE-SyncUtility;
|
||||||
|
Type=Application
|
||||||
|
Exec=@APPLICATION_EXECUTABLE@
|
||||||
|
Name=@APPLICATION_NAME@ desktop sync client
|
||||||
|
GenericName=Folder Sync
|
||||||
|
Icon=@APPLICATION_SHORTNAME@
|
||||||
35
mirall.qrc
@@ -1,37 +1,16 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/mirall">
|
<qresource prefix="/mirall">
|
||||||
<file>resources/mirall-32.png</file>
|
|
||||||
<file>resources/mirall-64.png</file>
|
|
||||||
<file>resources/mirall-128.png</file>
|
|
||||||
<file>resources/folder-grey-32.png</file>
|
|
||||||
<file>resources/folder-remote-32.png</file>
|
|
||||||
<file>resources/folder-grey-22.png</file>
|
|
||||||
<file>resources/folder-remote-22.png</file>
|
|
||||||
<file>resources/mirall-22.png</file>
|
|
||||||
<file>resources/mirall-48.png</file>
|
|
||||||
<file>resources/folder-grey-48.png</file>
|
|
||||||
<file>resources/folder-remote-48.png</file>
|
|
||||||
<file>resources/dialog-close.png</file>
|
<file>resources/dialog-close.png</file>
|
||||||
<file>resources/dialog-ok.png</file>
|
<file>resources/dialog-ok.png</file>
|
||||||
<file>resources/dialog-cancel.png</file>
|
<file>resources/dialog-cancel.png</file>
|
||||||
<file>resources/view-refresh.png</file>
|
<file>resources/folder-remote-32.png</file>
|
||||||
<file>resources/folder-favorites.png</file>
|
<file>resources/folder-remote.png</file>
|
||||||
<file>resources/folder-sync-48.png</file>
|
<file>resources/folder-sync.png</file>
|
||||||
<file>resources/folder-important.png</file>
|
|
||||||
<file>resources/folder-grey.png</file>
|
<file>resources/folder-grey.png</file>
|
||||||
<file>resources/owncloud_splash.png</file>
|
<file>resources/mirall-32.png</file>
|
||||||
|
<file>resources/mirall-128.png</file>
|
||||||
|
<file>resources/mirall-48.png</file>
|
||||||
<file>resources/task-ongoing.png</file>
|
<file>resources/task-ongoing.png</file>
|
||||||
|
<file>resources/view-refresh.png</file>
|
||||||
<file>resources/owncloud-icon-22.png</file>
|
|
||||||
<file>resources/owncloud-icon-32.png</file>
|
|
||||||
<file>resources/owncloud-icon-48.png</file>
|
|
||||||
<file>resources/owncloud-icon-64.png</file>
|
|
||||||
<file>resources/owncloud-icon-128.png</file>
|
|
||||||
<file>resources/owncloud-framed-64.png</file>
|
|
||||||
<file>resources/owncloud-error-48.png</file>
|
|
||||||
<file>resources/owncloud-sync-48.png</file>
|
|
||||||
<file>resources/owncloud-sync-ok-48.png</file>
|
|
||||||
|
|
||||||
<file>resources/warning-16.png</file>
|
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 668 B |
|
Before Width: | Height: | Size: 883 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
BIN
resources/lock-http.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
resources/lock-https.png
Normal file
|
After Width: | Height: | Size: 478 B |
|
Before Width: | Height: | Size: 523 B |
|
Before Width: | Height: | Size: 523 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 596 B |
@@ -3,6 +3,13 @@ include(${QT_USE_FILE})
|
|||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
QT4_ADD_RESOURCES ( MIRALL_RC_SRC ../mirall.qrc)
|
QT4_ADD_RESOURCES ( MIRALL_RC_SRC ../mirall.qrc)
|
||||||
|
if ( DEFINED OEM_THEME_DIR)
|
||||||
|
QT4_ADD_RESOURCES ( MIRALL_RC_SRC ${OEM_THEME_DIR}/theme.qrc)
|
||||||
|
set(theme_dir ${OEM_THEME_DIR}/theme)
|
||||||
|
else()
|
||||||
|
QT4_ADD_RESOURCES ( MIRALL_RC_SRC ../theme.qrc)
|
||||||
|
set(theme_dir ${CMAKE_CURRENT_SOURCE_DIR}/../theme)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(mirall_UI
|
set(mirall_UI
|
||||||
mirall/folderwizardsourcepage.ui
|
mirall/folderwizardsourcepage.ui
|
||||||
@@ -18,6 +25,7 @@ mirall/owncloudwizardresultpage.ui
|
|||||||
mirall/owncloudcredentialspage.ui
|
mirall/owncloudcredentialspage.ui
|
||||||
mirall/sslerrordialog.ui
|
mirall/sslerrordialog.ui
|
||||||
mirall/proxydialog.ui
|
mirall/proxydialog.ui
|
||||||
|
mirall/fileitemdialog.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
set(3rdparty_SRC
|
set(3rdparty_SRC
|
||||||
@@ -56,7 +64,6 @@ set(libsync_SRCS
|
|||||||
mirall/folderman.cpp
|
mirall/folderman.cpp
|
||||||
mirall/folder.cpp
|
mirall/folder.cpp
|
||||||
mirall/folderwatcher.cpp
|
mirall/folderwatcher.cpp
|
||||||
mirall/gitfolder.cpp
|
|
||||||
mirall/syncresult.cpp
|
mirall/syncresult.cpp
|
||||||
mirall/unisonfolder.cpp
|
mirall/unisonfolder.cpp
|
||||||
mirall/networklocation.cpp
|
mirall/networklocation.cpp
|
||||||
@@ -70,41 +77,76 @@ set(libsync_SRCS
|
|||||||
mirall/owncloudtheme.cpp
|
mirall/owncloudtheme.cpp
|
||||||
mirall/miralltheme.cpp
|
mirall/miralltheme.cpp
|
||||||
mirall/owncloudinfo.cpp
|
mirall/owncloudinfo.cpp
|
||||||
|
mirall/logger.cpp
|
||||||
|
mirall/utility.cpp
|
||||||
)
|
)
|
||||||
set(libsync_HEADERS
|
set(libsync_HEADERS
|
||||||
mirall/folderman.h
|
mirall/folderman.h
|
||||||
mirall/folder.h
|
mirall/folder.h
|
||||||
mirall/folderwatcher.h
|
mirall/folderwatcher.h
|
||||||
mirall/gitfolder.h
|
|
||||||
mirall/unisonfolder.h
|
mirall/unisonfolder.h
|
||||||
mirall/csyncfolder.h
|
mirall/csyncfolder.h
|
||||||
mirall/owncloudfolder.h
|
mirall/owncloudfolder.h
|
||||||
mirall/csyncthread.h
|
mirall/csyncthread.h
|
||||||
mirall/owncloudinfo.h
|
mirall/owncloudinfo.h
|
||||||
mirall/credentialstore.h
|
mirall/credentialstore.h
|
||||||
|
mirall/logger.h
|
||||||
)
|
)
|
||||||
|
|
||||||
IF( INOTIFY_FOUND )
|
IF( INOTIFY_FOUND )
|
||||||
set(libsync_SRCS ${libsync_SRCS} mirall/inotify.cpp)
|
set(libsync_SRCS ${libsync_SRCS} mirall/inotify.cpp)
|
||||||
|
set(libsync_SRCS ${libsync_SRCS} mirall/folderwatcher_inotify.cpp)
|
||||||
set(libsync_HEADERS ${libsync_HEADERS} mirall/inotify.h)
|
set(libsync_HEADERS ${libsync_HEADERS} mirall/inotify.h)
|
||||||
|
set(libsync_HEADERS ${libsync_HEADERS} mirall/folderwatcher_inotify.h)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
IF( WIN32 )
|
||||||
|
set(libsync_SRCS ${libsync_SRCS} mirall/folderwatcher_win.cpp)
|
||||||
|
set(libsync_HEADERS ${libsync_HEADERS} mirall/folderwatcher_win.h)
|
||||||
|
ENDIF()
|
||||||
|
IF( APPLE )
|
||||||
|
set(libsync_SRCS ${libsync_SRCS} mirall/folderwatcher_mac.cpp)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
qt4_wrap_cpp(syncMoc ${libsync_HEADERS})
|
qt4_wrap_cpp(syncMoc ${libsync_HEADERS})
|
||||||
|
|
||||||
add_library(mirallsync SHARED ${libsync_SRCS} ${syncMoc})
|
list(APPEND libsync_LINK_TARGETS
|
||||||
|
${QT_LIBRARIES}
|
||||||
|
${CSYNC_LIBRARY}
|
||||||
|
dl
|
||||||
|
)
|
||||||
|
|
||||||
|
if(QTKEYCHAIN_FOUND)
|
||||||
|
list(APPEND libsync_LINK_TARGETS ${QTKEYCHAIN_LIBRARY})
|
||||||
|
include_directories(${QTKEYCHAIN_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(owncloudsync SHARED ${libsync_SRCS} ${syncMoc})
|
add_library(owncloudsync SHARED ${libsync_SRCS} ${syncMoc})
|
||||||
set_target_properties( owncloudsync PROPERTIES COMPILE_DEFINITIONS OWNCLOUD_CLIENT)
|
set_target_properties( owncloudsync PROPERTIES COMPILE_DEFINITIONS OWNCLOUD_CLIENT)
|
||||||
target_link_libraries(mirallsync ${QT_LIBRARIES} ${CSYNC_LIBRARY} )
|
set_target_properties( owncloudsync PROPERTIES
|
||||||
target_link_libraries(owncloudsync ${QT_LIBRARIES} ${CSYNC_LIBRARY} )
|
VERSION ${VERSION}
|
||||||
|
SOVERSION ${SOVERSION}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(owncloudsync ${libsync_LINK_TARGETS} )
|
||||||
|
|
||||||
|
if ( APPLE )
|
||||||
|
target_link_libraries(owncloudsync /System/Library/Frameworks/CoreServices.framework)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
install(TARGETS mirallsync owncloudsync
|
install(TARGETS owncloudsync
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
)
|
)
|
||||||
|
if(NOT WIN32)
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
|
||||||
|
${APPLICATION_SHORTNAME}.desktop)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_SHORTNAME}.desktop DESTINATION share/applications )
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
install(TARGETS mirallsync owncloudsync DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
|
install(TARGETS owncloudsync DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(mirall_SRCS
|
set(mirall_SRCS
|
||||||
@@ -118,6 +160,7 @@ set(mirall_SRCS
|
|||||||
mirall/sslerrordialog.cpp
|
mirall/sslerrordialog.cpp
|
||||||
mirall/logbrowser.cpp
|
mirall/logbrowser.cpp
|
||||||
mirall/proxydialog.cpp
|
mirall/proxydialog.cpp
|
||||||
|
mirall/fileitemdialog.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(mirall_HEADERS
|
set(mirall_HEADERS
|
||||||
@@ -130,6 +173,7 @@ set(mirall_HEADERS
|
|||||||
mirall/sslerrordialog.h
|
mirall/sslerrordialog.h
|
||||||
mirall/logbrowser.h
|
mirall/logbrowser.h
|
||||||
mirall/proxydialog.h
|
mirall/proxydialog.h
|
||||||
|
mirall/fileitemdialog.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if( UNIX AND NOT APPLE)
|
if( UNIX AND NOT APPLE)
|
||||||
@@ -161,15 +205,21 @@ set( final_src
|
|||||||
# add executable icon on windows and osx
|
# add executable icon on windows and osx
|
||||||
include( AddAppIconMacro )
|
include( AddAppIconMacro )
|
||||||
set(ownCloud_old ${ownCloud})
|
set(ownCloud_old ${ownCloud})
|
||||||
kde4_add_app_icon( ownCloud "${CMAKE_CURRENT_SOURCE_DIR}/../resources/owncloud-icon-*.png")
|
|
||||||
|
kde4_add_app_icon( ownCloud "${theme_dir}/colored/${APPLICATION_SHORTNAME}-icon*.png")
|
||||||
list(APPEND final_src ${ownCloud})
|
list(APPEND final_src ${ownCloud})
|
||||||
set(ownCloud ${ownCloud_old})
|
set(ownCloud ${ownCloud_old})
|
||||||
|
|
||||||
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/resources/mirall-48.png DESTINATION share/icons/hicolor/48x48/apps/ RENAME mirall.png)
|
if(NOT WIN32)
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/resources/owncloud-icon-48.png DESTINATION share/icons/hicolor/48x48/apps/ RENAME owncloud.png)
|
install(FILES ${CMAKE_SOURCE_DIR}/resources/mirall-48.png
|
||||||
|
DESTINATION share/icons/hicolor/48x48/apps/ RENAME mirall.png)
|
||||||
|
install(FILES
|
||||||
|
${theme_dir}/colored/${APPLICATION_SHORTNAME}-icon-48.png
|
||||||
|
DESTINATION share/icons/hicolor/48x48/apps/ RENAME ${APPLICATION_SHORTNAME}.png)
|
||||||
|
endif(NOT WIN32)
|
||||||
|
|
||||||
install(FILES ${mirall_I18N} DESTINATION share/mirall/i18n)
|
install(FILES ${mirall_I18N} DESTINATION share/mirall/i18n)
|
||||||
|
|
||||||
@@ -183,7 +233,7 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
|||||||
add_executable( mirall WIN32 main.cpp ${final_src})
|
add_executable( mirall WIN32 main.cpp ${final_src})
|
||||||
|
|
||||||
target_link_libraries(mirall ${QT_LIBRARIES} )
|
target_link_libraries(mirall ${QT_LIBRARIES} )
|
||||||
target_link_libraries(mirall mirallsync)
|
target_link_libraries(mirall owncloudsync)
|
||||||
target_link_libraries(mirall ${CSYNC_LIBRARY})
|
target_link_libraries(mirall ${CSYNC_LIBRARY})
|
||||||
|
|
||||||
set_target_properties( mirall PROPERTIES
|
set_target_properties( mirall PROPERTIES
|
||||||
@@ -210,8 +260,13 @@ else()
|
|||||||
else()
|
else()
|
||||||
install(FILES /usr/local/lib/ocsync-0/ocsync_owncloud.so DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Plugins)
|
install(FILES /usr/local/lib/ocsync-0/ocsync_owncloud.so DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Plugins)
|
||||||
endif()
|
endif()
|
||||||
install(FILES ${mirall_I18N} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/translations)
|
|
||||||
|
|
||||||
|
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
|
||||||
|
install(FILES ${mirall_I18N} DESTINATION ${QM_DIR})
|
||||||
|
file(GLOB qt_I18N ${QT_TRANSLATIONS_DIR}/qt_??.qm ${QT_TRANSLATIONS_DIR}/qt_??_??.qm)
|
||||||
|
install(FILES ${qt_I18N} DESTINATION ${QM_DIR})
|
||||||
|
file(GLOB qtkeychain_I18N ${QT_TRANSLATIONS_DIR}/qtkeychain*.qm)
|
||||||
|
install(FILES ${qtkeychain_I18N} DESTINATION ${QM_DIR})
|
||||||
list(APPEND dirs "/usr/local/lib")
|
list(APPEND dirs "/usr/local/lib")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -230,7 +285,7 @@ install(TARGETS ${APPLICATION_EXECUTABLE}
|
|||||||
BUNDLE DESTINATION "."
|
BUNDLE DESTINATION "."
|
||||||
)
|
)
|
||||||
|
|
||||||
#FIXME: find a nice solution to make the second if(BUILD_OWNCLOUD_OSX_BUNDLE) unneccessary
|
#FIXME: find a nice solution to make the second if(BUILD_OWNCLOUD_OSX_BUNDLE) unnecessary
|
||||||
# currently it needs to be done because the code right above needs to be executed no matter
|
# currently it needs to be done because the code right above needs to be executed no matter
|
||||||
# if building a bundle or not and the install_qt4_executable needs to be called afterwards
|
# if building a bundle or not and the install_qt4_executable needs to be called afterwards
|
||||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// if help requested, show on command line and exit.
|
// if help requested, show on command line and exit.
|
||||||
if( ! app.giveHelp() )
|
if( ! app.giveHelp() ) {
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
} else {
|
||||||
|
app.showHelp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LOG_TO_CALLBACK // FIXME: This should be in csync.
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "mirall/application.h"
|
#include "mirall/application.h"
|
||||||
@@ -32,14 +31,13 @@
|
|||||||
#include "mirall/proxydialog.h"
|
#include "mirall/proxydialog.h"
|
||||||
#include "mirall/version.h"
|
#include "mirall/version.h"
|
||||||
#include "mirall/credentialstore.h"
|
#include "mirall/credentialstore.h"
|
||||||
|
#include "mirall/logger.h"
|
||||||
|
|
||||||
#ifdef WITH_CSYNC
|
#ifdef WITH_CSYNC
|
||||||
#include "mirall/csyncfolder.h"
|
#include "mirall/csyncfolder.h"
|
||||||
#endif
|
#endif
|
||||||
#include "mirall/inotify.h"
|
#include "mirall/inotify.h"
|
||||||
|
|
||||||
#include <csync.h>
|
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
@@ -50,6 +48,10 @@
|
|||||||
#include <QNetworkProxy>
|
#include <QNetworkProxy>
|
||||||
#include <QNetworkProxyFactory>
|
#include <QNetworkProxyFactory>
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
// application logging handler.
|
// application logging handler.
|
||||||
@@ -59,9 +61,20 @@ void mirallLogCatcher(QtMsgType type, const char *msg)
|
|||||||
Logger::instance()->mirallLog( QString::fromUtf8(msg) );
|
Logger::instance()->mirallLog( QString::fromUtf8(msg) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void csyncLogCatcher(const char *msg)
|
namespace {
|
||||||
|
QString applicationTrPath()
|
||||||
{
|
{
|
||||||
Logger::instance()->csyncLog( QString::fromUtf8(msg) );
|
#ifdef Q_OS_LINUX
|
||||||
|
// FIXME - proper path!
|
||||||
|
return QLatin1String("/usr/share/mirall/i18n/");
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
return QApplication::applicationDirPath()+QLatin1String("/../Resources/Translations"); // path defaults to app dir.
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
return QApplication::applicationDirPath();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
@@ -69,56 +82,46 @@ void csyncLogCatcher(const char *msg)
|
|||||||
Application::Application(int &argc, char **argv) :
|
Application::Application(int &argc, char **argv) :
|
||||||
SharedTools::QtSingleApplication(argc, argv),
|
SharedTools::QtSingleApplication(argc, argv),
|
||||||
_tray(0),
|
_tray(0),
|
||||||
_sslErrorDialog(0),
|
|
||||||
#if QT_VERSION >= 0x040700
|
#if QT_VERSION >= 0x040700
|
||||||
_networkMgr(new QNetworkConfigurationManager(this)),
|
_networkMgr(new QNetworkConfigurationManager(this)),
|
||||||
#endif
|
#endif
|
||||||
|
_sslErrorDialog(0),
|
||||||
_contextMenu(0),
|
_contextMenu(0),
|
||||||
_theme(Theme::instance()),
|
_theme(Theme::instance()),
|
||||||
_updateDetector(0),
|
_updateDetector(0),
|
||||||
|
_logBrowser(0),
|
||||||
_showLogWindow(false),
|
_showLogWindow(false),
|
||||||
_logFlush(false),
|
_logFlush(false),
|
||||||
_helpOnly(false),
|
_helpOnly(false),
|
||||||
_logBrowser(0)
|
_fileItemDialog(0)
|
||||||
{
|
{
|
||||||
setApplicationName( _theme->appName() );
|
setApplicationName( _theme->appNameGUI() );
|
||||||
setWindowIcon( _theme->applicationIcon() );
|
setWindowIcon( _theme->applicationIcon() );
|
||||||
|
|
||||||
parseOptions(arguments());
|
parseOptions(arguments());
|
||||||
|
setupTranslations();
|
||||||
setupLogBrowser();
|
setupLogBrowser();
|
||||||
//no need to waste time;
|
//no need to waste time;
|
||||||
if ( _helpOnly ) return;
|
if ( _helpOnly ) return;
|
||||||
processEvents();
|
|
||||||
|
|
||||||
QTranslator *qtTranslator = new QTranslator(this);
|
|
||||||
qtTranslator->load(QLatin1String("qt_") + QLocale::system().name(),
|
|
||||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
|
||||||
installTranslator(qtTranslator);
|
|
||||||
|
|
||||||
QTranslator *mirallTranslator = new QTranslator(this);
|
|
||||||
|
|
||||||
QString locale = Theme::instance()->enforcedLocale();
|
|
||||||
if (locale.isEmpty()) locale = QLocale::system().name();
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
// FIXME - proper path!
|
// HACK: bump the refcount for libgnutls by calling dlopen()
|
||||||
mirallTranslator->load(QLatin1String("mirall_") + locale, QLatin1String("/usr/share/mirall/i18n/"));
|
// so gnutls, which is an dependency of libneon on some linux
|
||||||
|
// distros, and does not cleanup it's FDs properly, does
|
||||||
|
// not get unloaded. This works around a FD exhaustion crash
|
||||||
|
// (#154). We are not using gnutls at all and it's fine
|
||||||
|
// if loading fails, so no error handling is performed here.
|
||||||
|
dlopen("libgnutls.so", RTLD_LAZY|RTLD_NODELETE);
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
mirallTranslator->load(QLatin1String("mirall_") + locale, applicationDirPath()+QLatin1String("/../translations") ); // path defaults to app dir.
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_WIN32
|
|
||||||
mirallTranslator->load(QLatin1String("mirall_") + locale, applicationDirPath());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
installTranslator(mirallTranslator);
|
|
||||||
|
|
||||||
connect( this, SIGNAL(messageReceived(QString)), SLOT(slotParseOptions(QString)));
|
connect( this, SIGNAL(messageReceived(QString)), SLOT(slotParseOptions(QString)));
|
||||||
|
connect( Logger::instance(), SIGNAL(guiLog(QString,QString)),
|
||||||
|
this, SLOT(slotShowTrayMessage(QString,QString)));
|
||||||
// create folder manager for sync folder management
|
// create folder manager for sync folder management
|
||||||
_folderMan = new FolderMan(this);
|
_folderMan = new FolderMan(this);
|
||||||
connect( _folderMan, SIGNAL(folderSyncStateChange(QString)),
|
connect( _folderMan, SIGNAL(folderSyncStateChange(QString)),
|
||||||
this,SLOT(slotSyncStateChange(QString)));
|
this,SLOT(slotSyncStateChange(QString)));
|
||||||
|
_folderMan->setSyncEnabled(false);
|
||||||
|
|
||||||
/* use a signal mapper to map the open requests to the alias names */
|
/* use a signal mapper to map the open requests to the alias names */
|
||||||
_folderOpenActionMapper = new QSignalMapper(this);
|
_folderOpenActionMapper = new QSignalMapper(this);
|
||||||
@@ -130,16 +133,14 @@ Application::Application(int &argc, char **argv) :
|
|||||||
_folderWizard = new FolderWizard;
|
_folderWizard = new FolderWizard;
|
||||||
|
|
||||||
_owncloudSetupWizard = new OwncloudSetupWizard( _folderMan, _theme, this );
|
_owncloudSetupWizard = new OwncloudSetupWizard( _folderMan, _theme, this );
|
||||||
connect( _owncloudSetupWizard, SIGNAL(ownCloudWizardDone(int)), SLOT(slotStartFolderSetup(int)));
|
connect( _owncloudSetupWizard, SIGNAL(ownCloudWizardDone(int)),
|
||||||
|
this, SLOT(slotownCloudWizardDone(int)));
|
||||||
|
|
||||||
_statusDialog = new StatusDialog( _theme );
|
_statusDialog = new StatusDialog( _theme );
|
||||||
connect( _statusDialog, SIGNAL(addASync()), this, SLOT(slotAddFolder()) );
|
connect( _statusDialog, SIGNAL(addASync()), this, SLOT(slotAddFolder()) );
|
||||||
|
|
||||||
connect( _statusDialog, SIGNAL(removeFolderAlias( const QString&)),
|
connect( _statusDialog, SIGNAL(removeFolderAlias( const QString&)),
|
||||||
SLOT(slotRemoveFolder(const QString&)));
|
SLOT(slotRemoveFolder(const QString&)));
|
||||||
|
|
||||||
connect( _statusDialog, SIGNAL(openLogBrowser()), this, SLOT(slotOpenLogBrowser()));
|
|
||||||
|
|
||||||
connect( _statusDialog, SIGNAL(enableFolderAlias(QString,bool)),
|
connect( _statusDialog, SIGNAL(enableFolderAlias(QString,bool)),
|
||||||
SLOT(slotEnableFolder(QString,bool)));
|
SLOT(slotEnableFolder(QString,bool)));
|
||||||
connect( _statusDialog, SIGNAL(infoFolderAlias(const QString&)),
|
connect( _statusDialog, SIGNAL(infoFolderAlias(const QString&)),
|
||||||
@@ -147,17 +148,21 @@ Application::Application(int &argc, char **argv) :
|
|||||||
connect( _statusDialog, SIGNAL(openFolderAlias(const QString&)),
|
connect( _statusDialog, SIGNAL(openFolderAlias(const QString&)),
|
||||||
SLOT(slotFolderOpenAction(QString)));
|
SLOT(slotFolderOpenAction(QString)));
|
||||||
|
|
||||||
|
#if 0
|
||||||
#if QT_VERSION >= 0x040700
|
#if QT_VERSION >= 0x040700
|
||||||
qDebug() << "* Network is" << (_networkMgr->isOnline() ? "online" : "offline");
|
qDebug() << "* Network is" << (_networkMgr->isOnline() ? "online" : "offline");
|
||||||
foreach (const QNetworkConfiguration& netCfg, _networkMgr->allConfigurations(QNetworkConfiguration::Active)) {
|
foreach (const QNetworkConfiguration& netCfg, _networkMgr->allConfigurations(QNetworkConfiguration::Active)) {
|
||||||
//qDebug() << "Network:" << netCfg.identifier();
|
//qDebug() << "Network:" << netCfg.identifier();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
setupActions();
|
setupActions();
|
||||||
setupSystemTray();
|
setupSystemTray();
|
||||||
setupProxy();
|
setupProxy();
|
||||||
processEvents();
|
|
||||||
|
|
||||||
|
int cnt = _folderMan->setupFolders();
|
||||||
|
_statusDialog->setFolderList( _folderMan->map() );
|
||||||
|
|
||||||
QObject::connect( this, SIGNAL(messageReceived(QString)),
|
QObject::connect( this, SIGNAL(messageReceived(QString)),
|
||||||
this, SLOT(slotOpenStatus()) );
|
this, SLOT(slotOpenStatus()) );
|
||||||
@@ -178,6 +183,8 @@ Application::Application(int &argc, char **argv) :
|
|||||||
Application::~Application()
|
Application::~Application()
|
||||||
{
|
{
|
||||||
delete _tray; // needed, see ctor
|
delete _tray; // needed, see ctor
|
||||||
|
if( _fileItemDialog) delete _fileItemDialog;
|
||||||
|
if( _statusDialog && ! _helpOnly) delete _statusDialog;
|
||||||
qDebug() << "* Mirall shutdown";
|
qDebug() << "* Mirall shutdown";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,9 +228,9 @@ void Application::slotOwnCloudFound( const QString& url, const QString& versionS
|
|||||||
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
|
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
|
||||||
|
|
||||||
if( version.startsWith("4.0") ) {
|
if( version.startsWith("4.0") ) {
|
||||||
QMessageBox::warning(0, tr("%1 Server Mismatch").arg(_theme->appName()),
|
QMessageBox::warning(0, tr("%1 Server Mismatch").arg(_theme->appNameGUI()),
|
||||||
tr("<p>The configured server for this client is too old.</p>"
|
tr("<p>The configured server for this client is too old.</p>"
|
||||||
"<p>Please update to the latest %1 server and restart the client.</p>").arg(_theme->appName()));
|
"<p>Please update to the latest %1 server and restart the client.</p>").arg(_theme->appNameGUI()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,17 +239,10 @@ void Application::slotOwnCloudFound( const QString& url, const QString& versionS
|
|||||||
|
|
||||||
void Application::slotNoOwnCloudFound( QNetworkReply* reply )
|
void Application::slotNoOwnCloudFound( QNetworkReply* reply )
|
||||||
{
|
{
|
||||||
qDebug() << "** Application: NO ownCloud found!";
|
Q_UNUSED(reply)
|
||||||
QString msg;
|
|
||||||
if( reply ) {
|
qDebug() << "** Application: NO ownCloud found! Going offline";
|
||||||
QString url( reply->url().toString() );
|
|
||||||
url.remove( QLatin1String("/status.php") );
|
|
||||||
msg = tr("<p>The %1 at %2 could not be reached.</p>").arg(_theme->appName()).arg( url );
|
|
||||||
msg += tr("<p>The detailed error message is<br/><tt>%1</tt></p>").arg( reply->errorString() );
|
|
||||||
}
|
|
||||||
msg += tr("<p>Please check your configuration by clicking on the tray icon.</p>");
|
|
||||||
|
|
||||||
QMessageBox::warning(0, tr("%1 Connection Failed").arg(_theme->appName()), msg );
|
|
||||||
_actionAddFolder->setEnabled( false );
|
_actionAddFolder->setEnabled( false );
|
||||||
|
|
||||||
// Disconnect.
|
// Disconnect.
|
||||||
@@ -256,15 +256,27 @@ void Application::slotNoOwnCloudFound( QNetworkReply* reply )
|
|||||||
this,SLOT(slotAuthCheck(QString,QNetworkReply*)));
|
this,SLOT(slotAuthCheck(QString,QNetworkReply*)));
|
||||||
|
|
||||||
setupContextMenu();
|
setupContextMenu();
|
||||||
|
QTimer::singleShot( 30*1000, this, SLOT( slotStartFolderSetup() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::slotFetchCredentials()
|
void Application::slotFetchCredentials()
|
||||||
{
|
{
|
||||||
connect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)),
|
QString trayMessage;
|
||||||
this, SLOT(slotCredentialsFetched(bool)) );
|
|
||||||
CredentialStore::instance()->fetchCredentials();
|
if( CredentialStore::instance()->canTryAgain() ) {
|
||||||
if( CredentialStore::instance()->state() == CredentialStore::TooManyAttempts ) {
|
connect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)),
|
||||||
QString trayMessage = tr("Too many user attempts to enter password.");
|
this, SLOT(slotCredentialsFetched(bool)) );
|
||||||
|
CredentialStore::instance()->fetchCredentials();
|
||||||
|
if( CredentialStore::instance()->state() == CredentialStore::TooManyAttempts ) {
|
||||||
|
trayMessage = tr("Too many attempts to get a valid password.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "Can not try again to fetch Credentials.";
|
||||||
|
trayMessage = tr("%1 user credentials are wrong. Please check configuration.")
|
||||||
|
.arg(Theme::instance()->appNameGUI());
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !trayMessage.isEmpty() ) {
|
||||||
_tray->showMessage(tr("Credentials"), trayMessage);
|
_tray->showMessage(tr("Credentials"), trayMessage);
|
||||||
_actionOpenStatus->setEnabled( false );
|
_actionOpenStatus->setEnabled( false );
|
||||||
_actionAddFolder->setEnabled( false );
|
_actionAddFolder->setEnabled( false );
|
||||||
@@ -279,6 +291,8 @@ void Application::slotCredentialsFetched(bool ok)
|
|||||||
trayMessage = tr("Error: Could not retrieve the password!");
|
trayMessage = tr("Error: Could not retrieve the password!");
|
||||||
if( CredentialStore::instance()->state() == CredentialStore::UserCanceled ) {
|
if( CredentialStore::instance()->state() == CredentialStore::UserCanceled ) {
|
||||||
trayMessage = tr("Password dialog was canceled!");
|
trayMessage = tr("Password dialog was canceled!");
|
||||||
|
} else {
|
||||||
|
trayMessage = CredentialStore::instance()->errorMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !trayMessage.isEmpty() ) {
|
if( !trayMessage.isEmpty() ) {
|
||||||
@@ -289,6 +303,8 @@ void Application::slotCredentialsFetched(bool ok)
|
|||||||
_actionAddFolder->setEnabled( false );
|
_actionAddFolder->setEnabled( false );
|
||||||
_actionOpenStatus->setEnabled( false );
|
_actionOpenStatus->setEnabled( false );
|
||||||
} else {
|
} else {
|
||||||
|
ownCloudInfo::instance()->setCredentials( CredentialStore::instance()->user(),
|
||||||
|
CredentialStore::instance()->password() );
|
||||||
// Credential fetched ok.
|
// Credential fetched ok.
|
||||||
QTimer::singleShot( 0, this, SLOT( slotCheckAuthentication() ));
|
QTimer::singleShot( 0, this, SLOT( slotCheckAuthentication() ));
|
||||||
}
|
}
|
||||||
@@ -312,16 +328,16 @@ void Application::slotAuthCheck( const QString& ,QNetworkReply *reply )
|
|||||||
|
|
||||||
if( reply->error() == QNetworkReply::AuthenticationRequiredError ) { // returned if the user is wrong.
|
if( reply->error() == QNetworkReply::AuthenticationRequiredError ) { // returned if the user is wrong.
|
||||||
qDebug() << "******** Password is wrong!";
|
qDebug() << "******** Password is wrong!";
|
||||||
QMessageBox::warning(0, tr("No %1 Connection").arg(_theme->appName()),
|
QMessageBox::warning(0, tr("No %1 Connection").arg(_theme->appNameGUI()),
|
||||||
tr("<p>Your %1 credentials are not correct.</p>"
|
tr("<p>Your %1 credentials are not correct.</p>"
|
||||||
"<p>Please correct them by starting the configuration dialog from the tray!</p>")
|
"<p>Please correct them by starting the configuration dialog from the tray!</p>")
|
||||||
.arg(_theme->appName()));
|
.arg(_theme->appNameGUI()));
|
||||||
_actionAddFolder->setEnabled( false );
|
_actionAddFolder->setEnabled( false );
|
||||||
ok = false;
|
ok = false;
|
||||||
} else if( reply->error() == QNetworkReply::OperationCanceledError ) {
|
} else if( reply->error() == QNetworkReply::OperationCanceledError ) {
|
||||||
// the username was wrong and ownCloudInfo was closing the request after a couple of auth tries.
|
// the username was wrong and ownCloudInfo was closing the request after a couple of auth tries.
|
||||||
qDebug() << "******** Username or password is wrong!";
|
qDebug() << "******** Username or password is wrong!";
|
||||||
QMessageBox::warning(0, tr("No %1 Connection").arg(_theme->appName()),
|
QMessageBox::warning(0, tr("No %1 Connection").arg(_theme->appNameGUI()),
|
||||||
tr("<p>Either your user name or your password are not correct.</p>"
|
tr("<p>Either your user name or your password are not correct.</p>"
|
||||||
"<p>Please correct it by starting the configuration dialog from the tray!</p>"));
|
"<p>Please correct it by starting the configuration dialog from the tray!</p>"));
|
||||||
_actionAddFolder->setEnabled( false );
|
_actionAddFolder->setEnabled( false );
|
||||||
@@ -334,20 +350,24 @@ void Application::slotAuthCheck( const QString& ,QNetworkReply *reply )
|
|||||||
|
|
||||||
if( ok ) {
|
if( ok ) {
|
||||||
qDebug() << "######## Credentials are ok!";
|
qDebug() << "######## Credentials are ok!";
|
||||||
int cnt = _folderMan->setupFolders();
|
_folderMan->setSyncEnabled(true);
|
||||||
if( cnt ) {
|
QMetaObject::invokeMethod(_folderMan, "slotScheduleFolderSync");
|
||||||
_tray->setIcon(_theme->applicationIcon());
|
|
||||||
_tray->show();
|
|
||||||
processEvents();
|
|
||||||
|
|
||||||
if( _tray )
|
_tray->setIcon( _theme->syncStateIcon( SyncResult::NotYetStarted, true ) );
|
||||||
_tray->showMessage(tr("%1 Sync Started").arg(_theme->appName()),
|
_tray->show();
|
||||||
tr("Sync started for %1 configured sync folder(s).").arg(cnt));
|
|
||||||
|
int cnt = _folderMan->map().size();
|
||||||
|
if( _tray )
|
||||||
|
_tray->showMessage(tr("%1 Sync Started").arg(_theme->appNameGUI()),
|
||||||
|
tr("Sync started for %1 configured sync folder(s).").arg(cnt));
|
||||||
|
|
||||||
|
// queue up the sync for all folders.
|
||||||
|
_folderMan->slotScheduleAllFolders();
|
||||||
|
|
||||||
|
computeOverallSyncStatus();
|
||||||
|
|
||||||
_statusDialog->setFolderList( _folderMan->map() );
|
|
||||||
computeOverallSyncStatus();
|
|
||||||
}
|
|
||||||
_actionAddFolder->setEnabled( true );
|
_actionAddFolder->setEnabled( true );
|
||||||
|
_actionOpenStatus->setEnabled( true );
|
||||||
setupContextMenu();
|
setupContextMenu();
|
||||||
} else {
|
} else {
|
||||||
slotFetchCredentials();
|
slotFetchCredentials();
|
||||||
@@ -390,12 +410,24 @@ void Application::slotSSLFailed( QNetworkReply *reply, QList<QSslError> errors )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::slotownCloudWizardDone( int res )
|
||||||
|
{
|
||||||
|
if( res == QDialog::Accepted ) {
|
||||||
|
int cnt = _folderMan->setupFolders();
|
||||||
|
qDebug() << "Set up " << cnt << " folders.";
|
||||||
|
_statusDialog->setFolderList( _folderMan->map() );
|
||||||
|
}
|
||||||
|
_folderMan->setSyncEnabled( true );
|
||||||
|
slotStartFolderSetup( res );
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setupActions()
|
void Application::setupActions()
|
||||||
{
|
{
|
||||||
_actionOpenoC = new QAction(tr("Open %1 in browser...").arg(_theme->appName()), this);
|
_actionOpenoC = new QAction(tr("Open %1 in browser...").arg(_theme->appNameGUI()), this);
|
||||||
QObject::connect(_actionOpenoC, SIGNAL(triggered(bool)), SLOT(slotOpenOwnCloud()));
|
QObject::connect(_actionOpenoC, SIGNAL(triggered(bool)), SLOT(slotOpenOwnCloud()));
|
||||||
_actionOpenStatus = new QAction(tr("Open status..."), this);
|
_actionOpenStatus = new QAction(tr("Open status..."), this);
|
||||||
QObject::connect(_actionOpenStatus, SIGNAL(triggered(bool)), SLOT(slotOpenStatus()));
|
QObject::connect(_actionOpenStatus, SIGNAL(triggered(bool)), SLOT(slotOpenStatus()));
|
||||||
|
_actionOpenStatus->setEnabled( false );
|
||||||
_actionAddFolder = new QAction(tr("Add folder..."), this);
|
_actionAddFolder = new QAction(tr("Add folder..."), this);
|
||||||
QObject::connect(_actionAddFolder, SIGNAL(triggered(bool)), SLOT(slotAddFolder()));
|
QObject::connect(_actionAddFolder, SIGNAL(triggered(bool)), SLOT(slotAddFolder()));
|
||||||
_actionConfigure = new QAction(tr("Configure..."), this);
|
_actionConfigure = new QAction(tr("Configure..."), this);
|
||||||
@@ -413,7 +445,7 @@ void Application::setupSystemTray()
|
|||||||
// Setting a parent heres will crash on X11 since by the time qapp runs
|
// Setting a parent heres will crash on X11 since by the time qapp runs
|
||||||
// its childrens dtors, the X11->screen variable queried for is gone -> crash
|
// its childrens dtors, the X11->screen variable queried for is gone -> crash
|
||||||
_tray = new QSystemTrayIcon;
|
_tray = new QSystemTrayIcon;
|
||||||
_tray->setIcon( _theme->applicationIcon() ); // load the grey icon
|
_tray->setIcon( _theme->syncStateIcon( SyncResult::NotYetStarted, true ) );
|
||||||
|
|
||||||
connect(_tray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
connect(_tray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||||
SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
|
SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
|
||||||
@@ -439,7 +471,7 @@ void Application::setupContextMenu()
|
|||||||
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
||||||
_tray->setContextMenu(_contextMenu);
|
_tray->setContextMenu(_contextMenu);
|
||||||
}
|
}
|
||||||
_contextMenu->setTitle(_theme->appName() );
|
_contextMenu->setTitle(_theme->appNameGUI() );
|
||||||
_contextMenu->addAction(_actionOpenStatus);
|
_contextMenu->addAction(_actionOpenStatus);
|
||||||
_contextMenu->addAction(_actionOpenoC);
|
_contextMenu->addAction(_actionOpenoC);
|
||||||
|
|
||||||
@@ -458,7 +490,7 @@ void Application::setupContextMenu()
|
|||||||
Folder *folder = _folderMan->map().value(li.first());
|
Folder *folder = _folderMan->map().value(li.first());
|
||||||
if( folder ) {
|
if( folder ) {
|
||||||
// if there is singleFolder mode, a generic open action is displayed.
|
// if there is singleFolder mode, a generic open action is displayed.
|
||||||
QAction *action = new QAction( tr("Open %1 folder").arg(_theme->appName()), this);
|
QAction *action = new QAction( tr("Open %1 folder").arg(_theme->appNameGUI()), this);
|
||||||
action->setIcon( _theme->trayFolderIcon( folder->backend()) );
|
action->setIcon( _theme->trayFolderIcon( folder->backend()) );
|
||||||
|
|
||||||
connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map()));
|
connect( action, SIGNAL(triggered()),_folderOpenActionMapper,SLOT(map()));
|
||||||
@@ -489,8 +521,11 @@ void Application::setupContextMenu()
|
|||||||
_contextMenu->addAction(_actionConfigure);
|
_contextMenu->addAction(_actionConfigure);
|
||||||
_contextMenu->addAction(_actionConfigureProxy);
|
_contextMenu->addAction(_actionConfigureProxy);
|
||||||
_contextMenu->addSeparator();
|
_contextMenu->addSeparator();
|
||||||
_contextMenu->addAction(_actionAbout);
|
|
||||||
_contextMenu->addSeparator();
|
if (!Theme::instance()->about().isEmpty()) {
|
||||||
|
_contextMenu->addAction(_actionAbout);
|
||||||
|
_contextMenu->addSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
_contextMenu->addAction(_actionQuit);
|
_contextMenu->addAction(_actionQuit);
|
||||||
}
|
}
|
||||||
@@ -502,7 +537,6 @@ void Application::setupLogBrowser()
|
|||||||
// init the log browser.
|
// init the log browser.
|
||||||
_logBrowser = new LogBrowser;
|
_logBrowser = new LogBrowser;
|
||||||
qInstallMsgHandler( mirallLogCatcher );
|
qInstallMsgHandler( mirallLogCatcher );
|
||||||
csync_set_log_callback( csyncLogCatcher );
|
|
||||||
// ## TODO: allow new log name maybe?
|
// ## TODO: allow new log name maybe?
|
||||||
if (!_logFile.isEmpty()) {
|
if (!_logFile.isEmpty()) {
|
||||||
qDebug() << "Logging into logfile: " << _logFile << " with flush " << _logFlush;
|
qDebug() << "Logging into logfile: " << _logFile << " with flush " << _logFlush;
|
||||||
@@ -513,8 +547,9 @@ void Application::setupLogBrowser()
|
|||||||
if (_showLogWindow)
|
if (_showLogWindow)
|
||||||
slotOpenLogBrowser();
|
slotOpenLogBrowser();
|
||||||
|
|
||||||
qDebug() << QString::fromLatin1( "################## %1 %2 %3 ").arg(_theme->appName())
|
qDebug() << QString::fromLatin1( "################## %1 %2 (%3) %4").arg(_theme->appName())
|
||||||
.arg( QLocale::system().name() )
|
.arg( QLocale::system().name() )
|
||||||
|
.arg(property("ui_lang").toString())
|
||||||
.arg(_theme->version());
|
.arg(_theme->version());
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -590,7 +625,8 @@ void Application::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
|
|||||||
// A click on the tray icon should only open the status window on Win and
|
// A click on the tray icon should only open the status window on Win and
|
||||||
// Linux, not on Mac. They want a menu entry.
|
// Linux, not on Mac. They want a menu entry.
|
||||||
// If the user canceled login, rather open the login window.
|
// If the user canceled login, rather open the login window.
|
||||||
if( CredentialStore::instance()->state() == CredentialStore::UserCanceled ) {
|
if( CredentialStore::instance()->state() == CredentialStore::UserCanceled ||
|
||||||
|
CredentialStore::instance()->state() == CredentialStore::Error ) {
|
||||||
slotFetchCredentials();
|
slotFetchCredentials();
|
||||||
}
|
}
|
||||||
#if defined Q_WS_WIN || defined Q_WS_X11
|
#if defined Q_WS_WIN || defined Q_WS_X11
|
||||||
@@ -602,7 +638,7 @@ void Application::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
|
|||||||
|
|
||||||
void Application::slotAddFolder()
|
void Application::slotAddFolder()
|
||||||
{
|
{
|
||||||
_folderMan->disableFoldersWithRestore();
|
_folderMan->setSyncEnabled(false); // do not start more syncs.
|
||||||
|
|
||||||
Folder::Map folderMap = _folderMan->map();
|
Folder::Map folderMap = _folderMan->map();
|
||||||
|
|
||||||
@@ -630,6 +666,8 @@ void Application::slotAddFolder()
|
|||||||
targetPath = _folderWizard->field(QLatin1String("targetURLFolder")).toString();
|
targetPath = _folderWizard->field(QLatin1String("targetURLFolder")).toString();
|
||||||
onlyOnline = _folderWizard->field(QLatin1String("onlyOnline?")).toBool();
|
onlyOnline = _folderWizard->field(QLatin1String("onlyOnline?")).toBool();
|
||||||
onlyThisLAN = _folderWizard->field(QLatin1String("onlyThisLAN?")).toBool();
|
onlyThisLAN = _folderWizard->field(QLatin1String("onlyThisLAN?")).toBool();
|
||||||
|
(void) onlyOnline;
|
||||||
|
(void) onlyThisLAN;
|
||||||
} else if( _folderWizard->field(QLatin1String("OC?")).toBool() ||
|
} else if( _folderWizard->field(QLatin1String("OC?")).toBool() ||
|
||||||
Theme::instance()->singleSyncFolder()) {
|
Theme::instance()->singleSyncFolder()) {
|
||||||
// setup a ownCloud folder
|
// setup a ownCloud folder
|
||||||
@@ -640,6 +678,8 @@ void Application::slotAddFolder()
|
|||||||
goodData = false;
|
goodData = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_folderMan->setSyncEnabled(true); // do start sync again.
|
||||||
|
|
||||||
if( goodData ) {
|
if( goodData ) {
|
||||||
_folderMan->addFolderDefinition( backend, alias, sourceFolder, targetPath, onlyThisLAN );
|
_folderMan->addFolderDefinition( backend, alias, sourceFolder, targetPath, onlyThisLAN );
|
||||||
Folder *f = _folderMan->setupFolderFromConfigFile( alias );
|
Folder *f = _folderMan->setupFolderFromConfigFile( alias );
|
||||||
@@ -653,7 +693,8 @@ void Application::slotAddFolder()
|
|||||||
} else {
|
} else {
|
||||||
qDebug() << "* Folder wizard cancelled";
|
qDebug() << "* Folder wizard cancelled";
|
||||||
}
|
}
|
||||||
_folderMan->restoreEnabledFolders();
|
_folderMan->setSyncEnabled(true);
|
||||||
|
_folderMan->slotScheduleAllFolders();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::slotOpenStatus()
|
void Application::slotOpenStatus()
|
||||||
@@ -673,6 +714,7 @@ void Application::slotOpenStatus()
|
|||||||
|
|
||||||
if( !cfgFile.exists() ) {
|
if( !cfgFile.exists() ) {
|
||||||
qDebug() << "No configured folders yet, start the Owncloud integration dialog.";
|
qDebug() << "No configured folders yet, start the Owncloud integration dialog.";
|
||||||
|
_folderMan->setSyncEnabled(false);
|
||||||
_owncloudSetupWizard->startWizard(true); // with intro
|
_owncloudSetupWizard->startWizard(true); // with intro
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "#============# Status dialog starting #=============#";
|
qDebug() << "#============# Status dialog starting #=============#";
|
||||||
@@ -680,7 +722,11 @@ void Application::slotOpenStatus()
|
|||||||
_statusDialog->setFolderList( _folderMan->map() );
|
_statusDialog->setFolderList( _folderMan->map() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
raiseDialog( raiseWidget );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::raiseDialog( QWidget *raiseWidget )
|
||||||
|
{
|
||||||
// viel hilft viel ;-)
|
// viel hilft viel ;-)
|
||||||
if( raiseWidget ) {
|
if( raiseWidget ) {
|
||||||
#if defined(Q_WS_WIN) || defined (Q_OS_MAC)
|
#if defined(Q_WS_WIN) || defined (Q_OS_MAC)
|
||||||
@@ -705,10 +751,8 @@ void Application::slotOpenLogBrowser()
|
|||||||
|
|
||||||
void Application::slotAbout()
|
void Application::slotAbout()
|
||||||
{
|
{
|
||||||
QMessageBox::about(0, tr("About %1").arg(_theme->appName()),
|
QMessageBox::about(0, tr("About %1").arg(_theme->appNameGUI()),
|
||||||
tr("%1 client, version %2\n\nCopyright 2012, the ownCloud developers.")
|
Theme::instance()->about());
|
||||||
.arg(_theme->appName())
|
|
||||||
.arg(MIRALL_STRINGIFY(MIRALL_VERSION)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -735,80 +779,19 @@ void Application::slotRemoveFolder( const QString& alias )
|
|||||||
setupContextMenu();
|
setupContextMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open the File list info dialog.
|
||||||
void Application::slotInfoFolder( const QString& alias )
|
void Application::slotInfoFolder( const QString& alias )
|
||||||
{
|
{
|
||||||
qDebug() << "details of folder with alias " << alias;
|
qDebug() << "details of folder with alias " << alias;
|
||||||
|
|
||||||
|
if( !_fileItemDialog ) {
|
||||||
|
_fileItemDialog = new FileItemDialog(_theme);
|
||||||
|
}
|
||||||
|
|
||||||
SyncResult folderResult = _folderMan->syncResult( alias );
|
SyncResult folderResult = _folderMan->syncResult( alias );
|
||||||
|
|
||||||
bool enabled = true;
|
_fileItemDialog->setSyncResult( folderResult );
|
||||||
Folder *f = _folderMan->folder( alias );
|
raiseDialog( _fileItemDialog );
|
||||||
if( f && ! f->syncEnabled() ) {
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString folderMessage;
|
|
||||||
|
|
||||||
SyncResult::Status syncStatus = folderResult.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::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 = QLatin1String("<b>") + folderMessage + QLatin1String("</b><br/>");
|
|
||||||
|
|
||||||
QMessageBox infoBox( QMessageBox::Information, tr( "Folder information" ), alias, QMessageBox::Ok );
|
|
||||||
QStringList li = folderResult.errorStrings();
|
|
||||||
foreach( const QString& l, li ) {
|
|
||||||
folderMessage += QString::fromLatin1("<p>%1</p>").arg( l );
|
|
||||||
}
|
|
||||||
|
|
||||||
infoBox.setText( folderMessage );
|
|
||||||
|
|
||||||
// qDebug() << "informative text: " << infoBox.informativeText();
|
|
||||||
|
|
||||||
if ( !folderResult.syncChanges().isEmpty() ) {
|
|
||||||
QString details;
|
|
||||||
QHash < QString, QStringList > changes = folderResult.syncChanges();
|
|
||||||
QHash< QString, QStringList >::const_iterator change_it = changes.constBegin();
|
|
||||||
for(; change_it != changes.constEnd(); ++change_it ) {
|
|
||||||
QString changeType = tr( "Unknown" );
|
|
||||||
if ( change_it.key() == QLatin1String("changed") ) {
|
|
||||||
changeType = tr( "Changed files:\n" );
|
|
||||||
} else if ( change_it.key() == QLatin1String("added") ) {
|
|
||||||
changeType = tr( "Added files:\n" );
|
|
||||||
} else if ( change_it.key() == QLatin1String("deleted") ) {
|
|
||||||
changeType = tr( "New files in the server, or files deleted locally:\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList files = change_it.value();
|
|
||||||
QString fileList;
|
|
||||||
foreach( const QString& file, files) {
|
|
||||||
fileList += file + QLatin1Char('\n');
|
|
||||||
}
|
|
||||||
details += changeType + fileList;
|
|
||||||
}
|
|
||||||
infoBox.setDetailedText(details);
|
|
||||||
qDebug() << "detailed text: " << infoBox.detailedText();
|
|
||||||
}
|
|
||||||
infoBox.exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::slotEnableFolder(const QString& alias, const bool enable)
|
void Application::slotEnableFolder(const QString& alias, const bool enable)
|
||||||
@@ -842,9 +825,8 @@ void Application::slotEnableFolder(const QString& alias, const bool enable)
|
|||||||
|
|
||||||
void Application::slotConfigure()
|
void Application::slotConfigure()
|
||||||
{
|
{
|
||||||
_folderMan->disableFoldersWithRestore();
|
_folderMan->setSyncEnabled(false); // do not start more syncs.
|
||||||
_owncloudSetupWizard->startWizard(false);
|
_owncloudSetupWizard->startWizard(false);
|
||||||
_folderMan->restoreEnabledFolders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::slotConfigureProxy()
|
void Application::slotConfigureProxy()
|
||||||
@@ -863,6 +845,11 @@ void Application::slotParseOptions(const QString &opts)
|
|||||||
setupLogBrowser();
|
setupLogBrowser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::slotShowTrayMessage(const QString &title, const QString &msg)
|
||||||
|
{
|
||||||
|
_tray->showMessage(title, msg);
|
||||||
|
}
|
||||||
|
|
||||||
void Application::slotSyncStateChange( const QString& alias )
|
void Application::slotSyncStateChange( const QString& alias )
|
||||||
{
|
{
|
||||||
SyncResult result = _folderMan->syncResult( alias );
|
SyncResult result = _folderMan->syncResult( alias );
|
||||||
@@ -870,6 +857,10 @@ void Application::slotSyncStateChange( const QString& alias )
|
|||||||
// do not promote LocalSyncState to the status dialog.
|
// do not promote LocalSyncState to the status dialog.
|
||||||
if( !result.localRunOnly() ) {
|
if( !result.localRunOnly() ) {
|
||||||
_statusDialog->slotUpdateFolderState( _folderMan->folder(alias) );
|
_statusDialog->slotUpdateFolderState( _folderMan->folder(alias) );
|
||||||
|
|
||||||
|
if( _fileItemDialog && _fileItemDialog->isVisible() ) {
|
||||||
|
_fileItemDialog->setSyncResult( _folderMan->syncResult(alias) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
computeOverallSyncStatus();
|
computeOverallSyncStatus();
|
||||||
|
|
||||||
@@ -882,10 +873,12 @@ void Application::parseOptions(const QStringList &options)
|
|||||||
// skip file name;
|
// skip file name;
|
||||||
if (it.hasNext()) it.next();
|
if (it.hasNext()) it.next();
|
||||||
|
|
||||||
|
//parse options; if help or bad option exit
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString option = it.next();
|
QString option = it.next();
|
||||||
if (option == QLatin1String("--help")) {
|
if (option == QLatin1String("--help") || option == QLatin1String("-h")) {
|
||||||
showHelp();
|
setHelp();
|
||||||
|
break;
|
||||||
} else if (option == QLatin1String("--logwindow") ||
|
} else if (option == QLatin1String("--logwindow") ||
|
||||||
option == QLatin1String("-l")) {
|
option == QLatin1String("-l")) {
|
||||||
_showLogWindow = true;
|
_showLogWindow = true;
|
||||||
@@ -893,12 +886,24 @@ void Application::parseOptions(const QStringList &options)
|
|||||||
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
||||||
_logFile = it.next();
|
_logFile = it.next();
|
||||||
} else {
|
} else {
|
||||||
showHelp();
|
setHelp();
|
||||||
}
|
}
|
||||||
} else if (option == QLatin1String("--logflush")) {
|
} else if (option == QLatin1String("--logflush")) {
|
||||||
_logFlush = true;
|
_logFlush = true;
|
||||||
|
} else if (option == QLatin1String("--monoicons")) {
|
||||||
|
_theme->setSystrayUseMonoIcons(true);
|
||||||
|
} else if (option == QLatin1String("--confdir")) {
|
||||||
|
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
|
||||||
|
QString confDir = it.next();
|
||||||
|
MirallConfigFile::setConfDir( confDir );
|
||||||
|
} else {
|
||||||
|
showHelp();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setHelp();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::computeOverallSyncStatus()
|
void Application::computeOverallSyncStatus()
|
||||||
@@ -927,10 +932,18 @@ void Application::computeOverallSyncStatus()
|
|||||||
folderMessage = tr( "Waits to start syncing." );
|
folderMessage = tr( "Waits to start syncing." );
|
||||||
overallResult.setStatus( SyncResult::NotYetStarted );
|
overallResult.setStatus( SyncResult::NotYetStarted );
|
||||||
break;
|
break;
|
||||||
|
case SyncResult::SyncPrepare:
|
||||||
|
folderMessage = tr( "Preparing for sync." );
|
||||||
|
overallResult.setStatus( SyncResult::SyncPrepare );
|
||||||
|
break;
|
||||||
case SyncResult::SyncRunning:
|
case SyncResult::SyncRunning:
|
||||||
folderMessage = tr( "Sync is running." );
|
folderMessage = tr( "Sync is running." );
|
||||||
overallResult.setStatus( SyncResult::SyncRunning );
|
overallResult.setStatus( SyncResult::SyncRunning );
|
||||||
break;
|
break;
|
||||||
|
case SyncResult::Unavailable:
|
||||||
|
folderMessage = tr( "Server is currently not available." );
|
||||||
|
overallResult.setStatus( SyncResult::Unavailable );
|
||||||
|
break;
|
||||||
case SyncResult::Success:
|
case SyncResult::Success:
|
||||||
if( overallResult.status() == SyncResult::Undefined ) {
|
if( overallResult.status() == SyncResult::Undefined ) {
|
||||||
folderMessage = tr( "Last Sync was successful." );
|
folderMessage = tr( "Last Sync was successful." );
|
||||||
@@ -972,7 +985,7 @@ void Application::computeOverallSyncStatus()
|
|||||||
else
|
else
|
||||||
trayMessage = tr("No sync folders configured.");
|
trayMessage = tr("No sync folders configured.");
|
||||||
|
|
||||||
QIcon statusIcon = _theme->syncStateIcon( overallResult.status()); // size 48 before
|
QIcon statusIcon = _theme->syncStateIcon( overallResult.status(), true); // size 48 before
|
||||||
|
|
||||||
_tray->setIcon( statusIcon );
|
_tray->setIcon( statusIcon );
|
||||||
_tray->setToolTip(trayMessage);
|
_tray->setToolTip(trayMessage);
|
||||||
@@ -981,19 +994,97 @@ void Application::computeOverallSyncStatus()
|
|||||||
|
|
||||||
void Application::showHelp()
|
void Application::showHelp()
|
||||||
{
|
{
|
||||||
|
setHelp();
|
||||||
std::cout << _theme->appName().toLatin1().constData() << " version " <<
|
std::cout << _theme->appName().toLatin1().constData() << " version " <<
|
||||||
_theme->version().toLatin1().constData() << std::endl << std::endl;
|
_theme->version().toLatin1().constData() << std::endl << std::endl;
|
||||||
std::cout << "File synchronisation desktop utility." << std::endl << std::endl;
|
std::cout << "File synchronisation desktop utility." << std::endl << std::endl;
|
||||||
std::cout << "Options:" << std::endl;
|
std::cout << "Options:" << std::endl;
|
||||||
|
std::cout << " -h --help : show this help screen." << std::endl;
|
||||||
std::cout << " --logwindow : open a window to show log output." << std::endl;
|
std::cout << " --logwindow : open a window to show log output." << std::endl;
|
||||||
std::cout << " --logfile <filename> : write log output to file <filename>." << std::endl;
|
std::cout << " --logfile <filename> : write log output to file <filename>." << std::endl;
|
||||||
std::cout << " --flushlog : flush the log file after every write." << std::endl;
|
std::cout << " --logflush : flush the log file after every write." << std::endl;
|
||||||
|
std::cout << " --monoicons : Use black/white pictograms for systray." << std::endl;
|
||||||
|
std::cout << " --confdir <dirname> : Use the given configuration directory." << std::endl;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
if (_theme->appName() == QLatin1String("ownCloud"))
|
if (_theme->appName() == QLatin1String("ownCloud"))
|
||||||
std::cout << "For more information, see http://www.owncloud.org" << std::endl;
|
std::cout << "For more information, see http://www.owncloud.org" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::setHelp()
|
||||||
|
{
|
||||||
_helpOnly = true;
|
_helpOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString substLang(const QString &lang)
|
||||||
|
{
|
||||||
|
// Map the more apropriate script codes
|
||||||
|
// to country codes as used by Qt and
|
||||||
|
// transifex translation conventions.
|
||||||
|
|
||||||
|
// Simplified Chinese
|
||||||
|
if (lang == QLatin1String("zh_Hans"))
|
||||||
|
return QLatin1String("zh_CN");
|
||||||
|
// Traditional Chinese
|
||||||
|
if (lang == QLatin1String("zh_Hant"))
|
||||||
|
return QLatin1String("zh_TW");
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::setupTranslations()
|
||||||
|
{
|
||||||
|
QStringList uiLanguages;
|
||||||
|
// uiLanguages crashes on Windows with 4.8.0 release builds
|
||||||
|
#if (QT_VERSION >= 0x040801) || (QT_VERSION >= 0x040800 && !defined(Q_OS_WIN))
|
||||||
|
uiLanguages = QLocale::system().uiLanguages();
|
||||||
|
#else
|
||||||
|
// older versions need to fall back to the systems locale
|
||||||
|
uiLanguages << QLocale::system().name();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QString enforcedLocale = Theme::instance()->enforcedLocale();
|
||||||
|
if (!enforcedLocale.isEmpty())
|
||||||
|
uiLanguages.prepend(enforcedLocale);
|
||||||
|
|
||||||
|
QTranslator *translator = new QTranslator(this);
|
||||||
|
QTranslator *qtTranslator = new QTranslator(this);
|
||||||
|
QTranslator *qtkeychainTranslator = new QTranslator(this);
|
||||||
|
|
||||||
|
foreach(QString lang, uiLanguages) {
|
||||||
|
lang.replace(QLatin1Char('-'), QLatin1Char('_')); // work around QTBUG-25973
|
||||||
|
lang = substLang(lang);
|
||||||
|
const QString trPath = applicationTrPath();
|
||||||
|
const QString trFile = QLatin1String("mirall_") + lang;
|
||||||
|
if (translator->load(trFile, trPath) ||
|
||||||
|
lang.startsWith(QLatin1String("en"))) {
|
||||||
|
// Permissive approach: Qt and keychain translations
|
||||||
|
// may be missing, but Qt translations must be there in order
|
||||||
|
// for us to accept the language. Otherwise, we try with the next.
|
||||||
|
// "en" is an exeption as it is the default language and may not
|
||||||
|
// have a translation file provided.
|
||||||
|
qDebug() << Q_FUNC_INFO << "Using" << lang << "translation";
|
||||||
|
setProperty("ui_lang", lang);
|
||||||
|
const QString qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
||||||
|
const QString qtTrFile = QLatin1String("qt_") + lang;
|
||||||
|
if (qtTranslator->load(qtTrFile, qtTrPath)) {
|
||||||
|
qtTranslator->load(qtTrFile, trPath);
|
||||||
|
}
|
||||||
|
const QString qtkeychainFile = QLatin1String("qt_") + lang;
|
||||||
|
if (!qtkeychainTranslator->load(qtkeychainFile, qtTrPath)) {
|
||||||
|
qtkeychainTranslator->load(qtkeychainFile, trPath);
|
||||||
|
}
|
||||||
|
if (!translator->isEmpty())
|
||||||
|
installTranslator(translator);
|
||||||
|
if (!qtTranslator->isEmpty())
|
||||||
|
installTranslator(qtTranslator);
|
||||||
|
if (!qtkeychainTranslator->isEmpty())
|
||||||
|
installTranslator(qtkeychainTranslator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (property("ui_lang").isNull())
|
||||||
|
setProperty("ui_lang", "C");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::giveHelp()
|
bool Application::giveHelp()
|
||||||
{
|
{
|
||||||
return _helpOnly;
|
return _helpOnly;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "mirall/folder.h"
|
#include "mirall/folder.h"
|
||||||
#include "mirall/logbrowser.h"
|
#include "mirall/logbrowser.h"
|
||||||
#include "mirall/folderman.h"
|
#include "mirall/folderman.h"
|
||||||
|
#include "mirall/fileitemdialog.h"
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
class QMenu;
|
class QMenu;
|
||||||
@@ -52,6 +53,7 @@ public:
|
|||||||
~Application();
|
~Application();
|
||||||
|
|
||||||
bool giveHelp();
|
bool giveHelp();
|
||||||
|
void showHelp();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
@@ -64,11 +66,14 @@ protected slots:
|
|||||||
void slotConfigure();
|
void slotConfigure();
|
||||||
void slotConfigureProxy();
|
void slotConfigureProxy();
|
||||||
void slotParseOptions( const QString& );
|
void slotParseOptions( const QString& );
|
||||||
|
void slotShowTrayMessage(const QString&, const QString&);
|
||||||
|
|
||||||
void slotSyncStateChange( const QString& );
|
void slotSyncStateChange( const QString& );
|
||||||
|
void slotownCloudWizardDone(int);
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void parseOptions(const QStringList& );
|
void parseOptions(const QStringList& );
|
||||||
|
void setupTranslations();
|
||||||
void setupActions();
|
void setupActions();
|
||||||
void setupSystemTray();
|
void setupSystemTray();
|
||||||
void setupContextMenu();
|
void setupContextMenu();
|
||||||
@@ -95,7 +100,8 @@ protected slots:
|
|||||||
void slotStartUpdateDetector();
|
void slotStartUpdateDetector();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void showHelp();
|
void setHelp();
|
||||||
|
void raiseDialog( QWidget* );
|
||||||
|
|
||||||
// configuration file -> folder
|
// configuration file -> folder
|
||||||
QSystemTrayIcon *_tray;
|
QSystemTrayIcon *_tray;
|
||||||
@@ -118,6 +124,7 @@ private:
|
|||||||
// tray's menu
|
// tray's menu
|
||||||
QMenu *_contextMenu;
|
QMenu *_contextMenu;
|
||||||
StatusDialog *_statusDialog;
|
StatusDialog *_statusDialog;
|
||||||
|
FileItemDialog *_fileItemDialog;
|
||||||
|
|
||||||
FolderMan *_folderMan;
|
FolderMan *_folderMan;
|
||||||
Theme *_theme;
|
Theme *_theme;
|
||||||
@@ -128,7 +135,7 @@ private:
|
|||||||
QString _logFile;
|
QString _logFile;
|
||||||
bool _showLogWindow;
|
bool _showLogWindow;
|
||||||
bool _logFlush;
|
bool _logFlush;
|
||||||
bool _helpOnly;
|
bool _helpOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Mirall
|
} // namespace Mirall
|
||||||
|
|||||||
@@ -12,18 +12,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include "mirall/credentialstore.h"
|
#include "mirall/credentialstore.h"
|
||||||
#include "mirall/mirallconfigfile.h"
|
#include "mirall/mirallconfigfile.h"
|
||||||
#include "mirall/theme.h"
|
#include "mirall/theme.h"
|
||||||
|
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
#include <qtkeychain/keychain.h>
|
||||||
|
using namespace QKeychain;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_LOGIN_ATTEMPTS 3
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
CredentialStore *CredentialStore::_instance=0;
|
CredentialStore *CredentialStore::_instance=0;
|
||||||
CredentialStore::CredState CredentialStore::_state = NotFetched;
|
CredentialStore::CredState CredentialStore::_state = NotFetched;
|
||||||
QString CredentialStore::_passwd = QString::null;
|
QString CredentialStore::_passwd = QString::null;
|
||||||
QString CredentialStore::_user = QString::null;
|
QString CredentialStore::_user = QString::null;
|
||||||
int CredentialStore::_tries = 0;
|
QString CredentialStore::_url = QString::null;
|
||||||
|
QString CredentialStore::_errorMsg = QString::null;
|
||||||
|
int CredentialStore::_tries = 0;
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
CredentialStore::CredentialType CredentialStore::_type = KeyChain;
|
||||||
|
#else
|
||||||
|
CredentialStore::CredentialType CredentialStore::_type = Settings;
|
||||||
|
#endif
|
||||||
|
|
||||||
CredentialStore::CredentialStore(QObject *parent) :
|
CredentialStore::CredentialStore(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
@@ -36,11 +53,11 @@ CredentialStore *CredentialStore::instance()
|
|||||||
return CredentialStore::_instance;
|
return CredentialStore::_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CredentialStore::password( const QString& ) const
|
QString CredentialStore::password() const
|
||||||
{
|
{
|
||||||
return _passwd;
|
return _passwd;
|
||||||
}
|
}
|
||||||
QString CredentialStore::user( const QString& ) const
|
QString CredentialStore::user() const
|
||||||
{
|
{
|
||||||
return _user;
|
return _user;
|
||||||
}
|
}
|
||||||
@@ -50,58 +67,104 @@ CredentialStore::CredState CredentialStore::state()
|
|||||||
return _state;
|
return _state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CredentialStore::canTryAgain()
|
||||||
|
{
|
||||||
|
bool canDoIt = false;
|
||||||
|
|
||||||
|
if( _tries > MAX_LOGIN_ATTEMPTS ) {
|
||||||
|
qDebug() << "canTryAgain: Max attempts reached.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _state == NotFetched ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( _type ) {
|
||||||
|
case CredentialStore::User:
|
||||||
|
canDoIt = true;
|
||||||
|
break;
|
||||||
|
case CredentialStore::Settings:
|
||||||
|
break;
|
||||||
|
case CredentialStore::KeyChain:
|
||||||
|
canDoIt = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return canDoIt;
|
||||||
|
}
|
||||||
|
|
||||||
void CredentialStore::fetchCredentials()
|
void CredentialStore::fetchCredentials()
|
||||||
{
|
{
|
||||||
_state = Fetching;
|
|
||||||
MirallConfigFile cfgFile;
|
MirallConfigFile cfgFile;
|
||||||
MirallConfigFile::CredentialType t;
|
if( ++_tries > MAX_LOGIN_ATTEMPTS ) {
|
||||||
|
|
||||||
if( _tries++ == 3 ) {
|
|
||||||
qDebug() << "Too many attempts to enter password!";
|
qDebug() << "Too many attempts to enter password!";
|
||||||
_state = TooManyAttempts;
|
_state = TooManyAttempts;
|
||||||
|
emit( fetchCredentialsFinished(false) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t = cfgFile.credentialType();
|
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
QString pwd;
|
QString pwd;
|
||||||
_state = Fetching;
|
|
||||||
_user = cfgFile.ownCloudUser();
|
_user = cfgFile.ownCloudUser();
|
||||||
|
_url = cfgFile.ownCloudUrl();
|
||||||
|
if( !cfgFile.passwordStorageAllowed() ) {
|
||||||
|
_type = CredentialStore::User;
|
||||||
|
}
|
||||||
|
|
||||||
switch( t ) {
|
QString key = keyChainKey(_url);
|
||||||
case MirallConfigFile::User: {
|
|
||||||
|
if( key.isNull() ) {
|
||||||
|
qDebug() << "Can not fetch credentials, url is zero!";
|
||||||
|
_state = Error;
|
||||||
|
emit( fetchCredentialsFinished(false) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( _type ) {
|
||||||
|
case CredentialStore::User: {
|
||||||
/* Ask the user for the password */
|
/* Ask the user for the password */
|
||||||
/* Fixme: Move user interaction out here. */
|
/* Fixme: Move user interaction out here. */
|
||||||
pwd = QInputDialog::getText(0, QApplication::translate("MirallConfigFile","Password Required"),
|
_state = AsyncFetching;
|
||||||
QApplication::translate("MirallConfigFile","Please enter your %1 password:")
|
_inputDialog = new QInputDialog;
|
||||||
.arg(Theme::instance()->appName()),
|
_inputDialog->setWindowTitle(QApplication::translate("MirallConfigFile","Password Required") );
|
||||||
QLineEdit::Password,
|
_inputDialog->setLabelText( QApplication::translate("MirallConfigFile","Please enter your %1 password:")
|
||||||
QString::null, &ok);
|
.arg(Theme::instance()->appNameGUI()));
|
||||||
if( !ok ) {
|
_inputDialog->setInputMode( QInputDialog::TextInput );
|
||||||
_state = UserCanceled;
|
_inputDialog->setTextEchoMode( QLineEdit::Password );
|
||||||
}
|
|
||||||
|
connect(_inputDialog, SIGNAL(finished(int)), SLOT(slotUserDialogDone(int)));
|
||||||
|
_inputDialog->exec();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MirallConfigFile::Settings: {
|
case CredentialStore::Settings: {
|
||||||
/* Read from config file. */
|
/* Read from config file. */
|
||||||
|
_state = Fetching;
|
||||||
pwd = cfgFile.ownCloudPasswd();
|
pwd = cfgFile.ownCloudPasswd();
|
||||||
ok = true;
|
ok = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MirallConfigFile::KeyChain: {
|
case CredentialStore::KeyChain: {
|
||||||
/* Qt Keychain is not yet implemented. */
|
// If the credentials are here already, return.
|
||||||
#ifdef HAVE_QTKEYCHAIN
|
if( _state == Ok ) {
|
||||||
|
emit(fetchCredentialsFinished(true));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// otherwise fetch asynchronious.
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
_state = AsyncFetching;
|
||||||
if( !_user.isEmpty() ) {
|
if( !_user.isEmpty() ) {
|
||||||
ReadPasswordJoei b job( QLatin1String(Theme::instance()->appName()) );
|
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
|
||||||
job.setAutoDelete( false );
|
job->setKey( key );
|
||||||
job.setKey( _user );
|
|
||||||
|
|
||||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), this,
|
connect( job, SIGNAL(finished(QKeychain::Job*)), this,
|
||||||
SLOT(slotKeyChainFinished(QKeyChain::Job*)));
|
SLOT(slotKeyChainReadFinished(QKeychain::Job*)));
|
||||||
job.start();
|
job->start();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
qDebug() << "QtKeyChain: Not yet implemented!";
|
qDebug() << "QtKeyChain: Not yet implemented!";
|
||||||
|
_state = Error;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -110,45 +173,230 @@ void CredentialStore::fetchCredentials()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ok ) {
|
if( _state == Fetching ) { // ...but not AsyncFetching
|
||||||
_passwd = pwd;
|
if( ok ) {
|
||||||
_state = Ok;
|
_passwd = pwd;
|
||||||
}
|
_state = Ok;
|
||||||
if( !ok && _state == Fetching ) {
|
|
||||||
_state = Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit( fetchCredentialsFinished(ok) );
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_QTKEYCHAIN
|
|
||||||
void CredentialsStore::slotKeyChainFinished(QKeyChain::Job* job)
|
|
||||||
{
|
|
||||||
if( job ) {
|
|
||||||
if( job->error() ) {
|
|
||||||
qDebug() << "Error mit keychain: " << job->errorString();
|
|
||||||
} else {
|
|
||||||
_passwd = job.textData();
|
|
||||||
}
|
}
|
||||||
|
if( !ok && _state == Fetching ) {
|
||||||
|
_state = Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit( fetchCredentialsFinished(ok) );
|
||||||
|
} else {
|
||||||
|
// in case of AsyncFetching nothing happens here. The finished-Slot
|
||||||
|
// will emit the finish signal.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
void CredentialStore::slotUserDialogDone( int result )
|
||||||
QByteArray CredentialStore::basicAuthHeader() const
|
|
||||||
{
|
{
|
||||||
QString concatenated = _user + QLatin1Char(':') + _passwd;
|
if( result == QDialog::Accepted ) {
|
||||||
const QString b(QLatin1String("Basic "));
|
_passwd = _inputDialog->textValue();
|
||||||
QByteArray data = b.toLocal8Bit() + concatenated.toLocal8Bit().toBase64();
|
_state = Ok;
|
||||||
|
} else {
|
||||||
return data;
|
_state = UserCanceled;
|
||||||
|
_passwd = QString::null;
|
||||||
|
}
|
||||||
|
_inputDialog->deleteLater();
|
||||||
|
emit(fetchCredentialsFinished(_state == Ok));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CredentialStore::setCredentials( const QString& user, const QString& pwd )
|
void CredentialStore::reset()
|
||||||
|
{
|
||||||
|
_state = NotFetched;
|
||||||
|
_user = QString::null;
|
||||||
|
_passwd = QString::null;
|
||||||
|
_tries = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CredentialStore::keyChainKey( const QString& url ) const
|
||||||
|
{
|
||||||
|
QString u(url);
|
||||||
|
if( u.isEmpty() ) {
|
||||||
|
qDebug() << "Empty url in keyChain, error!";
|
||||||
|
return QString::null;
|
||||||
|
}
|
||||||
|
if( _user.isEmpty() ) {
|
||||||
|
qDebug() << "Error: User is emty!";
|
||||||
|
return QString::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !u.endsWith(QChar('/')) ) {
|
||||||
|
u.append(QChar('/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString key = _user+QLatin1Char(':')+u;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CredentialStore::slotKeyChainReadFinished(QKeychain::Job* job)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
ReadPasswordJob *pwdJob = static_cast<ReadPasswordJob*>(job);
|
||||||
|
if( pwdJob ) {
|
||||||
|
switch( pwdJob->error() ) {
|
||||||
|
case QKeychain::NoError:
|
||||||
|
_passwd = pwdJob->textData();
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
// Currently there is a bug in the keychain on linux that if no
|
||||||
|
// entry is there, an empty password comes back, but no error.
|
||||||
|
if( _passwd.isEmpty() ) {
|
||||||
|
_state = EntryNotFound;
|
||||||
|
_errorMsg = tr("No password entry found in keychain. Please reconfigure.");
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
_state = Ok;
|
||||||
|
break;
|
||||||
|
case QKeychain::EntryNotFound:
|
||||||
|
_state = EntryNotFound;
|
||||||
|
break;
|
||||||
|
case QKeychain::CouldNotDeleteEntry:
|
||||||
|
_state = Error;
|
||||||
|
break;
|
||||||
|
case QKeychain::AccessDeniedByUser:
|
||||||
|
_state = AccessDeniedByUser;
|
||||||
|
break;
|
||||||
|
case QKeychain::AccessDenied:
|
||||||
|
_state = AccessDenied;
|
||||||
|
break;
|
||||||
|
case QKeychain::NoBackendAvailable:
|
||||||
|
_state = NoKeychainBackend;
|
||||||
|
break;
|
||||||
|
case QKeychain::NotImplemented:
|
||||||
|
_state = NoKeychainBackend;
|
||||||
|
break;
|
||||||
|
case QKeychain::OtherError:
|
||||||
|
default:
|
||||||
|
_state = Error;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* In case there is no backend, tranparentely switch to Settings file. */
|
||||||
|
if( _state == NoKeychainBackend ) {
|
||||||
|
qDebug() << "No Storage Backend, falling back to Settings mode.";
|
||||||
|
_type = CredentialStore::Settings;
|
||||||
|
fetchCredentials();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _state == EntryNotFound ) {
|
||||||
|
// try to migrate.
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _state != Ok ) {
|
||||||
|
qDebug() << "Error with keychain: " << pwdJob->errorString();
|
||||||
|
if(_errorMsg.isEmpty()) _errorMsg = pwdJob->errorString();
|
||||||
|
} else {
|
||||||
|
_errorMsg = QString::null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_state = Error;
|
||||||
|
qDebug() << "Error: KeyChain Read Password Job failed!";
|
||||||
|
}
|
||||||
|
emit(fetchCredentialsFinished(_state == Ok));
|
||||||
|
#else
|
||||||
|
(void) job;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CredentialStore::errorMessage()
|
||||||
|
{
|
||||||
|
return _errorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CredentialStore::setCredentials( const QString& url, const QString& user,
|
||||||
|
const QString& pwd, bool allowToStore )
|
||||||
{
|
{
|
||||||
_passwd = pwd;
|
_passwd = pwd;
|
||||||
_user = user;
|
_user = user;
|
||||||
|
if( allowToStore ) {
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
_type = KeyChain;
|
||||||
|
#else
|
||||||
|
_type = Settings;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
_type = User;
|
||||||
|
}
|
||||||
|
_url = url;
|
||||||
_state = Ok;
|
_state = Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CredentialStore::saveCredentials( )
|
||||||
|
{
|
||||||
|
MirallConfigFile cfgFile;
|
||||||
|
QString key = keyChainKey(_url);
|
||||||
|
if( key.isNull() ) {
|
||||||
|
qDebug() << "Error: Can not save credentials, URL is zero!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
WritePasswordJob *job = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch( _type ) {
|
||||||
|
case CredentialStore::User:
|
||||||
|
deleteKeyChainCredential( key );
|
||||||
|
break;
|
||||||
|
case CredentialStore::KeyChain:
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
// Set password in KeyChain
|
||||||
|
job = new WritePasswordJob(Theme::instance()->appName());
|
||||||
|
job->setKey( key );
|
||||||
|
job->setTextData(_passwd);
|
||||||
|
|
||||||
|
connect( job, SIGNAL(finished(QKeychain::Job*)), this,
|
||||||
|
SLOT(slotKeyChainWriteFinished(QKeychain::Job*)));
|
||||||
|
job->start();
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case CredentialStore::Settings:
|
||||||
|
cfgFile.writePassword( _passwd );
|
||||||
|
reset();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// unsupported.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CredentialStore::slotKeyChainWriteFinished( QKeychain::Job *job )
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
WritePasswordJob *pwdJob = static_cast<WritePasswordJob*>(job);
|
||||||
|
if( pwdJob ) {
|
||||||
|
QKeychain::Error err = pwdJob->error();
|
||||||
|
|
||||||
|
if( err != QKeychain::NoError ) {
|
||||||
|
qDebug() << "Error with keychain: " << pwdJob->errorString();
|
||||||
|
if( err == NoBackendAvailable || err == NotImplemented ||
|
||||||
|
pwdJob->errorString().contains(QLatin1String("Could not open wallet"))) {
|
||||||
|
_type = Settings;
|
||||||
|
saveCredentials();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "Successfully stored password for user " << _user;
|
||||||
|
// Try to remove password formerly stored in the config file.
|
||||||
|
MirallConfigFile cfgFile;
|
||||||
|
cfgFile.clearPasswordFromConfig();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "Error: KeyChain Write Password Job failed!";
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void) job;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called if a user chooses to not store the password locally.
|
||||||
|
void CredentialStore::deleteKeyChainCredential( const QString& key )
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
// Start the remove job, do not care so much about the result.
|
||||||
|
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
|
||||||
|
job->setKey( key );
|
||||||
|
job->start();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,11 @@
|
|||||||
#define CREDENTIALSTORE_H
|
#define CREDENTIALSTORE_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
|
namespace QKeychain {
|
||||||
|
class Job;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
@@ -42,10 +47,26 @@ class CredentialStore : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum CredState { NotFetched = 0, Ok, UserCanceled, Fetching, Error, TooManyAttempts };
|
enum CredState { NotFetched = 0,
|
||||||
|
Ok,
|
||||||
|
UserCanceled,
|
||||||
|
Fetching,
|
||||||
|
AsyncFetching,
|
||||||
|
EntryNotFound,
|
||||||
|
AccessDeniedByUser,
|
||||||
|
AccessDenied,
|
||||||
|
NoKeychainBackend,
|
||||||
|
Error,
|
||||||
|
TooManyAttempts };
|
||||||
|
|
||||||
QString password( const QString& connection = QString::null ) const;
|
enum CredentialType {
|
||||||
QString user( const QString& connection = QString::null ) const;
|
User = 0,
|
||||||
|
Settings,
|
||||||
|
KeyChain
|
||||||
|
};
|
||||||
|
|
||||||
|
QString password( ) const;
|
||||||
|
QString user( ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief state
|
* @brief state
|
||||||
@@ -61,12 +82,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void fetchCredentials();
|
void fetchCredentials();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief basicAuthHeader - return a basic authentication header.
|
|
||||||
* @return a QByteArray with a ready to use Header for HTTP basic auth.
|
|
||||||
*/
|
|
||||||
QByteArray basicAuthHeader() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief instance - singleton pointer.
|
* @brief instance - singleton pointer.
|
||||||
* @return the singleton pointer to access the object.
|
* @return the singleton pointer to access the object.
|
||||||
@@ -77,11 +92,24 @@ public:
|
|||||||
* @brief setCredentials - sets the user credentials.
|
* @brief setCredentials - sets the user credentials.
|
||||||
*
|
*
|
||||||
* This function is called from the setup wizard to set the credentials
|
* This function is called from the setup wizard to set the credentials
|
||||||
* int this store. The function also sets the state to ok.
|
* int this store. Note that it does not store the password.
|
||||||
|
* The function also sets the state to ok.
|
||||||
|
* @param url - the connection url
|
||||||
* @param user - the user name
|
* @param user - the user name
|
||||||
* @param password - the password.
|
* @param password - the password.
|
||||||
*/
|
*/
|
||||||
void setCredentials( const QString&, const QString& );
|
void setCredentials( const QString&, const QString&, const QString&, bool );
|
||||||
|
|
||||||
|
void saveCredentials( );
|
||||||
|
|
||||||
|
QString errorMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief canTryAgain - check if another try to get credentials makes sense.
|
||||||
|
*/
|
||||||
|
bool canTryAgain();
|
||||||
|
|
||||||
|
void reset();
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* @brief fetchCredentialsFinished
|
* @brief fetchCredentialsFinished
|
||||||
@@ -93,19 +121,25 @@ signals:
|
|||||||
*/
|
*/
|
||||||
void fetchCredentialsFinished(bool);
|
void fetchCredentialsFinished(bool);
|
||||||
|
|
||||||
private slots:
|
protected slots:
|
||||||
#ifdef HAVE_QTKEYCHAIN
|
void slotKeyChainReadFinished( QKeychain::Job* );
|
||||||
void slotKeyChainFinished(QKeyChain::Job* job);
|
void slotKeyChainWriteFinished( QKeychain::Job* );
|
||||||
#endif
|
void slotUserDialogDone(int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit CredentialStore(QObject *parent = 0);
|
explicit CredentialStore(QObject *parent = 0);
|
||||||
|
void deleteKeyChainCredential( const QString& );
|
||||||
|
QString keyChainKey( const QString& ) const;
|
||||||
|
|
||||||
static CredentialStore *_instance;
|
static CredentialStore *_instance;
|
||||||
static CredState _state;
|
static CredState _state;
|
||||||
static QString _passwd;
|
static QString _passwd;
|
||||||
static QString _user;
|
static QString _user;
|
||||||
|
static QString _url;
|
||||||
|
static QString _errorMsg;
|
||||||
static int _tries;
|
static int _tries;
|
||||||
|
static CredentialType _type;
|
||||||
|
QInputDialog *_inputDialog;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ void CSyncFolder::startSync(const QStringList &pathList)
|
|||||||
delete _thread;
|
delete _thread;
|
||||||
_errors.clear();
|
_errors.clear();
|
||||||
_csyncError = false;
|
_csyncError = false;
|
||||||
|
_syncResult.setStatus( SyncResult::SyncRunning );
|
||||||
|
emit syncStateChange();
|
||||||
|
|
||||||
_thread = new QThread(this);
|
_thread = new QThread(this);
|
||||||
_csync = new CSyncThread( path(), secondPath() );
|
_csync = new CSyncThread( path(), secondPath() );
|
||||||
@@ -87,7 +89,7 @@ void CSyncFolder::slotCSyncFinished()
|
|||||||
SyncResult res(SyncResult::Success);
|
SyncResult res(SyncResult::Success);
|
||||||
if( _csyncError ) {
|
if( _csyncError ) {
|
||||||
res.setStatus( SyncResult::Error );
|
res.setStatus( SyncResult::Error );
|
||||||
res.setErrorString( _errors.join(QLatin1String("\\n")));
|
res.setErrorString( _errors.join(QLatin1String("\n")));
|
||||||
}
|
}
|
||||||
emit syncFinished( res );
|
emit syncFinished( res );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,20 @@
|
|||||||
#include "mirall/csyncthread.h"
|
#include "mirall/csyncthread.h"
|
||||||
#include "mirall/mirallconfigfile.h"
|
#include "mirall/mirallconfigfile.h"
|
||||||
#include "mirall/theme.h"
|
#include "mirall/theme.h"
|
||||||
|
#include "mirall/logger.h"
|
||||||
|
#include "mirall/utility.h"
|
||||||
|
#include "mirall/owncloudinfo.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QSslSocket>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
@@ -25,6 +37,8 @@
|
|||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QSslCertificate>
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
@@ -37,122 +51,18 @@ QString CSyncThread::_csyncConfigDir; // to be able to remove the lock file.
|
|||||||
|
|
||||||
QMutex CSyncThread::_mutex;
|
QMutex CSyncThread::_mutex;
|
||||||
|
|
||||||
struct proxyInfo_s {
|
void csyncLogCatcher(CSYNC *ctx,
|
||||||
char *proxyType;
|
int verbosity,
|
||||||
char *proxyHost;
|
const char *function,
|
||||||
char *proxyPort;
|
const char *buffer,
|
||||||
char *proxyUser;
|
void *userdata)
|
||||||
char *proxyPwd;
|
|
||||||
};
|
|
||||||
typedef proxyInfo_s ProxyInfo;
|
|
||||||
|
|
||||||
walkStats_s::walkStats_s() {
|
|
||||||
errorType = 0;
|
|
||||||
|
|
||||||
eval = 0;
|
|
||||||
removed = 0;
|
|
||||||
renamed = 0;
|
|
||||||
newFiles = 0;
|
|
||||||
conflicts = 0;
|
|
||||||
ignores = 0;
|
|
||||||
sync = 0;
|
|
||||||
error = 0;
|
|
||||||
|
|
||||||
dirPermErrors = 0;
|
|
||||||
|
|
||||||
seenFiles = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int CSyncThread::recordStats( TREE_WALK_FILE* file )
|
|
||||||
{
|
{
|
||||||
if( ! file ) return -1;
|
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
|
||||||
_mutex.lock();
|
|
||||||
|
|
||||||
_walkStats.seenFiles++;
|
|
||||||
|
|
||||||
switch(file->instruction) {
|
|
||||||
case CSYNC_INSTRUCTION_NONE:
|
|
||||||
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_EVAL:
|
|
||||||
_walkStats.eval++;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_REMOVE:
|
|
||||||
_walkStats.removed++;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_RENAME:
|
|
||||||
_walkStats.renamed++;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_NEW:
|
|
||||||
_walkStats.newFiles++;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_CONFLICT:
|
|
||||||
_walkStats.conflicts++;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_IGNORE:
|
|
||||||
_walkStats.ignores++;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_SYNC:
|
|
||||||
_walkStats.sync++;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_STAT_ERROR:
|
|
||||||
case CSYNC_INSTRUCTION_ERROR:
|
|
||||||
/* instructions for the propagator */
|
|
||||||
case CSYNC_INSTRUCTION_DELETED:
|
|
||||||
case CSYNC_INSTRUCTION_UPDATED:
|
|
||||||
_walkStats.error++;
|
|
||||||
_walkStats.errorType = WALK_ERROR_INSTRUCTIONS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_walkStats.error++;
|
|
||||||
_walkStats.errorType = WALK_ERROR_WALK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int re = 0;
|
|
||||||
// qDebug() << _walkStats.seenFiles << ". Path: " << file->path << ": uid= " << file->uid << " - type: " << file->type;
|
|
||||||
if( !( _walkStats.errorType == WALK_ERROR_NONE || _walkStats.errorType == WALK_ERROR_DIR_PERMS )) {
|
|
||||||
re = -1;
|
|
||||||
}
|
|
||||||
_mutex.unlock();
|
|
||||||
|
|
||||||
return re;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSyncThread::treewalk( TREE_WALK_FILE* file, void *data )
|
CSyncThread::CSyncThread(const QString &source, const QString &target)
|
||||||
{
|
|
||||||
int re = static_cast<CSyncThread*>(data)->recordStats( file );
|
|
||||||
if( re > -1 )
|
|
||||||
return static_cast<CSyncThread*>(data)->treewalkFile( file );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CSyncThread::treewalkFile( TREE_WALK_FILE *file )
|
|
||||||
{
|
|
||||||
if( ! file ) return -1;
|
|
||||||
SyncFileItem item;
|
|
||||||
item.file = QString::fromUtf8( file->path );
|
|
||||||
item.instruction = file->instruction;
|
|
||||||
|
|
||||||
QFileInfo fi( _source, item.file );
|
|
||||||
if( !(fi.isWritable() && fi.isExecutable()) ) {
|
|
||||||
_walkStats.dirPermErrors++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mutex.lock();
|
|
||||||
_syncedItems.append(item);
|
|
||||||
_mutex.unlock();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSyncThread::CSyncThread(const QString &source, const QString &target, bool localCheckOnly)
|
|
||||||
|
|
||||||
: _source(source)
|
: _source(source)
|
||||||
, _target(target)
|
, _target(target)
|
||||||
, _localCheckOnly( localCheckOnly )
|
|
||||||
|
|
||||||
{
|
{
|
||||||
_mutex.lock();
|
_mutex.lock();
|
||||||
@@ -165,219 +75,356 @@ CSyncThread::~CSyncThread()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* proxyTypeToCStr(QNetworkProxy::ProxyType type)
|
QString CSyncThread::csyncErrorToString( CSYNC_ERROR_CODE err, const char *errString )
|
||||||
|
{
|
||||||
|
QString errStr;
|
||||||
|
|
||||||
|
switch( err ) {
|
||||||
|
case CSYNC_ERR_NONE:
|
||||||
|
errStr = tr("Success.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_LOG:
|
||||||
|
errStr = tr("CSync Logging setup failed.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_LOCK:
|
||||||
|
errStr = tr("CSync failed to create a lock file.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_STATEDB_LOAD:
|
||||||
|
errStr = tr("CSync failed to load the state db.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_MODULE:
|
||||||
|
errStr = tr("<p>The %1 plugin for csync could not be loaded.<br/>Please verify the installation!</p>").arg(Theme::instance()->appNameGUI());
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_TIMESKEW:
|
||||||
|
errStr = tr("The system time on this client is different than the system time on the server. "
|
||||||
|
"Please use a time synchronization service (NTP) on the server and client machines "
|
||||||
|
"so that the times remain the same.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_FILESYSTEM:
|
||||||
|
errStr = tr("CSync could not detect the filesystem type.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_TREE:
|
||||||
|
errStr = tr("CSync got an error while processing internal trees.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_MEM:
|
||||||
|
errStr = tr("CSync failed to reserve memory.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_PARAM:
|
||||||
|
errStr = tr("CSync fatal parameter error.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_UPDATE:
|
||||||
|
errStr = tr("CSync processing step update failed.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_RECONCILE:
|
||||||
|
errStr = tr("CSync processing step reconcile failed.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_PROPAGATE:
|
||||||
|
errStr = tr("CSync processing step propagate failed.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_ACCESS_FAILED:
|
||||||
|
errStr = tr("<p>The target directory %1 does not exist.</p><p>Please check the sync setup.</p>").arg(_target);
|
||||||
|
// this is critical. The database has to be removed.
|
||||||
|
emit wipeDb();
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_REMOTE_CREATE:
|
||||||
|
case CSYNC_ERR_REMOTE_STAT:
|
||||||
|
errStr = tr("A remote file can not be written. Please check the remote access.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_LOCAL_CREATE:
|
||||||
|
case CSYNC_ERR_LOCAL_STAT:
|
||||||
|
errStr = tr("The local filesystem can not be written. Please check permissions.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_PROXY:
|
||||||
|
errStr = tr("CSync failed to connect through a proxy.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_LOOKUP:
|
||||||
|
errStr = tr("CSync failed to lookup proxy or server.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_AUTH_SERVER:
|
||||||
|
errStr = tr("CSync failed to authenticate at the %1 server.").arg(Theme::instance()->appNameGUI());
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_AUTH_PROXY:
|
||||||
|
errStr = tr("CSync failed to authenticate at the proxy.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_CONNECT:
|
||||||
|
errStr = tr("CSync failed to connect to the network.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_TIMEOUT:
|
||||||
|
errStr = tr("A network connection timeout happend.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_HTTP:
|
||||||
|
errStr = tr("A HTTP transmission error happened.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_PERM:
|
||||||
|
errStr = tr("CSync failed due to not handled permission deniend.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_NOT_FOUND:
|
||||||
|
errStr = tr("CSync failed to find a specific file.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_EXISTS:
|
||||||
|
errStr = tr("CSync tried to create a directory that already exists.");
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_NOSPC:
|
||||||
|
errStr = tr("CSync: No space on %1 server available.").arg(Theme::instance()->appNameGUI());
|
||||||
|
break;
|
||||||
|
case CSYNC_ERR_UNSPEC:
|
||||||
|
errStr = tr("CSync unspecified error.");
|
||||||
|
|
||||||
|
default:
|
||||||
|
errStr = tr("An internal error number %1 happend.").arg( (int) err );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( errString ) {
|
||||||
|
errStr += tr("<br/>Backend Message: ")+QString::fromUtf8(errString);
|
||||||
|
}
|
||||||
|
return errStr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* CSyncThread::proxyTypeToCStr(QNetworkProxy::ProxyType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case QNetworkProxy::NoProxy:
|
case QNetworkProxy::NoProxy:
|
||||||
return qstrdup("NoProxy");
|
return "NoProxy";
|
||||||
case QNetworkProxy::DefaultProxy:
|
case QNetworkProxy::DefaultProxy:
|
||||||
return qstrdup("DefaultProxy");
|
return "DefaultProxy";
|
||||||
case QNetworkProxy::Socks5Proxy:
|
case QNetworkProxy::Socks5Proxy:
|
||||||
return qstrdup("Socks5Proxy");
|
return "Socks5Proxy";
|
||||||
case QNetworkProxy::HttpProxy:
|
case QNetworkProxy::HttpProxy:
|
||||||
return qstrdup("HttpProxy");
|
return "HttpProxy";
|
||||||
case QNetworkProxy::HttpCachingProxy:
|
case QNetworkProxy::HttpCachingProxy:
|
||||||
return qstrdup("HttpCachingProxy");
|
return "HttpCachingProxy";
|
||||||
case QNetworkProxy::FtpCachingProxy:
|
case QNetworkProxy::FtpCachingProxy:
|
||||||
return qstrdup("FtpCachingProxy");
|
return "FtpCachingProxy";
|
||||||
default:
|
default:
|
||||||
return qstrdup("NoProxy");
|
return "NoProxy";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSyncThread::treewalkLocal( TREE_WALK_FILE* file, void *data )
|
||||||
|
{
|
||||||
|
return static_cast<CSyncThread*>(data)->treewalkFile( file, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSyncThread::treewalkRemote( TREE_WALK_FILE* file, void *data )
|
||||||
|
{
|
||||||
|
return static_cast<CSyncThread*>(data)->treewalkFile( file, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSyncThread::walkFinalize(TREE_WALK_FILE* file, void *data )
|
||||||
|
{
|
||||||
|
return static_cast<CSyncThread*>(data)->treewalkError( file);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSyncThread::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||||
|
{
|
||||||
|
if( ! file ) return -1;
|
||||||
|
SyncFileItem item;
|
||||||
|
item._file = QString::fromUtf8( file->path );
|
||||||
|
item._instruction = file->instruction;
|
||||||
|
item._dir = SyncFileItem::None;
|
||||||
|
|
||||||
|
SyncFileItem::Direction dir;
|
||||||
|
|
||||||
|
int re = 0;
|
||||||
|
|
||||||
|
switch(file->instruction) {
|
||||||
|
case CSYNC_INSTRUCTION_NONE:
|
||||||
|
case CSYNC_INSTRUCTION_IGNORE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!_needsUpdate)
|
||||||
|
_needsUpdate = true;
|
||||||
|
}
|
||||||
|
switch(file->instruction) {
|
||||||
|
case CSYNC_INSTRUCTION_NONE:
|
||||||
|
// No need to do anything.
|
||||||
|
return re;
|
||||||
|
break;
|
||||||
|
case CSYNC_INSTRUCTION_RENAME:
|
||||||
|
dir = !remote ? SyncFileItem::Down : SyncFileItem::Up;
|
||||||
|
item._renameTarget = QString::fromUtf8( file->rename_path );
|
||||||
|
break;
|
||||||
|
case CSYNC_INSTRUCTION_REMOVE:
|
||||||
|
dir = !remote ? SyncFileItem::Down : SyncFileItem::Up;
|
||||||
|
break;
|
||||||
|
case CSYNC_INSTRUCTION_CONFLICT:
|
||||||
|
case CSYNC_INSTRUCTION_IGNORE:
|
||||||
|
case CSYNC_INSTRUCTION_ERROR:
|
||||||
|
dir = SyncFileItem::None;
|
||||||
|
break;
|
||||||
|
case CSYNC_INSTRUCTION_EVAL:
|
||||||
|
case CSYNC_INSTRUCTION_NEW:
|
||||||
|
case CSYNC_INSTRUCTION_SYNC:
|
||||||
|
case CSYNC_INSTRUCTION_STAT_ERROR:
|
||||||
|
case CSYNC_INSTRUCTION_DELETED:
|
||||||
|
case CSYNC_INSTRUCTION_UPDATED:
|
||||||
|
default:
|
||||||
|
dir = remote ? SyncFileItem::Down : SyncFileItem::Up;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
item._dir = dir;
|
||||||
|
_mutex.lock();
|
||||||
|
_syncedItems.append(item);
|
||||||
|
_mutex.unlock();
|
||||||
|
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSyncThread::treewalkError(TREE_WALK_FILE* file)
|
||||||
|
{
|
||||||
|
SyncFileItem item;
|
||||||
|
item._file= QString::fromUtf8(file->path);
|
||||||
|
int indx = _syncedItems.indexOf(item);
|
||||||
|
|
||||||
|
if ( indx == -1 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if( file &&
|
||||||
|
file->instruction == CSYNC_INSTRUCTION_STAT_ERROR ||
|
||||||
|
file->instruction == CSYNC_INSTRUCTION_ERROR ) {
|
||||||
|
_mutex.lock();
|
||||||
|
_syncedItems[indx]._instruction = file->instruction;
|
||||||
|
_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CSyncRunScopeHelper {
|
||||||
|
CSyncRunScopeHelper(CSYNC *_ctx, CSyncThread *_parent)
|
||||||
|
: ctx(_ctx), parent(_parent)
|
||||||
|
{
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
~CSyncRunScopeHelper() {
|
||||||
|
csync_destroy(ctx);
|
||||||
|
|
||||||
|
qDebug() << "CSync run took " << t.elapsed() << " Milliseconds";
|
||||||
|
emit(parent->finished());
|
||||||
|
}
|
||||||
|
CSYNC *ctx;
|
||||||
|
QTime t;
|
||||||
|
CSyncThread *parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CSyncThread::handleSyncError(CSYNC *ctx, const char *state) {
|
||||||
|
CSYNC_ERROR_CODE err = csync_get_error( ctx );
|
||||||
|
const char *errMsg = csync_get_error_string( ctx );
|
||||||
|
QString errStr = csyncErrorToString(err, errMsg);
|
||||||
|
qDebug() << " #### ERROR during "<< state << ": " << errStr;
|
||||||
|
switch (err) {
|
||||||
|
case CSYNC_ERR_SERVICE_UNAVAILABLE:
|
||||||
|
case CSYNC_ERR_CONNECT:
|
||||||
|
emit csyncUnavailable();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
emit csyncError(errStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSyncThread::startSync()
|
void CSyncThread::startSync()
|
||||||
{
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "Sync started";
|
||||||
|
|
||||||
|
static int syncsRunning = 0;
|
||||||
|
syncsRunning++;
|
||||||
|
assert(syncsRunning == 1);
|
||||||
|
|
||||||
qDebug() << "starting to sync " << qApp->thread() << QThread::currentThread();
|
qDebug() << "starting to sync " << qApp->thread() << QThread::currentThread();
|
||||||
CSYNC *csync;
|
CSYNC *csync;
|
||||||
QTime walkTime;
|
int proxyPort = _proxy.port();
|
||||||
|
|
||||||
ProxyInfo proxyInfo;
|
|
||||||
|
|
||||||
emit(started());
|
|
||||||
|
|
||||||
_mutex.lock();
|
_mutex.lock();
|
||||||
|
_syncedItems.clear();
|
||||||
proxyInfo.proxyType = proxyTypeToCStr( _proxy.type() );
|
_needsUpdate = false;
|
||||||
proxyInfo.proxyHost = qstrdup( _proxy.hostName().toAscii().constData() );
|
_mutex.unlock();
|
||||||
proxyInfo.proxyPort = qstrdup( QByteArray::number( _proxy.port() ).constData() );
|
|
||||||
proxyInfo.proxyUser = qstrdup( _proxy.user().toAscii().constData() );
|
|
||||||
proxyInfo.proxyPwd = qstrdup( _proxy.password().toAscii().constData() );
|
|
||||||
|
|
||||||
if( csync_create(&csync,
|
if( csync_create(&csync,
|
||||||
_source.toUtf8().data(),
|
_source.toUtf8().data(),
|
||||||
_target.toUtf8().data()) < 0 ) {
|
_target.toUtf8().data()) < 0 ) {
|
||||||
emit csyncError( tr("CSync create failed.") );
|
emit csyncError( tr("CSync create failed.") );
|
||||||
}
|
}
|
||||||
_csyncConfigDir = QString::fromUtf8( csync_get_config_dir( csync ));
|
|
||||||
_mutex.unlock();
|
|
||||||
|
|
||||||
qDebug() << "## CSync Thread local only: " << _localCheckOnly;
|
|
||||||
csync_set_auth_callback( csync, getauth );
|
|
||||||
csync_enable_conflictcopys(csync);
|
|
||||||
|
|
||||||
|
|
||||||
MirallConfigFile cfg;
|
MirallConfigFile cfg;
|
||||||
QString excludeList = cfg.excludeFile();
|
|
||||||
|
|
||||||
if( !excludeList.isEmpty() ) {
|
|
||||||
qDebug() << "==== added CSync exclude List: " << excludeList.toAscii();
|
|
||||||
csync_add_exclude_list( csync, excludeList.toAscii() );
|
|
||||||
}
|
|
||||||
|
|
||||||
csync_set_config_dir( csync, cfg.configPath().toUtf8() );
|
csync_set_config_dir( csync, cfg.configPath().toUtf8() );
|
||||||
|
|
||||||
QTime t;
|
|
||||||
t.start();
|
|
||||||
|
|
||||||
_mutex.lock();
|
_mutex.lock();
|
||||||
if( _localCheckOnly ) {
|
_csyncConfigDir = cfg.configPath();
|
||||||
csync_set_local_only( csync, true );
|
|
||||||
}
|
|
||||||
csync_set_userdata(csync, (void*) &proxyInfo);
|
|
||||||
_mutex.unlock();
|
_mutex.unlock();
|
||||||
|
|
||||||
if( csync_init(csync) < 0 ) {
|
csync_enable_conflictcopys(csync);
|
||||||
CSYNC_ERROR_CODE err = csync_get_error( csync );
|
QString excludeList = cfg.excludeFile();
|
||||||
QString errStr;
|
if( !excludeList.isEmpty() ) {
|
||||||
|
qDebug() << "==== added CSync exclude List: " << excludeList.toUtf8();
|
||||||
switch( err ) {
|
csync_add_exclude_list( csync, excludeList.toUtf8() );
|
||||||
case CSYNC_ERR_LOCK:
|
|
||||||
errStr = tr("CSync failed to create a lock file.");
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_STATEDB_LOAD:
|
|
||||||
errStr = tr("CSync failed to load the state db.");
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_TIMESKEW:
|
|
||||||
errStr = tr("The system time on this client is different than the system time on the server. "
|
|
||||||
"Please use a time synchronization service (NTP) on the server and client machines "
|
|
||||||
"so that the times remain the same.");
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_FILESYSTEM:
|
|
||||||
errStr = tr("CSync could not detect the filesystem type.");
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_TREE:
|
|
||||||
errStr = tr("CSync got an error while processing internal trees.");
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_ACCESS_FAILED:
|
|
||||||
errStr = tr("<p>The target directory %1 does not exist.</p><p>Please check the sync setup.</p>").arg(_target);
|
|
||||||
// this is critical. The database has to be removed.
|
|
||||||
emitStateDb(csync); // to make the name of the csync db known.
|
|
||||||
emit wipeDb();
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_MODULE:
|
|
||||||
errStr = tr("<p>The %1 plugin for csync could not be loaded.<br/>Please verify the installation!</p>").arg(Theme::instance()->appName());
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_LOCAL_CREATE:
|
|
||||||
case CSYNC_ERR_LOCAL_STAT:
|
|
||||||
errStr = tr("The local filesystem can not be written. Please check permissions.");
|
|
||||||
break;
|
|
||||||
case CSYNC_ERR_REMOTE_CREATE:
|
|
||||||
case CSYNC_ERR_REMOTE_STAT:
|
|
||||||
errStr = tr("A remote file can not be written. Please check the remote access.");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errStr = tr("An internal error number %1 happend.").arg( (int) err );
|
|
||||||
}
|
|
||||||
qDebug() << " #### ERROR String emitted: " << errStr;
|
|
||||||
emit csyncError(errStr);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emitStateDb(csync);
|
// cleans up behind us and emits finished() to ease error handling
|
||||||
|
CSyncRunScopeHelper helper(csync, this);
|
||||||
qDebug() << "#### Update start #################################################### >>";
|
|
||||||
if( csync_update(csync) < 0 ) {
|
|
||||||
CSYNC_ERROR_CODE err = csync_get_error( csync );
|
|
||||||
QString errStr;
|
|
||||||
|
|
||||||
switch( err ) {
|
|
||||||
case CSYNC_ERR_PROXY:
|
|
||||||
errStr = tr("CSync failed to reach the host. Either host or proxy settings are not valid.");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errStr = tr("CSync Update failed.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
emit csyncError( errStr );
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
qDebug() << "<<#### Update end ###########################################################";
|
|
||||||
|
|
||||||
csync_set_userdata(csync, this);
|
csync_set_userdata(csync, this);
|
||||||
|
|
||||||
walkTime.start();
|
csync_set_log_callback( csync, csyncLogCatcher );
|
||||||
if( csync_walk_local_tree(csync, &treewalk, 0) < 0 ) {
|
csync_set_auth_callback( csync, getauth );
|
||||||
qDebug() << "Error in treewalk.";
|
csync_set_progress_callback( csync, progress );
|
||||||
if( _walkStats.errorType == WALK_ERROR_WALK ) {
|
|
||||||
emit csyncError(tr("CSync encountered an error while examining the file system.\n"
|
if( csync_init(csync) < 0 ) {
|
||||||
"Syncing is not possible."));
|
handleSyncError(csync, "csync_init");
|
||||||
} else if( _walkStats.errorType == WALK_ERROR_INSTRUCTIONS ) {
|
return;
|
||||||
emit csyncError(tr("CSync update generated a strange instruction.\n"
|
|
||||||
"Please write a bug report."));
|
|
||||||
}
|
|
||||||
emit csyncError(tr("Local filesystem problems. Better disable Syncing and check."));
|
|
||||||
goto cleanup;
|
|
||||||
} else {
|
|
||||||
// only warn, do not stop the sync process.
|
|
||||||
if( _walkStats.errorType == WALK_ERROR_DIR_PERMS ) {
|
|
||||||
emit csyncError(tr("The local filesystem has %1 write protected directories."
|
|
||||||
"That can hinder successful syncing.<p/>"
|
|
||||||
"Please make sure that all local directories are writeable.").arg(_walkStats.dirPermErrors));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit the treewalk results.
|
// set module properties, mainly the proxy information.
|
||||||
emit treeWalkResult(_syncedItems, _walkStats);
|
// do not use QLatin1String here because that has to be real const char* for C.
|
||||||
|
csync_set_log_verbosity(csync, 11);
|
||||||
|
csync_set_module_property(csync, "csync_context", csync);
|
||||||
|
csync_set_module_property(csync, "proxy_type", (char*) proxyTypeToCStr(_proxy.type()) );
|
||||||
|
csync_set_module_property(csync, "proxy_host", _proxy.hostName().toUtf8().data() );
|
||||||
|
csync_set_module_property(csync, "proxy_port", &proxyPort );
|
||||||
|
csync_set_module_property(csync, "proxy_user", _proxy.user().toUtf8().data() );
|
||||||
|
csync_set_module_property(csync, "proxy_pwd" , _proxy.password().toUtf8().data() );
|
||||||
|
|
||||||
_mutex.lock();
|
qDebug() << "#### Update start #################################################### >>";
|
||||||
if( _localCheckOnly ) {
|
if( csync_update(csync) < 0 ) {
|
||||||
_mutex.unlock();
|
handleSyncError(csync, "csync_update");
|
||||||
qDebug() << " ..... Local only walk finished: " << walkTime.elapsed();
|
return;
|
||||||
// we have to go out here as its local check only.
|
}
|
||||||
goto cleanup;
|
qDebug() << "<<#### Update end ###########################################################";
|
||||||
} else {
|
|
||||||
_mutex.unlock();
|
|
||||||
// check if we can write all over.
|
|
||||||
|
|
||||||
if( csync_reconcile(csync) < 0 ) {
|
if( csync_reconcile(csync) < 0 ) {
|
||||||
emit csyncError(tr("CSync reconcile failed."));
|
handleSyncError(csync, "cysnc_reconcile");
|
||||||
goto cleanup;
|
return;
|
||||||
}
|
}
|
||||||
if( csync_propagate(csync) < 0 ) {
|
|
||||||
emit csyncError(tr("File exchange with ownCloud failed. Sync was stopped."));
|
bool walkOk = true;
|
||||||
goto cleanup;
|
if( csync_walk_local_tree(csync, &treewalkLocal, 0) < 0 ) {
|
||||||
|
qDebug() << "Error in local treewalk.";
|
||||||
|
walkOk = false;
|
||||||
|
}
|
||||||
|
if( walkOk && csync_walk_remote_tree(csync, &treewalkRemote, 0) < 0 ) {
|
||||||
|
qDebug() << "Error in remote treewalk.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_needsUpdate)
|
||||||
|
emit(started());
|
||||||
|
|
||||||
|
if( csync_propagate(csync) < 0 ) {
|
||||||
|
handleSyncError(csync, "cysnc_reconcile");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( walkOk ) {
|
||||||
|
if( csync_walk_local_tree(csync, &walkFinalize, 0) < 0 ||
|
||||||
|
csync_walk_remote_tree( csync, &walkFinalize, 0 ) < 0 ) {
|
||||||
|
qDebug() << "Error in finalize treewalk.";
|
||||||
|
} else {
|
||||||
|
// emit the treewalk results.
|
||||||
|
emit treeWalkResult(_syncedItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cleanup:
|
syncsRunning--;
|
||||||
csync_destroy(csync);
|
qDebug() << Q_FUNC_INFO << "Sync finished";
|
||||||
|
|
||||||
if( proxyInfo.proxyType ) delete[] proxyInfo.proxyType;
|
|
||||||
if( proxyInfo.proxyHost ) delete[] proxyInfo.proxyHost;
|
|
||||||
if( proxyInfo.proxyPort ) delete[] proxyInfo.proxyPort;
|
|
||||||
if( proxyInfo.proxyUser ) delete[] proxyInfo.proxyUser;
|
|
||||||
if( proxyInfo.proxyPwd ) delete[] proxyInfo.proxyPwd ;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Attention: do not delete the wStat memory here. it is deleted in the
|
|
||||||
* slot catching the signel treeWalkResult because this thread can faster
|
|
||||||
* die than the slot has read out the data.
|
|
||||||
*/
|
|
||||||
qDebug() << "CSync run took " << t.elapsed() << " Milliseconds";
|
|
||||||
emit(finished());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSyncThread::emitStateDb( CSYNC *csync )
|
|
||||||
{
|
|
||||||
// After csync_init the statedb file name can be emitted
|
|
||||||
const char *statedb = csync_get_statedb_file( csync );
|
|
||||||
if( statedb ) {
|
|
||||||
QString stateDbFile = QString::fromUtf8(statedb);
|
|
||||||
free((void*)statedb);
|
|
||||||
|
|
||||||
emit csyncStateDbFile( stateDbFile );
|
|
||||||
} else {
|
|
||||||
qDebug() << "WRN: Unable to get csync statedb file name";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSyncThread::setConnectionDetails( const QString &user, const QString &passwd, const QNetworkProxy &proxy )
|
void CSyncThread::setConnectionDetails( const QString &user, const QString &passwd, const QNetworkProxy &proxy )
|
||||||
@@ -404,27 +451,69 @@ int CSyncThread::getauth(const char *prompt,
|
|||||||
{
|
{
|
||||||
int re = 0;
|
int re = 0;
|
||||||
|
|
||||||
QString qPrompt = QString::fromLocal8Bit( prompt ).trimmed();
|
QString qPrompt = QString::fromLatin1( prompt ).trimmed();
|
||||||
_mutex.lock();
|
|
||||||
|
|
||||||
if( qPrompt == QLatin1String("Enter your username:") ) {
|
if( qPrompt == QLatin1String("Enter your username:") ) {
|
||||||
// qDebug() << "OOO Username requested!";
|
// qDebug() << "OOO Username requested!";
|
||||||
|
QMutexLocker locker( &_mutex );
|
||||||
qstrncpy( buf, _user.toUtf8().constData(), len );
|
qstrncpy( buf, _user.toUtf8().constData(), len );
|
||||||
} else if( qPrompt == QLatin1String("Enter your password:") ) {
|
} else if( qPrompt == QLatin1String("Enter your password:") ) {
|
||||||
|
QMutexLocker locker( &_mutex );
|
||||||
// qDebug() << "OOO Password requested!";
|
// qDebug() << "OOO Password requested!";
|
||||||
qstrncpy( buf, _passwd.toUtf8().constData(), len );
|
qstrncpy( buf, _passwd.toUtf8().constData(), len );
|
||||||
} else {
|
} else {
|
||||||
if( qPrompt.startsWith( QLatin1String("There are problems with the SSL certificate:"))) {
|
if( qPrompt.startsWith( QLatin1String("There are problems with the SSL certificate:"))) {
|
||||||
// SSL is requested. If the program came here, the SSL check was done by mirall
|
// SSL is requested. If the program came here, the SSL check was done by mirall
|
||||||
// the answer is simply yes here.
|
// It needs to be checked if the chain is still equal to the one which
|
||||||
qstrcpy( buf, "yes" );
|
// was verified by the user.
|
||||||
|
QRegExp regexp("fingerprint: ([\\w\\d:]+)");
|
||||||
|
bool certOk = false;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// This is the set of certificates which QNAM accepted, so we should accept
|
||||||
|
// them as well
|
||||||
|
QList<QSslCertificate> certs = ownCloudInfo::instance()->certificateChain();
|
||||||
|
|
||||||
|
while (!certOk && (pos = regexp.indexIn(qPrompt, 1+pos)) != -1) {
|
||||||
|
QString neon_fingerprint = regexp.cap(1);
|
||||||
|
|
||||||
|
foreach( const QSslCertificate& c, certs ) {
|
||||||
|
QString verified_shasum = Utility::formatFingerprint(c.digest(QCryptographicHash::Sha1).toHex());
|
||||||
|
qDebug() << "SSL Fingerprint from neon: " << neon_fingerprint << " compared to verified: " << verified_shasum;
|
||||||
|
if( verified_shasum == neon_fingerprint ) {
|
||||||
|
certOk = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// certOk = false; DEBUG setting, keep disabled!
|
||||||
|
if( !certOk ) { // Problem!
|
||||||
|
qstrcpy( buf, "no" );
|
||||||
|
re = -1;
|
||||||
|
} else {
|
||||||
|
qstrcpy( buf, "yes" ); // Certificate is fine!
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Unknown prompt: <" << prompt << ">";
|
qDebug() << "Unknown prompt: <" << prompt << ">";
|
||||||
re = -1;
|
re = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_mutex.unlock();
|
|
||||||
return re;
|
return re;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CSyncThread::progress(const char *remote_url, enum csync_notify_type_e kind,
|
||||||
|
long long o1, long long o2, void *userdata)
|
||||||
|
{
|
||||||
|
(void) o1; (void) o2;
|
||||||
|
if (kind == CSYNC_NOTIFY_FINISHED_DOWNLOAD) {
|
||||||
|
QString path = QUrl::fromEncoded(remote_url).toString();
|
||||||
|
CSyncThread *thread = static_cast<CSyncThread*>(userdata);
|
||||||
|
thread->fileReceived(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
#ifndef CSYNCTHREAD_H
|
|
||||||
#define CSYNCTHREAD_H
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
|
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
|
||||||
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
||||||
@@ -16,6 +13,9 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef CSYNCTHREAD_H
|
||||||
|
#define CSYNCTHREAD_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
@@ -25,61 +25,34 @@
|
|||||||
|
|
||||||
#include <csync.h>
|
#include <csync.h>
|
||||||
|
|
||||||
|
#include "mirall/syncfileitem.h"
|
||||||
|
|
||||||
class QProcess;
|
class QProcess;
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
enum walkErrorTypes {
|
|
||||||
WALK_ERROR_NONE = 0,
|
|
||||||
WALK_ERROR_WALK,
|
|
||||||
WALK_ERROR_INSTRUCTIONS,
|
|
||||||
WALK_ERROR_DIR_PERMS
|
|
||||||
};
|
|
||||||
|
|
||||||
struct walkStats_s {
|
|
||||||
walkStats_s();
|
|
||||||
|
|
||||||
int errorType;
|
|
||||||
|
|
||||||
ulong eval;
|
|
||||||
ulong removed;
|
|
||||||
ulong renamed;
|
|
||||||
ulong newFiles;
|
|
||||||
ulong conflicts;
|
|
||||||
ulong ignores;
|
|
||||||
ulong sync;
|
|
||||||
ulong error;
|
|
||||||
|
|
||||||
ulong dirPermErrors;
|
|
||||||
|
|
||||||
ulong seenFiles;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef walkStats_s WalkStats;
|
|
||||||
|
|
||||||
struct syncFileItem_s {
|
|
||||||
QString file;
|
|
||||||
csync_instructions_e instruction;
|
|
||||||
};
|
|
||||||
typedef syncFileItem_s SyncFileItem;
|
|
||||||
|
|
||||||
typedef QVector<SyncFileItem> SyncFileItemVector;
|
|
||||||
|
|
||||||
class CSyncThread : public QObject
|
class CSyncThread : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
CSyncThread(const QString &source, const QString &target, bool = false);
|
CSyncThread(const QString &source, const QString &target);
|
||||||
~CSyncThread();
|
~CSyncThread();
|
||||||
|
|
||||||
static void setConnectionDetails( const QString&, const QString&, const QNetworkProxy& );
|
static void setConnectionDetails( const QString&, const QString&, const QNetworkProxy& );
|
||||||
static QString csyncConfigDir();
|
static QString csyncConfigDir();
|
||||||
|
|
||||||
|
const char* proxyTypeToCStr(QNetworkProxy::ProxyType);
|
||||||
|
QString csyncErrorToString( CSYNC_ERROR_CODE, const char * );
|
||||||
|
|
||||||
Q_INVOKABLE void startSync();
|
Q_INVOKABLE void startSync();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void treeWalkResult(const SyncFileItemVector&, const WalkStats&);
|
void fileReceived( const QString& );
|
||||||
|
void fileRemoved( const QString& );
|
||||||
void csyncError( const QString& );
|
void csyncError( const QString& );
|
||||||
|
void csyncWarning( const QString& );
|
||||||
|
void csyncUnavailable();
|
||||||
|
void treeWalkResult(const SyncFileItemVector&);
|
||||||
|
|
||||||
void csyncStateDbFile( const QString& );
|
void csyncStateDbFile( const QString& );
|
||||||
void wipeDb();
|
void wipeDb();
|
||||||
@@ -88,10 +61,18 @@ signals:
|
|||||||
void started();
|
void started();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int treewalk( TREE_WALK_FILE* file, void *data );
|
void handleSyncError(CSYNC *ctx, const char *state);
|
||||||
int recordStats( TREE_WALK_FILE* file);
|
static void progress(const char *remote_url,
|
||||||
void emitStateDb( CSYNC *csync );
|
enum csync_notify_type_e kind,
|
||||||
int treewalkFile( TREE_WALK_FILE* );
|
long long o1, long long o2,
|
||||||
|
void *userdata);
|
||||||
|
|
||||||
|
static int treewalkLocal( TREE_WALK_FILE*, void *);
|
||||||
|
static int treewalkRemote( TREE_WALK_FILE*, void *);
|
||||||
|
int treewalkFile( TREE_WALK_FILE*, bool );
|
||||||
|
int treewalkError( TREE_WALK_FILE* );
|
||||||
|
|
||||||
|
static int walkFinalize(TREE_WALK_FILE*, void* );
|
||||||
|
|
||||||
static int getauth(const char *prompt,
|
static int getauth(const char *prompt,
|
||||||
char *buf,
|
char *buf,
|
||||||
@@ -108,12 +89,13 @@ private:
|
|||||||
|
|
||||||
static QString _csyncConfigDir;
|
static QString _csyncConfigDir;
|
||||||
|
|
||||||
|
SyncFileItemVector _syncedItems;
|
||||||
|
|
||||||
QString _source;
|
QString _source;
|
||||||
QString _target;
|
QString _target;
|
||||||
bool _localCheckOnly;
|
bool _needsUpdate;
|
||||||
|
|
||||||
QVector <SyncFileItem> _syncedItems;
|
friend class CSyncRunScopeHelper;
|
||||||
WalkStats _walkStats;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
295
src/mirall/fileitemdialog.cpp
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* 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/theme.h"
|
||||||
|
#include "mirall/syncresult.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(Theme *theme, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
_theme(theme)
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
connect(_dialogButtonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()),
|
||||||
|
this, SLOT(accept()));
|
||||||
|
|
||||||
|
QStringList header;
|
||||||
|
header << tr("Files");
|
||||||
|
QString firstColString = tr("File Count");
|
||||||
|
header << firstColString;
|
||||||
|
_treeWidget->setHeaderLabels( header );
|
||||||
|
|
||||||
|
_treeWidget->setColumnWidth(0, 480);
|
||||||
|
_timer.setInterval(1000);
|
||||||
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotSetFolderMessage()));
|
||||||
|
|
||||||
|
QPushButton *copyBtn = _dialogButtonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole);
|
||||||
|
connect(copyBtn, SIGNAL(clicked()), SLOT(copyToClipboard()));
|
||||||
|
|
||||||
|
setWindowTitle(tr("Sync Protocol"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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::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() ) {
|
||||||
|
_errorLabel->setVisible(true);
|
||||||
|
_errorLabel->setTextFormat(Qt::RichText);
|
||||||
|
QString errStr;
|
||||||
|
foreach( QString err, result.errorStrings() ) {
|
||||||
|
errStr.append(QString("<p>%1</p>").arg(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
_errorLabel->setText(errStr);
|
||||||
|
} else {
|
||||||
|
_errorLabel->setText(QString::null);
|
||||||
|
_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);
|
||||||
|
|
||||||
|
_timelabel->setText(tr("%1 (finished %2 sec. ago)").arg(_folderMessage).arg(secs));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileItemDialog::copyToClipboard()
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
QTextStream ts(&text);
|
||||||
|
|
||||||
|
int topLevelItems = _treeWidget->topLevelItemCount();
|
||||||
|
for (int i = 0; i < topLevelItems; i++) {
|
||||||
|
QTreeWidgetItem *item = _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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileItemDialog::accept()
|
||||||
|
{
|
||||||
|
_timer.stop();
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileItemDialog::setSyncFileItems( const SyncFileItemVector& list )
|
||||||
|
{
|
||||||
|
_treeWidget->clear();
|
||||||
|
QStringList strings;
|
||||||
|
QFont headerFont;
|
||||||
|
headerFont.setWeight(QFont::Bold);
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
strings.append(tr("Synced Files"));
|
||||||
|
_syncedFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_SUCCESS );
|
||||||
|
_syncedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||||
|
_treeWidget->addTopLevelItem(_syncedFileItem);
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
strings.append(tr("New Files"));
|
||||||
|
_newFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_NEW );
|
||||||
|
_newFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||||
|
_treeWidget->addTopLevelItem(_newFileItem);
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
strings.append(tr("Deleted Files"));
|
||||||
|
_deletedFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_DELETED );
|
||||||
|
_deletedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||||
|
_treeWidget->addTopLevelItem(_deletedFileItem);
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
strings.append(tr("Renamed Files"));
|
||||||
|
_renamedFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_RENAME);
|
||||||
|
_renamedFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||||
|
_treeWidget->addTopLevelItem(_renamedFileItem);
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
strings.append(tr("Ignored Files"));
|
||||||
|
_ignoredFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_IGNORE);
|
||||||
|
_ignoredFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||||
|
_treeWidget->addTopLevelItem(_renamedFileItem);
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
strings.append(tr("Errors"));
|
||||||
|
_errorFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_ERROR );
|
||||||
|
_errorFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||||
|
_treeWidget->addTopLevelItem(_errorFileItem);
|
||||||
|
|
||||||
|
strings.clear();
|
||||||
|
strings.append(tr("Conflicts"));
|
||||||
|
_conflictFileItem = new QTreeWidgetItem( _treeWidget, strings, TYPE_CONFLICT);
|
||||||
|
_conflictFileItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
|
||||||
|
_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("Up");
|
||||||
|
if( item._dir == SyncFileItem::Down ) dir = tr("Down");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
65
src/mirall/fileitemdialog.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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 Theme;
|
||||||
|
class SyncResult;
|
||||||
|
|
||||||
|
|
||||||
|
class FileItemDialog : public QDialog, public Ui::_fileItemDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FileItemDialog(Theme*, QWidget *parent = 0);
|
||||||
|
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;
|
||||||
|
|
||||||
|
Theme *_theme;
|
||||||
|
QString _folderMessage;
|
||||||
|
QDateTime _lastSyncTime;
|
||||||
|
QTimer _timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // FILEITEMDIALOG_H
|
||||||
87
src/mirall/fileitemdialog.ui
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>_fileItemDialog</class>
|
||||||
|
<widget class="QWidget" name="_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>
|
||||||
@@ -25,7 +25,7 @@ QStringList FileUtils::subFoldersList(QString folder,
|
|||||||
SubFolderListOptions options)
|
SubFolderListOptions options)
|
||||||
{
|
{
|
||||||
QDir dir(folder);
|
QDir dir(folder);
|
||||||
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
|
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
|
||||||
|
|
||||||
QFileInfoList list = dir.entryInfoList();
|
QFileInfoList list = dir.entryInfoList();
|
||||||
QStringList dirList;
|
QStringList dirList;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include "mirall/folder.h"
|
#include "mirall/folder.h"
|
||||||
#include "mirall/folderwatcher.h"
|
#include "mirall/folderwatcher.h"
|
||||||
@@ -48,7 +49,6 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP
|
|||||||
QObject::connect(_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout()));
|
QObject::connect(_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout()));
|
||||||
_pollTimer->start();
|
_pollTimer->start();
|
||||||
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
_watcher = new Mirall::FolderWatcher(path, this);
|
_watcher = new Mirall::FolderWatcher(path, this);
|
||||||
|
|
||||||
MirallConfigFile cfg;
|
MirallConfigFile cfg;
|
||||||
@@ -57,7 +57,6 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP
|
|||||||
|
|
||||||
QObject::connect(_watcher, SIGNAL(folderChanged(const QStringList &)),
|
QObject::connect(_watcher, SIGNAL(folderChanged(const QStringList &)),
|
||||||
SLOT(slotChanged(const QStringList &)));
|
SLOT(slotChanged(const QStringList &)));
|
||||||
#endif
|
|
||||||
QObject::connect(this, SIGNAL(syncStarted()),
|
QObject::connect(this, SIGNAL(syncStarted()),
|
||||||
SLOT(slotSyncStarted()));
|
SLOT(slotSyncStarted()));
|
||||||
QObject::connect(this, SIGNAL(syncFinished(const SyncResult &)),
|
QObject::connect(this, SIGNAL(syncFinished(const SyncResult &)),
|
||||||
@@ -153,9 +152,7 @@ bool Folder::syncEnabled() const
|
|||||||
void Folder::setSyncEnabled( bool doit )
|
void Folder::setSyncEnabled( bool doit )
|
||||||
{
|
{
|
||||||
_enabled = doit;
|
_enabled = doit;
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
_watcher->setEventsEnabled( doit );
|
_watcher->setEventsEnabled( doit );
|
||||||
#endif
|
|
||||||
if( doit && ! _pollTimer->isActive() ) {
|
if( doit && ! _pollTimer->isActive() ) {
|
||||||
_pollTimer->start();
|
_pollTimer->start();
|
||||||
}
|
}
|
||||||
@@ -196,6 +193,11 @@ int Folder::pollInterval() const
|
|||||||
return _pollTimer->interval();
|
return _pollTimer->interval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Folder::setSyncState(SyncResult::Status state)
|
||||||
|
{
|
||||||
|
_syncResult.setStatus(state);
|
||||||
|
}
|
||||||
|
|
||||||
void Folder::setPollInterval(int milliseconds)
|
void Folder::setPollInterval(int milliseconds)
|
||||||
{
|
{
|
||||||
_pollTimer->setInterval( milliseconds );
|
_pollTimer->setInterval( milliseconds );
|
||||||
@@ -217,12 +219,10 @@ void Folder::incrementErrorCount()
|
|||||||
// of the watcher is doubled.
|
// of the watcher is doubled.
|
||||||
_errorCount++;
|
_errorCount++;
|
||||||
if( _errorCount > 1 ) {
|
if( _errorCount > 1 ) {
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
int interval = _watcher->eventInterval();
|
int interval = _watcher->eventInterval();
|
||||||
int newInt = 2*interval;
|
int newInt = 2*interval;
|
||||||
qDebug() << "Set new watcher interval to " << newInt;
|
qDebug() << "Set new watcher interval to " << newInt;
|
||||||
_watcher->setEventInterval( newInt );
|
_watcher->setEventInterval( newInt );
|
||||||
#endif
|
|
||||||
_errorCount = 0;
|
_errorCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,18 +253,10 @@ void Folder::evaluateSync(const QStringList &pathList)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Folder::startSync( const QStringList &pathList )
|
|
||||||
{
|
|
||||||
_syncResult.setStatus( SyncResult::SyncRunning );
|
|
||||||
emit syncStateChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Folder::slotPollTimerTimeout()
|
void Folder::slotPollTimerTimeout()
|
||||||
{
|
{
|
||||||
qDebug() << "* Polling" << alias() << "for changes. Ignoring all pending events until now";
|
qDebug() << "* Polling" << alias() << "for changes. Ignoring all pending events until now";
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
_watcher->clearPendingEvents();
|
_watcher->clearPendingEvents();
|
||||||
#endif
|
|
||||||
evaluateSync(QStringList());
|
evaluateSync(QStringList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,16 +275,12 @@ void Folder::slotChanged(const QStringList &pathList)
|
|||||||
void Folder::slotSyncStarted()
|
void Folder::slotSyncStarted()
|
||||||
{
|
{
|
||||||
// disable events until syncing is done
|
// disable events until syncing is done
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
_watcher->setEventsEnabled(false);
|
_watcher->setEventsEnabled(false);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Folder::slotSyncFinished(const SyncResult &result)
|
void Folder::slotSyncFinished(const SyncResult &result)
|
||||||
{
|
{
|
||||||
#ifdef USE_INOTIFY
|
_watcher->setEventsEnabledDelayed(2000);
|
||||||
_watcher->setEventsEnabled(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
qDebug() << "OO folder slotSyncFinished: result: " << int(result.status()) << " local: " << result.localRunOnly();
|
qDebug() << "OO folder slotSyncFinished: result: " << int(result.status()) << " local: " << result.localRunOnly();
|
||||||
emit syncStateChange();
|
emit syncStateChange();
|
||||||
|
|||||||
@@ -15,12 +15,12 @@
|
|||||||
#ifndef MIRALL_FOLDER_H
|
#ifndef MIRALL_FOLDER_H
|
||||||
#define MIRALL_FOLDER_H
|
#define MIRALL_FOLDER_H
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040700
|
#if QT_VERSION >= 0x040700
|
||||||
#include <QNetworkConfigurationManager>
|
#include <QNetworkConfigurationManager>
|
||||||
@@ -29,15 +29,12 @@
|
|||||||
#include "mirall/syncresult.h"
|
#include "mirall/syncresult.h"
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
class QTimer;
|
|
||||||
class QIcon;
|
class QIcon;
|
||||||
class QFileSystemWatcher;
|
class QFileSystemWatcher;
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
class FolderWatcher;
|
class FolderWatcher;
|
||||||
#endif
|
|
||||||
|
|
||||||
class Folder : public QObject
|
class Folder : public QObject
|
||||||
{
|
{
|
||||||
@@ -48,6 +45,7 @@ public:
|
|||||||
virtual ~Folder();
|
virtual ~Folder();
|
||||||
|
|
||||||
typedef QHash<QString, Folder*> Map;
|
typedef QHash<QString, Folder*> Map;
|
||||||
|
typedef QHashIterator<QString, Folder*> MapIterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* alias or nickname
|
* alias or nickname
|
||||||
@@ -151,6 +149,12 @@ public:
|
|||||||
QIcon icon( int size ) const;
|
QIcon icon( int size ) const;
|
||||||
QTimer *_pollTimer;
|
QTimer *_pollTimer;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void syncStateChange();
|
||||||
|
void syncStarted();
|
||||||
|
void syncFinished(const SyncResult &result);
|
||||||
|
void scheduleToSync( const QString& );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void slotSyncFinished(const SyncResult &);
|
void slotSyncFinished(const SyncResult &);
|
||||||
|
|
||||||
@@ -164,32 +168,40 @@ public slots:
|
|||||||
*/
|
*/
|
||||||
virtual void slotTerminateSync() = 0;
|
virtual void slotTerminateSync() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets minimum amounts of milliseconds that will separate
|
||||||
|
* poll intervals
|
||||||
|
*/
|
||||||
|
void setPollInterval( int );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* The minimum amounts of seconds to wait before
|
* The minimum amounts of seconds to wait before
|
||||||
* doing a full sync to see if the remote changed
|
* doing a full sync to see if the remote changed
|
||||||
*/
|
*/
|
||||||
int pollInterval() const;
|
int pollInterval() const;
|
||||||
|
void setSyncState(SyncResult::Status state);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets minimum amounts of milliseconds that will separate
|
|
||||||
* poll intervals
|
|
||||||
*/
|
|
||||||
void setPollInterval( int );
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void syncStateChange();
|
|
||||||
void syncStarted();
|
|
||||||
void syncFinished(const SyncResult &result);
|
|
||||||
void scheduleToSync( const QString& );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
FolderWatcher *_watcher;
|
FolderWatcher *_watcher;
|
||||||
#endif
|
|
||||||
int _errorCount;
|
int _errorCount;
|
||||||
SyncResult _syncResult;
|
SyncResult _syncResult;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
|
||||||
|
void slotOnlineChanged(bool online);
|
||||||
|
|
||||||
|
void slotPollTimerTimeout();
|
||||||
|
|
||||||
|
/* called when the watcher detect a list of changed
|
||||||
|
paths */
|
||||||
|
|
||||||
|
void slotSyncStarted();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered by a file system watcher on the local sync dir
|
||||||
|
*/
|
||||||
|
virtual void slotLocalPathChanged( const QString& );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -216,22 +228,6 @@ private:
|
|||||||
bool _enabled;
|
bool _enabled;
|
||||||
QString _backend;
|
QString _backend;
|
||||||
|
|
||||||
protected slots:
|
|
||||||
|
|
||||||
void slotOnlineChanged(bool online);
|
|
||||||
|
|
||||||
void slotPollTimerTimeout();
|
|
||||||
|
|
||||||
/* called when the watcher detect a list of changed
|
|
||||||
paths */
|
|
||||||
|
|
||||||
void slotSyncStarted();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered by a file system watcher on the local sync dir
|
|
||||||
*/
|
|
||||||
virtual void slotLocalPathChanged( const QString& );
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,19 +21,28 @@
|
|||||||
#include "mirall/inotify.h"
|
#include "mirall/inotify.h"
|
||||||
#include "mirall/theme.h"
|
#include "mirall/theme.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <shlobj.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
FolderMan::FolderMan(QObject *parent) :
|
FolderMan::FolderMan(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent),
|
||||||
|
_syncEnabled( true )
|
||||||
{
|
{
|
||||||
// if QDir::mkpath would not be so stupid, I would not need to have this
|
// if QDir::mkpath would not be so stupid, I would not need to have this
|
||||||
// duplication of folderConfigPath() here
|
// duplication of folderConfigPath() here
|
||||||
QDir storageDir(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
|
MirallConfigFile cfg;
|
||||||
|
QDir storageDir(cfg.configPath());
|
||||||
storageDir.mkpath(QLatin1String("folders"));
|
storageDir.mkpath(QLatin1String("folders"));
|
||||||
_folderConfigPath = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QLatin1String("/folders");
|
_folderConfigPath = cfg.configPath() + QLatin1String("folders");
|
||||||
|
|
||||||
_folderChangeSignalMapper = new QSignalMapper(this);
|
_folderChangeSignalMapper = new QSignalMapper(this);
|
||||||
connect(_folderChangeSignalMapper, SIGNAL(mapped(const QString &)),
|
connect(_folderChangeSignalMapper, SIGNAL(mapped(const QString &)),
|
||||||
@@ -77,7 +86,15 @@ int FolderMan::setupKnownFolders()
|
|||||||
{
|
{
|
||||||
qDebug() << "* Setup folders from " << _folderConfigPath;
|
qDebug() << "* Setup folders from " << _folderConfigPath;
|
||||||
|
|
||||||
_folderMap.clear(); // FIXME: check if delete of folder structure happens
|
// first terminate sync jobs.
|
||||||
|
terminateCurrentSync();
|
||||||
|
|
||||||
|
// clear the list of existing folders.
|
||||||
|
Folder::MapIterator i(_folderMap);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
delete _folderMap.take( i.key() );
|
||||||
|
}
|
||||||
|
|
||||||
QDir dir( _folderConfigPath );
|
QDir dir( _folderConfigPath );
|
||||||
dir.setFilter(QDir::Files);
|
dir.setFilter(QDir::Files);
|
||||||
@@ -93,6 +110,23 @@ int FolderMan::setupKnownFolders()
|
|||||||
return _folderMap.size();
|
return _folderMap.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderMan::wipeAllJournals()
|
||||||
|
{
|
||||||
|
terminateCurrentSync();
|
||||||
|
|
||||||
|
foreach( Folder *f, _folderMap.values() ) {
|
||||||
|
f->wipe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderMan::terminateCurrentSync()
|
||||||
|
{
|
||||||
|
if( !_currentSyncFolder.isEmpty() ) {
|
||||||
|
qDebug() << "Terminating syncing on folder " << _currentSyncFolder;
|
||||||
|
terminateSyncProcess( _currentSyncFolder );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define SLASH_TAG QLatin1String("__SLASH__")
|
#define SLASH_TAG QLatin1String("__SLASH__")
|
||||||
#define BSLASH_TAG QLatin1String("__BSLASH__")
|
#define BSLASH_TAG QLatin1String("__BSLASH__")
|
||||||
#define QMARK_TAG QLatin1String("__QMARK__")
|
#define QMARK_TAG QLatin1String("__QMARK__")
|
||||||
@@ -240,25 +274,6 @@ Folder* FolderMan::setupFolderFromConfigFile(const QString &file) {
|
|||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderMan::disableFoldersWithRestore()
|
|
||||||
{
|
|
||||||
_folderEnabledMap.clear();
|
|
||||||
foreach( Folder *f, _folderMap ) {
|
|
||||||
// store the enabled state, then make sure it is disabled
|
|
||||||
_folderEnabledMap.insert(f->alias(), f->syncEnabled());
|
|
||||||
f->setSyncEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMan::restoreEnabledFolders()
|
|
||||||
{
|
|
||||||
foreach( Folder *f, _folderMap ) {
|
|
||||||
if (_folderEnabledMap.contains( f->alias() )) {
|
|
||||||
f->setSyncEnabled( _folderEnabledMap.value( f->alias() ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderMan::slotEnableFolder( const QString& alias, bool enable )
|
void FolderMan::slotEnableFolder( const QString& alias, bool enable )
|
||||||
{
|
{
|
||||||
if( ! _folderMap.contains( alias ) ) {
|
if( ! _folderMap.contains( alias ) ) {
|
||||||
@@ -279,6 +294,9 @@ void FolderMan::terminateSyncProcess( const QString& alias )
|
|||||||
Folder *f = _folderMap[alias];
|
Folder *f = _folderMap[alias];
|
||||||
if( f ) {
|
if( f ) {
|
||||||
f->slotTerminateSync();
|
f->slotTerminateSync();
|
||||||
|
|
||||||
|
if(_currentSyncFolder == alias )
|
||||||
|
_currentSyncFolder = QString::null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,6 +321,13 @@ SyncResult FolderMan::syncResult( const QString& alias )
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderMan::slotScheduleAllFolders()
|
||||||
|
{
|
||||||
|
foreach( Folder *f, _folderMap.values() ) {
|
||||||
|
slotScheduleSync( f->alias() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if a folder wants to be synced, it calls this slot and is added
|
* if a folder wants to be synced, it calls this slot and is added
|
||||||
* to the queue. The slot to actually start a sync is called afterwards.
|
* to the queue. The slot to actually start a sync is called afterwards.
|
||||||
@@ -314,15 +339,22 @@ void FolderMan::slotScheduleSync( const QString& alias )
|
|||||||
qDebug() << "Schedule folder " << alias << " to sync!";
|
qDebug() << "Schedule folder " << alias << " to sync!";
|
||||||
if( _currentSyncFolder == alias ) {
|
if( _currentSyncFolder == alias ) {
|
||||||
// the current folder is currently syncing.
|
// the current folder is currently syncing.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _scheduleQueue.contains( alias ) ) {
|
if( ! _scheduleQueue.contains(alias )) {
|
||||||
qDebug() << " II> Sync for folder " << alias << " already scheduled, do not enqueue!";
|
_scheduleQueue.append(alias);
|
||||||
} else {
|
} else {
|
||||||
_scheduleQueue.append( alias );
|
qDebug() << " II> Sync for folder " << alias << " already scheduled, do not enqueue!";
|
||||||
|
|
||||||
slotScheduleFolderSync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slotScheduleFolderSync();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderMan::setSyncEnabled( bool enabled )
|
||||||
|
{
|
||||||
|
_syncEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -337,6 +369,11 @@ void FolderMan::slotScheduleFolderSync()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( ! _syncEnabled ) {
|
||||||
|
qDebug() << "FolderMan: Syncing is disabled, no scheduling.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qDebug() << "XX slotScheduleFolderSync: folderQueue size: " << _scheduleQueue.count();
|
qDebug() << "XX slotScheduleFolderSync: folderQueue size: " << _scheduleQueue.count();
|
||||||
if( ! _scheduleQueue.isEmpty() ) {
|
if( ! _scheduleQueue.isEmpty() ) {
|
||||||
const QString alias = _scheduleQueue.takeFirst();
|
const QString alias = _scheduleQueue.takeFirst();
|
||||||
@@ -388,7 +425,6 @@ void FolderMan::addFolderDefinition( const QString& backend, const QString& alia
|
|||||||
settings.setValue(QString::fromLatin1("%1/connection").arg(escapedAlias), Theme::instance()->appName());
|
settings.setValue(QString::fromLatin1("%1/connection").arg(escapedAlias), Theme::instance()->appName());
|
||||||
settings.setValue(QString::fromLatin1("%1/onlyThisLAN").arg(escapedAlias), onlyThisLAN );
|
settings.setValue(QString::fromLatin1("%1/onlyThisLAN").arg(escapedAlias), onlyThisLAN );
|
||||||
settings.sync();
|
settings.sync();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderMan::removeAllFolderDefinitions()
|
void FolderMan::removeAllFolderDefinitions()
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "mirall/folder.h"
|
#include "mirall/folder.h"
|
||||||
#include "mirall/folderwatcher.h"
|
#include "mirall/folderwatcher.h"
|
||||||
|
#include "mirall/syncfileitem.h"
|
||||||
|
|
||||||
class QSignalMapper;
|
class QSignalMapper;
|
||||||
|
|
||||||
@@ -36,8 +37,6 @@ public:
|
|||||||
~FolderMan();
|
~FolderMan();
|
||||||
|
|
||||||
int setupFolders();
|
int setupFolders();
|
||||||
void disableFoldersWithRestore();
|
|
||||||
void restoreEnabledFolders();
|
|
||||||
|
|
||||||
Mirall::Folder::Map map();
|
Mirall::Folder::Map map();
|
||||||
|
|
||||||
@@ -72,6 +71,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void removeAllFolderDefinitions();
|
void removeAllFolderDefinitions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes csync journals from all folders.
|
||||||
|
*/
|
||||||
|
void wipeAllJournals();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* signal to indicate a folder named by alias has changed its sync state.
|
* signal to indicate a folder named by alias has changed its sync state.
|
||||||
@@ -90,6 +94,12 @@ public slots:
|
|||||||
|
|
||||||
void terminateSyncProcess( const QString& );
|
void terminateSyncProcess( const QString& );
|
||||||
|
|
||||||
|
// if enabled is set to false, no new folders will start to sync.
|
||||||
|
// the current one will finish.
|
||||||
|
void setSyncEnabled( bool );
|
||||||
|
|
||||||
|
void slotScheduleAllFolders();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
// slot to add a folder to the syncing queue
|
// slot to add a folder to the syncing queue
|
||||||
void slotScheduleSync( const QString & );
|
void slotScheduleSync( const QString & );
|
||||||
@@ -101,6 +111,7 @@ private:
|
|||||||
// finds all folder configuration files
|
// finds all folder configuration files
|
||||||
// and create the folders
|
// and create the folders
|
||||||
int setupKnownFolders();
|
int setupKnownFolders();
|
||||||
|
void terminateCurrentSync();
|
||||||
|
|
||||||
// Escaping of the alias which is used in QSettings AND the file
|
// Escaping of the alias which is used in QSettings AND the file
|
||||||
// system, thus need to be escaped.
|
// system, thus need to be escaped.
|
||||||
@@ -111,11 +122,11 @@ private:
|
|||||||
|
|
||||||
FolderWatcher *_configFolderWatcher;
|
FolderWatcher *_configFolderWatcher;
|
||||||
Folder::Map _folderMap;
|
Folder::Map _folderMap;
|
||||||
QHash<QString, bool> _folderEnabledMap;
|
|
||||||
QString _folderConfigPath;
|
QString _folderConfigPath;
|
||||||
QSignalMapper *_folderChangeSignalMapper;
|
QSignalMapper *_folderChangeSignalMapper;
|
||||||
QString _currentSyncFolder;
|
QString _currentSyncFolder;
|
||||||
QStringList _scheduleQueue;
|
QStringList _scheduleQueue;
|
||||||
|
bool _syncEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,20 +28,18 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
#include <sys/inotify.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const uint32_t standard_event_mask =
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | IN_ONLYDIR | IN_DONT_FOLLOW;
|
|
||||||
#else
|
|
||||||
0;
|
|
||||||
#endif
|
|
||||||
/* minimum amount of seconds between two
|
/* minimum amount of seconds between two
|
||||||
events to consider it a new event */
|
events to consider it a new event */
|
||||||
#define DEFAULT_EVENT_INTERVAL_MSEC 1000
|
#define DEFAULT_EVENT_INTERVAL_MSEC 1000
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
#include "mirall/folderwatcher_win.h"
|
||||||
|
#elif defined(Q_OS_MAC)
|
||||||
|
#include "mirall/folderwatcher_mac.h"
|
||||||
|
#elif defined(USE_INOTIFY)
|
||||||
|
#include "mirall/folderwatcher_inotify.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
|
FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
|
||||||
@@ -49,19 +47,13 @@ FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
|
|||||||
_eventsEnabled(true),
|
_eventsEnabled(true),
|
||||||
_eventInterval(DEFAULT_EVENT_INTERVAL_MSEC),
|
_eventInterval(DEFAULT_EVENT_INTERVAL_MSEC),
|
||||||
_root(root),
|
_root(root),
|
||||||
_processTimer(new QTimer(this)),
|
_processTimer(new QTimer(this))
|
||||||
_lastMask(0),
|
|
||||||
_initialSyncDone(false)
|
|
||||||
{
|
{
|
||||||
#ifdef USE_INOTIFY
|
_d = new FolderWatcherPrivate(this);
|
||||||
|
|
||||||
_processTimer->setSingleShot(true);
|
_processTimer->setSingleShot(true);
|
||||||
QObject::connect(_processTimer, SIGNAL(timeout()), this, SLOT(slotProcessTimerTimeout()));
|
QObject::connect(_processTimer, SIGNAL(timeout()), this, SLOT(slotProcessTimerTimeout()));
|
||||||
|
|
||||||
_inotify = new INotify(standard_event_mask);
|
|
||||||
slotAddFolderRecursive(root);
|
|
||||||
QObject::connect(_inotify, SIGNAL(notifyEvent(int, int, const QString &)),
|
|
||||||
this, SLOT(slotINotifyEvent(int, int, const QString &)));
|
|
||||||
#endif
|
|
||||||
// do a first synchronization to get changes while
|
// do a first synchronization to get changes while
|
||||||
// the application was not running
|
// the application was not running
|
||||||
setProcessTimer();
|
setProcessTimer();
|
||||||
@@ -69,7 +61,7 @@ FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
|
|||||||
|
|
||||||
FolderWatcher::~FolderWatcher()
|
FolderWatcher::~FolderWatcher()
|
||||||
{
|
{
|
||||||
|
delete _d;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FolderWatcher::root() const
|
QString FolderWatcher::root() const
|
||||||
@@ -99,11 +91,22 @@ void FolderWatcher::addIgnore(const QString &pattern)
|
|||||||
_ignores.append(pattern);
|
_ignores.append(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList FolderWatcher::ignores() const
|
||||||
|
{
|
||||||
|
return _ignores;
|
||||||
|
}
|
||||||
|
|
||||||
bool FolderWatcher::eventsEnabled() const
|
bool FolderWatcher::eventsEnabled() const
|
||||||
{
|
{
|
||||||
return _eventsEnabled;
|
return _eventsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderWatcher::setEventsEnabledDelayed( int delay_msec )
|
||||||
|
{
|
||||||
|
qDebug() << "Starting Event logging again in " << delay_msec << " milliseconds";
|
||||||
|
QTimer::singleShot( delay_msec, this, SLOT(setEventsEnabled()));
|
||||||
|
}
|
||||||
|
|
||||||
void FolderWatcher::setEventsEnabled(bool enabled)
|
void FolderWatcher::setEventsEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
qDebug() << " * event notification " << (enabled ? "enabled" : "disabled");
|
qDebug() << " * event notification " << (enabled ? "enabled" : "disabled");
|
||||||
@@ -139,142 +142,16 @@ void FolderWatcher::setEventInterval(int seconds)
|
|||||||
_eventInterval = seconds;
|
_eventInterval = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FolderWatcher::folders() const
|
|
||||||
{
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
return _inotify->directories();
|
|
||||||
#else
|
|
||||||
return QStringList();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderWatcher::slotAddFolderRecursive(const QString &path)
|
|
||||||
{
|
|
||||||
int subdirs = 0;
|
|
||||||
qDebug() << "(+) Watcher:" << path;
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
|
|
||||||
_inotify->addPath(path);
|
|
||||||
QStringList watchedFolders(_inotify->directories());
|
|
||||||
// qDebug() << "currently watching " << watchedFolders;
|
|
||||||
QStringListIterator subfoldersIt(FileUtils::subFoldersList(path, FileUtils::SubFolderRecursive));
|
|
||||||
while (subfoldersIt.hasNext()) {
|
|
||||||
QString subfolder = subfoldersIt.next();
|
|
||||||
// qDebug() << " (**) subfolder: " << subfolder;
|
|
||||||
QDir folder (subfolder);
|
|
||||||
if (folder.exists() && !watchedFolders.contains(folder.path())) {
|
|
||||||
subdirs++;
|
|
||||||
// check that it does not match the ignore list
|
|
||||||
foreach ( const QString& pattern, _ignores) {
|
|
||||||
QRegExp regexp(pattern);
|
|
||||||
regexp.setPatternSyntax(QRegExp::Wildcard);
|
|
||||||
if ( regexp.exactMatch(folder.path()) ) {
|
|
||||||
qDebug() << "* Not adding" << folder.path();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
_inotify->addPath(folder.path());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
qDebug() << " `-> discarded:" << folder.path();
|
|
||||||
}
|
|
||||||
if (subdirs >0)
|
|
||||||
qDebug() << " `-> and" << subdirs << "subdirectories";
|
|
||||||
#else
|
|
||||||
qDebug() << "** Watcher is not compiled in!";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderWatcher::slotINotifyEvent(int mask, int cookie, const QString &path)
|
|
||||||
{
|
|
||||||
int lastMask = _lastMask;
|
|
||||||
QString lastPath = _lastPath;
|
|
||||||
|
|
||||||
_lastMask = mask;
|
|
||||||
_lastPath = path;
|
|
||||||
|
|
||||||
if( ! eventsEnabled() ) return;
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
qDebug() << "** Inotify Event " << mask << " on " << path;
|
|
||||||
// cancel close write events that come after create
|
|
||||||
if (lastMask == IN_CREATE && mask == IN_CLOSE_WRITE
|
|
||||||
&& lastPath == path ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IN_IGNORED & mask) {
|
|
||||||
//qDebug() << "IGNORE event";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IN_Q_OVERFLOW & mask) {
|
|
||||||
//qDebug() << "OVERFLOW";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask & IN_CREATE) {
|
|
||||||
//qDebug() << cookie << " CREATE: " << path;
|
|
||||||
if (QFileInfo(path).isDir()) {
|
|
||||||
//setEventsEnabled(false);
|
|
||||||
slotAddFolderRecursive(path);
|
|
||||||
//setEventsEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mask & IN_DELETE) {
|
|
||||||
//qDebug() << cookie << " DELETE: " << path;
|
|
||||||
if ( QFileInfo(path).isDir() && _inotify->directories().contains(path) ) {
|
|
||||||
qDebug() << "(-) Watcher:" << path;
|
|
||||||
_inotify->removePath(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mask & IN_CLOSE_WRITE) {
|
|
||||||
//qDebug() << cookie << " WRITABLE CLOSED: " << path;
|
|
||||||
}
|
|
||||||
else if (mask & IN_MOVE) {
|
|
||||||
//qDebug() << cookie << " MOVE: " << path;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//qDebug() << cookie << " OTHER " << mask << " :" << path;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const QString& pattern, _ignores) {
|
|
||||||
QRegExp regexp(pattern);
|
|
||||||
regexp.setPatternSyntax(QRegExp::Wildcard);
|
|
||||||
|
|
||||||
if (regexp.exactMatch(path)) {
|
|
||||||
qDebug() << "* Discarded by ignore pattern: " << path;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QFileInfo fInfo(path);
|
|
||||||
if( regexp.exactMatch(fInfo.fileName())) {
|
|
||||||
qDebug() << "* Discarded by ignore pattern:" << path;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( fInfo.isHidden() ) {
|
|
||||||
qDebug() << "* Discarded as is hidden!";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !_pendingPathes.contains( path )) {
|
|
||||||
_pendingPathes[path] = 0;
|
|
||||||
}
|
|
||||||
_pendingPathes[path] = _pendingPathes[path]+mask;
|
|
||||||
#endif
|
|
||||||
setProcessTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderWatcher::slotProcessTimerTimeout()
|
void FolderWatcher::slotProcessTimerTimeout()
|
||||||
{
|
{
|
||||||
qDebug() << "* Processing of event queue for" << root();
|
qDebug() << "* Processing of event queue for" << root();
|
||||||
|
|
||||||
if (!_pendingPathes.empty() || !_initialSyncDone) {
|
if (!_pendingPathes.empty() ) {
|
||||||
QStringList notifyPaths = _pendingPathes.keys();
|
QStringList notifyPaths = _pendingPathes.keys();
|
||||||
_pendingPathes.clear();
|
_pendingPathes.clear();
|
||||||
//qDebug() << lastEventTime << eventTime;
|
//qDebug() << lastEventTime << eventTime;
|
||||||
qDebug() << " * Notify" << notifyPaths.size() << "changed items for" << root();
|
qDebug() << " * Notify" << notifyPaths.size() << "change items for" << root();
|
||||||
emit folderChanged(notifyPaths);
|
emit folderChanged(notifyPaths);
|
||||||
_initialSyncDone = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,12 +160,23 @@ void FolderWatcher::setProcessTimer()
|
|||||||
if (!_processTimer->isActive()) {
|
if (!_processTimer->isActive()) {
|
||||||
qDebug() << "* Pending events for" << root()
|
qDebug() << "* Pending events for" << root()
|
||||||
<< "will be processed after events stop for"
|
<< "will be processed after events stop for"
|
||||||
<< eventInterval() << "seconds ("
|
<< eventInterval() << "milliseconds ("
|
||||||
<< QTime::currentTime().addSecs(eventInterval()).toString(QLatin1String("HH:mm:ss"))
|
<< QTime::currentTime().addSecs(eventInterval()).toString(QLatin1String("HH:mm:ss"))
|
||||||
<< ")." << _pendingPathes.size() << "events until now )";
|
<< ")." << _pendingPathes.size() << "events until now )";
|
||||||
}
|
}
|
||||||
_processTimer->start(eventInterval());
|
_processTimer->start(eventInterval());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderWatcher::changeDetected(const QString& f)
|
||||||
|
{
|
||||||
|
if( ! eventsEnabled() ) {
|
||||||
|
// qDebug() << "FolderWatcher::changeDetected when eventsEnabled() -> ignore";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pendingPathes[f] = 1; //_pendingPathes[path]+mask;
|
||||||
|
setProcessTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Mirall
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,7 @@ class QTimer;
|
|||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
#ifdef USE_INOTIFY
|
class FolderWatcherPrivate;
|
||||||
class INotify;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watches a folder and sub folders for changes
|
* Watches a folder and sub folders for changes
|
||||||
@@ -53,11 +51,6 @@ public:
|
|||||||
FolderWatcher(const QString &root, QObject *parent = 0L);
|
FolderWatcher(const QString &root, QObject *parent = 0L);
|
||||||
~FolderWatcher();
|
~FolderWatcher();
|
||||||
|
|
||||||
/**
|
|
||||||
* All watched folders and subfolders
|
|
||||||
*/
|
|
||||||
QStringList folders() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root path being monitored
|
* Root path being monitored
|
||||||
*/
|
*/
|
||||||
@@ -82,13 +75,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool eventsEnabled() const;
|
bool eventsEnabled() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Enabled or disables folderChanged() events.
|
|
||||||
* If disabled, events are accumulated and emptied
|
|
||||||
* the next time a folderChanged() event happens.
|
|
||||||
*/
|
|
||||||
void setEventsEnabled(bool enabled);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all pending events
|
* Clear all pending events
|
||||||
*/
|
*/
|
||||||
@@ -106,6 +92,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setEventInterval(int seconds);
|
void setEventInterval(int seconds);
|
||||||
|
|
||||||
|
QStringList ignores() const;
|
||||||
|
public slots:
|
||||||
|
/**
|
||||||
|
* Enabled or disables folderChanged() events.
|
||||||
|
* If disabled, events are accumulated and emptied
|
||||||
|
* the next time a folderChanged() event happens.
|
||||||
|
*/
|
||||||
|
void setEventsEnabled(bool enabled=true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setEventsEnabledDelayed - start event logging after a while
|
||||||
|
* @param delay - delay time in milliseconds
|
||||||
|
* @param enabled - enable the events.
|
||||||
|
*/
|
||||||
|
void setEventsEnabledDelayed( int );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* Emitted when one of the paths is changed
|
* Emitted when one of the paths is changed
|
||||||
@@ -116,32 +118,24 @@ protected:
|
|||||||
void setProcessTimer();
|
void setProcessTimer();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void slotINotifyEvent(int mask, int cookie, const QString &path);
|
|
||||||
void slotAddFolderRecursive(const QString &path);
|
|
||||||
// called when the manually process timer triggers
|
// called when the manually process timer triggers
|
||||||
void slotProcessTimerTimeout();
|
void slotProcessTimerTimeout();
|
||||||
|
void changeDetected(const QString &f);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QHash<QString, int> _pendingPathes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _eventsEnabled;
|
bool _eventsEnabled;
|
||||||
int _eventInterval;
|
int _eventInterval;
|
||||||
#ifdef USE_INOTIFY
|
FolderWatcherPrivate *_d;
|
||||||
INotify *_inotify;
|
|
||||||
#endif
|
|
||||||
QString _root;
|
QString _root;
|
||||||
// paths pending to notified
|
// paths pending to notified
|
||||||
// QStringList _pendingPaths;
|
// QStringList _pendingPaths;
|
||||||
QHash<QString, int> _pendingPathes;
|
|
||||||
|
|
||||||
QTimer *_processTimer;
|
QTimer *_processTimer;
|
||||||
|
|
||||||
// to cancel events that belong to the same action
|
|
||||||
int _lastMask;
|
|
||||||
QString _lastPath;
|
|
||||||
QStringList _ignores;
|
QStringList _ignores;
|
||||||
|
|
||||||
// for the initial synchronization, without
|
friend class FolderWatcherPrivate;
|
||||||
// any file changed
|
|
||||||
bool _initialSyncDone;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
158
src/mirall/folderwatcher_inotify.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
|
||||||
|
#include "mirall/inotify.h"
|
||||||
|
#include "mirall/folderwatcher.h"
|
||||||
|
#include "mirall/fileutils.h"
|
||||||
|
|
||||||
|
#include "mirall/folderwatcher_inotify.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
static const uint32_t standard_event_mask =
|
||||||
|
IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVE |
|
||||||
|
IN_CREATE |IN_DELETE | IN_DELETE_SELF |
|
||||||
|
IN_MOVE_SELF |IN_UNMOUNT |IN_ONLYDIR |
|
||||||
|
IN_DONT_FOLLOW;
|
||||||
|
|
||||||
|
FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p)
|
||||||
|
: QObject(), _parent(p), _lastMask(0)
|
||||||
|
|
||||||
|
{
|
||||||
|
_inotify = new INotify(this, standard_event_mask);
|
||||||
|
slotAddFolderRecursive(_parent->root());
|
||||||
|
QObject::connect(_inotify, SIGNAL(notifyEvent(int, int, const QString &)),
|
||||||
|
this, SLOT(slotINotifyEvent(int, int, const QString &)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
|
||||||
|
{
|
||||||
|
int subdirs = 0;
|
||||||
|
qDebug() << "(+) Watcher:" << path;
|
||||||
|
|
||||||
|
_inotify->addPath(path);
|
||||||
|
QStringList watchedFolders(_inotify->directories());
|
||||||
|
// qDebug() << "currently watching " << watchedFolders;
|
||||||
|
QStringListIterator subfoldersIt(FileUtils::subFoldersList(path, FileUtils::SubFolderRecursive));
|
||||||
|
while (subfoldersIt.hasNext()) {
|
||||||
|
QString subfolder = subfoldersIt.next();
|
||||||
|
// qDebug() << " (**) subfolder: " << subfolder;
|
||||||
|
QDir folder (subfolder);
|
||||||
|
if (folder.exists() && !watchedFolders.contains(folder.path())) {
|
||||||
|
subdirs++;
|
||||||
|
// check that it does not match the ignore list
|
||||||
|
foreach ( const QString& pattern, _parent->ignores()) {
|
||||||
|
QRegExp regexp(pattern);
|
||||||
|
regexp.setPatternSyntax(QRegExp::Wildcard);
|
||||||
|
if ( regexp.exactMatch(folder.path()) ) {
|
||||||
|
qDebug() << "* Not adding" << folder.path();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
_inotify->addPath(folder.path());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qDebug() << " `-> discarded:" << folder.path();
|
||||||
|
}
|
||||||
|
if (subdirs >0)
|
||||||
|
qDebug() << " `-> and" << subdirs << "subdirectories";
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderWatcherPrivate::slotINotifyEvent(int mask, int cookie, const QString &path)
|
||||||
|
{
|
||||||
|
int lastMask = _lastMask;
|
||||||
|
QString lastPath = _lastPath;
|
||||||
|
|
||||||
|
_lastMask = mask;
|
||||||
|
_lastPath = path;
|
||||||
|
|
||||||
|
// TODO: Unify behaviour acress backends!
|
||||||
|
if( ! _parent->eventsEnabled() ) return;
|
||||||
|
qDebug() << "** Inotify Event " << mask << " on " << path;
|
||||||
|
// cancel close write events that come after create
|
||||||
|
if (lastMask == IN_CREATE && mask == IN_CLOSE_WRITE
|
||||||
|
&& lastPath == path ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IN_IGNORED & mask) {
|
||||||
|
//qDebug() << "IGNORE event";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IN_Q_OVERFLOW & mask) {
|
||||||
|
//qDebug() << "OVERFLOW";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask & IN_CREATE) {
|
||||||
|
//qDebug() << cookie << " CREATE: " << path;
|
||||||
|
if (QFileInfo(path).isDir()) {
|
||||||
|
//setEventsEnabled(false);
|
||||||
|
slotAddFolderRecursive(path);
|
||||||
|
//setEventsEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mask & IN_DELETE) {
|
||||||
|
//qDebug() << cookie << " DELETE: " << path;
|
||||||
|
if ( QFileInfo(path).isDir() && _inotify->directories().contains(path) ) {
|
||||||
|
qDebug() << "(-) Watcher:" << path;
|
||||||
|
_inotify->removePath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mask & IN_CLOSE_WRITE) {
|
||||||
|
//qDebug() << cookie << " WRITABLE CLOSED: " << path;
|
||||||
|
}
|
||||||
|
else if (mask & IN_MOVE) {
|
||||||
|
//qDebug() << cookie << " MOVE: " << path;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//qDebug() << cookie << " OTHER " << mask << " :" << path;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QString& pattern, _parent->ignores()) {
|
||||||
|
QRegExp regexp(pattern);
|
||||||
|
regexp.setPatternSyntax(QRegExp::Wildcard);
|
||||||
|
|
||||||
|
if (regexp.exactMatch(path)) {
|
||||||
|
qDebug() << "* Discarded by ignore pattern: " << path;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFileInfo fInfo(path);
|
||||||
|
if( regexp.exactMatch(fInfo.fileName())) {
|
||||||
|
qDebug() << "* Discarded by ignore pattern:" << path;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( fInfo.isHidden() ) {
|
||||||
|
qDebug() << "* Discarded as is hidden!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !_parent->_pendingPathes.contains( path )) {
|
||||||
|
_parent->_pendingPathes[path] = 0;
|
||||||
|
}
|
||||||
|
_parent->_pendingPathes[path] = _parent->_pendingPathes[path]+mask;
|
||||||
|
_parent->setProcessTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Mirall
|
||||||
42
src/mirall/folderwatcher_inotify.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MIRALL_FOLDERWATCHER_INOTIFY_H
|
||||||
|
#define MIRALL_FOLDERWATCHER_INOTIFY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
class INotify;
|
||||||
|
class FolderWatcher;
|
||||||
|
|
||||||
|
class FolderWatcherPrivate : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FolderWatcherPrivate(FolderWatcher *p);
|
||||||
|
private slots:
|
||||||
|
void slotAddFolderRecursive(const QString &path);
|
||||||
|
void slotINotifyEvent(int mask, int cookie, const QString &path);
|
||||||
|
private:
|
||||||
|
INotify *_inotify;
|
||||||
|
FolderWatcher *_parent;
|
||||||
|
// to cancel events that belong to the same action
|
||||||
|
int _lastMask;
|
||||||
|
QString _lastPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MIRALL_FOLDERWATCHER_INOTIFY_H
|
||||||
86
src/mirall/folderwatcher_mac.cpp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Markus Goetz <markus@woboq.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "mirall/folder.h"
|
||||||
|
#include "mirall/folderwatcher.h"
|
||||||
|
#include "mirall/folderwatcher_mac.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p)
|
||||||
|
: parent(p)
|
||||||
|
{
|
||||||
|
folder = parent->root();
|
||||||
|
this->startWatching();
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderWatcherPrivate::~FolderWatcherPrivate()
|
||||||
|
{
|
||||||
|
FSEventStreamStop(stream);
|
||||||
|
FSEventStreamInvalidate(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void callback(
|
||||||
|
ConstFSEventStreamRef streamRef,
|
||||||
|
void *clientCallBackInfo,
|
||||||
|
size_t numEvents,
|
||||||
|
void *eventPaths,
|
||||||
|
const FSEventStreamEventFlags eventFlags[],
|
||||||
|
const FSEventStreamEventId eventIds[])
|
||||||
|
{
|
||||||
|
qDebug() << "FolderWatcherPrivate::callback by OS X";
|
||||||
|
reinterpret_cast<FolderWatcherPrivate*>(clientCallBackInfo)->doNotifyParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderWatcherPrivate::startWatching()
|
||||||
|
{
|
||||||
|
qDebug() << "FolderWatcherPrivate::startWatching()" << folder;
|
||||||
|
CFStringRef folderCF = CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(folder.unicode()),
|
||||||
|
folder.length());
|
||||||
|
CFArrayRef pathsToWatch = CFStringCreateArrayBySeparatingStrings (NULL, folderCF, CFSTR(":"));
|
||||||
|
|
||||||
|
//CFStringCreateArrayBySeparatingStrings (NULL, folderCF, CFSTR(":"));
|
||||||
|
|
||||||
|
FSEventStreamContext ctx = {0, this, NULL, NULL, NULL};
|
||||||
|
|
||||||
|
// TODO: Add kFSEventStreamCreateFlagFileEvents ?
|
||||||
|
|
||||||
|
stream = FSEventStreamCreate(NULL,
|
||||||
|
&callback,
|
||||||
|
&ctx,
|
||||||
|
pathsToWatch,
|
||||||
|
kFSEventStreamEventIdSinceNow,
|
||||||
|
0, // latency
|
||||||
|
kFSEventStreamCreateFlagNone
|
||||||
|
);
|
||||||
|
|
||||||
|
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
|
FSEventStreamStart(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderWatcherPrivate::doNotifyParent() {
|
||||||
|
parent->changeDetected(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // ns mirall
|
||||||
47
src/mirall/folderwatcher_mac.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Markus Goetz <markus@woboq.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MIRALL_FOLDERWATCHER_MAC_H
|
||||||
|
#define MIRALL_FOLDERWATCHER_MAC_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Mirall
|
||||||
|
{
|
||||||
|
|
||||||
|
class FolderWatcherPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
FolderWatcherPrivate(FolderWatcher *p);
|
||||||
|
~FolderWatcherPrivate();
|
||||||
|
|
||||||
|
void startWatching();
|
||||||
|
void doNotifyParent();
|
||||||
|
|
||||||
|
private:
|
||||||
|
FolderWatcher *parent;
|
||||||
|
|
||||||
|
QString folder;
|
||||||
|
|
||||||
|
FSEventStreamRef stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
91
src/mirall/folderwatcher_win.cpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "mirall/folderwatcher.h"
|
||||||
|
#include "mirall/folderwatcher_win.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
void WatcherThread::run()
|
||||||
|
{
|
||||||
|
_handle = FindFirstChangeNotification((wchar_t*)_path.utf16(),
|
||||||
|
true, // recursive watch
|
||||||
|
FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||||
|
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||||
|
FILE_NOTIFY_CHANGE_LAST_WRITE);
|
||||||
|
|
||||||
|
if (_handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification function failed, stopping watcher!";
|
||||||
|
FindCloseChangeNotification(_handle);
|
||||||
|
_handle = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_handle == NULL)
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification returned null, stopping watcher!";
|
||||||
|
FindCloseChangeNotification(_handle);
|
||||||
|
_handle = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
switch(WaitForSingleObject(_handle, /*wait*/ INFINITE)) {
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
if (FindNextChangeNotification(_handle) == false) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification returned FALSE, stopping watcher!";
|
||||||
|
FindCloseChangeNotification(_handle);
|
||||||
|
_handle = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// qDebug() << Q_FUNC_INFO << "Change detected in" << _path << "from" << QThread::currentThread ();
|
||||||
|
emit changed(_path);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << Q_FUNC_INFO << "Error while watching";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WatcherThread::~WatcherThread()
|
||||||
|
{
|
||||||
|
if (_handle)
|
||||||
|
FindCloseChangeNotification(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p)
|
||||||
|
: _parent(p)
|
||||||
|
{
|
||||||
|
_thread = new WatcherThread(p->root());
|
||||||
|
connect(_thread, SIGNAL(changed(const QString&)),
|
||||||
|
_parent,SLOT(changeDetected(const QString&)));
|
||||||
|
_thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderWatcherPrivate::~FolderWatcherPrivate()
|
||||||
|
{
|
||||||
|
_thread->terminate();
|
||||||
|
_thread->wait();
|
||||||
|
delete _thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Mirall
|
||||||
58
src/mirall/folderwatcher_win.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MIRALL_FOLDERWATCHER_WIN_H
|
||||||
|
#define MIRALL_FOLDERWATCHER_WIN_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
class FolderWatcher;
|
||||||
|
|
||||||
|
// watcher thread
|
||||||
|
|
||||||
|
class WatcherThread : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
WatcherThread(const QString &path) :
|
||||||
|
QThread(), _path(path), _handle(0) {}
|
||||||
|
|
||||||
|
~WatcherThread();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void changed(const QString &path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _path;
|
||||||
|
HANDLE _handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FolderWatcherPrivate : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FolderWatcherPrivate(FolderWatcher *p);
|
||||||
|
~FolderWatcherPrivate();
|
||||||
|
private:
|
||||||
|
FolderWatcher *_parent;
|
||||||
|
WatcherThread *_thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MIRALL_FOLDERWATCHER_WIN_H
|
||||||
@@ -38,7 +38,7 @@ FolderWizardSourcePage::FolderWizardSourcePage()
|
|||||||
registerField(QLatin1String("sourceFolder*"), _ui.localFolderLineEdit);
|
registerField(QLatin1String("sourceFolder*"), _ui.localFolderLineEdit);
|
||||||
_ui.localFolderLineEdit->setText( QString::fromLatin1( "%1/%2").arg( QDir::homePath() ).arg(Theme::instance()->appName() ) );
|
_ui.localFolderLineEdit->setText( QString::fromLatin1( "%1/%2").arg( QDir::homePath() ).arg(Theme::instance()->appName() ) );
|
||||||
registerField(QLatin1String("alias*"), _ui.aliasLineEdit);
|
registerField(QLatin1String("alias*"), _ui.aliasLineEdit);
|
||||||
_ui.aliasLineEdit->setText( Theme::instance()->appName() );
|
_ui.aliasLineEdit->setText( Theme::instance()->appNameGUI() );
|
||||||
|
|
||||||
_ui.warnLabel->hide();
|
_ui.warnLabel->hide();
|
||||||
#if QT_VERSION >= 0x040700
|
#if QT_VERSION >= 0x040700
|
||||||
@@ -78,10 +78,17 @@ bool FolderWizardSourcePage::isComplete() const
|
|||||||
if( ! map ) return false;
|
if( ! map ) return false;
|
||||||
|
|
||||||
if( isOk ) {
|
if( isOk ) {
|
||||||
Folder::Map::const_iterator i = map->begin();
|
Folder::Map::const_iterator i = map->constBegin();
|
||||||
while( isOk && i != map->constEnd() ) {
|
while( isOk && i != map->constEnd() ) {
|
||||||
Folder *f = static_cast<Folder*>(i.value());
|
Folder *f = static_cast<Folder*>(i.value());
|
||||||
QString folderDir = QDir( f->path() ).canonicalPath();
|
QString folderDir = QDir( f->path() ).canonicalPath();
|
||||||
|
if( folderDir.isEmpty() )
|
||||||
|
{
|
||||||
|
isOk = true;
|
||||||
|
qDebug() << "Absolute path for folder: " << f->path() << " doesn't exist. Skipping.";
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if( ! folderDir.endsWith(QLatin1Char('/')) ) folderDir.append(QLatin1Char('/'));
|
if( ! folderDir.endsWith(QLatin1Char('/')) ) folderDir.append(QLatin1Char('/'));
|
||||||
|
|
||||||
qDebug() << "Checking local path: " << folderDir << " <-> " << userInput;
|
qDebug() << "Checking local path: " << folderDir << " <-> " << userInput;
|
||||||
@@ -110,7 +117,7 @@ bool FolderWizardSourcePage::isComplete() const
|
|||||||
isOk = false;
|
isOk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Folder::Map::const_iterator i = map->begin();
|
Folder::Map::const_iterator i = map->constBegin();
|
||||||
bool goon = true;
|
bool goon = true;
|
||||||
while( goon && i != map->constEnd() ) {
|
while( goon && i != map->constEnd() ) {
|
||||||
Folder *f = static_cast<Folder*>(i.value());
|
Folder *f = static_cast<Folder*>(i.value());
|
||||||
@@ -209,7 +216,7 @@ void FolderWizardTargetPage::slotDirCheckReply(const QString &url, QNetworkReply
|
|||||||
showWarn();
|
showWarn();
|
||||||
} else {
|
} else {
|
||||||
showWarn( tr("The folder is not available on your %1.<br/>Click to create it." )
|
showWarn( tr("The folder is not available on your %1.<br/>Click to create it." )
|
||||||
.arg( Theme::instance()->appName() ), true );
|
.arg( Theme::instance()->appNameGUI() ), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
emit completeChanged();
|
emit completeChanged();
|
||||||
@@ -234,10 +241,10 @@ void FolderWizardTargetPage::slotCreateRemoteFolderFinished( QNetworkReply::Netw
|
|||||||
// the webDAV server seems to return a 202 even if mkdir was successful.
|
// the webDAV server seems to return a 202 even if mkdir was successful.
|
||||||
if( error == QNetworkReply::NoError ||
|
if( error == QNetworkReply::NoError ||
|
||||||
error == QNetworkReply::ContentOperationNotPermittedError) {
|
error == QNetworkReply::ContentOperationNotPermittedError) {
|
||||||
showWarn( tr("Folder was successfully created on %1.").arg( Theme::instance()->appName() ), false );
|
showWarn( tr("Folder was successfully created on %1.").arg( Theme::instance()->appNameGUI() ), false );
|
||||||
slotTimerFires();
|
slotTimerFires();
|
||||||
} else {
|
} else {
|
||||||
showWarn( tr("Failed to create the folder on %1.<br/>Please check manually.").arg( Theme::instance()->appName() ), false );
|
showWarn( tr("Failed to create the folder on %1.<br/>Please check manually.").arg( Theme::instance()->appNameGUI() ), false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +320,7 @@ void FolderWizardTargetPage::slotOwnCloudFound( const QString& url, const QStrin
|
|||||||
if( infoStr.isEmpty() ) {
|
if( infoStr.isEmpty() ) {
|
||||||
} else {
|
} else {
|
||||||
_ui.OCLabel->setText( tr("to your <a href=\"%1\">%2</a> (version %3)").arg(url)
|
_ui.OCLabel->setText( tr("to your <a href=\"%1\">%2</a> (version %3)").arg(url)
|
||||||
.arg(Theme::instance()->appName()).arg(infoStr));
|
.arg(Theme::instance()->appNameGUI()).arg(infoStr));
|
||||||
_ui.OCFolderLineEdit->setEnabled( true );
|
_ui.OCFolderLineEdit->setEnabled( true );
|
||||||
_ui.OCRadioBtn->setEnabled( true );
|
_ui.OCRadioBtn->setEnabled( true );
|
||||||
qDebug() << "ownCloud found on " << url << " with version: " << infoStr;
|
qDebug() << "ownCloud found on " << url << " with version: " << infoStr;
|
||||||
@@ -323,9 +330,9 @@ void FolderWizardTargetPage::slotOwnCloudFound( const QString& url, const QStrin
|
|||||||
void FolderWizardTargetPage::slotNoOwnCloudFound( QNetworkReply* error )
|
void FolderWizardTargetPage::slotNoOwnCloudFound( QNetworkReply* error )
|
||||||
{
|
{
|
||||||
qDebug() << "No ownCloud configured: " << error->error();
|
qDebug() << "No ownCloud configured: " << error->error();
|
||||||
_ui.OCLabel->setText( tr("no configured %1 found!").arg(Theme::instance()->appName()) );
|
_ui.OCLabel->setText( tr("no configured %1 found!").arg(Theme::instance()->appNameGUI()) );
|
||||||
showWarn( tr("%1 could not be reached:<br/><tt>%2</tt>")
|
showWarn( tr("%1 could not be reached:<br/><tt>%2</tt>")
|
||||||
.arg(Theme::instance()->appName()).arg(error->errorString()));
|
.arg(Theme::instance()->appNameGUI()).arg(error->errorString()));
|
||||||
_ui.OCRadioBtn->setEnabled( false );
|
_ui.OCRadioBtn->setEnabled( false );
|
||||||
_ui.OCFolderLineEdit->setEnabled( false );
|
_ui.OCFolderLineEdit->setEnabled( false );
|
||||||
}
|
}
|
||||||
@@ -455,20 +462,29 @@ bool FolderWizardOwncloudPage::isComplete() const
|
|||||||
|
|
||||||
FolderWizard::FolderWizard( QWidget *parent )
|
FolderWizard::FolderWizard( QWidget *parent )
|
||||||
: QWizard(parent),
|
: QWizard(parent),
|
||||||
_folderWizardSourcePage(0)
|
_folderWizardSourcePage(0),
|
||||||
|
_folderWizardTargetPage(0)
|
||||||
{
|
{
|
||||||
_folderWizardSourcePage = new FolderWizardSourcePage();
|
_folderWizardSourcePage = new FolderWizardSourcePage();
|
||||||
setPage(Page_Source, _folderWizardSourcePage );
|
setPage(Page_Source, _folderWizardSourcePage );
|
||||||
if (!Theme::instance()->singleSyncFolder())
|
if (!Theme::instance()->singleSyncFolder()) {
|
||||||
setPage(Page_Target, new FolderWizardTargetPage());
|
_folderWizardTargetPage = new FolderWizardTargetPage();
|
||||||
// setPage(Page_Network, new FolderWizardNetworkPage());
|
setPage(Page_Target, _folderWizardTargetPage );
|
||||||
// setPage(Page_Owncloud, new FolderWizardOwncloudPage());
|
}
|
||||||
setWindowTitle( tr( "%1 Folder Wizard" ).arg( Theme::instance()->appName() ) );
|
|
||||||
|
setWindowTitle( tr( "%1 Folder Wizard" ).arg( Theme::instance()->appNameGUI() ) );
|
||||||
#ifdef Q_WS_MAC
|
#ifdef Q_WS_MAC
|
||||||
setWizardStyle( QWizard::ModernStyle );
|
setWizardStyle( QWizard::ModernStyle );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FolderWizard::~FolderWizard()
|
||||||
|
{
|
||||||
|
delete _folderWizardSourcePage;
|
||||||
|
if( _folderWizardTargetPage )
|
||||||
|
delete _folderWizardTargetPage;
|
||||||
|
}
|
||||||
|
|
||||||
void FolderWizard::setFolderMap( Folder::Map *fm)
|
void FolderWizard::setFolderMap( Folder::Map *fm)
|
||||||
{
|
{
|
||||||
if( _folderWizardSourcePage ) {
|
if( _folderWizardSourcePage ) {
|
||||||
|
|||||||
@@ -149,11 +149,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
FolderWizard(QWidget *parent = 0);
|
FolderWizard(QWidget *parent = 0);
|
||||||
|
~FolderWizard();
|
||||||
void setFolderMap( Folder::Map* );
|
void setFolderMap( Folder::Map* );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FolderWizardSourcePage *_folderWizardSourcePage;
|
FolderWizardSourcePage *_folderWizardSourcePage;
|
||||||
|
FolderWizardTargetPage *_folderWizardTargetPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>520</width>
|
<width>520</width>
|
||||||
<height>360</height>
|
<height>367</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -71,9 +71,6 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="pixmap">
|
|
||||||
<pixmap resource="../../mirall.qrc">:/mirall/resources/owncloud-icon-48.png</pixmap>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
@@ -100,7 +97,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Folder on ownCloud:</string>
|
<string>Remote folder:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -133,7 +130,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="pixmap">
|
<property name="pixmap">
|
||||||
<pixmap resource="../../mirall.qrc">:/mirall/resources/folder-grey-32.png</pixmap>
|
<pixmap>:/mirall/resources/folder-grey-32.png</pixmap>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mirall/gitfolder.h"
|
|
||||||
|
|
||||||
#include <QMutexLocker>
|
|
||||||
#include <QProcess>
|
|
||||||
|
|
||||||
namespace Mirall {
|
|
||||||
|
|
||||||
GitFolder::GitFolder(const QString &alias,
|
|
||||||
const QString &path,
|
|
||||||
const QString &secondPath,
|
|
||||||
QObject *parent)
|
|
||||||
: Folder(alias, path, secondPath, parent)
|
|
||||||
{
|
|
||||||
_syncProcess = new QProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
GitFolder::~GitFolder()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void GitFolder::startSync()
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&_syncMutex);
|
|
||||||
emit syncStarted();
|
|
||||||
emit syncFinished(SyncResult(SyncResult::Success));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // ns
|
|
||||||
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MIRALL_GITFOLDER_H
|
|
||||||
#define MIRALL_GITFOLDER_H
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include "mirall/folder.h"
|
|
||||||
|
|
||||||
class QProcess;
|
|
||||||
|
|
||||||
namespace Mirall {
|
|
||||||
|
|
||||||
class GitFolder : public Folder
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* path : Local folder to be keep in sync
|
|
||||||
* remote: git repo url to sync from/to
|
|
||||||
*/
|
|
||||||
GitFolder(const QString &alias,
|
|
||||||
const QString &path,
|
|
||||||
const QString &secondPath, QObject *parent = 0L);
|
|
||||||
virtual ~GitFolder();
|
|
||||||
|
|
||||||
virtual void startSync();
|
|
||||||
private:
|
|
||||||
QMutex _syncMutex;
|
|
||||||
QProcess *_syncProcess;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -16,9 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "inotify.h"
|
#include "inotify.h"
|
||||||
#include "mirall/folder.h"
|
#include "mirall/folder.h"
|
||||||
@@ -36,11 +34,15 @@
|
|||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
INotify::INotify(int mask) : _mask(mask)
|
INotify::INotify(QObject *parent, int mask)
|
||||||
|
: QObject(parent),
|
||||||
|
_mask(mask)
|
||||||
{
|
{
|
||||||
_fd = inotify_init();
|
_fd = inotify_init();
|
||||||
|
if (_fd == -1)
|
||||||
|
qDebug() << Q_FUNC_INFO << "notify_init() failed: " << strerror(errno);
|
||||||
_notifier = new QSocketNotifier(_fd, QSocketNotifier::Read);
|
_notifier = new QSocketNotifier(_fd, QSocketNotifier::Read);
|
||||||
QObject::connect(_notifier, SIGNAL(activated(int)), SLOT(slotActivated(int)));
|
connect(_notifier, SIGNAL(activated(int)), SLOT(slotActivated(int)));
|
||||||
_buffer_size = DEFAULT_READ_BUFFERSIZE;
|
_buffer_size = DEFAULT_READ_BUFFERSIZE;
|
||||||
_buffer = (char *) malloc(_buffer_size);
|
_buffer = (char *) malloc(_buffer_size);
|
||||||
}
|
}
|
||||||
@@ -112,6 +114,7 @@ INotify::~INotify()
|
|||||||
|
|
||||||
close(_fd);
|
close(_fd);
|
||||||
free(_buffer);
|
free(_buffer);
|
||||||
|
delete _notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
void INotify::addPath(const QString &path)
|
void INotify::addPath(const QString &path)
|
||||||
@@ -121,7 +124,7 @@ void INotify::addPath(const QString &path)
|
|||||||
if( wd > -1 )
|
if( wd > -1 )
|
||||||
_wds[path] = wd;
|
_wds[path] = wd;
|
||||||
else
|
else
|
||||||
qDebug() << "WRN: Could not watch " << path;
|
qDebug() << "WRN: Could not watch " << path << ':' << strerror(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INotify::removePath(const QString &path)
|
void INotify::removePath(const QString &path)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class INotify : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
INotify(int mask);
|
INotify(QObject *parent, int mask);
|
||||||
~INotify();
|
~INotify();
|
||||||
|
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|||||||
@@ -30,70 +30,10 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "mirall/mirallconfigfile.h"
|
#include "mirall/mirallconfigfile.h"
|
||||||
|
#include "mirall/logger.h"
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
Logger* Logger::_instance=0;
|
|
||||||
|
|
||||||
Logger::Logger( QObject* parent)
|
|
||||||
: QObject(parent),
|
|
||||||
_showTime(true)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger *Logger::instance()
|
|
||||||
{
|
|
||||||
if( !Logger::_instance ) Logger::_instance = new Logger;
|
|
||||||
return Logger::_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::destroy()
|
|
||||||
{
|
|
||||||
if( Logger::_instance ) {
|
|
||||||
delete Logger::_instance;
|
|
||||||
Logger::_instance = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::log(Log log)
|
|
||||||
{
|
|
||||||
QString msg;
|
|
||||||
if( _showTime ) {
|
|
||||||
msg = log.timeStamp.toString(QLatin1String("MM-dd hh:mm:ss:zzz")) + QLatin1Char(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
if( log.source == Log::CSync ) {
|
|
||||||
// msg += "csync - ";
|
|
||||||
} else {
|
|
||||||
// msg += "ownCloud - ";
|
|
||||||
}
|
|
||||||
msg += log.message;
|
|
||||||
// _logs.append(log);
|
|
||||||
// std::cout << qPrintable(log.message) << std::endl;
|
|
||||||
emit newLog(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::csyncLog( const QString& message )
|
|
||||||
{
|
|
||||||
Log log;
|
|
||||||
log.source = Log::CSync;
|
|
||||||
log.timeStamp = QDateTime::currentDateTime();
|
|
||||||
log.message = message;
|
|
||||||
|
|
||||||
Logger::instance()->log(log);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::mirallLog( const QString& message )
|
|
||||||
{
|
|
||||||
Log log_;
|
|
||||||
log_.source = Log::Mirall;
|
|
||||||
log_.timeStamp = QDateTime::currentDateTime();
|
|
||||||
log_.message = message;
|
|
||||||
|
|
||||||
Logger::instance()->log( log_ );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==============================================================================
|
// ==============================================================================
|
||||||
|
|
||||||
LogWidget::LogWidget(QWidget *parent)
|
LogWidget::LogWidget(QWidget *parent)
|
||||||
@@ -248,7 +188,6 @@ void LogBrowser::search( const QString& str )
|
|||||||
void LogBrowser::slotSave()
|
void LogBrowser::slotSave()
|
||||||
{
|
{
|
||||||
_saveBtn->setEnabled(false);
|
_saveBtn->setEnabled(false);
|
||||||
QCoreApplication::processEvents();
|
|
||||||
|
|
||||||
QString saveFile = QFileDialog::getSaveFileName( this, tr("Save log file"), QDir::homePath() );
|
QString saveFile = QFileDialog::getSaveFileName( this, tr("Save log file"), QDir::homePath() );
|
||||||
|
|
||||||
|
|||||||
@@ -28,43 +28,6 @@
|
|||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
struct Log{
|
|
||||||
typedef enum{
|
|
||||||
Mirall,
|
|
||||||
CSync
|
|
||||||
} Source;
|
|
||||||
|
|
||||||
QDateTime timeStamp;
|
|
||||||
Source source;
|
|
||||||
QString message;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Logger : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
void log(Log log);
|
|
||||||
|
|
||||||
static void csyncLog( const QString& message );
|
|
||||||
static void mirallLog( const QString& message );
|
|
||||||
|
|
||||||
const QList<Log>& logs() const {return _logs;}
|
|
||||||
|
|
||||||
static Logger* instance();
|
|
||||||
static void destroy();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void newLog(const QString&);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Logger(QObject* parent=0);
|
|
||||||
QList<Log> _logs;
|
|
||||||
bool _showTime;
|
|
||||||
bool _doLogging;
|
|
||||||
|
|
||||||
static Logger* _instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LogWidget : public QPlainTextEdit
|
class LogWidget : public QPlainTextEdit
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|||||||
80
src/mirall/logger.cpp
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mirall/logger.h"
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
Logger* Logger::_instance=0;
|
||||||
|
|
||||||
|
Logger::Logger( QObject* parent)
|
||||||
|
: QObject(parent),
|
||||||
|
_showTime(true)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger *Logger::instance()
|
||||||
|
{
|
||||||
|
if( !Logger::_instance ) Logger::_instance = new Logger;
|
||||||
|
return Logger::_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::destroy()
|
||||||
|
{
|
||||||
|
if( Logger::_instance ) {
|
||||||
|
delete Logger::_instance;
|
||||||
|
Logger::_instance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::log(Log log)
|
||||||
|
{
|
||||||
|
QString msg;
|
||||||
|
if( _showTime ) {
|
||||||
|
msg = log.timeStamp.toString(QLatin1String("MM-dd hh:mm:ss:zzz")) + QLatin1Char(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if( log.source == Log::CSync ) {
|
||||||
|
// msg += "csync - ";
|
||||||
|
} else {
|
||||||
|
// msg += "ownCloud - ";
|
||||||
|
}
|
||||||
|
msg += log.message;
|
||||||
|
// _logs.append(log);
|
||||||
|
// std::cout << qPrintable(log.message) << std::endl;
|
||||||
|
emit newLog(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::csyncLog( const QString& message )
|
||||||
|
{
|
||||||
|
Log log;
|
||||||
|
log.source = Log::CSync;
|
||||||
|
log.timeStamp = QDateTime::currentDateTime();
|
||||||
|
log.message = message;
|
||||||
|
|
||||||
|
Logger::instance()->log(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::mirallLog( const QString& message )
|
||||||
|
{
|
||||||
|
Log log_;
|
||||||
|
log_.source = Log::Mirall;
|
||||||
|
log_.timeStamp = QDateTime::currentDateTime();
|
||||||
|
log_.message = message;
|
||||||
|
|
||||||
|
Logger::instance()->log( log_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Mirall
|
||||||
64
src/mirall/logger.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOGGER_H
|
||||||
|
#define LOGGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
namespace Mirall {
|
||||||
|
|
||||||
|
struct Log{
|
||||||
|
typedef enum{
|
||||||
|
Mirall,
|
||||||
|
CSync
|
||||||
|
} Source;
|
||||||
|
|
||||||
|
QDateTime timeStamp;
|
||||||
|
Source source;
|
||||||
|
QString message;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Logger : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
void log(Log log);
|
||||||
|
|
||||||
|
static void csyncLog( const QString& message );
|
||||||
|
static void mirallLog( const QString& message );
|
||||||
|
|
||||||
|
const QList<Log>& logs() const {return _logs;}
|
||||||
|
|
||||||
|
static Logger* instance();
|
||||||
|
static void destroy();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void newLog(const QString&);
|
||||||
|
void guiLog(const QString&, const QString&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Logger(QObject* parent=0);
|
||||||
|
QList<Log> _logs;
|
||||||
|
bool _showTime;
|
||||||
|
bool _doLogging;
|
||||||
|
|
||||||
|
static Logger* _instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Mirall
|
||||||
|
|
||||||
|
#endif // LOGGER_H
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "mirall/mirallconfigfile.h"
|
#include "mirall/mirallconfigfile.h"
|
||||||
|
#include "mirall/owncloudinfo.h"
|
||||||
#include "mirall/owncloudtheme.h"
|
#include "mirall/owncloudtheme.h"
|
||||||
#include "mirall/miralltheme.h"
|
#include "mirall/miralltheme.h"
|
||||||
#include "mirall/credentialstore.h"
|
#include "mirall/credentialstore.h"
|
||||||
@@ -23,14 +24,13 @@
|
|||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
|
||||||
#define DEFAULT_REMOTE_POLL_INTERVAL 30000 // default remote poll time in milliseconds
|
#define DEFAULT_REMOTE_POLL_INTERVAL 30000 // default remote poll time in milliseconds
|
||||||
#define DEFAULT_LOCAL_POLL_INTERVAL 10000 // default local poll time in milliseconds
|
|
||||||
#define DEFAULT_POLL_TIMER_EXEED 10
|
|
||||||
|
|
||||||
#define CA_CERTS_KEY QLatin1String("CaCertificates")
|
#define CA_CERTS_KEY QLatin1String("CaCertificates")
|
||||||
|
|
||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
QString MirallConfigFile::_oCVersion;
|
QString MirallConfigFile::_oCVersion;
|
||||||
|
QString MirallConfigFile::_confDir = QString::null;
|
||||||
bool MirallConfigFile::_askedUser = false;
|
bool MirallConfigFile::_askedUser = false;
|
||||||
|
|
||||||
MirallConfigFile::MirallConfigFile( const QString& appendix )
|
MirallConfigFile::MirallConfigFile( const QString& appendix )
|
||||||
@@ -38,9 +38,23 @@ MirallConfigFile::MirallConfigFile( const QString& appendix )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MirallConfigFile::setConfDir(const QString &value)
|
||||||
|
{
|
||||||
|
if( value.isEmpty() ) return;
|
||||||
|
|
||||||
|
QFileInfo fi(value);
|
||||||
|
if( fi.exists() && fi.isDir() ) {
|
||||||
|
qDebug() << "** Using custom dir " << value;
|
||||||
|
_confDir=value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString MirallConfigFile::configPath() const
|
QString MirallConfigFile::configPath() const
|
||||||
{
|
{
|
||||||
QString dir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
|
QString dir = _confDir;
|
||||||
|
if( _confDir.isEmpty() )
|
||||||
|
_confDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
|
||||||
|
|
||||||
if( !dir.endsWith(QLatin1Char('/')) ) dir.append(QLatin1Char('/'));
|
if( !dir.endsWith(QLatin1Char('/')) ) dir.append(QLatin1Char('/'));
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
@@ -85,7 +99,7 @@ QString MirallConfigFile::excludeFile() const
|
|||||||
QString MirallConfigFile::configFile() const
|
QString MirallConfigFile::configFile() const
|
||||||
{
|
{
|
||||||
if( qApp->applicationName().isEmpty() ) {
|
if( qApp->applicationName().isEmpty() ) {
|
||||||
qApp->setApplicationName( Theme::instance()->appName() );
|
qApp->setApplicationName( Theme::instance()->appNameGUI() );
|
||||||
}
|
}
|
||||||
QString dir = configPath() + Theme::instance()->configFileName();
|
QString dir = configPath() + Theme::instance()->configFileName();
|
||||||
if( !_customHandle.isEmpty() ) {
|
if( !_customHandle.isEmpty() ) {
|
||||||
@@ -127,7 +141,6 @@ void MirallConfigFile::writeOwncloudConfig( const QString& connection,
|
|||||||
{
|
{
|
||||||
const QString file = configFile();
|
const QString file = configFile();
|
||||||
qDebug() << "*** writing mirall config to " << file << " Skippwd: " << skipPwd;
|
qDebug() << "*** writing mirall config to " << file << " Skippwd: " << skipPwd;
|
||||||
QString pwd( passwd );
|
|
||||||
|
|
||||||
QSettings settings( file, QSettings::IniFormat);
|
QSettings settings( file, QSettings::IniFormat);
|
||||||
settings.setIniCodec( "UTF-8" );
|
settings.setIniCodec( "UTF-8" );
|
||||||
@@ -143,22 +156,69 @@ void MirallConfigFile::writeOwncloudConfig( const QString& connection,
|
|||||||
settings.beginGroup( connection );
|
settings.beginGroup( connection );
|
||||||
settings.setValue( QLatin1String("url"), cloudsUrl );
|
settings.setValue( QLatin1String("url"), cloudsUrl );
|
||||||
settings.setValue( QLatin1String("user"), user );
|
settings.setValue( QLatin1String("user"), user );
|
||||||
if( skipPwd ) {
|
|
||||||
pwd.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray pwdba = pwd.toUtf8();
|
|
||||||
settings.setValue( QLatin1String("passwd"), QVariant(pwdba.toBase64()) );
|
#ifdef WITH_QTKEYCHAIN
|
||||||
|
// Password is stored to QtKeyChain now by default in CredentialStore
|
||||||
|
// The CredentialStore calls clearPasswordFromConfig after the creds
|
||||||
|
// were successfully wiritten to delete the passwd entry from config.
|
||||||
|
qDebug() << "Going to delete the password from settings file.";
|
||||||
|
#else
|
||||||
|
if( !skipPwd )
|
||||||
|
writePassword( passwd );
|
||||||
|
#endif
|
||||||
|
if( !skipPwd )
|
||||||
|
writePassword( passwd );
|
||||||
|
else
|
||||||
|
clearPasswordFromConfig(); // wipe the password.
|
||||||
|
|
||||||
settings.setValue( QLatin1String("nostoredpassword"), QVariant(skipPwd) );
|
settings.setValue( QLatin1String("nostoredpassword"), QVariant(skipPwd) );
|
||||||
settings.sync();
|
settings.sync();
|
||||||
// check the perms, only read-write for the owner.
|
// check the perms, only read-write for the owner.
|
||||||
QFile::setPermissions( file, QFile::ReadOwner|QFile::WriteOwner );
|
QFile::setPermissions( file, QFile::ReadOwner|QFile::WriteOwner );
|
||||||
|
|
||||||
// inform the credential store about the password change.
|
// Store credentials temporar until the config is finalized.
|
||||||
CredentialStore::instance()->setCredentials( user, pwd );
|
ownCloudInfo::instance()->setCredentials( user, passwd, _customHandle );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is called after the password was successfully stored into the
|
||||||
|
// QKeyChain in CredentialStore.
|
||||||
|
void MirallConfigFile::clearPasswordFromConfig( const QString& connection )
|
||||||
|
{
|
||||||
|
const QString file = configFile();
|
||||||
|
QString con( defaultConnection() );
|
||||||
|
if( !connection.isEmpty() )
|
||||||
|
con = connection;
|
||||||
|
|
||||||
|
QSettings settings( file, QSettings::IniFormat);
|
||||||
|
settings.setIniCodec( "UTF-8" );
|
||||||
|
settings.beginGroup( con );
|
||||||
|
settings.remove(QLatin1String("passwd"));
|
||||||
|
settings.remove(QLatin1String("password"));
|
||||||
|
settings.sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MirallConfigFile::writePassword( const QString& passwd, const QString& connection )
|
||||||
|
{
|
||||||
|
const QString file = configFile();
|
||||||
|
QString pwd( passwd );
|
||||||
|
QString con( defaultConnection() );
|
||||||
|
if( !connection.isEmpty() )
|
||||||
|
con = connection;
|
||||||
|
|
||||||
|
QSettings settings( file, QSettings::IniFormat);
|
||||||
|
settings.setIniCodec( "UTF-8" );
|
||||||
|
|
||||||
|
// store password into settings file.
|
||||||
|
settings.beginGroup( con );
|
||||||
|
QByteArray pwdba = pwd.toUtf8();
|
||||||
|
settings.setValue( QLatin1String("passwd"), QVariant(pwdba.toBase64()) );
|
||||||
|
settings.sync();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// set the url, called from redirect handling.
|
// set the url, called from redirect handling.
|
||||||
void MirallConfigFile::setOwnCloudUrl( const QString& connection, const QString & url )
|
void MirallConfigFile::setOwnCloudUrl( const QString& connection, const QString & url )
|
||||||
{
|
{
|
||||||
@@ -224,13 +284,6 @@ QString MirallConfigFile::ownCloudUrl( const QString& connection, bool webdav )
|
|||||||
settings.setIniCodec( "UTF-8" );
|
settings.setIniCodec( "UTF-8" );
|
||||||
settings.beginGroup( con );
|
settings.beginGroup( con );
|
||||||
|
|
||||||
// For the WebDAV connect it is required to know which version the server is running
|
|
||||||
// because the url changed :-/
|
|
||||||
if( webdav && _oCVersion.isEmpty() ) {
|
|
||||||
qDebug() << "######## Config does not yet know the ownCloud server version #########";
|
|
||||||
qDebug() << "###################### THIS SHOULD NOT HAPPEN! ########################";
|
|
||||||
}
|
|
||||||
|
|
||||||
QString url = settings.value( QLatin1String("url") ).toString();
|
QString url = settings.value( QLatin1String("url") ).toString();
|
||||||
if( ! url.isEmpty() ) {
|
if( ! url.isEmpty() ) {
|
||||||
if( ! url.endsWith(QLatin1Char('/'))) url.append(QLatin1String("/"));
|
if( ! url.endsWith(QLatin1Char('/'))) url.append(QLatin1String("/"));
|
||||||
@@ -267,70 +320,40 @@ int MirallConfigFile::remotePollInterval( const QString& connection ) const
|
|||||||
settings.beginGroup( con );
|
settings.beginGroup( con );
|
||||||
|
|
||||||
int remoteInterval = settings.value( QLatin1String("remotePollInterval"), DEFAULT_REMOTE_POLL_INTERVAL ).toInt();
|
int remoteInterval = settings.value( QLatin1String("remotePollInterval"), DEFAULT_REMOTE_POLL_INTERVAL ).toInt();
|
||||||
int localInterval = settings.value(QLatin1String("localPollInterval"), DEFAULT_LOCAL_POLL_INTERVAL ).toInt();
|
if( remoteInterval < 5000) {
|
||||||
if( remoteInterval < 2*localInterval ) {
|
qDebug() << "Remote Interval is less than 5 seconds, reverting to" << DEFAULT_REMOTE_POLL_INTERVAL;
|
||||||
qDebug() << "WARN: remote poll Interval should at least be twice as local poll interval!";
|
|
||||||
}
|
|
||||||
if( remoteInterval < 5000 || remoteInterval < localInterval ) {
|
|
||||||
qDebug() << "Remote Interval is smaller than local Interval";
|
|
||||||
remoteInterval = DEFAULT_REMOTE_POLL_INTERVAL;
|
remoteInterval = DEFAULT_REMOTE_POLL_INTERVAL;
|
||||||
}
|
}
|
||||||
return remoteInterval;
|
return remoteInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MirallConfigFile::localPollInterval( const QString& connection ) const
|
void MirallConfigFile::setRemotePollInterval(int interval, const QString &connection )
|
||||||
{
|
{
|
||||||
QString con( connection );
|
QString con( connection );
|
||||||
if( connection.isEmpty() ) con = defaultConnection();
|
if( connection.isEmpty() ) con = defaultConnection();
|
||||||
|
|
||||||
QSettings settings( configFile(), QSettings::IniFormat );
|
if( interval < 5000 ) {
|
||||||
settings.setIniCodec( "UTF-8" );
|
qDebug() << "Remote Poll interval of " << interval << " is below fife seconds.";
|
||||||
settings.beginGroup( con );
|
return;
|
||||||
|
}
|
||||||
int remoteInterval = settings.value( QLatin1String("remotePollInterval"), DEFAULT_REMOTE_POLL_INTERVAL ).toInt();
|
QSettings settings( configFile(), QSettings::IniFormat );
|
||||||
int localInterval = settings.value(QLatin1String("localPollInterval"), DEFAULT_LOCAL_POLL_INTERVAL ).toInt();
|
settings.setIniCodec( "UTF-8" );
|
||||||
if( remoteInterval < 2*localInterval ) {
|
settings.beginGroup( con );
|
||||||
qDebug() << "WARN: remote poll Interval should at least be twice as local poll interval!";
|
settings.setValue("remotePollInterval", interval );
|
||||||
}
|
settings.sync();
|
||||||
if( localInterval < 2500 || remoteInterval < localInterval ) {
|
|
||||||
qDebug() << "Remote Interval is smaller than local Interval";
|
|
||||||
localInterval = DEFAULT_LOCAL_POLL_INTERVAL;
|
|
||||||
}
|
|
||||||
return localInterval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MirallConfigFile::pollTimerExceedFactor( const QString& connection ) const
|
bool MirallConfigFile::passwordStorageAllowed( const QString& connection )
|
||||||
{
|
{
|
||||||
QString con( connection );
|
QString con( connection );
|
||||||
if( connection.isEmpty() ) con = defaultConnection();
|
if( connection.isEmpty() ) con = defaultConnection();
|
||||||
|
|
||||||
QSettings settings( configFile(), QSettings::IniFormat );
|
|
||||||
settings.setIniCodec( "UTF-8" );
|
|
||||||
settings.beginGroup( con );
|
|
||||||
|
|
||||||
int pte = settings.value( QLatin1String("pollTimerExeedFactor"), DEFAULT_POLL_TIMER_EXEED).toInt();
|
|
||||||
|
|
||||||
if( pte < 1 ) pte = DEFAULT_POLL_TIMER_EXEED;
|
|
||||||
|
|
||||||
return pte;
|
|
||||||
}
|
|
||||||
|
|
||||||
MirallConfigFile::CredentialType MirallConfigFile::credentialType() const
|
|
||||||
{
|
|
||||||
QString con; /* ( connection ); */
|
|
||||||
/* if( connection.isEmpty() ) */ con = defaultConnection();
|
|
||||||
CredentialType ct = Settings;
|
|
||||||
|
|
||||||
QSettings settings( configFile(), QSettings::IniFormat );
|
QSettings settings( configFile(), QSettings::IniFormat );
|
||||||
settings.setIniCodec( "UTF-8" );
|
settings.setIniCodec( "UTF-8" );
|
||||||
settings.beginGroup( con );
|
settings.beginGroup( con );
|
||||||
|
|
||||||
bool skipPwd = settings.value( QLatin1String("nostoredpassword"), false ).toBool();
|
bool skipPwd = settings.value( QLatin1String("nostoredpassword"), false ).toBool();
|
||||||
if( skipPwd ) {
|
return !skipPwd;
|
||||||
ct = User;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ct;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MirallConfigFile::ownCloudPasswd( const QString& connection ) const
|
QString MirallConfigFile::ownCloudPasswd( const QString& connection ) const
|
||||||
@@ -390,6 +413,20 @@ bool MirallConfigFile::ownCloudSkipUpdateCheck( const QString& connection ) cons
|
|||||||
return skipIt;
|
return skipIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MirallConfigFile::setOwnCloudSkipUpdateCheck( bool skip, const QString& connection )
|
||||||
|
{
|
||||||
|
QString con( connection );
|
||||||
|
if( connection.isEmpty() ) con = defaultConnection();
|
||||||
|
|
||||||
|
QSettings settings( configFile(), QSettings::IniFormat );
|
||||||
|
settings.setIniCodec( "UTF-8" );
|
||||||
|
settings.beginGroup( con );
|
||||||
|
|
||||||
|
settings.setValue( QLatin1String("skipUpdateCheck"), QVariant(skip) );
|
||||||
|
settings.sync();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int MirallConfigFile::maxLogLines() const
|
int MirallConfigFile::maxLogLines() const
|
||||||
{
|
{
|
||||||
QSettings settings( configFile(), QSettings::IniFormat );
|
QSettings settings( configFile(), QSettings::IniFormat );
|
||||||
@@ -399,6 +436,16 @@ int MirallConfigFile::maxLogLines() const
|
|||||||
return logLines;
|
return logLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MirallConfigFile::setMaxLogLines( int lines )
|
||||||
|
{
|
||||||
|
QSettings settings( configFile(), QSettings::IniFormat );
|
||||||
|
settings.setIniCodec( "UTF-8" );
|
||||||
|
|
||||||
|
settings.beginGroup(QLatin1String("Logging"));
|
||||||
|
settings.setValue(QLatin1String("maxLogLines"), lines);
|
||||||
|
settings.sync();
|
||||||
|
}
|
||||||
|
|
||||||
// remove a custom config file.
|
// remove a custom config file.
|
||||||
void MirallConfigFile::cleanupCustomConfig()
|
void MirallConfigFile::cleanupCustomConfig()
|
||||||
{
|
{
|
||||||
@@ -421,6 +468,7 @@ void MirallConfigFile::acceptCustomConfig()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString srcConfig = configFile(); // this considers the custom handle
|
QString srcConfig = configFile(); // this considers the custom handle
|
||||||
|
|
||||||
_customHandle.clear();
|
_customHandle.clear();
|
||||||
QString targetConfig = configFile();
|
QString targetConfig = configFile();
|
||||||
QString targetBak = targetConfig + QLatin1String(".bak");
|
QString targetBak = targetConfig + QLatin1String(".bak");
|
||||||
@@ -441,69 +489,19 @@ void MirallConfigFile::acceptCustomConfig()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
QFile::remove( targetBak );
|
QFile::remove( targetBak );
|
||||||
}
|
|
||||||
|
|
||||||
QVariant MirallConfigFile::customMedia( customMediaType type )
|
// inform the credential store about the password change.
|
||||||
{
|
QString url = ownCloudUrl();
|
||||||
QVariant re;
|
QString user = ownCloudUser();
|
||||||
QString key;
|
QString pwd = ownCloudPasswd();
|
||||||
|
bool allow = passwordStorageAllowed();
|
||||||
|
|
||||||
if( type == oCSetupTop ) {
|
if( pwd.isEmpty() ) {
|
||||||
key = QLatin1String("oCSetupTop");
|
qDebug() << "Password is empty, skipping to write cred store.";
|
||||||
} else if( type == oCSetupSide ) {
|
|
||||||
key = QLatin1String("oCSetupSide");
|
|
||||||
} else if( type == oCSetupBottom) {
|
|
||||||
key = QLatin1String("oCSetupBottom");
|
|
||||||
} else if( type == oCSetupFixUrl ) {
|
|
||||||
key = QLatin1String("oCSetupFixUrl");
|
|
||||||
} else if( type == oCSetupResultTop ) {
|
|
||||||
key = QLatin1String("oCSetupResultTop");
|
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Wrong media type.";
|
CredentialStore::instance()->setCredentials(url, user, pwd, allow);
|
||||||
|
CredentialStore::instance()->saveCredentials();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !key.isEmpty() ) {
|
|
||||||
const QString customFile("custom.ini");
|
|
||||||
QFileInfo fi;
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
|
||||||
fi.setFile( QApplication::applicationDirPath(), customFile );
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
// exec path is inside the bundle
|
|
||||||
fi.setFile( QApplication::applicationDirPath(),
|
|
||||||
QLatin1String("../Resources/") + customFile );
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
fi.setFile( QString("/etc/%1").arg(Theme::instance()->appName()), customFile );
|
|
||||||
#endif
|
|
||||||
QSettings settings( fi.absoluteFilePath(), QSettings::IniFormat );
|
|
||||||
|
|
||||||
QString cfg = settings.fileName();
|
|
||||||
qDebug() << "Trying to read config ini file at " << cfg;
|
|
||||||
|
|
||||||
settings.setIniCodec( "UTF-8" );
|
|
||||||
settings.beginGroup(QLatin1String("GUICustomize"));
|
|
||||||
QString val = settings.value( key ).toString();
|
|
||||||
|
|
||||||
// if file is relative, prepend the application dir path.
|
|
||||||
QFileInfo checkFi(val);
|
|
||||||
if( !val.isEmpty() && checkFi.isRelative() ) {
|
|
||||||
checkFi.setFile( QApplication::applicationDirPath(), val );
|
|
||||||
val = checkFi.absoluteFilePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !val.isEmpty() ) {
|
|
||||||
QPixmap pix( val );
|
|
||||||
if( pix.isNull() ) {
|
|
||||||
// pixmap loading hasn't succeeded. We take the text instead.
|
|
||||||
re.setValue( val );
|
|
||||||
} else {
|
|
||||||
re.setValue( pix );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return re;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MirallConfigFile::setProxyType(int proxyType,
|
void MirallConfigFile::setProxyType(int proxyType,
|
||||||
@@ -520,7 +518,7 @@ void MirallConfigFile::setProxyType(int proxyType,
|
|||||||
settings.setValue(QLatin1String("host"), host);
|
settings.setValue(QLatin1String("host"), host);
|
||||||
settings.setValue(QLatin1String("port"), port);
|
settings.setValue(QLatin1String("port"), port);
|
||||||
settings.setValue(QLatin1String("user"), user);
|
settings.setValue(QLatin1String("user"), user);
|
||||||
settings.setValue(QLatin1String("pass"), pass);
|
settings.setValue(QLatin1String("pass"), pass.toUtf8().toBase64());
|
||||||
|
|
||||||
settings.sync();
|
settings.sync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,19 +30,13 @@ class MirallConfigFile
|
|||||||
public:
|
public:
|
||||||
MirallConfigFile( const QString& appendix = QString() );
|
MirallConfigFile( const QString& appendix = QString() );
|
||||||
|
|
||||||
enum customMediaType {
|
// enum customMediaType {
|
||||||
oCSetupTop, // ownCloud connect page
|
// oCSetupTop, // ownCloud connect page
|
||||||
oCSetupSide,
|
// oCSetupSide,
|
||||||
oCSetupBottom,
|
// oCSetupBottom,
|
||||||
oCSetupFixUrl,
|
// oCSetupFixUrl,
|
||||||
oCSetupResultTop // ownCloud connect result page
|
// oCSetupResultTop // ownCloud connect result page
|
||||||
};
|
// };
|
||||||
|
|
||||||
enum CredentialType {
|
|
||||||
User = 0,
|
|
||||||
Settings,
|
|
||||||
KeyChain
|
|
||||||
};
|
|
||||||
|
|
||||||
QString configPath() const;
|
QString configPath() const;
|
||||||
QString configFile() const;
|
QString configFile() const;
|
||||||
@@ -61,6 +55,7 @@ public:
|
|||||||
|
|
||||||
void removeConnection( const QString& connection = QString() );
|
void removeConnection( const QString& connection = QString() );
|
||||||
|
|
||||||
|
QString ownCloudUser( const QString& connection = QString() ) const;
|
||||||
QString ownCloudUrl( const QString& connection = QString(), bool webdav = false ) const;
|
QString ownCloudUrl( const QString& connection = QString(), bool webdav = false ) const;
|
||||||
|
|
||||||
void setOwnCloudUrl(const QString &connection, const QString& );
|
void setOwnCloudUrl(const QString &connection, const QString& );
|
||||||
@@ -69,22 +64,22 @@ public:
|
|||||||
QByteArray caCerts();
|
QByteArray caCerts();
|
||||||
void setCaCerts( const QByteArray& );
|
void setCaCerts( const QByteArray& );
|
||||||
|
|
||||||
CredentialType credentialType() const;
|
bool passwordStorageAllowed(const QString &connection = QString::null );
|
||||||
|
|
||||||
QString ownCloudVersion() const;
|
QString ownCloudVersion() const;
|
||||||
void setOwnCloudVersion( const QString& );
|
void setOwnCloudVersion( const QString& );
|
||||||
|
|
||||||
QVariant customMedia( customMediaType );
|
|
||||||
|
|
||||||
// max count of lines in the log window
|
// max count of lines in the log window
|
||||||
int maxLogLines() const;
|
int maxLogLines() const;
|
||||||
|
void setMaxLogLines(int);
|
||||||
|
|
||||||
bool ownCloudSkipUpdateCheck( const QString& connection = QString() ) const;
|
bool ownCloudSkipUpdateCheck( const QString& connection = QString() ) const;
|
||||||
|
void setOwnCloudSkipUpdateCheck( bool, const QString& );
|
||||||
|
|
||||||
/* Poll intervals in milliseconds */
|
/* Server poll interval in milliseconds */
|
||||||
int localPollInterval ( const QString& connection = QString() ) const;
|
|
||||||
int remotePollInterval( const QString& connection = QString() ) const;
|
int remotePollInterval( const QString& connection = QString() ) const;
|
||||||
int pollTimerExceedFactor( const QString& connection = QString() ) const;
|
/* Set poll interval. Value in microseconds has to be larger than 5000 */
|
||||||
|
void setRemotePollInterval(int interval, const QString& connection = QString() );
|
||||||
|
|
||||||
// Custom Config: accept the custom config to become the main one.
|
// Custom Config: accept the custom config to become the main one.
|
||||||
void acceptCustomConfig();
|
void acceptCustomConfig();
|
||||||
@@ -103,10 +98,14 @@ public:
|
|||||||
int proxyPort() const;
|
int proxyPort() const;
|
||||||
QString proxyUser() const;
|
QString proxyUser() const;
|
||||||
QString proxyPassword() const;
|
QString proxyPassword() const;
|
||||||
|
|
||||||
|
static void setConfDir(const QString &value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// these classes can only be access from CredentialStore as a friend class.
|
||||||
QString ownCloudPasswd( const QString& connection = QString() ) const;
|
QString ownCloudPasswd( const QString& connection = QString() ) const;
|
||||||
QString ownCloudUser( const QString& connection = QString() ) const;
|
void clearPasswordFromConfig( const QString& connect = QString() );
|
||||||
|
bool writePassword( const QString& passwd, const QString& connection = QString() );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant getValue(const QString& param, const QString& group) const;
|
QVariant getValue(const QString& param, const QString& group) const;
|
||||||
@@ -115,7 +114,9 @@ private:
|
|||||||
private:
|
private:
|
||||||
static bool _askedUser;
|
static bool _askedUser;
|
||||||
static QString _oCVersion;
|
static QString _oCVersion;
|
||||||
|
static QString _confDir;
|
||||||
QString _customHandle;
|
QString _customHandle;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ QIcon mirallTheme::folderIcon( const QString& backend ) const
|
|||||||
return themeIcon( name );
|
return themeIcon( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon mirallTheme::syncStateIcon( SyncResult::Status status ) const
|
QIcon mirallTheme::syncStateIcon( SyncResult::Status status, bool sysTray ) const
|
||||||
{
|
{
|
||||||
QString statusIcon;
|
QString statusIcon;
|
||||||
|
|
||||||
@@ -71,6 +71,7 @@ QIcon mirallTheme::syncStateIcon( SyncResult::Status status ) const
|
|||||||
statusIcon = QLatin1String("dialog-close");
|
statusIcon = QLatin1String("dialog-close");
|
||||||
break;
|
break;
|
||||||
case SyncResult::NotYetStarted:
|
case SyncResult::NotYetStarted:
|
||||||
|
case SyncResult::SyncPrepare:
|
||||||
statusIcon = QLatin1String("task-ongoing");
|
statusIcon = QLatin1String("task-ongoing");
|
||||||
break;
|
break;
|
||||||
case SyncResult::SyncRunning:
|
case SyncResult::SyncRunning:
|
||||||
@@ -88,7 +89,7 @@ QIcon mirallTheme::syncStateIcon( SyncResult::Status status ) const
|
|||||||
default:
|
default:
|
||||||
statusIcon = QLatin1String("dialog-close");
|
statusIcon = QLatin1String("dialog-close");
|
||||||
}
|
}
|
||||||
return themeIcon( statusIcon );
|
return themeIcon( statusIcon, sysTray );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public:
|
|||||||
QPixmap splashScreen() const;
|
QPixmap splashScreen() const;
|
||||||
|
|
||||||
QIcon folderIcon( const QString& ) const;
|
QIcon folderIcon( const QString& ) const;
|
||||||
QIcon syncStateIcon(SyncResult::Status) const;
|
QIcon syncStateIcon(SyncResult::Status, bool) const;
|
||||||
QIcon folderDisabledIcon() const;
|
QIcon folderDisabledIcon() const;
|
||||||
QIcon applicationIcon() const;
|
QIcon applicationIcon() const;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "mirall/mirallconfigfile.h"
|
#include "mirall/mirallconfigfile.h"
|
||||||
#include "mirall/owncloudinfo.h"
|
#include "mirall/owncloudinfo.h"
|
||||||
#include "mirall/credentialstore.h"
|
#include "mirall/credentialstore.h"
|
||||||
|
#include "mirall/logger.h"
|
||||||
|
|
||||||
#include <csync.h>
|
#include <csync.h>
|
||||||
|
|
||||||
@@ -35,6 +36,19 @@
|
|||||||
namespace Mirall {
|
namespace Mirall {
|
||||||
|
|
||||||
|
|
||||||
|
static QString replaceScheme(const QString &urlStr)
|
||||||
|
{
|
||||||
|
|
||||||
|
QUrl url( urlStr );
|
||||||
|
if( url.scheme() == QLatin1String("http") ) {
|
||||||
|
url.setScheme( QLatin1String("owncloud") );
|
||||||
|
} else {
|
||||||
|
// connect SSL!
|
||||||
|
url.setScheme( QLatin1String("ownclouds") );
|
||||||
|
}
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
ownCloudFolder::ownCloudFolder(const QString &alias,
|
ownCloudFolder::ownCloudFolder(const QString &alias,
|
||||||
const QString &path,
|
const QString &path,
|
||||||
const QString &secondPath,
|
const QString &secondPath,
|
||||||
@@ -42,35 +56,16 @@ ownCloudFolder::ownCloudFolder(const QString &alias,
|
|||||||
: Folder(alias, path, secondPath, parent)
|
: Folder(alias, path, secondPath, parent)
|
||||||
, _secondPath(secondPath)
|
, _secondPath(secondPath)
|
||||||
, _thread(0)
|
, _thread(0)
|
||||||
, _localCheckOnly( false )
|
|
||||||
, _localFileChanges( false )
|
|
||||||
, _csync(0)
|
, _csync(0)
|
||||||
, _pollTimerCnt(0)
|
|
||||||
, _csyncError(false)
|
, _csyncError(false)
|
||||||
|
, _csyncUnavail(false)
|
||||||
, _wipeDb(false)
|
, _wipeDb(false)
|
||||||
, _lastSeenFiles(0)
|
|
||||||
{
|
{
|
||||||
#ifdef USE_INOTIFY
|
ServerActionNotifier *notifier = new ServerActionNotifier(this);
|
||||||
|
connect(notifier, SIGNAL(guiLog(QString,QString)), Logger::instance(), SIGNAL(guiLog(QString,QString)));
|
||||||
|
connect(this, SIGNAL(syncFinished(SyncResult)), notifier, SLOT(slotSyncFinished(SyncResult)));
|
||||||
qDebug() << "****** ownCloud folder using watcher *******";
|
qDebug() << "****** ownCloud folder using watcher *******";
|
||||||
// The folder interval is set in the folder parent class.
|
// The folder interval is set in the folder parent class.
|
||||||
#else
|
|
||||||
/* If local polling is used, the polltimer of class Folder has to fire more
|
|
||||||
* often
|
|
||||||
* Set a local poll time of 2000 milliseconds, which results in a 30 seconds
|
|
||||||
* remote poll interval, defined in slotPollTimerRemoteCheck
|
|
||||||
*/
|
|
||||||
|
|
||||||
MirallConfigFile cfgFile;
|
|
||||||
|
|
||||||
_pollTimer->stop();
|
|
||||||
connect( _pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerRemoteCheck()));
|
|
||||||
setPollInterval( cfgFile.localPollInterval()- 500 + (int)( 1000.0*qrand()/(RAND_MAX+1.0) ) );
|
|
||||||
_pollTimerExceed = cfgFile.pollTimerExceedFactor();
|
|
||||||
|
|
||||||
_pollTimerCnt = _pollTimerExceed-1; // start the syncing quickly!
|
|
||||||
_pollTimer->start();
|
|
||||||
qDebug() << "****** ownCloud folder using local poll *******";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ownCloudFolder::~ownCloudFolder()
|
ownCloudFolder::~ownCloudFolder()
|
||||||
@@ -78,13 +73,6 @@ ownCloudFolder::~ownCloudFolder()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only used if INotify is not available. */
|
|
||||||
void ownCloudFolder::slotPollTimerRemoteCheck()
|
|
||||||
{
|
|
||||||
_pollTimerCnt++;
|
|
||||||
qDebug() << "**** Poll Timer for Folder " << alias() << " increase: " << _pollTimerCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ownCloudFolder::isBusy() const
|
bool ownCloudFolder::isBusy() const
|
||||||
{
|
{
|
||||||
return ( _thread && _thread->isRunning() );
|
return ( _thread && _thread->isRunning() );
|
||||||
@@ -123,43 +111,27 @@ void ownCloudFolder::startSync(const QStringList &pathList)
|
|||||||
qCritical() << "* ERROR csync is still running and new sync requested.";
|
qCritical() << "* ERROR csync is still running and new sync requested.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete _csync;
|
delete _csync;
|
||||||
delete _thread;
|
delete _thread;
|
||||||
_errors.clear();
|
_errors.clear();
|
||||||
_csyncError = false;
|
_csyncError = false;
|
||||||
|
_csyncUnavail = false;
|
||||||
_wipeDb = false;
|
_wipeDb = false;
|
||||||
|
|
||||||
MirallConfigFile cfgFile;
|
MirallConfigFile cfgFile;
|
||||||
|
|
||||||
QUrl url( _secondPath );
|
|
||||||
if( url.scheme() == QLatin1String("http") ) {
|
|
||||||
url.setScheme( QLatin1String("owncloud") );
|
|
||||||
} else {
|
|
||||||
// connect SSL!
|
|
||||||
url.setScheme( QLatin1String("ownclouds") );
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_INOTIFY
|
|
||||||
// if there is a watcher and no polling, ever sync is remote.
|
|
||||||
_localCheckOnly = false;
|
|
||||||
_syncResult.clearErrors();
|
_syncResult.clearErrors();
|
||||||
#else
|
// we now have watchers for everything, so every sync is remote.
|
||||||
_localCheckOnly = true;
|
_syncResult.setLocalRunOnly( false );
|
||||||
if( _pollTimerCnt >= _pollTimerExceed || _localFileChanges ) {
|
_syncResult.setStatus( SyncResult::SyncPrepare );
|
||||||
_localCheckOnly = false;
|
emit syncStateChange();
|
||||||
_pollTimerCnt = 0;
|
|
||||||
_localFileChanges = false;
|
|
||||||
_syncResult.clearErrors();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_syncResult.setLocalRunOnly( _localCheckOnly );
|
|
||||||
Folder::startSync( pathList );
|
|
||||||
|
|
||||||
|
QString url = replaceScheme(_secondPath);
|
||||||
|
|
||||||
qDebug() << "*** Start syncing url to ownCloud: " << url.toString() << ", with localOnly: " << _localCheckOnly;
|
qDebug() << "*** Start syncing url to ownCloud: " << url;
|
||||||
|
|
||||||
_thread = new QThread(this);
|
_thread = new QThread(this);
|
||||||
_csync = new CSyncThread( path(), url.toString(), _localCheckOnly );
|
_csync = new CSyncThread( path(), url);
|
||||||
_csync->moveToThread(_thread);
|
_csync->moveToThread(_thread);
|
||||||
|
|
||||||
QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QUrl(cfgFile.ownCloudUrl()));
|
QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QUrl(cfgFile.ownCloudUrl()));
|
||||||
@@ -170,57 +142,24 @@ void ownCloudFolder::startSync(const QStringList &pathList)
|
|||||||
_csync->setConnectionDetails( CredentialStore::instance()->user(),
|
_csync->setConnectionDetails( CredentialStore::instance()->user(),
|
||||||
CredentialStore::instance()->password(),
|
CredentialStore::instance()->password(),
|
||||||
proxy );
|
proxy );
|
||||||
|
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
|
||||||
|
connect( _csync, SIGNAL(treeWalkResult(const SyncFileItemVector&)),
|
||||||
|
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
|
||||||
|
|
||||||
connect(_csync, SIGNAL(started()), SLOT(slotCSyncStarted()), Qt::QueuedConnection);
|
connect(_csync, SIGNAL(started()), SLOT(slotCSyncStarted()), Qt::QueuedConnection);
|
||||||
connect(_csync, SIGNAL(finished()), SLOT(slotCSyncFinished()), Qt::QueuedConnection);
|
connect(_csync, SIGNAL(finished()), SLOT(slotCSyncFinished()), Qt::QueuedConnection);
|
||||||
connect(_csync, SIGNAL(csyncError(const QString)), SLOT(slotCSyncError(const QString)), Qt::QueuedConnection);
|
connect(_csync, SIGNAL(csyncError(QString)), SLOT(slotCSyncError(QString)), Qt::QueuedConnection);
|
||||||
|
connect(_csync, SIGNAL(csyncUnavailable()), SLOT(slotCsyncUnavailable()), Qt::QueuedConnection);
|
||||||
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
|
|
||||||
qRegisterMetaType<WalkStats>("WalkStats");
|
|
||||||
connect( _csync, SIGNAL(treeWalkResult(SyncFileItemVector,WalkStats)),
|
|
||||||
this, SLOT(slotThreadTreeWalkResult(SyncFileItemVector, WalkStats)), Qt::QueuedConnection);
|
|
||||||
_thread->start();
|
_thread->start();
|
||||||
QMetaObject::invokeMethod(_csync, "startSync", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(_csync, "startSync", Qt::QueuedConnection);
|
||||||
|
emit syncStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ownCloudFolder::slotCSyncStarted()
|
void ownCloudFolder::slotCSyncStarted()
|
||||||
{
|
{
|
||||||
qDebug() << " * csync thread started";
|
qDebug() << " * csync thread started";
|
||||||
emit syncStarted();
|
_syncResult.setStatus(SyncResult::SyncRunning);
|
||||||
}
|
emit syncStateChange();
|
||||||
|
|
||||||
void ownCloudFolder::slotThreadTreeWalkResult(const SyncFileItemVector& items, const WalkStats& wStats )
|
|
||||||
{
|
|
||||||
_items = items;
|
|
||||||
qDebug() << "Seen files: " << wStats.seenFiles;
|
|
||||||
|
|
||||||
/* check if there are happend changes in the file system */
|
|
||||||
qDebug() << "New files: " << wStats.newFiles;
|
|
||||||
qDebug() << "Updated files: " << wStats.eval;
|
|
||||||
qDebug() << "Walked files: " << wStats.seenFiles;
|
|
||||||
qDebug() << "Eval files: " << wStats.eval;
|
|
||||||
qDebug() << "Removed files: " << wStats.removed;
|
|
||||||
qDebug() << "Renamed files: " << wStats.renamed;
|
|
||||||
|
|
||||||
if( ! _localCheckOnly ) _lastSeenFiles = 0;
|
|
||||||
_localFileChanges = false;
|
|
||||||
|
|
||||||
#ifndef USE_INOTIFY
|
|
||||||
if( _lastSeenFiles > 0 && _lastSeenFiles != wStats.seenFiles ) {
|
|
||||||
qDebug() << "*** last seen files different from currently seen number " << _lastSeenFiles << "<>" << wStats.seenFiles << " => full Sync needed";
|
|
||||||
_localFileChanges = true;
|
|
||||||
}
|
|
||||||
if( (wStats.newFiles + wStats.eval + wStats.removed + wStats.renamed) > 0 ) {
|
|
||||||
qDebug() << "*** Local changes, lets do a full sync!" ;
|
|
||||||
_localFileChanges = true;
|
|
||||||
}
|
|
||||||
if( _pollTimerCnt < _pollTimerExceed ) {
|
|
||||||
qDebug() << " *** No local changes, finalize, pollTimerCounter is "<< _pollTimerCnt ;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_lastSeenFiles = wStats.seenFiles;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ownCloudFolder::slotCSyncError(const QString& err)
|
void ownCloudFolder::slotCSyncError(const QString& err)
|
||||||
@@ -229,6 +168,11 @@ void ownCloudFolder::slotCSyncError(const QString& err)
|
|||||||
_csyncError = true;
|
_csyncError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ownCloudFolder::slotCsyncUnavailable()
|
||||||
|
{
|
||||||
|
_csyncUnavail = true;
|
||||||
|
}
|
||||||
|
|
||||||
void ownCloudFolder::slotCSyncFinished()
|
void ownCloudFolder::slotCSyncFinished()
|
||||||
{
|
{
|
||||||
qDebug() << "-> CSync Finished slot with error " << _csyncError;
|
qDebug() << "-> CSync Finished slot with error " << _csyncError;
|
||||||
@@ -240,17 +184,23 @@ void ownCloudFolder::slotCSyncFinished()
|
|||||||
_syncResult.setErrorStrings( _errors );
|
_syncResult.setErrorStrings( _errors );
|
||||||
qDebug() << " * owncloud csync thread finished with error";
|
qDebug() << " * owncloud csync thread finished with error";
|
||||||
if( _wipeDb ) wipe();
|
if( _wipeDb ) wipe();
|
||||||
|
} else if (_csyncUnavail) {
|
||||||
|
_syncResult.setStatus(SyncResult::Unavailable);
|
||||||
} else {
|
} else {
|
||||||
_syncResult.setStatus(SyncResult::Success);
|
_syncResult.setStatus(SyncResult::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ! _localCheckOnly ) _lastSeenFiles = 0;
|
|
||||||
if( _thread && _thread->isRunning() ) {
|
if( _thread && _thread->isRunning() ) {
|
||||||
_thread->quit();
|
_thread->quit();
|
||||||
}
|
}
|
||||||
emit syncFinished( _syncResult );
|
emit syncFinished( _syncResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ownCloudFolder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
|
||||||
|
{
|
||||||
|
_syncResult.setSyncFileItemVector(items);
|
||||||
|
}
|
||||||
|
|
||||||
void ownCloudFolder::slotTerminateSync()
|
void ownCloudFolder::slotTerminateSync()
|
||||||
{
|
{
|
||||||
qDebug() << "folder " << alias() << " Terminating!";
|
qDebug() << "folder " << alias() << " Terminating!";
|
||||||
@@ -260,10 +210,7 @@ void ownCloudFolder::slotTerminateSync()
|
|||||||
if( _thread ) {
|
if( _thread ) {
|
||||||
_thread->terminate();
|
_thread->terminate();
|
||||||
_thread->wait();
|
_thread->wait();
|
||||||
// TODO: crashes on win, leak for now, fix properly after 1.1.0
|
_csync->deleteLater();
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
delete _csync;
|
|
||||||
#endif
|
|
||||||
delete _thread;
|
delete _thread;
|
||||||
_csync = 0;
|
_csync = 0;
|
||||||
_thread = 0;
|
_thread = 0;
|
||||||
@@ -330,54 +277,72 @@ void ownCloudFolder::wipe()
|
|||||||
_wipeDb = false;
|
_wipeDb = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncFileStatus ownCloudFolder::fileStatus( const QString& file )
|
ServerActionNotifier::ServerActionNotifier(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
if( file.isEmpty() ) return STATUS_NONE;
|
}
|
||||||
QFileInfo fi( path(), file );
|
|
||||||
|
|
||||||
foreach( const SyncFileItem item, _items ) {
|
void ServerActionNotifier::slotSyncFinished(const SyncResult &result)
|
||||||
qDebug() << "FileStatus compare: " << item.file << " <> " << fi.absoluteFilePath();
|
{
|
||||||
|
SyncFileItemVector items = result.syncFileItemVector();
|
||||||
|
if (items.count() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if( item.file == fi.absoluteFilePath() ) {
|
int newItems = 0;
|
||||||
switch( item.instruction ) {
|
int removedItems = 0;
|
||||||
case CSYNC_INSTRUCTION_NONE:
|
int updatedItems = 0;
|
||||||
return STATUS_NONE;
|
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;
|
break;
|
||||||
case CSYNC_INSTRUCTION_EVAL:
|
case CSYNC_INSTRUCTION_REMOVE:
|
||||||
return STATUS_EVAL;
|
removedItems++;
|
||||||
break;
|
if (firstItemDeleted.isEmpty())
|
||||||
case CSYNC_INSTRUCTION_RENAME:
|
firstItemDeleted = item;
|
||||||
return STATUS_RENAME;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_NEW:
|
|
||||||
return STATUS_NEW;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_CONFLICT:
|
|
||||||
return STATUS_CONFLICT;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_IGNORE:
|
|
||||||
return STATUS_IGNORE;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_SYNC:
|
|
||||||
case CSYNC_INSTRUCTION_UPDATED:
|
|
||||||
return STATUS_SYNC;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_STAT_ERROR:
|
|
||||||
return STATUS_STAT_ERROR;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_ERROR:
|
|
||||||
return STATUS_ERROR;
|
|
||||||
break;
|
|
||||||
case CSYNC_INSTRUCTION_DELETED:
|
|
||||||
case CSYNC_INSTRUCTION_REMOVE:
|
|
||||||
return STATUS_REMOVE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
|
case CSYNC_INSTRUCTION_UPDATED:
|
||||||
|
updatedItems++;
|
||||||
|
if (firstItemUpdated.isEmpty())
|
||||||
|
firstItemUpdated = item;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// nothing.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return STATUS_NEW;
|
|
||||||
|
if (newItems > 0) {
|
||||||
|
QString file = QDir::toNativeSeparators(firstItemNew._file);
|
||||||
|
if (newItems == 1)
|
||||||
|
emit guiLog(tr("New file available"), tr("'%1' has been synced to this machine.").arg(file));
|
||||||
|
else
|
||||||
|
emit guiLog(tr("New files available"), tr("'%1' and %n other file(s) have been synced to this machine.",
|
||||||
|
"", newItems-1).arg(file));
|
||||||
|
}
|
||||||
|
if (removedItems > 0) {
|
||||||
|
QString file = QDir::toNativeSeparators(firstItemDeleted._file);
|
||||||
|
if (removedItems == 1)
|
||||||
|
emit guiLog(tr("File removed"), tr("'%1' has been removed.").arg(file));
|
||||||
|
else
|
||||||
|
emit guiLog(tr("New files available"), tr("'%1' and %n other file(s) have been removed.",
|
||||||
|
"", removedItems-1).arg(file));
|
||||||
|
}
|
||||||
|
if (updatedItems > 0) {
|
||||||
|
QString file = QDir::toNativeSeparators(firstItemUpdated._file);
|
||||||
|
if (updatedItems == 1)
|
||||||
|
emit guiLog(tr("File removed"), tr("'%1' has been updated.").arg(file));
|
||||||
|
else
|
||||||
|
emit guiLog(tr("New files available"), tr("'%1' and %n other file(s) have been updated.",
|
||||||
|
"", updatedItems-1).arg(file));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ns
|
} // ns
|
||||||
|
|||||||