Comparar commits
167 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| e7abeef144 | |||
| 61fd884423 | |||
| d7e4158dd5 | |||
| be3ecd655f | |||
| cefd732179 | |||
| 714cd5c826 | |||
| 3c210c093d | |||
| ca49c6a9df | |||
| 502a7c0e6e | |||
| 1a0f79038b | |||
| c924ad63fe | |||
| 01a7212104 | |||
| 841b3b2365 | |||
| ed416b827f | |||
| 35501fddcd | |||
| 885fb23f2e | |||
| d1946674d3 | |||
| 366562bda7 | |||
| 0b593831f6 | |||
| ea00805227 | |||
| b784e849ba | |||
| b1dc1676ef | |||
| b15f140ae9 | |||
| 1ad4804b3c | |||
| ce0e7e4a5d | |||
| 7121b64c59 | |||
| 1afdeb7216 | |||
| 876407e2e7 | |||
| 6abe714dff | |||
| 37606dab4b | |||
| b637ae1e53 | |||
| cc8a54d314 | |||
| b734958ab9 | |||
| 5287984307 | |||
| e8cce4d1a1 | |||
| b2c01ffe21 | |||
| 517dea6958 | |||
| 225e6c6b9f | |||
| 5f2645b84a | |||
| fc4b11e224 | |||
| cf3383dd59 | |||
| ead6ba50e7 | |||
| 191a6b7d2b | |||
| 096511fc89 | |||
| 85687ce4a2 | |||
| a6bfb23d20 | |||
| 9298891d00 | |||
| 3a1dc6f23e | |||
| a2e5a6628d | |||
| 6b3278cd8e | |||
| 11f225aada | |||
| 8979981553 | |||
| 5a83b30303 | |||
| 986b23856f | |||
| 42ffed3f57 | |||
| 3f399225fa | |||
| dc5d0e367c | |||
| 63712de170 | |||
| 43673d6694 | |||
| f195648b90 | |||
| 06f77acfa1 | |||
| f04a693fbe | |||
| c012711763 | |||
| c6daa8e59b | |||
| 7cc6c1a10f | |||
| 7f73cc1694 | |||
| 87973ac692 | |||
| 84e5ad7346 | |||
| 4559bb5553 | |||
| 2d51a78ee7 | |||
| 95a380ae9e | |||
| f0ce8b8fd4 | |||
| aeb1f10621 | |||
| a3e7f513e6 | |||
| 8b63a6f29b | |||
| 133a8ec225 | |||
| 131747ea4b | |||
| a7f1f886d3 | |||
| 72a90199db | |||
| e69702799f | |||
| 118aead9b9 | |||
| 49bb861045 | |||
| 1d6661e7e4 | |||
| a43173fa90 | |||
| d2a24b5186 | |||
| 40f44c2389 | |||
| 441b5bd1dc | |||
| dc2f0d59cb | |||
| 4dcfacf2d5 | |||
| b7485106ef | |||
| f82893496b | |||
| c418e58f88 | |||
| 3020dc75ab | |||
| 9ea359de52 | |||
| c5daf7d1b6 | |||
| b7d7f424c5 | |||
| e1fa6f1a0d | |||
| a23e0fef8d | |||
| 0fd0b08c09 | |||
| ce1690b450 | |||
| 46bd473664 | |||
| 8fbb55a0c8 | |||
| f046a7e7fe | |||
| b154e1baa1 | |||
| 119a9983a9 | |||
| 2e06b4be66 | |||
| 0ec2e71f58 | |||
| 2ed2ef3b28 | |||
| e7e91b6931 | |||
| 1f9d02e7fa | |||
| 2ee70db7cd | |||
| 3e34d000f2 | |||
| 7f520a6f28 | |||
| 23f72ecf7b | |||
| 8c57e7621b | |||
| 1c001ee138 | |||
| fab82107bb | |||
| 41568c885d | |||
| dba2efe367 | |||
| e3b07f569a | |||
| 65a307970b | |||
| 3e3ca14b4c | |||
| d4e0941c27 | |||
| 9dc57359b9 | |||
| 06b31d7cf0 | |||
| 421a8cc6b7 | |||
| 3a448fda91 | |||
| e890c4ae1b | |||
| 7ada625161 | |||
| 7d8dd54b19 | |||
| 0b275c4933 | |||
| e529bbed90 | |||
| 39e97779ec | |||
| 629d46ca25 | |||
| c5a35ad56f | |||
| 1e94161ec1 | |||
| 6f78ff200c | |||
| 02e96484a8 | |||
| 67b0e4dd15 | |||
| 5b7ec19778 | |||
| e71c617bfd | |||
| f1432992d3 | |||
| 348b7bf4eb | |||
| 30479cc5a2 | |||
| 1ba1bdec2d | |||
| 8993af4378 | |||
| 9a58d0e559 | |||
| b04cb23ed5 | |||
| ced986e010 | |||
| cde9b3ac85 | |||
| f9dfdd58df | |||
| c9f9388ef6 | |||
| b8cb180e4b | |||
| e579504181 | |||
| 7c034b427e | |||
| 08868594ae | |||
| cc6e548a78 | |||
| 89670e5ce4 | |||
| 96a7118d05 | |||
| 2c1f31cecb | |||
| 94be12b9e4 | |||
| 1862fb77ff | |||
| 06b619f0ed | |||
| f5cc6cfd07 | |||
| 0f5cf00e35 | |||
| b5da8423a6 | |||
| c3de0a2d4b |
@@ -21,7 +21,6 @@ else()
|
||||
set(APPLICATION_REV_DOMAIN_INSTALLER ${APPLICATION_REV_DOMAIN})
|
||||
endif()
|
||||
|
||||
|
||||
if (NOT DEFINED APPLICATION_SHORTNAME)
|
||||
set ( APPLICATION_SHORTNAME ${APPLICATION_NAME} )
|
||||
endif()
|
||||
|
||||
@@ -1,6 +1,34 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 1.7.0 (release 2014-10-xx)
|
||||
version 1.7.1 (release 2014-12-18)
|
||||
* Documentation fixes and updates
|
||||
* Nautilus Python plugin fixed for Python 3
|
||||
* GUI wording fixes plus improved log messages
|
||||
* Fix hidning of the database files in the sync directories
|
||||
* Compare http download size with the header value to avoid broken
|
||||
downloads, bug #2528
|
||||
* Avoid initial ETag fetch job at startup, which is not needed.
|
||||
* Add chunk size http header to PUT requests
|
||||
* Fixed deteteCookie method of our CookieJar, fix for Shibboleth
|
||||
* Added fallback for distros where XDG_RUNTIME_DIR is undefined
|
||||
* Fix the setup wizard, bug #1989, #2264
|
||||
* Fix scheduling of ETag check jobs, bug #2553
|
||||
* Fix to avoid syncing more than one folder at a time, bug #2407
|
||||
* Use fife minutes timeout for all network jobs
|
||||
* Cleanup for Folderwizard wording
|
||||
* Improve journal check: Remove corrupted journal files, bug #2547
|
||||
* Fix item count in progress dialog for deletes, bug #1132
|
||||
* Display correct file count on deletion (#1132)
|
||||
* Fix reinitializing the folder using the wizard in certain cases (#2606)
|
||||
* Mac OS: Fixed branding of the pkg file
|
||||
* Mac OS: Fix display of overlay icons in certain situations (#1132)
|
||||
* Mac OS: Use a bundled version of OpenSSL (#764, #2600, #2510)
|
||||
* Win32: improved filesystem watcher
|
||||
* Win32: Improve threading with shell integration
|
||||
* Win32: Upgraded to OpenSSL 1.0.1j
|
||||
* Win32: Improve reliability of Installer, fix removal of Shell Extensions
|
||||
|
||||
version 1.7.0 (release 2014-11-07)
|
||||
|
||||
* oC7 Sharing: Handle new sharing options of ownCloud 7 correctly.
|
||||
* Added Selective sync: Ability to unselect server folders which are
|
||||
|
||||
@@ -8,6 +8,9 @@ set( APPLICATION_UPDATE_URL "https://updates.owncloud.com/client/" CACHE string
|
||||
set( THEME_CLASS "ownCloudTheme" )
|
||||
set( APPLICATION_REV_DOMAIN "com.owncloud.desktopclient" )
|
||||
set( WIN_SETUP_BITMAP_PATH "${CMAKE_SOURCE_DIR}/admin/win/nsi" )
|
||||
|
||||
set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-background.png" CACHE STRING "The MacOSX installer background image")
|
||||
|
||||
# set( THEME_INCLUDE "${OEM_THEME_DIR}/mytheme.h" )
|
||||
# set( APPLICATION_LICENSE "${OEM_THEME_DIR}/license.txt )
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ It uses OCSync as its syncing backend.
|
||||
## Building the source code
|
||||
|
||||
Please refer to doc/building.rst, or
|
||||
[Building the Client](http://doc.owncloud.org/desktop/1.5/building.html)
|
||||
[Building the Client](http://doc.owncloud.org/desktop/1.7/building.html)
|
||||
in the ownCloud client manual.
|
||||
|
||||
## Authors
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set( MIRALL_VERSION_MAJOR 1 )
|
||||
set( MIRALL_VERSION_MINOR 7 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_VERSION_PATCH 1 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
|
||||
# Check if varialbe MAC_INSTALLER_BACKGROUND_FILE is defined. That might come
|
||||
# from the OEM.cmake for branded clients or from OWNCLOUD.cmake for the non
|
||||
# branded client.
|
||||
# Make sure that the MAC_INSTALLER_BACKGROUND_FILE contains the full path, ie.
|
||||
# includes CMAKE_SOURCE_DIR or so.
|
||||
|
||||
if (DEFINED MAC_INSTALLER_BACKGROUND_FILE )
|
||||
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "1")
|
||||
else()
|
||||
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
|
||||
endif()
|
||||
|
||||
configure_file(create_mac_pkg.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
|
||||
configure_file(macosx.pkgproj ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
|
||||
configure_file(macosx.pkgproj ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
|
||||
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh)
|
||||
|
||||
@@ -33,7 +33,6 @@ FRAMEWORK_SEARCH_PATH=[
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '.']
|
||||
|
||||
QT_PLUGINS = [
|
||||
'accessible/libqtaccessiblewidgets.dylib',
|
||||
'sqldrivers/libqsqlite.dylib',
|
||||
'platforms/libqcocoa.dylib',
|
||||
'imageformats/libqgif.dylib',
|
||||
|
||||
@@ -471,13 +471,18 @@
|
||||
</dict>
|
||||
<key>PACKAGE_SCRIPTS</key>
|
||||
<dict>
|
||||
<key>POSTINSTALL_PATH</key>
|
||||
<dict/>
|
||||
<key>PREINSTALL_PATH</key>
|
||||
<dict/>
|
||||
<key>RESOURCES</key>
|
||||
<array/>
|
||||
</dict>
|
||||
<key>POSTINSTALL_PATH</key>
|
||||
<dict/>
|
||||
<key>PREINSTALL_PATH</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>@CMAKE_CURRENT_BINARY_DIR@/pre_install.sh</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>RESOURCES</key>
|
||||
<array/>
|
||||
</dict>
|
||||
<key>PACKAGE_SETTINGS</key>
|
||||
<dict>
|
||||
<key>AUTHENTICATION</key>
|
||||
@@ -1055,12 +1060,12 @@
|
||||
<key>BACKGROUND_PATH</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>@CMAKE_SOURCE_DIR@/admin/osx/installer-background.png</string>
|
||||
<string>@MAC_INSTALLER_BACKGROUND_FILE@</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>CUSTOM</key>
|
||||
<integer>1</integer>
|
||||
<integer>@MAC_INSTALLER_DO_CUSTOM_BACKGROUND@</integer>
|
||||
<key>SCALING</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
# kill the old version. see issue #2044
|
||||
killall @APPLICATION_EXECUTABLE@
|
||||
|
||||
# Unload the Finder plugin. see issue #2105
|
||||
killall Finder
|
||||
|
||||
@@ -5,26 +5,6 @@
|
||||
src_app="$1"
|
||||
identity="$2"
|
||||
|
||||
QT_FMWK_VERSION="5"
|
||||
|
||||
fix_frameworks() {
|
||||
TMP_APP=$1
|
||||
QT_FMWK_PATH=$2
|
||||
QT_FMWKS=$3/Qt*.framework
|
||||
|
||||
echo "Patching Qt frameworks..."
|
||||
for FMWK in $QT_FMWKS; do
|
||||
FMWK_NAME=`basename -s .framework $FMWK`
|
||||
FMWK=`basename $FMWK`
|
||||
FMWK_PATH="${TMP_APP}/Contents/Frameworks/${FMWK}"
|
||||
mkdir -p "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources/"
|
||||
cp -avf "${QT_FMWK_PATH}/${FMWK}/Contents/Info.plist" "${FMWK_PATH}/Versions/${QT_FMWK_VERSION}/Resources"
|
||||
(cd "${FMWK_PATH}" && ln -sf "Versions/${QT_FMWK_VERSION}/Resources" "Resources")
|
||||
perl -pi -e "s/${FMWK_NAME}_debug/${FMWK_NAME}/" "${FMWK_PATH}/Resources/Info.plist"
|
||||
done
|
||||
}
|
||||
|
||||
fix_frameworks "$src_app" `qmake -query QT_INSTALL_LIBS` "$src_app"/Contents/Frameworks
|
||||
codesign -s "$identity" --force --verbose=4 --deep "$src_app"
|
||||
|
||||
# Just for our debug purposes:
|
||||
|
||||
@@ -15,8 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odinstalovat ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Odinstalovat ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vyberte možnost údržby k provedení."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instalují se náležitosti ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Stavová ikona pro Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instaluji stavovou ikonu pro Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Stavové ikony pro Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instaluji stavové ikony pro Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Zástupce v Nabídce Start"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Přidávám zástupce pro ${APPLICATION_NAME} do Nabídky Start."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Zástupce na ploše"
|
||||
|
||||
@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Desinstalli ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalli ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Vali hooldustegevus, mida sa soovid sooritada."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Paigaldan ${APPLICATION_NAME} põhiosa."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Windows Exploreri staatuse ikoon"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Windows Exploreri staatuse ikooni paigaldamine"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Start Menüü Programmide viit"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Lisan ${APPLICATION_NAME} viida Start menüüsse."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Töölaua otsetee"
|
||||
@@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "Paigaldaja on juba k
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "See desinstallija vajab admini ligipääsu, proovi uuesti"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "See desinstallija on juba käimas"
|
||||
StrCpy $SectionGroup_Shortcuts "Viidad"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Montrer les notes de version"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Le(s) processus en cours d’exécution ${APPLICATION_EXECUTABLE} doit être stoppé afin de poursuivre.$\nVoulez-vous que le programme d’installation s’en charge pour vous ?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Fermeture du processus ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Afficher les notes de version"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Le(s) processus en cours d’exécution ${APPLICATION_EXECUTABLE} doit (doivent) être stoppé(s) afin de poursuivre.$\nVoulez-vous que le programme d’installation s’en charge pour vous ?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Fermeture des processus ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Les processus à stopper n'ont pas été trouvés."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Une vieille version de ${APPLICATION_NAME} est installée sur votre système. Il est recommandé que vous désinstalliez cette version avant l'installation. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Une ancienne version de ${APPLICATION_NAME} est installée sur votre système. Il est recommandé de désinstaller cette version avant de continuer. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Désinstaller avant d'installer à nouveau"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Ne pas désinstaller"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Déjà installée"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choisissez comment vous voulez installer ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Choisissez comment installer ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Une version plus récente de ${APPLICATION_NAME} est déjà installée ! Il n'est pas recommandé d'installer une version plus ancienne. Si vous voulez vraiment installer cette version plus ancienne, il est préférable de d'abord désinstaller la version courante. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} est déjà installée.\nSélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} est déjà installé.\nSélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Ajouter/Réinstaller des composants"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Désinstaller ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Désinstaller ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choisir l'option de maintenance à appliquer."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installer les essentiels de ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Choisir l'opération de maintenance à effectuer."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installation des essentiels de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Icônes d'état pour l'Explorateur Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installation des icones d'état pour l'Explorateur Windows"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Raccourci programme du menu Démarrer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Ajouter un raccourci pour ${APPLICATION_NAME} au menu Démarrer."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Ajout d'un raccourci pour ${APPLICATION_NAME} au menu Démarrer."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Raccourci Bureau"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Créer un raccourci Bureau"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Création d'un raccourci sur le Bureau"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Raccourci de lancement rapide"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Créer un raccourci de lancement rapide"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Création d'un raccourci de lancement rapide"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Essentiels de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Raccourci de ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Raccourci Bureau de ${APPLICATION_NAME}."
|
||||
@@ -32,15 +34,13 @@ StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Oui, supprimer ce dossier de données."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Écriture du désinstallateur"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Écriture des clefs de registre du désinstallateur"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Terminé"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Il semble que ${APPLICATION_NAME} ne soit pas installée dans le dossier '$INSTDIR'.$\n$\nVoulez-vous poursuivre (non recommandé) ?"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Il semble que ${APPLICATION_NAME} ne soit pas installé dans le dossier '$INSTDIR'.$\n$\nVoulez-vous poursuivre (non recommandé) ?"
|
||||
StrCpy $UNINSTALL_ABORT "Désinstallation interrompue par l'utilisateur"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Raccourci de lancement rapide (N/A)"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Raccourci de lancement rapide (non disponible)"
|
||||
StrCpy $INIT_NO_DESKTOP "Raccourci bureau (remplace l’existant)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Echec d'élévation, erreur :"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Échec d'élévation, erreur :"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Cet installateur requiert les droits administrateur, essayez à nouveau"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Une installation est déjà en cours."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Ce désinstallateur requiert les droits administrateur, essayez à nouveau"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Une désinstallation est déjà en cours."
|
||||
StrCpy $SectionGroup_Shortcuts "Raccourcis"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status icons for Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing status icons for Windows Explorer"
|
||||
|
||||
@@ -15,8 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "${APPLICATION_NAME} entfernen"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "${APPLICATION_NAME} entfernen"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Wählen Sie zur Ausführung die Wartungsoption."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Installiere ${APPLICATION_NAME} Basis."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Status-Icons für den Windows-Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installiere Status-Icons für den Windows-Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Statussymbole für den Windows-Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Statussymbole für den Windows-Explorer werden installiert"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Installiere Verknüpfung im Programmmenü"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Füge Verknüpfung für ${APPLICATION_NAME} dem Startmenü hinzu."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Desktop-Verknüpfung"
|
||||
@@ -38,7 +38,7 @@ StrCpy $UNINSTALL_MESSAGEBOX "Es scheint, als ob ${APPLICATION_NAME} nicht im Ve
|
||||
StrCpy $UNINSTALL_ABORT "Deinstallation vom Benutzer abgebrochen"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Schnellstart-Verknüpfung (Nicht verfügbar)"
|
||||
StrCpy $INIT_NO_DESKTOP "Desktop-Verknüpfung (überschreibt vorhandene)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Kann Rechte nicht erhöhen, Fehler:"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Rechte können nicht erhöht werden, Fehler:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Dieses Installationsprogramm erfordert Administrator-Rechte, bitte erneut versuchen"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Das Installationsprogramm wird bereits ausgeführt."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Das Deinstallationsprogramm erfordert Administrator-Rechte. Bitte erneut versuchen."
|
||||
|
||||
@@ -16,7 +16,7 @@ StrCpy $UNINSTALLER_APPDATA_TITLE "
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Επιλέξτε την επιλογή συντήρησης που θα πραγματοποιηθεί."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Εγκατάσταση βάσης ${APPLICATION_NAME} σε εξέλιξη."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Εικονίδια κατάστασης για την Εξερεύνηση των Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Εγκατάσταση εικονιδίων κατάστασης στην Εξερεύνηση των Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Εγκατάσταση εικονιδίων κατάστασης για την Εξερεύνηση των Windows"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Συντόμευση στο Αρχικό Μενού"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Προσθήκη συντόμευσης για την ${APPLICATION_NAME} στο Αρχικό Μενού."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Συντόμευση επιφάνειας εργασίας"
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de lançamento"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Encontrados processos ${APPLICATION_EXECUTABLE} que precisam de ser parados.$\nDeseja que o instalador os pare ?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "A terminar processos ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Processo para terminar não foi encontrado!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Está instalada uma versão anterior de ${APPLICATION_NAME} no seu sistema. Recomenda-se que desinstale primeiro a versão atual antes de instalar. Selecione a operação que pretende fazer, e clique Seguinte para continuar."
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Processos(s) ${APPLICATION_EXECUTABLE} em execução. Estes processos precisam de ser interrompidos.$\\nDeseja que o instalador os termine automaticamente?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "A terminar os processos ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Não foi encontrado o processo a terminar!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Uma versão antiga de ${APPLICATION_NAME} está instalada no sistema. É recomendado que você desinstale a versão atual antes de instalar. Selecione a operação que deseja executar e clique em $\"Avançar$\" para continuar."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Não desinstalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Não desinstale"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolha como pretende instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Já esta instalada uma nova versão dfe ${APPLICATION_NAME}! Não se recomenda instalar uma versão anterior. Se quer mesmo instalar esta versão mais antiga, é melhor desinstalar primeiro a versão atual. Selecione a operação que pretende fazer e clique Seguinte para continuar."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uma versão mais recente do ${APPLICATION_NAME} já está instalada! Não é recomendada a instalação de uma versão mais antiga. Se realmente deseja instalar esta versão, aconselha-se a desinstalação da versão atual primeiro. Selecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} já está instalado.\nSelecione a operação que deseja fazer, e clique Seguinte para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Adicionar/Reinstalar Componentes"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalar ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolha a opção de manutenção a fazer."
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolha a opção de manutenção a realizar."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "A instalar o essencial de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Icons de estado para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "A instalar icons de estado para Windows Explorer"
|
||||
@@ -40,7 +40,7 @@ StrCpy $INIT_NO_QUICK_LAUNCH "Atalho de Início Rápido (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Atalho do Ambiente de Trabalho (sobrepõe o existente)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Incapaz de elevar, erro:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Este instalador precisa de permissões de administrador, tente novamente"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "O instalador já está a correr."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este desinstalador precisa de acesso de administrador; tente novamente"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "O desinstalador já está a correr."
|
||||
StrCpy $INIT_INSTALLER_RUNNING "O instalador já está em execução."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Este desinstalador requer permissões de administrador, tente novamente"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "O desinstalador já está em execução."
|
||||
StrCpy $SectionGroup_Shortcuts "Atalhos"
|
||||
|
||||
@@ -27,14 +27,14 @@ StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Зависимости прилож
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Ярлык приложения ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Ярлык на рабочем столе для ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Ярлык в меню быстрого запуска для ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Удалить папку данных ${APPLICATION_NAME} с вашего компьютера."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Вы хотите удалить папку с данными ${APPLICATION_NAME} ?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Оставьте неактивным, для сохранения папки с данными приложения, для последующего их использования."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Да, удалить эту папку с данными."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Удалить каталог данных ${APPLICATION_NAME} с вашего компьютера."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Вы хотите удалить каталог с данными ${APPLICATION_NAME} ?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Оставьте неактивным, для сохранения каталога с данными приложения, для последующего их использования."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Да, удалить этот каталог с данными."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Сохранение деинсталятора"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Запись ключей реестра"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Завершено"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Скорее всего, приложение ${APPLICATION_NAME} уже установлено в директорию '$INSTDIR'.\nВсе равно продолжить (не рекомендуется)?"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Скорее всего, приложение ${APPLICATION_NAME} уже установлено в каталог '$INSTDIR'.\nВсе равно продолжить (не рекомендуется)?"
|
||||
StrCpy $UNINSTALL_ABORT "Удаление отменено пользователем"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Ярлык быстрого запуска (недоступен)"
|
||||
StrCpy $INIT_NO_DESKTOP "Ярлык на рабочем столе (перезаписать существующий)"
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar las notas de la versión"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "El/los proceso/s ${APPLICATION_EXECUTABLE} debe/n ser detenidos.$\n¿Quiere que el instalador lo haga por usted?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Deteniendo el/los proceso/s ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso a detener no encontrado!"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso para detener no encontrado!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} se encuentra instalada en el sistema. Se recomienda de instalar la versión actual antes de instalar la nueva. Seleccione la operacion deseada y haga click en Siguiente para continuar."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "No desinstalar"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ya está instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Elija como quiere instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Elija cómo quiere instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Una nueva versión de ${APPLICATION_NAME} ya está instalada. No es recomendable instalar una versión anterior. Si realmente quiere instalar esta versión anterior, es mejor que desinstale la versión actual primero. Seleccione la operación que desea realizar y pulse Next para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ya está instalada.\nSeleccione la operación que desea realizar y pulse Next para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Añadir/Reinstalar componentes"
|
||||
@@ -17,7 +17,7 @@ StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Elija la opcion de mantenim
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} esenciales."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Íconos de estado para el Explorador de Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando íconos de estado para el Explorador de Windows"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso Directo al Programa Menú de Inicio"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo al programa Menú de Inicio"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Añadiendo accesos directos para ${APPLICATION_NAME} en el Menú de Inicio."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo de Escritorio"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando Accesos Directos de Escritorio"
|
||||
@@ -27,20 +27,20 @@ StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esencial."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Acceso Directo de ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Acceso Directo de Escritorio para ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Lanzador Rápido de Accesos Director para ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Remueva la carpeta de datos de ${APPLICATION_NAME} del computador."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Elimine la carpeta de datos de ${APPLICATION_NAME} del computador."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "¿Desea eliminar la carpeta de datos de ${APPLICATION_NAME}?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Deja sin marcar para mantener la carpeta de datos para uso posterior, o del marque para eliminar la carpeta de datos."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Si, Elimine esta carpeta de datos."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Escribiendo Desinstalador"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Escribiendo Llaves en el Registro del Instalador"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Déjelo sin marcar para mantener la carpeta de datos para uso posterior o márquelo para eliminar la carpeta de datos."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Sí, elimine esta carpeta de datos."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Escribiendo desinstalador"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Escribiendo claves en el registro del instalador"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Terminado"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Parece que ${APPLICATION_NAME} no está instalado en el directorio '$INSTDIR'.$$ ¿Continuar de todos modos? (No Recomendado)"
|
||||
StrCpy $UNINSTALL_ABORT "Desinstalación cancelada por el usuario"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Acceso Directo al Lanzador Rápido (N/A)"
|
||||
StrCpy $INIT_NO_DESKTOP "Atajo de escritorio (sobreescribe el existente)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "No se ha podido elevar, Error:"
|
||||
StrCpy $UAC_ERROR_ELEVATE "No se ha podido elevar, error:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "El instalador requiere acceso administrativo, intente de nuevo"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "El instalador ya se encuentra en ejecución"
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "El desinstalador requiere acceso administrativo, intente de nuevo"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "El desinstalador ya se encuentra en ejecución."
|
||||
StrCpy $SectionGroup_Shortcuts "Accesos Directos"
|
||||
StrCpy $SectionGroup_Shortcuts "Accesos directos"
|
||||
|
||||
@@ -41,6 +41,6 @@ StrCpy $INIT_NO_DESKTOP "Skrivbordsgenväg (skriver över nuvarande)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Kunde inte få förhöjda rättigheter, fel:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Detta installationsprogram kräver adminstratörs rättigheter, försök igen"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Installationsprogrammet körs redan."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Detta avinstallationsprogram kräver administratörs rättigheter, försök igen"
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Detta avinstallationsprogram kräver administratörsrättigheter, försök igen"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallationsprogrammet körs redan."
|
||||
StrCpy $SectionGroup_Shortcuts "Genvägar"
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Показати примітки до випуску"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Знайдено процес(и) ${APPLICATION_EXECUTABLE}, які необхідно зупинити.$\nХочете щоб програма установки зробила це самостійно?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Завершення процесів ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Не знайдено процеси, які необхідно зупинити!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Знайдено застарілу версію програми ${APPLICATION_NAME}. Рекомендуємо її спочатку видалити. Оберіть подальшу дію та натисніть $\"Далі$\"."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Видалити перед установкою"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Не видаляти"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Установлено"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Оберіть, як ви хочете установити ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Знайдено новішу версію ${APPLICATION_NAME}! Ми не рекомендуємо встановлювати стару версію. Якщо ви все ж бажаєте встановити цю версію, спочатку видаліть поточну версію. Оберіть подальшу дію та натисніть $\"Далі$\"."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} вже встановлено.↩\nОберіть подальшу дію та натисніть $\"Далі$\"."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Додати/Перевстановити компоненти"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Видалити ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Видалити ${APPLICATION_NAME}"
|
||||
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Оберіть опцію обслуговування для виконання."
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Установка залежностей ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Значки стану для провідника Windows"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Установка значків стану для провідника Windows"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Ярлик в меню Пуск"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Створення ярлика ${APPLICATION_NAME} в меню Пуск."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Ярлик на Робочому столі"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Створення ярлика на Робочому столі"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Ярлик на панелі швидкого запуску"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Створення ярлика на панелі швидкого запуску"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} залежності."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "${APPLICATION_NAME} ярлик."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Ярлик ${APPLICATION_NAME} на Робочому столі."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Ярлик ${APPLICATION_NAME} на панелі швидкого запуску."
|
||||
StrCpy $UNINSTALLER_APPDATA_SUBTITLE "Видалити теку даних ${APPLICATION_NAME} з вашого комп'ютера."
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_1 "Ви дійсно бажаєте видалити теку даних ${APPLICATION_NAME}?"
|
||||
StrCpy $UNINSTALLER_APPDATA_LABEL_2 "Залиште неактивним, для збереження теки з даними програми, для подальшого використання."
|
||||
StrCpy $UNINSTALLER_APPDATA_CHECKBOX "Так, видалити теку даних."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Збереження Програми видалення"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Запис ключів реєстру"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Завершено"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Скоріш за все ${APPLICATION_NAME} вже встановлено в теку '$INSTDIR'.$↩$\nВсе одно продовжити (не рекомендується)?"
|
||||
StrCpy $UNINSTALL_ABORT "Видалення перервано користувачем."
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Ярлик в області швидкого запуску (недоступний)"
|
||||
StrCpy $INIT_NO_DESKTOP "Ярлик на Робочому столі (перезаписати існуючий)"
|
||||
StrCpy $UAC_ERROR_ELEVATE "Неможливо підняти, помилка:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Для установки потрібні права адміністратора, спробуйте ще раз"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "Установка вже запущена."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Для видалення потрібні права адміністратора, спробуйте ще раз"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Програма видалення вже запущено."
|
||||
StrCpy $SectionGroup_Shortcuts "Ярлики"
|
||||
@@ -6,6 +6,7 @@
|
||||
!insertmacro MUI_LANGUAGE "SpanishInternational"
|
||||
!insertmacro MUI_LANGUAGE "Dutch"
|
||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||
!insertmacro MUI_LANGUAGE "Ukrainian"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "Catalan"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SET(WINDRES_EXECUTABLE ${CMAKE_RC_COMPILER})
|
||||
SET(WINDRES_EXECUTABLE_BASE ${CMAKE_RC_COMPILER})
|
||||
|
||||
# This macro is taken from kdelibs/cmake/modules/KDE4Macros.cmake.
|
||||
#
|
||||
@@ -21,7 +21,7 @@ macro (KDE4_ADD_APP_ICON appsources pattern)
|
||||
else(NOT WINCE)
|
||||
find_program(PNG2ICO_EXECUTABLE NAMES png2ico PATHS ${HOST_BINDIR} NO_DEFAULT_PATH )
|
||||
endif(NOT WINCE)
|
||||
find_program(WINDRES_EXECUTABLE NAMES windres)
|
||||
find_program(WINDRES_EXECUTABLE NAMES ${WINDRES_EXECUTABLE_BASE})
|
||||
if(MSVC)
|
||||
set(WINDRES_EXECUTABLE TRUE)
|
||||
endif(MSVC)
|
||||
|
||||
@@ -396,8 +396,6 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "${PLATFORMS_DLL_PATH}\qwindows.dll"
|
||||
SetOutPath "$INSTDIR\accessible"
|
||||
File "${ACCESSIBLE_DLL_PATH}\qtaccessiblewidgets.dll"
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qgif.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qjpeg.dll"
|
||||
@@ -419,13 +417,17 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
File "${QT_DLL_PATH}\Qt5PrintSupport.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Qml.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Quick.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Sensors.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Sql.dll"
|
||||
File "${QT_DLL_PATH}\Qt5WebKit.dll"
|
||||
File "${QT_DLL_PATH}\Qt5WebKitWidgets.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Widgets.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Xml.dll"
|
||||
|
||||
;QtWebKit dependencies
|
||||
File "${QT_DLL_PATH}\Qt5Multimedia.dll"
|
||||
File "${QT_DLL_PATH}\Qt5MultimediaWidgets.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Sensors.dll"
|
||||
|
||||
;Qt deps
|
||||
File "${MING_BIN}\libpng16-16.dll"
|
||||
File "${MING_BIN}\icudata53.dll"
|
||||
@@ -456,7 +458,6 @@ Section "${APPLICATION_NAME}" SEC_APPLICATION
|
||||
File "${MING_BIN}\libproxy.dll"
|
||||
File "${MING_BIN}\libmodman.dll"
|
||||
File "${MING_BIN}\libxml2-2.dll"
|
||||
|
||||
;MinGW stuff
|
||||
File "${MING_BIN}\libgcc_s_sjlj-1.dll"
|
||||
File "${MING_BIN}\libstdc++-6.dll"
|
||||
@@ -476,6 +477,8 @@ SectionEnd
|
||||
File "${BUILD_PATH}\vcredist_x64.exe"
|
||||
Call InstallRedistributables
|
||||
CreateDirectory "$INSTDIR\shellext"
|
||||
!define LIBRARY_COM
|
||||
!define LIBRARY_SHELL_EXTENSION
|
||||
${If} ${RunningX64}
|
||||
!define LIBRARY_X64
|
||||
!insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\x64\OCUtil_x64.dll" "$INSTDIR\shellext\OCUtil_x64.dll" "$INSTDIR\shellext"
|
||||
@@ -485,6 +488,8 @@ SectionEnd
|
||||
!insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCUtil_x86.dll" "$INSTDIR\shellext\OCUtil_x86.dll" "$INSTDIR\shellext"
|
||||
!insertmacro InstallLib REGDLL NOTSHARED REBOOT_PROTECTED "${SOURCE_PATH}\binary\shell_integration\windows\Release\Win32\OCOverlays_x86.dll" "$INSTDIR\shellext\OCOverlays_x86.dll" "$INSTDIR\shellext"
|
||||
${Endif}
|
||||
!undef LIBRARY_COM
|
||||
!undef LIBRARY_SHELL_EXTENSION
|
||||
${MementoSectionEnd}
|
||||
!endif
|
||||
|
||||
@@ -640,15 +645,19 @@ Section Uninstall
|
||||
!define LIBRARY_COM
|
||||
!define LIBRARY_SHELL_EXTENSION
|
||||
${If} ${HasSection} SEC_SHELL_EXT
|
||||
DetailPrint "Uninstalling x64 overlay DLLs"
|
||||
!define LIBRARY_X64
|
||||
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCUtil_x64.dll"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCOverlays_x64.dll"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCOverlays_x64.dll"
|
||||
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCUtil_x64.dll"
|
||||
!undef LIBRARY_X64
|
||||
${Else}
|
||||
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCUtil_x86.dll"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR/shellext/OCOverlays_x86.dll"
|
||||
DetailPrint "Uninstalling x86 overlay DLLs"
|
||||
!insertmacro UnInstallLib REGDLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCOverlays_x86.dll"
|
||||
!insertmacro UnInstallLib DLL NOTSHARED REBOOT_PROTECTED "$INSTDIR\shellext\OCUtil_x86.dll"
|
||||
${EndIf}
|
||||
!endif
|
||||
!undef LIBRARY_COM
|
||||
!undef LIBRARY_SHELL_EXTENSION
|
||||
!endif
|
||||
|
||||
;Start menu shortcut
|
||||
!ifdef OPTION_SECTION_SC_START_MENU
|
||||
|
||||
@@ -254,6 +254,10 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
is_equal_files = (other->modtime == cur->modtime);
|
||||
} else {
|
||||
is_equal_files = ((other->size == cur->size) && (other->modtime == cur->modtime));
|
||||
// FIXME: do a binary comparision of the file here because of the following
|
||||
// edge case:
|
||||
// The files could still have different content, even though the mtime
|
||||
// and size are the same.
|
||||
}
|
||||
if (is_equal_files) {
|
||||
/* The files are considered equal. */
|
||||
|
||||
@@ -503,6 +503,8 @@ Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const cha
|
||||
|
||||
if( transfer->block_cnt > 1 ) {
|
||||
ne_add_request_header(req, "OC-Chunked", "1");
|
||||
snprintf(buf, sizeof(buf), "%"PRId64, transfer->threshold);
|
||||
ne_add_request_header(req, "OC-Chunk-Size", buf);
|
||||
}
|
||||
ne_add_request_header( req, "Content-Type", "application/octet-stream");
|
||||
|
||||
|
||||
@@ -127,10 +127,9 @@ glob_put( "$tmpdir2/*", "parallel" );
|
||||
|
||||
csync();
|
||||
|
||||
# We assume the smaller file finished first, blocking
|
||||
# the second file from being saved.
|
||||
assert( !-e localDir() . 'parallel/FILE.dat' );
|
||||
assert( -e localDir() . 'parallel/file.dat' );
|
||||
# only one file must exist
|
||||
assert( (!-e localDir() . 'parallel/FILE.dat' ) or (!-e localDir() . 'parallel/file.dat') );
|
||||
assert( (-e localDir() . 'parallel/FILE.dat' ) or (-e localDir() . 'parallel/file.dat') );
|
||||
|
||||
cleanup();
|
||||
system("rm -r " . $tmpdir);
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
Setting up an Account
|
||||
=====================
|
||||
|
||||
If no account has been configured, the ownCloud Client automatically assist in
|
||||
connecting to your ownCloud server after the application has been started.
|
||||
When you run the ownCloud Desktop Sync client the first time, it automatically
|
||||
opens the account setup wizard. Just follow these steps:
|
||||
|
||||
To set up an account:
|
||||
|
||||
1. Specify the URL to your Server. This is the same address that is used in the browser.
|
||||
1. Enter the URL to your Server. This is the same address used by your Web
|
||||
browser, for example ``https://example.com/owncloud``
|
||||
|
||||
.. image:: images/wizard_url.png
|
||||
:scale: 50 %
|
||||
|
||||
.. note:: Make sure to use ``https://`` if the server supports it. Otherwise,
|
||||
your password and all data will be transferred to the server unencrypted. This
|
||||
makes it easy for third parties to intercept your communication, and getting
|
||||
hold of your password!
|
||||
.. note:: Always use ``https://`` if SSL encryption is enabled on your server.
|
||||
Otherwise, your password and all traffic between your computer and the
|
||||
ownCloud server will be transmitted in the clear and wide open for
|
||||
eavesdroppers.
|
||||
|
||||
2. Enter the username and password. These are the same credentials used to log into the web interface.
|
||||
2. Enter your username and password. These are the same credentials used to
|
||||
log into the ownCloud Web interface.
|
||||
|
||||
.. image:: images/wizard_user.png
|
||||
:scale: 50 %
|
||||
|
||||
3. Choose the folder with which you want the ownCloud Client to synchronize the
|
||||
contents of your ownCloud account. By default, this is a folder called
|
||||
`ownCloud`. This folder is created in the home directory.
|
||||
3. Choose the local folder you want to store your ownCloud files in. By
|
||||
default, this is a folder called ``ownCloud`` in your home directory.
|
||||
|
||||
.. image:: images/wizard_targetfolder.png
|
||||
:scale: 50 %
|
||||
|
||||
The synchronization between the root directories of the ownCloud server begins.
|
||||
4. The synchronization automatically begins.
|
||||
|
||||
.. image:: images/wizard_overview.png
|
||||
:scale: 50 %
|
||||
@@ -40,3 +39,6 @@ When selecting a local folder that already contains data, you can choose from tw
|
||||
|
||||
* :guilabel:`Start a clean sync`: When selected, all files in the local folder on the
|
||||
client are deleted. These files are not syncrhonized to the ownCloud server.
|
||||
|
||||
See :doc:`navigating` to learn how to choose specific folders to sync with on
|
||||
your ownCloud server.
|
||||
@@ -1,3 +1,4 @@
|
||||
==============
|
||||
Advanced Usage
|
||||
==============
|
||||
|
||||
|
||||
@@ -25,16 +25,17 @@ result, the ownCloud Client runs on Linux, Windows, and MacOS.
|
||||
The Synchronization Process
|
||||
---------------------------
|
||||
|
||||
The process of synchronization keeps files in two separate repositories the same. When syncrhonized:
|
||||
The process of synchronization keeps files in two separate repositories the
|
||||
same. When synchronized:
|
||||
|
||||
- If a file is added to one repository it is copied to the other synchronized repository.
|
||||
- When a file is changed in one repository, the change is propagated to any
|
||||
syncrhonized other repositories- If a file is deleted in one repository, it
|
||||
is deleted in any other.
|
||||
- When a file is changed in one repository, the change is propagated to any other
|
||||
synchronized repository.
|
||||
- If a file is deleted in one repository, it is deleted in any other.
|
||||
|
||||
It is important to note that the ownCloud synchronization process does not use
|
||||
a typical client/server system where the server is always master. This is a
|
||||
major difference between the ownCloud syncrhonizatin process and other systems
|
||||
major difference between the ownCloud synchronization process and other systems
|
||||
like a file backup, where only changes to files or folders and the addition of
|
||||
new files are propagated, but these files and folders are never deleted unless
|
||||
explicitly deleted in the backup.
|
||||
@@ -64,7 +65,7 @@ To compare the modification times of two files from different systems, csync
|
||||
must operate on the same base. Before ownCloud Client version 1.1.0, csync
|
||||
required both device repositories to run on the exact same time. This
|
||||
requirement was achieved through the use of enterprise standard `NTP time
|
||||
synchronisation`_ on all machines.
|
||||
synchronization`_ on all machines.
|
||||
|
||||
Because this timing strategy is rather fragile without the use of NTP, ownCloud
|
||||
4.5 introduced a unique number (for each file?) that changes whenever the file
|
||||
@@ -123,8 +124,9 @@ traverses the file tree and compares the modification time of each file with an
|
||||
expected value stored in its database. If the value is not the same, the client
|
||||
determines that the file has been modified in the local repository.
|
||||
|
||||
.. note:: On the local side, the modificaton time a good attribute to use for detecting changes, because
|
||||
the value does not depend on time shifts and such.
|
||||
.. note:: On the local side, the modification time a good attribute to use for
|
||||
detecting changes, because
|
||||
the value does not depend on time shifts and such.
|
||||
|
||||
For the remote (that is, ownCloud server) repository, the client compares the
|
||||
ETag of each file with its expected value. Again, the expected ETag value is
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
The Automatic Updater
|
||||
=====================
|
||||
|
||||
To ensure that you are always using the latest version of the ownCloud client,
|
||||
an auto-update mechanism has been added in Version 1.5.1. The Automatic Updater
|
||||
ensures that you automatically profit from the latest features and bugfixes.
|
||||
The Automatic Updater ensures that you always have the
|
||||
latest features and bugfixes for your ownCloud synchronization client.
|
||||
|
||||
.. note:: The Automatic Updater functions differently, depending on the operating system.
|
||||
The Automatic Updater updates only on Mac OS X and Windows computers; Linux
|
||||
users only need to use their normal package managers. However, on Linux systems
|
||||
the Updater will check for updates and notify you when a new version is
|
||||
available.
|
||||
|
||||
.. note:: Because of various technical issues, desktop sync clients older than
|
||||
1.7 will not be allowed to connect and sync with the ownCloud 8.1 server. It is
|
||||
highly recommended to keep your client updated.
|
||||
|
||||
Basic Workflow
|
||||
--------------
|
||||
|
||||
The following sections describe how to use the Automatic Updater on different operating systems:
|
||||
The following sections describe how to use the Automatic Updater on different
|
||||
operating systems:
|
||||
|
||||
Windows
|
||||
^^^^^^^
|
||||
@@ -36,11 +43,10 @@ process for Mac OS X applications.
|
||||
Linux
|
||||
^^^^^
|
||||
|
||||
Linux distributions provide their own update tool, so ownCloud clients that use
|
||||
the Linux operating system do not perform any updates on their own. Linux
|
||||
operating systems do, however, check for the latest version of the ownCloud
|
||||
client and passively notify the user (``Settings -> General -> Updates``) when
|
||||
an update is available.
|
||||
Linux distributions provide their own update tools, so ownCloud clients that use
|
||||
the Linux operating system do not perform any updates on their own. The client
|
||||
will inform you (``Settings -> General -> Updates``) when an update is
|
||||
available.
|
||||
|
||||
|
||||
Preventing Automatic Updates
|
||||
@@ -52,7 +58,7 @@ deployment tools and policies. To address this case, it is possible to disable
|
||||
the auto-updater entirely. The following sections describe how to disable the
|
||||
auto-update mechanism for different operating systems.
|
||||
|
||||
Preventing Automatic Updates in Windows Environents
|
||||
Preventing Automatic Updates in Windows Environments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can prevent automatic updates from occuring in Windows environments using
|
||||
@@ -61,7 +67,7 @@ update check mechanism whereas the second method prevents any manual overrides.
|
||||
|
||||
To prevent automatic updates, but allow manual overrides:
|
||||
|
||||
1. Migrate to the following directory:
|
||||
1. Edit these Registry keys:
|
||||
|
||||
a. (32-bit) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud``
|
||||
b. (64-bit) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud``
|
||||
@@ -74,7 +80,8 @@ To manually override this key, use the same value in ``HKEY_CURRENT_USER``.
|
||||
|
||||
To prevent automatic updates and disallow manual overrides:
|
||||
|
||||
.. note::This is the preferred method of controlling the updater behavior using Group Policies.
|
||||
.. note::This is the preferred method of controlling the updater behavior using
|
||||
Group Policies.
|
||||
|
||||
1. Migrate to the following directory::
|
||||
|
||||
@@ -88,10 +95,10 @@ To prevent automatic updates and disallow manual overrides:
|
||||
Preventing Automatic Updates in Mac OS X Environments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can disable the automatic update mechanism in MAC OS X operating systems
|
||||
You can disable the automatic update mechanism in Mac OS X operating systems
|
||||
using the system-wide ``.plist`` file. To access this file:
|
||||
|
||||
1. Using the Windows explorer, migrate to the following location::
|
||||
1. Go to this directory::
|
||||
|
||||
/Library/Preferences/
|
||||
|
||||
@@ -112,16 +119,10 @@ to ``/Library/Preferences/com.owncloud.desktopclient.plist``.
|
||||
Preventing Automatic Updates in Linux Environments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Because Linux does not provide automatic updating functionality, there is no
|
||||
need to remove the automatic-update check. However, if you want to disable
|
||||
this check:
|
||||
Because the Linux client does not provide automatic updating functionality, there is no
|
||||
need to remove the automatic-update check. However, if you want to disable it edit your desktop
|
||||
client configuration file, ``$HOME/.local/share/data/ownCloud/owncloud.cfg``. Add these lines:
|
||||
|
||||
1. Locate and open the following file::
|
||||
|
||||
/etc/ownCloud/ownCloud.conf
|
||||
|
||||
2. Add the following content to the file::
|
||||
|
||||
[General]
|
||||
skipUpdateCheck=true
|
||||
[General]
|
||||
skipUpdateCheck=true
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ Linux
|
||||
-----
|
||||
|
||||
1. Add the `ownCloud repository from OBS`_.
|
||||
2. Install the dependencies (as root, or using ``sudo``) using the following commands for your specific Linux distribution:
|
||||
|
||||
* Debian/Ubuntu: ``apt-get update; apt-get build-dep owncloud-client``
|
||||
* openSUSE: ``zypper ref; zypper si -d owncloud-client``
|
||||
* Fedora/CentOS: ``yum install yum-utils; yum-builddep owncloud-client``
|
||||
2. Install the dependencies (as root, or using ``sudo``) using the following
|
||||
commands for your specific Linux distribution:
|
||||
|
||||
* Debian/Ubuntu: ``apt-get update; apt-get build-dep owncloud-client``
|
||||
* openSUSE: ``zypper ref; zypper si -d owncloud-client``
|
||||
* Fedora/CentOS: ``yum install yum-utils; yum-builddep owncloud-client``
|
||||
|
||||
3. Follow the `generic build instructions`_.
|
||||
|
||||
@@ -33,7 +34,7 @@ Mac OS X
|
||||
--------
|
||||
|
||||
In additon to needing XCode (along with the command line tools), developing in
|
||||
the MAC OS X environment requires extra dependencies. You can install these
|
||||
the Mac OS X environment requires extra dependencies. You can install these
|
||||
dependencies through MacPorts_ or Homebrew_. These dependencies are required
|
||||
only on the build machine, because non-standard libs are deployed in the app
|
||||
bundle.
|
||||
@@ -138,26 +139,26 @@ To cross-compile:
|
||||
Generic Build Instructions
|
||||
--------------------------
|
||||
|
||||
Compared to previous versions, building Mirall has become easier. Unlike
|
||||
earlier versions, CSync, which is the sync engine library of Mirall, is now
|
||||
part of the Mirall source repository and not a separate module.
|
||||
Compared to previous versions, building the desktop sync client has become
|
||||
easier. Unlike earlier versions, CSync, which is the sync engine library of the
|
||||
client, is now part of the client source repository and not a separate module.
|
||||
|
||||
You can download Mirall from the ownCloud `Client Download Page`_.
|
||||
You can download the client from the ownCloud `Client Download Page`_.
|
||||
|
||||
To build the most up to date version of the client:
|
||||
|
||||
1. Clone the latest versions of Mirall from Git_ as follows:
|
||||
1. Clone the latest versions of the client from Git_ as follows:
|
||||
|
||||
``git clone git://github.com/owncloud/mirall.git``
|
||||
``git clone git://github.com/owncloud/client.git``
|
||||
|
||||
2. Create build directories:
|
||||
|
||||
``mkdir mirall-build``
|
||||
``mkdir client-build``
|
||||
|
||||
3. Build mirall:
|
||||
3. Build the client:
|
||||
|
||||
``cd ../mirall-build``
|
||||
``cmake -DCMAKE_BUILD_TYPE="Debug" ../mirall``
|
||||
``cd ../client-build``
|
||||
``cmake -DCMAKE_BUILD_TYPE="Debug" ../client``
|
||||
|
||||
..note:: You must use absolute paths for the ``include`` and ``library``
|
||||
directories.
|
||||
|
||||
|
Depois Largura: | Altura: | Tamanho: 4.9 KiB |
|
Depois Largura: | Altura: | Tamanho: 4.1 KiB |
|
Depois Largura: | Altura: | Tamanho: 3.8 KiB |
|
Depois Largura: | Altura: | Tamanho: 4.7 KiB |
|
Depois Largura: | Altura: | Tamanho: 4.9 KiB |
|
Antes Largura: | Altura: | Tamanho: 1.3 KiB Depois Largura: | Altura: | Tamanho: 4.5 KiB |
|
Antes Largura: | Altura: | Tamanho: 96 KiB Depois Largura: | Altura: | Tamanho: 48 KiB |
@@ -1,7 +1,7 @@
|
||||
.. _contents:
|
||||
|
||||
Contents
|
||||
========
|
||||
ownCloud Desktop Client Manual
|
||||
==============================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
Installing the Synchronization Client
|
||||
=====================================
|
||||
Installing the Desktop Synchronization Client
|
||||
=============================================
|
||||
|
||||
The latest version of the ownCloud Synchronization Client can be obtained from
|
||||
the `ownCloud Website <http://www.owncloud.com>`_. You can download and install
|
||||
the client on Windows, MAC OSX, and various Linux software distrubutions. The
|
||||
following sections describe specific support and installation procedures for
|
||||
the different software platforms:
|
||||
The latest version of the ownCloud Desktop Synchronization Client can be
|
||||
obtained from the `ownCloud Website <http://www.owncloud.com>`_. You can
|
||||
download and install the client on Windows, Mac OS X, and various Linux software
|
||||
distrubutions. The following sections describe specific support and installation
|
||||
procedures for the different software platforms:
|
||||
|
||||
- :ref:`installing-windows`
|
||||
- :ref:`installing-macosx`
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
Available for Windows, MAC OS X, and various Linux distributions, the ownCloud
|
||||
Sync client is a desktop program installed on your computer. The client enables
|
||||
you to:
|
||||
Available for Windows, Mac OS X, and various Linux distributions, the ownCloud
|
||||
Desktop Sync client enables you to:
|
||||
|
||||
- Specify one or more directories on your computer that you want to synchronize
|
||||
to the ownCloud server.
|
||||
- Always have the latest files synchronized, wherever they are located.
|
||||
|
||||
Changes made to any synchronized file on the computer are automatically made to
|
||||
the files on the ownCloud server using the sync client.
|
||||
Your files are always automatically synchronized between your ownCloud server
|
||||
and local PC.
|
||||
|
||||
.. note:: Because of various technical issues, desktop sync clients older than
|
||||
1.7 will not be allowed to connect and sync with the ownCloud 8.1 server. It is
|
||||
highly recommended to keep your client updated.
|
||||
|
||||
@@ -3,18 +3,45 @@ Using the Synchronization Client
|
||||
|
||||
.. index:: navigating, usage
|
||||
|
||||
The ownCloud Client remains in the background and is visible as an icon in the
|
||||
system tray (Windows, KDE), status bar (MAC OS X), or notification area
|
||||
(Ubuntu).
|
||||
The ownCloud Desktop Client remains in the background and is visible as an icon
|
||||
in the system tray (Windows, KDE), status bar (Mac OS X), or notification area
|
||||
(Linux).
|
||||
|
||||
.. image:: images/icon.png
|
||||
|
||||
**ownCloud Desktop Client icon**
|
||||
The status indicator uses overlay icons to indicate the current status of your
|
||||
synchronization. The green circle with the white checkmark tells you that your
|
||||
synchronization is current and you are connected to your ownCloud server.
|
||||
|
||||
.. image:: images/icon-syncing.png
|
||||
|
||||
The blue icon with the white semi-circles means synchronization is in progress.
|
||||
|
||||
.. image:: images/icon-paused.png
|
||||
|
||||
The yellow overlay icon with the parallel lines tells you your synchronization
|
||||
has been paused. (Most likely by you, by opening the client and clicking
|
||||
Account > Pause.)
|
||||
|
||||
.. image:: images/icon-offline.png
|
||||
|
||||
The gray icon with three white dots means your sync client has lost its
|
||||
connection with your ownCloud server.
|
||||
|
||||
.. image:: images/icon-information.png
|
||||
|
||||
When you see a white circle with the letter "i" that is the informational icon,
|
||||
so you should click it to see what it has to tell you.
|
||||
|
||||
.. image:: images/icon-error.png
|
||||
|
||||
The red circle with the white "x" indicates a configuration error, such as an
|
||||
incorrect login or server URL.
|
||||
|
||||
Using the Desktop Client Menu
|
||||
-----------------------------
|
||||
|
||||
A right click on the icon (left click on Ubuntu and Mac OS X) provides the
|
||||
A right-click on the icon opens the
|
||||
following menu:
|
||||
|
||||
.. image:: images/menu.png
|
||||
@@ -23,14 +50,20 @@ following menu:
|
||||
|
||||
The Desktop Client menu provides the following options:
|
||||
|
||||
* ``Open ownCloud in browser``: Launches the ownCloud WEB interface.
|
||||
* ``Open folder 'ownCloud'``: Opens the ownCloud local folder. If you have defined multiple synchronization targets, the window displays each local folder.
|
||||
* **Disk space indicator**: Indicates the amount of space currently used on the server.
|
||||
* Operation indicator: Displays the status of the current synchronization process or indicates ``Up to date`` if the server and client are in sync.
|
||||
* **Recent Changes**: Displays the last six files modified by the synchronization operations and provides access to the current synchronization status listing all changes since the last restart of the ownCloud client.
|
||||
* ``Settings...``: Provides access to the settings menu.
|
||||
* ``Open ownCloud in browser``: Launches the ownCloud Web interface.
|
||||
* ``Open folder 'ownCloud'``: Opens your local ownCloud folder. If you have
|
||||
defined multiple synchronization targets, the window displays each local
|
||||
folder.
|
||||
* **Disk space indicator**: Indicates the amount of space currently used on the
|
||||
server.
|
||||
* **Operation indicator**: Displays the status of the current synchronization
|
||||
process or indicates ``Up to date`` if the server and client are in sync.
|
||||
* **Recent Changes**: Displays the last six files modified, and shows the
|
||||
current synchronization status listing all changes since the last restart of the
|
||||
ownCloud client.
|
||||
* ``Settings...``: The settings menu.
|
||||
* ``Help``: Opens a browser to display ownCloud Desktop Client Guide.
|
||||
* ``Sign out``: Disables the client from continued synchronizations.
|
||||
* ``Sign out``: Stops synchronization.
|
||||
* ``Quit ownCloud``: Quits the ownCloud Client, ending any currently running
|
||||
synchronizations.
|
||||
|
||||
@@ -39,7 +72,9 @@ Using the Account Settings Window
|
||||
|
||||
.. index:: account settings, user, password, Server URL
|
||||
|
||||
The ``Account`` window provides a summary for general settings associated with the ownCloud account. This window enalbes you to manage any synchronized folders in the account and enables you to modify them.
|
||||
The ``Account`` window provides a summary for your ownCloud account settings.
|
||||
You can manage which folders and files you want to synchronize, change your
|
||||
account settings, and pause and resume synchronization.
|
||||
|
||||
To access and modify the account settings:
|
||||
|
||||
@@ -48,25 +83,32 @@ To access and modify the account settings:
|
||||
|
||||
The fields and options in this window include:
|
||||
|
||||
* ``Connected to <ownCloud instance> as <user>`` field: Indicates the ownCloud server to which the client is synchronizing and the user account on that server.
|
||||
* ``Connected to <ownCloud instance> as <user>`` field: Your user account on an ownCloud
|
||||
server.
|
||||
|
||||
* ``Add Folder...`` button: Provides the ability to add another folder to the synchronization process (see ``Adding a Folder``).
|
||||
* ``Add Folder...`` button: Add another folder to the
|
||||
synchronization process (see ``Adding a Folder``).
|
||||
|
||||
* ``Pause/Resume`` button: Pauses the current sync (or prevents the client from starting a new sync) or resumes the sync process.
|
||||
* ``Pause/Resume`` button: Pauses the current sync (or prevents the client from
|
||||
starting a new sync), or resumes the sync process.
|
||||
|
||||
* ``Remove`` button: Removes the selected folder from the sync process. This button is used when you want to synchronize only a few folders and not the root folder. If only the root folder is available, you must first remove the root from the synchronization and then add individual folders that you want to synchronize as desired.
|
||||
* ``Remove`` button: Removes the selected folder from the sync process. This
|
||||
button is used when you want to synchronize only a few folders and not the
|
||||
root folder.
|
||||
|
||||
* ``Storage Usage`` field: Indicates the storage utilization on the ownCloud server.
|
||||
* ``Storage Usage`` field: Displays how much space your files are using on the
|
||||
ownCloud server.
|
||||
|
||||
* ``Edit Ignored Files`` button: Launches the Ignored Files Editor.
|
||||
|
||||
* ``Modify Account`` button: Enables you to change the ownCloud server to which you are synchronizing. This option launches the ``Setting up an Account`` windows (See ??).
|
||||
|
||||
* ``Modify Account`` button: Use this to change your ownCloud server settings
|
||||
by launching the account setup wizard (see :doc:`accountsetup`).
|
||||
|
||||
Adding a Folder
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The ``Add a Folder ...`` button enables you to add a new folder to the syncrhonization process.
|
||||
The ``Add Folder ...`` button enables you to add a new local folder to the
|
||||
synchronization process.
|
||||
|
||||
To add a new folder:
|
||||
|
||||
@@ -74,66 +116,61 @@ To add a new folder:
|
||||
|
||||
The ``Add Folder...`` window opens
|
||||
|
||||
.. image:: images/folderwizard_local.png
|
||||
:scale: 50 %
|
||||
.. image:: images/folderwizard_local.png
|
||||
|
||||
**``Add Folder...`` window (local folder)**
|
||||
2. Type a *unique* path and alias name to the folder, or use the ``Choose...``
|
||||
button to open a graphical file picker.
|
||||
|
||||
2. Specify a *unique* path and alias name to the folder or use the ``Choose...`` button to locate the new folder on your system to which you want to synchronize.
|
||||
|
||||
..note:: Nested synchronizations are not supported. In other words, you
|
||||
.. note:: Nested synchronizations are not supported. You
|
||||
cannot add a folder that is already contained within another synchronized
|
||||
folder. In addition, you cannot add a higher level (parent) folder that
|
||||
contains a folder to which you are already synchronizing. By default, the
|
||||
ownCloud Set Up Wizard syncrhonizes your entire ownCloud account to the root
|
||||
folder of the ownCloud server. Due to this default setup, you must first remove
|
||||
the top-level folder prior to specifying new synchronizations.
|
||||
ownCloud Set Up Wizard synchronizes your entire ownCloud account to the root
|
||||
folder of the ownCloud server. If you wish to sync certain specific folders and not
|
||||
the entire root, you must first remove the root folder.
|
||||
|
||||
3. Click 'Next' to continue.
|
||||
|
||||
A window opens prompting you to select a remote destination folder on the
|
||||
ownCloud server to which you want to synchronize.
|
||||
ownCloud server to synchronize.
|
||||
|
||||
.. image:: images/folderwizard_remote.png
|
||||
:scale: 50 %
|
||||
.. image:: images/folderwizard_remote.png
|
||||
|
||||
**``Add Folder...`` window (remote destination)**
|
||||
4. Select a folder on the ownCloud server to which you want to synchronize your
|
||||
newly added local folder.
|
||||
|
||||
4. Select a folder on the ownCloud server to which you want to synchronize your newly added folder.
|
||||
|
||||
..note:: A server folder can only be synchronized with a particular client once.
|
||||
If you attempt to sync the root directory, you cannot sync with other folders
|
||||
on the server. Similarly, if you sync with folder ``/a``, you cannot create
|
||||
another sync with ``/a/b``, since ``b`` is already being synched.
|
||||
.. note:: A server folder can only be synchronized with a particular client
|
||||
once. If you attempt to sync the root directory, you cannot sync with
|
||||
other folders on the server. Similarly, if you sync with folder ``/a``, you
|
||||
cannot create another sync with ``/a/b``, since ``b`` is already being
|
||||
synched.
|
||||
|
||||
Editing Ignored Files
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The :guilabel:`Ignored Files Editor` provides a list of preconfigured files
|
||||
that are ignored (that is, not synchronized) by the client and server during
|
||||
synchronizations. The Ignored Files Editor enables you to add patterns for
|
||||
files or directories that you want to exclude from the synchronization process.
|
||||
In addition to using standard characters, the Ignored Files Editor enables you
|
||||
to use wild cards (for example, using an asterisk ‘*’ to indicate multiple
|
||||
characters or a question mark ‘?’ to incidate a single character).
|
||||
The :guilabel:`Ignored Files Editor` provides a list of files that are ignored
|
||||
(that is, not synchronized) by the client and server during synchronizations.
|
||||
You may add additional files or directories that you want to exclude from the
|
||||
synchronization process. In addition to using standard characters, the Ignored
|
||||
Files Editor enables you to use wild cards (for example, using an asterisk ‘*’
|
||||
to indicate multiple characters or a question mark ‘?’ to incidate a single
|
||||
character).
|
||||
|
||||
For additional information about this editor, see `Using the Ignored Files Editor`_
|
||||
For additional information see `Using the Ignored Files
|
||||
Editor`_
|
||||
|
||||
Using the Activity Settings Window
|
||||
----------------------------------
|
||||
|
||||
.. index:: activity, recent changes, sync activity
|
||||
|
||||
The Activity window provides an in-depth account of recent synchronization
|
||||
activity. It shows files that have not been synchronized because they are on
|
||||
the ignored files list or because they cannot be synced in a cross-platform
|
||||
manner due to containing special characters that cannot be stored on certain
|
||||
file systems.
|
||||
The Activity window provides an in-depth account of recent synchronization activity. It
|
||||
shows files that have not been synchronized because they are on the ignored files list,
|
||||
or
|
||||
because they cannot be synced due to containing special characters that cannot be stored
|
||||
on certain file systems.
|
||||
|
||||
.. image:: images/settings_activity.png
|
||||
:scale: 50 %
|
||||
|
||||
**Activity settings window**
|
||||
|
||||
You can open the Activity window in one of the following ways:
|
||||
|
||||
@@ -147,89 +184,76 @@ Using the General Settings Window
|
||||
|
||||
.. index:: general settings, auto start, startup, desktop notifications
|
||||
|
||||
The General settings window enables you to set general settings for the
|
||||
ownCloud Desktop Client and provides information about the software version,
|
||||
its creator, and the existance of any updates.
|
||||
The General settings window has options for launching the client at system
|
||||
startup, notifications, and using monochrome icons.
|
||||
|
||||
.. image:: images/settings_general.png
|
||||
:scale: 50 %
|
||||
|
||||
**General settings window**
|
||||
|
||||
The settings and information contained in this window are as follows:
|
||||
|
||||
* ``Launch on System Startup`` checkbox: Provides the option to check (enable)
|
||||
or uncheck (disable) whether the ownCloud Desktop Client launches upon system
|
||||
startup. By default, this option is enabled (checked)once you have configured
|
||||
or uncheck (disable) whether the ownCloud Desktop Client launches at system
|
||||
startup. By default, this option is enabled (checked) after you have configured
|
||||
your account.
|
||||
|
||||
* ``Show Desktop Nofications`` checkbox: Provides the option to check (enable)
|
||||
or uncheck (disable) bubble notifications alerting you as to when a set of
|
||||
synchronization operations is performed.
|
||||
or uncheck (disable) notifications about sync activity.
|
||||
|
||||
* ``Use Monochrome Icons`` checkbox: Provides the option to check (enable) or
|
||||
uncheck (disable) the use of monochrome (visually less obtrusive) icons.
|
||||
|
||||
.. note:: This option can be useful on MAC OSX platforms.
|
||||
.. note:: This option can be useful on Mac OS X platforms.
|
||||
|
||||
* ``About`` field: Provides information about the software authors along with
|
||||
pertinent build conditions.
|
||||
|
||||
.. note:: Information in this field can be valuable when submitting a support request.
|
||||
.. note:: Information in this field can be valuable when submitting a support
|
||||
request.
|
||||
|
||||
* ``Updates`` field: Provides information about any available updates for the
|
||||
ownCloud Desktop Client.
|
||||
* ``Updates`` field: Notifies you of any available updates for the ownCloud Desktop
|
||||
Client.
|
||||
|
||||
Using the Network Settings Window
|
||||
---------------------------------
|
||||
|
||||
.. index:: proxy settings, SOCKS, bandwith, throttling, limiting
|
||||
|
||||
The Network settings window enables you to define network proxy settings as
|
||||
well as limit the download and upload bandwidth utilization of file
|
||||
synchronizations.
|
||||
The Network settings window enables you to define network proxy settings, and also to
|
||||
limit download and upload bandwidth.
|
||||
|
||||
.. image:: images/settings_network.png
|
||||
:scale: 50 %
|
||||
|
||||
**Network settings window**
|
||||
|
||||
Specifying Proxy Settings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A proxy server is a server (for example, a computer system or an application)
|
||||
that functions as an intermediary contact for requests from clients that are
|
||||
seeking resources from other servers. For the ownCloud Desktop Client, you can
|
||||
define the following proxy settings:
|
||||
* ``No Proxy`` option: Do not use a proxy.
|
||||
|
||||
* ``No Proxy`` option: Specifies that the ownCloud Client circumvent the default proxy configured on the system.
|
||||
* ``Use system proxy`` option: Default setting. Follows the systems proxy
|
||||
settings. On Linux systems, this setting uses the value of the variable
|
||||
``http_proxy``.
|
||||
settings.
|
||||
|
||||
* ``Specify proxy manually as`` option: Enables you to specify
|
||||
the following custom proxy settings:
|
||||
- ``HTTP(S)``: Used when you are required to use an HTTP(S) proxy server (for example, Squid or Microsoft Forefront TMG).
|
||||
- ``SOCKSv5``: Typically used in special company LAN setups, or in combination with the OpenSSH
|
||||
dynamic application level forwarding feature (see ``ssh -D``).
|
||||
- ``Host``: Host name or IP address of the proxy server along with the port number. HTTP proxies
|
||||
typically listen over Ports 8080 (default) or 3128. SOCKS servers typically listen over port 1080.
|
||||
* ``Proxy Server requires authentication`` checkbox: Provides the option to check (enable/require) or
|
||||
uncheck (disable/not require) proxy server authentication. When not checked, the proxy server must
|
||||
be configured to allow anonymous usage. When checked, a proxy server username and password is required.
|
||||
|
||||
- ``HTTP(S)``: Used when you are required to use an HTTP(S) proxy server (for
|
||||
example, Squid or Microsoft Forefront TMG).
|
||||
|
||||
- ``SOCKSv5``: Typically used in special company LAN setups, or in
|
||||
combination with the OpenSSH dynamic application level forwarding feature
|
||||
(see ``ssh -D``).
|
||||
|
||||
- ``Host``: Host name or IP address of the proxy server along with the port
|
||||
number. HTTP proxies typically listen over Ports 8080 (default) or 3128.
|
||||
SOCKS servers typically listen over port 1080.
|
||||
|
||||
* ``Proxy Server requires authentication`` checkbox: Provides the option to
|
||||
check (enable/require) or uncheck (disable/not require) proxy server
|
||||
authentication. When not checked, the proxy server must be configured to
|
||||
allow anonymous usage. When checked, a proxy server username and password is
|
||||
required.
|
||||
|
||||
Bandwidth Limiting
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Synchronization of files between a client and server can utilized a lot of
|
||||
bandwidth. Bandwidth limiting can assist in shaping the total download or
|
||||
upload bandwidth (or both) of your client/server connection to a more
|
||||
manageable level. By limiting your bandwidth usage, you can maintain free
|
||||
bandwidth for other applications to use.
|
||||
|
||||
The ownCloud Desktop Client enables you to limit (throttle) the bandwidth usage
|
||||
for both file downloads and file uploads. The Download Bandwidth field (for
|
||||
data flowing from the ownCloud server to the client) provides the following
|
||||
options:
|
||||
Synchronization of files between a client and server can use a lot of
|
||||
bandwidth, so you can limit how much your ownCloud sync client uses.
|
||||
|
||||
- ``No limit`` option: The default setting for the client; specifies that there
|
||||
are no limit settings on the amount of data downloaded from the server.
|
||||
@@ -259,20 +283,14 @@ Using the Ignored Files Editor
|
||||
|
||||
.. index:: ignored files, exclude files, pattern
|
||||
|
||||
You might have some files or directories that you do not want to backup and
|
||||
store on the server. To identify and exclude these files or directories, you
|
||||
can use the *Ignored Files Editor* that is embedded in the ownCloud Desktop
|
||||
Client.
|
||||
You might have some local files or directories that you do not want to backup
|
||||
and store on the server. To identify and exclude these files or directories, you
|
||||
can use the *Ignored Files Editor*.
|
||||
|
||||
.. image:: images/ignored_files_editor.png
|
||||
:scale: 50%
|
||||
|
||||
Ignored Files Editor window
|
||||
|
||||
The :guilabel:`Ignored Files Editor` enables you to define customized patterns that the
|
||||
ownCloud Client uses to identify files and directories that you want to exclude
|
||||
from the synchronization process. For your convenience, the editor is
|
||||
pre-populated with a default list of typically ignore patterns. These patterns
|
||||
For your convenience, the editor is
|
||||
pre-populated with a default list of typical ignore patterns. These patterns
|
||||
are contained in a system file (typically ``sync-exclude.lst``) located in the
|
||||
ownCloud Client application directory. You cannot modify these pre-populated
|
||||
patterns directly from the editor. However, if necessary, you can hover over
|
||||
@@ -285,14 +303,15 @@ pattern, locate the file, and edit the ``sync-exclude.lst`` file.
|
||||
Each line in the editor contains an ignore pattern string. When creating custom
|
||||
patterns, in addition to being able to use normal characters to define an
|
||||
ignore pattern, you can use wildcards characters for matching values. As an
|
||||
example, you can use an asterisk (``*``) to idenfify an arbitrary number of
|
||||
example, you can use an asterisk (``*``) to identify an arbitrary number of
|
||||
characters or a question mark (``?``) to identify a single character.
|
||||
|
||||
Patterns that end with a slash character (``/``) are applied to only directory
|
||||
components of the path being checked.
|
||||
|
||||
.. note:: Custom entries are currently not validated for syntactical
|
||||
correctness by the editor, but might fail to load correctly.
|
||||
correctness by the editor, so you will not see any warnings for bad
|
||||
syntax. If your synchronization does not work as you expected, check your syntax.
|
||||
|
||||
Each pattern string in the list is preceded by a checkbox. When the check box
|
||||
contains a check mark, in addition to ignoring the file or directory component
|
||||
@@ -305,9 +324,8 @@ this list:
|
||||
- The ownCloud Client always excludes files containing characters that cannot
|
||||
be synchronized to other file systems.
|
||||
|
||||
- As of ownCloud Desktop Client version 1.5.0, files are removed that cause
|
||||
individual errors three times during a synchronization. However, the client
|
||||
provides the option of retrying a synchronization three additional times on
|
||||
files that produce errors.
|
||||
- Files are removed that cause individual errors three times during a synchronization.
|
||||
However, the client provides the option of retrying a synchronization three additional
|
||||
times on files that produce errors.
|
||||
|
||||
For more detailed information see :ref:`ignored-files-label`.
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
When invoking the client from the command line, the following options are supported:
|
||||
You have the option of starting your ownCloud desktop client with the
|
||||
``owncloud`` command. The following options are supported:
|
||||
|
||||
``-h``, ``--help``
|
||||
Displays all the options below or, when used on Windows, opens a window displaying all options.
|
||||
``owncloud -h`` or ``owncloud --help``
|
||||
Displays all command options.
|
||||
|
||||
The other options are:
|
||||
|
||||
``--logwindow``
|
||||
Opens a window displaying log output.
|
||||
|
||||
``--logfile`` `<filename>`
|
||||
Write log output to the file specified. To write to stdout, specify `-` as the filename.
|
||||
Write log output to the file specified. To write to stdout, specify `-`
|
||||
as the filename.
|
||||
|
||||
``--logdir`` `<name>`
|
||||
Writes each synchronization log output in a new file in the specified directory.
|
||||
|
||||
Writes each synchronization log output in a new file in the specified
|
||||
directory.
|
||||
|
||||
``--logexpire`` `<hours>`
|
||||
Removes logs older than the value specified (in hours). This command is used with ``--logdir``.
|
||||
Removes logs older than the value specified (in hours). This command is
|
||||
used with ``--logdir``.
|
||||
|
||||
``--logflush``
|
||||
Clears (flushes) the log file after each write action.
|
||||
|
||||
``--confdir`` `<dirname>`
|
||||
Uses the specified configuration directory.
|
||||
|
||||
Uses the specified configuration directory.
|
||||
@@ -1,60 +1,56 @@
|
||||
The ownCloud Client packages contain a command line client that can be used to
|
||||
synchronize ownCloud files to client machines. The command line client is
|
||||
called ``owncloudcmd``.
|
||||
The ownCloud Client packages contain a command, ``owncloudcmd``, that can be
|
||||
used to synchronize ownCloud files to client machines.
|
||||
|
||||
owncloudcmd performs a single *sync run* and then exits the synchronization
|
||||
process. In this manner, owncloudcmd processes the differences between client
|
||||
and server directories and propagates the files to bring both repositories to
|
||||
the same state. Contrary to the GUI-based client, owncloudcmd does not repeat
|
||||
synchronizations on its own. It also does not monitor for file system changes.
|
||||
``owncloudcmd`` performs a single *sync run* and then exits the synchronization
|
||||
process. In this manner, ``owncloudcmd`` processes the differences between
|
||||
client and server directories and propagates the files to bring both
|
||||
repositories to the same state. Contrary to the GUI-based client,
|
||||
``owncloudcmd`` does not repeat synchronizations on its own. It also does not
|
||||
monitor for file system changes.
|
||||
|
||||
To invoke the owncloudcmd, you must provide the local and the remote repository
|
||||
urls using the following command::
|
||||
To invoke ``owncloudcmd``, you must provide the local and the remote repository
|
||||
URL using the following command::
|
||||
|
||||
owncloudcmd [OPTIONS...] sourcedir owncloudurl
|
||||
|
||||
where ``sourcedir`` is the local directory and ``owncloudurl`` is
|
||||
the server URL.
|
||||
|
||||
.. note:: Prior to the 1.6 version of owncloudcmd, the tool only accepted
|
||||
``owncloud://`` or ``ownclouds://`` in place of ``http://`` and ``https://`` as
|
||||
a scheme. See ``Examples`` for details.
|
||||
|
||||
Other comand line switches supported by owncloudcmd include the following:
|
||||
Other command line switches supported by ``owncloudcmd`` include the following:
|
||||
|
||||
``--user``, ``-u`` ``[user]``
|
||||
Use ``user`` as the login name.
|
||||
Specify the user's login name.
|
||||
|
||||
``--password``, ``-p`` ``[password]``
|
||||
Use ``password`` as the password.
|
||||
Specify the user's password.
|
||||
|
||||
``-n``
|
||||
Use ``netrc (5)`` for login.
|
||||
Use ``netrc (5)`` for login.
|
||||
|
||||
``--non-interactive``
|
||||
Do not prompt for questions.
|
||||
Do not prompt for questions.
|
||||
|
||||
``--silent``, ``-s``
|
||||
Inhibits verbose log output.
|
||||
Inhibits verbose log output.
|
||||
|
||||
``--trust``
|
||||
Trust any SSL certificate, including invalid ones.
|
||||
Trust any SSL certificate, including invalid ones.
|
||||
|
||||
``--httpproxy http://[user@pass:]<server>:<port>``
|
||||
Uses the specified ``server`` as the HTTP proxy.
|
||||
|
||||
``--unsyncedfolders [file]``
|
||||
File containing list of folders to not sync
|
||||
|
||||
Credential Handling
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, owncloudcmd reads the client configuration and uses the credentials
|
||||
of the GUI syncrhonization client. If no client is configured, or if you choose
|
||||
to use a different user to synchronize, you can specify the user password
|
||||
setting with the usual URL pattern. For example::
|
||||
By default, ``owncloudcmd`` reads the client configuration and uses the
|
||||
credentials of the GUI synchronization client. If no client is configured, or if
|
||||
you choose to use a different user to synchronize, you can specify the user
|
||||
password setting with the usual URL pattern. For example::
|
||||
|
||||
https://user:secret@192.168.178.2/remote.php/webdav
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
$ owncloudcmd / https://carla:secret@server/owncloud/remote.php/webdav/
|
||||
|
||||
To synchronize the ownCloud directory ``Music`` to the local directory
|
||||
``media/music``, through a proxy listening on port ``8080``, and on a gateway
|
||||
@@ -64,13 +60,5 @@ machine using IP address ``192.168.178.1``, the command line would be::
|
||||
$HOME/media/music \
|
||||
https://server/owncloud/remote.php/webdav/Music
|
||||
|
||||
``owncloudcmd`` will enquire user name and password, unless they have
|
||||
been specified on the command line or ``-n`` has been passed.
|
||||
|
||||
Using the legacy scheme, the command line would be::
|
||||
|
||||
$ owncloudcmd --httpproxy http://192.168.178.1:8080 \
|
||||
$HOME/media/music \
|
||||
ownclouds://server/owncloud/remote.php/webdav/Music
|
||||
|
||||
|
||||
``owncloudcmd`` will prompt for the user name and password, unless they have
|
||||
been specified on the command line or ``-n`` has been passed.
|
||||
@@ -15,21 +15,15 @@ Identifying Basic Functionality Problems
|
||||
:Performing a general ownCloud Server test:
|
||||
The first step in troubleshooting synchronization issues is to verify that
|
||||
you can log on to the ownCloud web application. To verify connectivity to the
|
||||
ownCloud server:
|
||||
|
||||
- Open a browser window and enter the server address to your own server in the location/address bar.
|
||||
|
||||
For example, if your ownCloud instance is installed at URL address
|
||||
``http://yourserver.com/owncloud``, enter ``http://yourserver.com/owncloud/``
|
||||
into your browsers location/address bar.
|
||||
|
||||
ownCloud server try logging in via your Web browser.
|
||||
|
||||
If you are not prompted for your username and password, or if a red warning
|
||||
box appears on the page, your server setup requires modification. Please verify
|
||||
that your server installation is working correctly.
|
||||
|
||||
:Ensure the WebDAV API is working:
|
||||
If all desktop clients fail to connect to the ownCloud Server, but access
|
||||
using the web interface functions properly, the problem is often a
|
||||
using the Web interface functions properly, the problem is often a
|
||||
misconfiguration of the WebDAV API.
|
||||
|
||||
The ownCloud Client uses the built-in WebDAV access of the server content.
|
||||
@@ -47,13 +41,13 @@ Identifying Basic Functionality Problems
|
||||
authentication backend is configured properly.
|
||||
|
||||
:Use a WebDAV command line tool to test:
|
||||
A more sophisticated test method for troubleshooting syncrhonization issues
|
||||
A more sophisticated test method for troubleshooting synchronization issues
|
||||
is to use a WebDAV command line client and log into the ownCloud WebDAV server.
|
||||
One such command line client -- called cadaver -- is available for Linux
|
||||
One such command line client -- called ``cadaver`` -- is available for Linux
|
||||
distributions. You can use this application to further verify that the WebDAV
|
||||
server is running properly using PROPFIND calls.
|
||||
|
||||
As an example, after installing the cadaver app, you can issue the
|
||||
As an example, after installing the ``cadaver`` app, you can issue the
|
||||
``propget`` command to obtain various properties pertaining to the current
|
||||
directory and also verify WebDAV server connection.
|
||||
|
||||
@@ -67,12 +61,12 @@ Other issues can affect synchronization of your ownCloud files:
|
||||
ensure that the folder to which you are synchronizing is not shared with
|
||||
other synchronization applications.
|
||||
|
||||
.. note:: Synchronizing the same directory with ownCloud and other
|
||||
synchronization software such as Unison, rsync, Microsoft Windows Offline
|
||||
Folders, or other cloud services such as DropBox or Microsoft SkyDrive is not
|
||||
supported and should not be attempted. In the worst case, it is possible that
|
||||
synchronizing folders or files using ownCloud and other synchronization
|
||||
software or services can result in data loss.
|
||||
- Synchronizing the same directory with ownCloud and other synchronization
|
||||
software such as Unison, rsync, Microsoft Windows Offline Folders, or other
|
||||
cloud services such as DropBox or Microsoft SkyDrive is not supported and
|
||||
should not be attempted. In the worst case, it is possible that synchronizing
|
||||
folders or files using ownCloud and other synchronization software or
|
||||
services can result in data loss.
|
||||
|
||||
- If you find that only specific files are not synrchronized, the
|
||||
synchronization protocol might be having an effect. Some files are
|
||||
@@ -86,9 +80,13 @@ Other issues can affect synchronization of your ownCloud files:
|
||||
|
||||
.. note:: The data directory on the server is exclusive to ownCloud and must not be modified manually.
|
||||
|
||||
If you are using a different file backend on the server, you can try to exclude a bug in the
|
||||
- If you are using a different file backend on the server, you can try to exclude a bug in the
|
||||
backend by reverting to the built-in backend.
|
||||
|
||||
- If you are experiencing slow upload/download speed or similar performance issues
|
||||
be aware that those could be caused by on-access virus scanning solutions, either
|
||||
on the server (like the files_antivirus app) or the client.
|
||||
|
||||
Log Files
|
||||
---------
|
||||
|
||||
@@ -131,9 +129,9 @@ mentioned above to save the log to a file.
|
||||
.. note:: You can also open a log window for an already running session, by
|
||||
restarting the client using the following command:
|
||||
|
||||
* Windows: ``C:\Program Files (x86)\ownCloud\owncloud.exe --logwindow``
|
||||
* Mac OS X: ``/Applications/owncloud.app/Contents/MacOS/owncloud --logwindow``
|
||||
* Linux: ``owncloud --logwindow``
|
||||
* Windows: ``C:\Program Files (x86)\ownCloud\owncloud.exe --logwindow``
|
||||
* Mac OS X: ``/Applications/owncloud.app/Contents/MacOS/owncloud --logwindow``
|
||||
* Linux: ``owncloud --logwindow``
|
||||
|
||||
Saving Files Directly
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -200,7 +198,7 @@ You can find more information about Apache logging at
|
||||
Core Dumps
|
||||
----------
|
||||
|
||||
On MAC OS X and Linux systems, and in the unlikely event the client software
|
||||
On Mac OS X and Linux systems, and in the unlikely event the client software
|
||||
crashes, the client is able to write a core dump file. Obtaining a core dump
|
||||
file can assist ownCloud Customer Support tremendously in the debugging
|
||||
process.
|
||||
|
||||
@@ -63,14 +63,14 @@ static ContentManager* sharedInstance = nil;
|
||||
{
|
||||
NSString *base = path;
|
||||
|
||||
_icnOk = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"ok.icns"]];
|
||||
_icnSync = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"sync.icns"]];
|
||||
_icnWarn = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"warning.icns"]];
|
||||
_icnErr = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"error.icns"]];
|
||||
_icnOkSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"ok_swm.icns"]];
|
||||
_icnSyncSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"sync_swm.icns"]];
|
||||
_icnWarnSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"warning_swm.icns"]];
|
||||
_icnErrSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingString:@"error_swm.icns"]];
|
||||
_icnOk = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"ok.icns"]];
|
||||
_icnSync = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"sync.icns"]];
|
||||
_icnWarn = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"warning.icns"]];
|
||||
_icnErr = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"error.icns"]];
|
||||
_icnOkSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"ok_swm.icns"]];
|
||||
_icnSyncSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"sync_swm.icns"]];
|
||||
_icnWarnSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"warning_swm.icns"]];
|
||||
_icnErrSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"error_swm.icns"]];
|
||||
|
||||
NSLog(@"Icon ok identifier: %d from %@", [_icnOk intValue], [base stringByAppendingString:@"ok.icns"]);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,19 @@ import socket
|
||||
|
||||
from gi.repository import GObject, Nautilus
|
||||
|
||||
|
||||
def get_runtime_dir():
|
||||
"""Returns the value of $XDG_RUNTIME_DIR, a directory path.
|
||||
|
||||
If the value is not set, returns the same default as in Qt5
|
||||
"""
|
||||
try:
|
||||
return os.environ['XDG_RUNTIME_DIR']
|
||||
except KeyError:
|
||||
fallback = '/tmp/runtime-' + os.environ['USER']
|
||||
return fallback
|
||||
|
||||
|
||||
class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.InfoProvider):
|
||||
|
||||
nautilusVFSFile_table = {}
|
||||
@@ -38,21 +51,21 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
try:
|
||||
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
postfix = "/"+self.appname+"/socket"
|
||||
sock_file = os.environ["XDG_RUNTIME_DIR"]+postfix
|
||||
sock_file = get_runtime_dir()+postfix
|
||||
print ("XXXX " + sock_file + " <=> " + postfix)
|
||||
if sock_file != postfix:
|
||||
try:
|
||||
print("Socket File: "+sock_file)
|
||||
self.sock.connect(sock_file)
|
||||
self.connected = True
|
||||
print("Setting connected to %r" % self.connected )
|
||||
self.watch_id = GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
|
||||
do_reconnect = False
|
||||
except Exception, e:
|
||||
print("Could not connect to unix socket." + str(e))
|
||||
else:
|
||||
print("Sock-File not valid: "+sock_file)
|
||||
except Exception, e:
|
||||
try:
|
||||
print("Socket File: "+sock_file)
|
||||
self.sock.connect(sock_file)
|
||||
self.connected = True
|
||||
print("Setting connected to %r" % self.connected )
|
||||
self.watch_id = GObject.io_add_watch(self.sock, GObject.IO_IN, self.handle_notify)
|
||||
do_reconnect = False
|
||||
except Exception as e:
|
||||
print("Could not connect to unix socket." + str(e))
|
||||
else:
|
||||
print("Sock-File not valid: "+sock_file)
|
||||
except Exception as e:
|
||||
print("Connect could not be established, try again later " + str(e))
|
||||
self.sock.close()
|
||||
# print("Returning %r" % do_reconnect)
|
||||
@@ -75,7 +88,7 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
return None
|
||||
|
||||
def askForOverlay(self, file):
|
||||
# print("Asking for overlay for "+file)
|
||||
# print("Asking for overlay for "+file)
|
||||
if os.path.isdir(file):
|
||||
folderStatus = self.sendCommand("RETRIEVE_FOLDER_STATUS:"+file+"\n");
|
||||
|
||||
@@ -85,15 +98,15 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
def invalidate_items_underneath(self, path):
|
||||
update_items = []
|
||||
if not self.nautilusVFSFile_table:
|
||||
self.askForOverlay(path)
|
||||
else:
|
||||
for p in self.nautilusVFSFile_table:
|
||||
if p == path or p.startswith(path):
|
||||
item = self.nautilusVFSFile_table[p]['item']
|
||||
update_items.append(item)
|
||||
self.askForOverlay(path)
|
||||
else:
|
||||
for p in self.nautilusVFSFile_table:
|
||||
if p == path or p.startswith(path):
|
||||
item = self.nautilusVFSFile_table[p]['item']
|
||||
update_items.append(item)
|
||||
|
||||
for item in update_items:
|
||||
item.invalidate_extension_info()
|
||||
for item in update_items:
|
||||
item.invalidate_extension_info()
|
||||
|
||||
# Handles a single line of server respoonse and sets the emblem
|
||||
def handle_server_response(self, l):
|
||||
@@ -118,16 +131,16 @@ class syncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
# file = parts[1]
|
||||
# print "Action for " + file + ": "+parts[0]
|
||||
if action == 'STATUS':
|
||||
newState = parts[1]
|
||||
newState = parts[1]
|
||||
emblem = Emblems[newState]
|
||||
if emblem:
|
||||
itemStore = self.find_item_for_file(parts[2])
|
||||
if itemStore:
|
||||
if( not itemStore['state'] or newState != itemStore['state'] ):
|
||||
item = itemStore['item']
|
||||
item.add_emblem(emblem)
|
||||
# print "Setting emblem on " + parts[2]+ "<>"+emblem+"<>"
|
||||
self.nautilusVFSFile_table[parts[2]] = {'item': item, 'state':newState}
|
||||
if( not itemStore['state'] or newState != itemStore['state'] ):
|
||||
item = itemStore['item']
|
||||
item.add_emblem(emblem)
|
||||
# print "Setting emblem on " + parts[2]+ "<>"+emblem+"<>"
|
||||
self.nautilusVFSFile_table[parts[2]] = {'item': item, 'state':newState}
|
||||
|
||||
elif action == 'UPDATE_VIEW':
|
||||
# Search all items underneath this path and invalidate them
|
||||
|
||||
@@ -127,8 +127,10 @@ void RemotePathChecker::workerThreadLoop()
|
||||
}
|
||||
else if (StringUtil::begins_with(response, wstring(L"UPDATE_VIEW"))) {
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
auto cache = _cache; // Make a copy of the cache under the mutex
|
||||
lock.unlock();
|
||||
// Request a status for all the items in the cache.
|
||||
for (auto it = _cache.begin(); it != _cache.end(); ++it) {
|
||||
for (auto it = cache.begin(); it != cache.end(); ++it) {
|
||||
if (!socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + it->first + L'\n').data())) {
|
||||
break;
|
||||
}
|
||||
@@ -192,6 +194,7 @@ bool RemotePathChecker::IsMonitoredPath(const wchar_t* filePath, int* state)
|
||||
}
|
||||
|
||||
_pending.push(filePath);
|
||||
lock.unlock();
|
||||
SetEvent(_newQueries);
|
||||
return false;
|
||||
|
||||
|
||||
@@ -241,7 +241,19 @@ void ShibbolethCredentials::persist(Account* account)
|
||||
void ShibbolethCredentials::invalidateToken(Account *account)
|
||||
{
|
||||
CookieJar *jar = static_cast<CookieJar*>(account->networkAccessManager()->cookieJar());
|
||||
jar->deleteCookie(_shibCookie);
|
||||
|
||||
// Remove the _shibCookie
|
||||
auto cookies = jar->allCookies();
|
||||
for (auto it = cookies.begin(); it != cookies.end(); ) {
|
||||
if (it->name() == _shibCookie.name()) {
|
||||
it = cookies.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
jar->setAllCookies(cookies);
|
||||
|
||||
// Clear all other temporary cookies
|
||||
jar->clearSessionCookies();
|
||||
removeShibCookie(account);
|
||||
_shibCookie = QNetworkCookie();
|
||||
|
||||
@@ -40,7 +40,7 @@ Q_OBJECT
|
||||
public:
|
||||
ShibbolethCredentials();
|
||||
|
||||
/* create a credidentials for an already connected account */
|
||||
/* create a credentials for an already connected account */
|
||||
ShibbolethCredentials(const QNetworkCookie &cookie, Account *acc);
|
||||
|
||||
void syncContextPreInit(CSYNC* ctx) Q_DECL_OVERRIDE;
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
enum State { Disconnected = 0, /// no network connection
|
||||
Connected, /// account is online
|
||||
SignedOut, /// Disconnected + credential token has been discarded
|
||||
InvalidCredidential /// The credidential are invalids and we are asking for them to the user
|
||||
InvalidCredential /// The credentials are invalid and we are asking the user for them
|
||||
};
|
||||
|
||||
QString davPath() const { return _davPath; }
|
||||
|
||||
@@ -202,10 +202,9 @@ void AccountSettings::slotFolderWizardAccepted()
|
||||
QStringList selectiveSyncBlackList
|
||||
= folderWizard->property("selectiveSyncBlackList").toStringList();
|
||||
|
||||
if (!FolderMan::ensureJournalGone( sourceFolder ))
|
||||
if (!folderMan->addFolderDefinition(alias, sourceFolder, targetPath, selectiveSyncBlackList))
|
||||
return;
|
||||
|
||||
folderMan->addFolderDefinition(alias, sourceFolder, targetPath, selectiveSyncBlackList );
|
||||
Folder *f = folderMan->setupFolderFromConfigFile( alias );
|
||||
slotAddFolder( f );
|
||||
folderMan->setSyncEnabled(true);
|
||||
@@ -662,25 +661,29 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
||||
// overall progress
|
||||
quint64 completedSize = progress.completedSize();
|
||||
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
|
||||
if (currentFile == ULLONG_MAX)
|
||||
currentFile = 0;
|
||||
quint64 totalSize = qMax(completedSize, progress._totalSize);
|
||||
quint64 totalFileCount = qMax(currentFile, progress._totalFileCount);
|
||||
QString overallSyncString;
|
||||
if (progress._totalSize > 0) {
|
||||
if (totalSize > 0) {
|
||||
QString s1 = Utility::octetsToString( completedSize );
|
||||
QString s2 = Utility::octetsToString( progress._totalSize );
|
||||
QString s2 = Utility::octetsToString( totalSize );
|
||||
overallSyncString = tr("%1 of %2, file %3 of %4\nTotal time left %5")
|
||||
.arg(s1, s2)
|
||||
.arg(currentFile).arg(progress._totalFileCount)
|
||||
.arg(currentFile).arg(totalFileCount)
|
||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 3, " ", true) );
|
||||
} else if (progress._totalFileCount > 0) {
|
||||
} else if (totalFileCount > 0) {
|
||||
// Don't attemt to estimate the time left if there is no kb to transfer.
|
||||
overallSyncString = tr("file %1 of %2") .arg(currentFile).arg(progress._totalFileCount);
|
||||
overallSyncString = tr("file %1 of %2") .arg(currentFile).arg(totalFileCount);
|
||||
}
|
||||
|
||||
item->setData( overallSyncString, FolderStatusDelegate::SyncProgressOverallString );
|
||||
|
||||
int overallPercent = 0;
|
||||
if( progress._totalFileCount > 0 ) {
|
||||
if( totalFileCount > 0 ) {
|
||||
// Add one 'byte' for each files so the percentage is moving when deleting or renaming files
|
||||
overallPercent = qRound(double(completedSize + progress._completedFileCount)/double(progress._totalSize + progress._totalFileCount) * 100.0);
|
||||
overallPercent = qRound(double(completedSize + progress._completedFileCount)/double(totalSize + totalFileCount) * 100.0);
|
||||
}
|
||||
item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent);
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ void Application::slotCheckConnection()
|
||||
Account *account = AccountManager::instance()->account();
|
||||
|
||||
if( account ) {
|
||||
if (account->state() == Account::InvalidCredidential
|
||||
if (account->state() == Account::InvalidCredential
|
||||
|| account->state() == Account::SignedOut) {
|
||||
//Do not try to connect if we are logged out
|
||||
if (!_userTriggeredConnect) {
|
||||
@@ -262,8 +262,8 @@ void Application::slotCredentialsFetched()
|
||||
account->setState(Account::SignedOut);
|
||||
return;
|
||||
}
|
||||
if (account->state() == Account::InvalidCredidential) {
|
||||
// Then we ask again for the credidentials if they are wrong again
|
||||
if (account->state() == Account::InvalidCredential) {
|
||||
// Then we ask again for the credentials if they are wrong again
|
||||
account->setState(Account::Disconnected);
|
||||
}
|
||||
slotCheckConnection();
|
||||
@@ -281,12 +281,11 @@ void Application::slotToggleFolderman(int state)
|
||||
_checkConnectionTimer.start();
|
||||
// fall through
|
||||
case Account::SignedOut:
|
||||
case Account::InvalidCredidential:
|
||||
case Account::InvalidCredential:
|
||||
folderMan->setSyncEnabled(false);
|
||||
folderMan->terminateSyncProcess();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::slotConnectionValidatorResult(ConnectionValidator::Status status)
|
||||
|
||||
@@ -91,27 +91,11 @@ QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const
|
||||
return cookies;
|
||||
}
|
||||
|
||||
bool CookieJar::deleteCookie(const QNetworkCookie &delCookie)
|
||||
{
|
||||
QList<QNetworkCookie> cookies = allCookies();
|
||||
bool removeSucceeded = false;
|
||||
foreach(const QNetworkCookie &cookie, cookies) {
|
||||
// ### cookies are not identical in attriutes, why?
|
||||
if (cookie.name() == delCookie.name()) {
|
||||
cookies.removeOne(cookie);
|
||||
removeSucceeded = true;
|
||||
}
|
||||
}
|
||||
setAllCookies(cookies);
|
||||
return removeSucceeded;
|
||||
}
|
||||
|
||||
void CookieJar::clearSessionCookies()
|
||||
{
|
||||
setAllCookies(removeExpired(allCookies()));
|
||||
}
|
||||
|
||||
|
||||
void CookieJar::save()
|
||||
{
|
||||
QFile file;
|
||||
|
||||
@@ -29,13 +29,11 @@ public:
|
||||
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url) Q_DECL_OVERRIDE;
|
||||
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const Q_DECL_OVERRIDE;
|
||||
|
||||
bool deleteCookie(const QNetworkCookie & cookie)
|
||||
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
|
||||
Q_DECL_OVERRIDE //that function is not virtual in Qt4
|
||||
#endif
|
||||
;
|
||||
void clearSessionCookies();
|
||||
|
||||
using QNetworkCookieJar::setAllCookies;
|
||||
using QNetworkCookieJar::allCookies;
|
||||
|
||||
signals:
|
||||
void newCookiesForUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url);
|
||||
private:
|
||||
|
||||
@@ -69,19 +69,11 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP
|
||||
qsrand(QTime::currentTime().msec());
|
||||
_timeSinceLastSync.start();
|
||||
|
||||
MirallConfigFile cfg;
|
||||
|
||||
_syncResult.setStatus( SyncResult::NotYetStarted );
|
||||
|
||||
// check if the local path exists
|
||||
checkLocalPath();
|
||||
|
||||
int polltime = cfg.remotePollInterval();
|
||||
qDebug() << "setting remote poll timer interval to" << polltime << "msec";
|
||||
_pollTimer.setInterval( polltime );
|
||||
QObject::connect(&_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout()));
|
||||
_pollTimer.start();
|
||||
|
||||
_syncResult.setFolder(alias);
|
||||
}
|
||||
|
||||
@@ -234,7 +226,6 @@ void Folder::setSyncPaused( bool paused )
|
||||
// do not stop or start the watcher here, that is done internally by
|
||||
// folder class. Even if the watcher fires, the folder does not
|
||||
// schedule itself because it checks the var. _enabled before.
|
||||
_pollTimer.stop();
|
||||
setSyncState(SyncResult::Paused);
|
||||
}
|
||||
}
|
||||
@@ -255,20 +246,24 @@ void Folder::prepareToSync()
|
||||
_syncResult.clearErrors();
|
||||
}
|
||||
|
||||
void Folder::slotPollTimerTimeout()
|
||||
void Folder::slotRunEtagJob()
|
||||
{
|
||||
qDebug() << "* Polling" << alias() << "for changes. (time since last sync:" << (_timeSinceLastSync.elapsed() / 1000) << "s)";
|
||||
qDebug() << "* Trying to check" << alias() << "for changes via ETag check. (time since last sync:" << (_timeSinceLastSync.elapsed() / 1000) << "s)";
|
||||
|
||||
|
||||
Account *account = AccountManager::instance()->account();
|
||||
|
||||
if (!account) {
|
||||
qDebug() << Q_FUNC_INFO << "No valid account object";
|
||||
qDebug() << Q_FUNC_INFO << alias() << "No valid account object, not trying to sync";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_requestEtagJob.isNull()) {
|
||||
qDebug() << Q_FUNC_INFO << alias() << "has ETag job queued, not trying to sync";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_paused || account->state() != Account::Connected) {
|
||||
qDebug() << "Not syncing. :" << _paused << account->state();
|
||||
qDebug() << "Not syncing. :" << alias() << _paused << account->state();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -306,11 +301,12 @@ void Folder::slotPollTimerTimeout()
|
||||
// Do the ordinary etag check for the root folder and only schedule a real
|
||||
// sync if it's different.
|
||||
|
||||
RequestEtagJob* job = new RequestEtagJob(account, remotePath(), this);
|
||||
_requestEtagJob = new RequestEtagJob(account, remotePath(), this);
|
||||
// check if the etag is different
|
||||
QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
||||
QObject::connect(job, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotNetworkUnavailable()));
|
||||
job->start();
|
||||
QObject::connect(_requestEtagJob, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
||||
QObject::connect(_requestEtagJob, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotNetworkUnavailable()));
|
||||
FolderMan::instance()->slotScheduleETagJob(alias(), _requestEtagJob);
|
||||
// The _requestEtagJob is auto deleting itself on finish. Our guard pointer _requestEtagJob will then be null.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,6 +580,9 @@ bool Folder::estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(!fn.endsWith(QLatin1Char('/'))) {
|
||||
fn.append(QLatin1Char('/'));
|
||||
}
|
||||
if (Utility::doesSetContainPrefix(_stateTaintedFolders, fn)) {
|
||||
qDebug() << Q_FUNC_INFO << "Folder is tainted, EVAL!" << fn;
|
||||
s->set(SyncFileStatus::STATUS_EVAL);
|
||||
@@ -620,6 +619,9 @@ void Folder::watcherSlot(QString fn)
|
||||
}
|
||||
// Make it a relative path depending on the folder
|
||||
QString relativePath = fn.remove(0, path().length());
|
||||
if( !relativePath.endsWith(QLatin1Char('/'))) {
|
||||
relativePath.append(QLatin1Char('/'));
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << fi.canonicalFilePath() << fn << relativePath;
|
||||
_stateTaintedFolders.insert(relativePath);
|
||||
|
||||
@@ -775,7 +777,6 @@ void Folder::startSync(const QStringList &pathList)
|
||||
|
||||
// disable events until syncing is done
|
||||
// _watcher->setEventsEnabled(false);
|
||||
_pollTimer.stop();
|
||||
emit syncStarted();
|
||||
}
|
||||
|
||||
@@ -906,9 +907,7 @@ void Folder::slotSyncFinished()
|
||||
// We will make sure that the poll timer occurs soon enough.
|
||||
// delay 1s, 4s, 9s
|
||||
int c = _consecutiveFollowUpSyncs;
|
||||
QTimer::singleShot(c*c * 1000, this, SLOT(slotPollTimerTimeout() ));
|
||||
} else {
|
||||
_pollTimer.start();
|
||||
QTimer::singleShot(c*c * 1000, this, SLOT(slotRunEtagJob() ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,7 +977,7 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool *cancel)
|
||||
// speed up next sync
|
||||
_lastEtag.clear();
|
||||
_forceSyncOnPollTimeout = true;
|
||||
QTimer::singleShot(50, this, SLOT(slotPollTimerTimeout()));
|
||||
QTimer::singleShot(50, this, SLOT(slotRunEtagJob()));
|
||||
}
|
||||
}
|
||||
} // namespace Mirall
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "mirall/syncjournaldb.h"
|
||||
#include "mirall/clientproxy.h"
|
||||
#include "mirall/syncfilestatus.h"
|
||||
#include "mirall/networkjobs.h"
|
||||
|
||||
#include <csync.h>
|
||||
|
||||
@@ -123,6 +124,9 @@ public:
|
||||
|
||||
bool estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s);
|
||||
|
||||
RequestEtagJob *etagJob() { return _requestEtagJob; }
|
||||
qint64 msecSinceLastSync() { return _timeSinceLastSync.elapsed(); }
|
||||
|
||||
signals:
|
||||
void syncStateChange();
|
||||
void syncStarted();
|
||||
@@ -165,7 +169,7 @@ private slots:
|
||||
void slotJobCompleted(const SyncFileItem&);
|
||||
void slotSyncItemDiscovered(const SyncFileItem & item);
|
||||
|
||||
void slotPollTimerTimeout();
|
||||
void slotRunEtagJob();
|
||||
void etagRetreived(const QString &);
|
||||
void slotNetworkUnavailable();
|
||||
|
||||
@@ -201,7 +205,7 @@ private:
|
||||
bool _csyncUnavail;
|
||||
bool _wipeDb;
|
||||
bool _proxyDirty;
|
||||
QTimer _pollTimer;
|
||||
QPointer<RequestEtagJob> _requestEtagJob;
|
||||
QString _lastEtag;
|
||||
QElapsedTimer _timeSinceLastSync;
|
||||
bool _forceSyncOnPollTimeout;
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <QMessageBox>
|
||||
#include <QPointer>
|
||||
#include <QtCore>
|
||||
#include <QMutableSetIterator>
|
||||
#include <QSet>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
@@ -66,6 +68,13 @@ FolderMan::FolderMan(QObject *parent) :
|
||||
|
||||
_socketApi = new SocketApi(this);
|
||||
_socketApi->slotReadExcludes();
|
||||
|
||||
MirallConfigFile cfg;
|
||||
int polltime = cfg.remotePollInterval();
|
||||
qDebug() << "setting remote poll timer interval to" << polltime << "msec";
|
||||
_etagPollTimer.setInterval( polltime );
|
||||
QObject::connect(&_etagPollTimer, SIGNAL(timeout()), this, SLOT(slotEtagPollTimerTimeout()));
|
||||
_etagPollTimer.start();
|
||||
}
|
||||
|
||||
FolderMan *FolderMan::instance()
|
||||
@@ -225,6 +234,7 @@ bool FolderMan::ensureJournalGone(const QString &localPath)
|
||||
// remove old .csync_journal file
|
||||
QString stateDbFile = localPath+QLatin1String("/.csync_journal.db");
|
||||
while (QFile::exists(stateDbFile) && !QFile::remove(stateDbFile)) {
|
||||
qDebug() << "Could not remove old db file at" << stateDbFile;
|
||||
int ret = QMessageBox::warning(0, tr("Could not reset folder state"),
|
||||
tr("An old sync journal '%1' was found, "
|
||||
"but could not be removed. Please make sure "
|
||||
@@ -390,21 +400,17 @@ void FolderMan::slotSetFolderPaused( const QString& alias, bool paused )
|
||||
}
|
||||
}
|
||||
|
||||
// this really terminates, ie. no questions, no prisoners.
|
||||
// this really terminates the current sync process
|
||||
// ie. no questions, no prisoners
|
||||
// csync still remains in a stable state, regardless of that.
|
||||
void FolderMan::terminateSyncProcess( const QString& alias )
|
||||
void FolderMan::terminateSyncProcess()
|
||||
{
|
||||
QString folderAlias = alias;
|
||||
if( alias.isEmpty() ) {
|
||||
folderAlias = _currentSyncFolder;
|
||||
}
|
||||
if( ! folderAlias.isEmpty() && _folderMap.contains(folderAlias) ) {
|
||||
Folder *f = _folderMap[folderAlias];
|
||||
if( ! _currentSyncFolder.isEmpty() && _folderMap.contains(_currentSyncFolder) ) {
|
||||
Folder *f = _folderMap[_currentSyncFolder];
|
||||
if( f ) {
|
||||
// This will, indirectly and eventually, call slotFolderSyncFinished
|
||||
// and thereby clear _currentSyncFolder.
|
||||
f->slotTerminateSync();
|
||||
if(_currentSyncFolder == folderAlias ) {
|
||||
_currentSyncFolder.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,6 +495,41 @@ void FolderMan::slotScheduleSync( const QString& alias )
|
||||
QTimer::singleShot(msBetweenRequestAndSync, this, SLOT(slotStartScheduledFolderSync()));
|
||||
}
|
||||
|
||||
void FolderMan::slotScheduleETagJob(const QString &/*alias*/, RequestEtagJob *job)
|
||||
{
|
||||
QObject::connect(job, SIGNAL(destroyed(QObject*)), this, SLOT(slotEtagJobDestroyed(QObject*)));
|
||||
QMetaObject::invokeMethod(this, "slotRunOneEtagJob", Qt::QueuedConnection);
|
||||
// maybe: add to queue
|
||||
}
|
||||
|
||||
void FolderMan::slotEtagJobDestroyed(QObject* /*o*/)
|
||||
{
|
||||
// _currentEtagJob is automatically cleared
|
||||
// maybe: remove from queue
|
||||
QMetaObject::invokeMethod(this, "slotRunOneEtagJob", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void FolderMan::slotRunOneEtagJob()
|
||||
{
|
||||
if (_currentEtagJob.isNull()) {
|
||||
QString alias;
|
||||
foreach(Folder *f, _folderMap) {
|
||||
if (f->etagJob()) {
|
||||
// Caveat: always grabs the first folder with a job, but we think this is Ok for now and avoids us having a seperate queue.
|
||||
_currentEtagJob = f->etagJob();
|
||||
alias = f->alias();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_currentEtagJob.isNull()) {
|
||||
qDebug() << "No more remote ETag check jobs to schedule.";
|
||||
} else {
|
||||
qDebug() << "Scheduling" << alias << "to check remote ETag";
|
||||
_currentEtagJob->start(); // on destroy/end it will continue the queue via slotEtagJobDestroyed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only enable or disable foldermans will to schedule and do syncs.
|
||||
// this is not the same as Pause and Resume of folders.
|
||||
void FolderMan::setSyncEnabled( bool enabled )
|
||||
@@ -545,6 +586,51 @@ void FolderMan::slotStartScheduledFolderSync()
|
||||
}
|
||||
}
|
||||
|
||||
void FolderMan::slotEtagPollTimerTimeout()
|
||||
{
|
||||
//qDebug() << Q_FUNC_INFO << "Checking if we need to make any folders check the remote ETag";
|
||||
MirallConfigFile cfg;
|
||||
int polltime = cfg.remotePollInterval();
|
||||
|
||||
QSet<QString> folderAliases = _folderMap.keys().toSet();
|
||||
QMutableSetIterator<QString> i(folderAliases);
|
||||
while (i.hasNext()) {
|
||||
QString alias = i.next();
|
||||
if (_currentSyncFolder == alias) {
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
if (_scheduleQueue.contains(alias)) {
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
Folder *f = _folderMap.value(alias);
|
||||
if (f && _disabledFolders.contains(f)) {
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
if (f && (f->etagJob() || f->isBusy() || f->syncPaused())) {
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
if (f && f->msecSinceLastSync() < polltime) {
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (folderAliases.isEmpty()) {
|
||||
qDebug() << Q_FUNC_INFO << "No folders need to check for the remote ETag";
|
||||
} else {
|
||||
qDebug() << Q_FUNC_INFO << "The following folders need to check for the remote ETag:" << folderAliases;
|
||||
i = folderAliases; // reset
|
||||
while (i.hasNext()) {
|
||||
QString alias = i.next();
|
||||
QMetaObject::invokeMethod(_folderMap.value(alias), "slotRunEtagJob", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FolderMan::slotFolderSyncStarted( )
|
||||
{
|
||||
qDebug() << ">===================================== sync started for " << _currentSyncFolder;
|
||||
@@ -565,9 +651,12 @@ void FolderMan::slotFolderSyncFinished( const SyncResult& )
|
||||
QTimer::singleShot(200, this, SLOT(slotStartScheduledFolderSync()));
|
||||
}
|
||||
|
||||
void FolderMan::addFolderDefinition(const QString& alias, const QString& sourceFolder,
|
||||
const QString& targetPath, const QStringList &selectiveSyncBlackList )
|
||||
bool FolderMan::addFolderDefinition(const QString& alias, const QString& sourceFolder,
|
||||
const QString& targetPath, const QStringList& selectiveSyncBlackList)
|
||||
{
|
||||
if (! ensureJournalGone(sourceFolder))
|
||||
return false;
|
||||
|
||||
QString escapedAlias = escapeAlias(alias);
|
||||
// Create a settings file named after the alias
|
||||
QSettings settings( _folderConfigPath + QLatin1Char('/') + escapedAlias, QSettings::IniFormat);
|
||||
@@ -579,6 +668,8 @@ void FolderMan::addFolderDefinition(const QString& alias, const QString& sourceF
|
||||
settings.setValue(QLatin1String("connection"), Theme::instance()->appName());
|
||||
settings.setValue(QLatin1String("blackList"), selectiveSyncBlackList);
|
||||
settings.sync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Folder *FolderMan::folderForPath(const QString &path)
|
||||
@@ -615,7 +706,7 @@ void FolderMan::slotRemoveFolder( const QString& alias )
|
||||
|
||||
if( _currentSyncFolder == alias ) {
|
||||
// terminate if the sync is currently underway.
|
||||
terminateSyncProcess( alias );
|
||||
terminateSyncProcess();
|
||||
}
|
||||
removeFolder(alias);
|
||||
}
|
||||
@@ -706,6 +797,8 @@ bool FolderMan::startFromScratch( const QString& localFolder )
|
||||
if( localFolder.startsWith(f->path()) ) {
|
||||
_socketApi->slotUnregisterPath(f->alias());
|
||||
}
|
||||
f->journalDb()->close();
|
||||
f->slotTerminateSync(); // Normaly it should not be running, but viel hilft viel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,13 @@ public:
|
||||
* QString alias
|
||||
* QString sourceFolder on local machine
|
||||
* QString targetPath on remote
|
||||
*
|
||||
* Ensures any existing journal in the sourceFolder is deleted.
|
||||
* Returns true on success.
|
||||
*/
|
||||
void addFolderDefinition(const QString&, const QString&, const QString& ,
|
||||
const QStringList &selectiveSyncBlacklist = QStringList() );
|
||||
bool addFolderDefinition(const QString& alias, const QString& sourceFolder,
|
||||
const QString& targetPath,
|
||||
const QStringList& selectiveSyncBlacklist = QStringList());
|
||||
|
||||
/** Returns the folder which the file or directory stored in path is in */
|
||||
Folder* folderForPath(const QString& path);
|
||||
@@ -108,11 +112,11 @@ public slots:
|
||||
void slotFolderSyncFinished( const SyncResult& );
|
||||
|
||||
/**
|
||||
* Terminates the specified folder sync (or the current one).
|
||||
* Terminates the current folder sync.
|
||||
*
|
||||
* It does not switch the folder to paused state.
|
||||
*/
|
||||
void terminateSyncProcess( const QString& alias = QString::null );
|
||||
void terminateSyncProcess();
|
||||
|
||||
/* unload and delete on folder object */
|
||||
void unloadFolder( const QString& alias );
|
||||
@@ -130,11 +134,16 @@ public slots:
|
||||
|
||||
// slot to add a folder to the syncing queue
|
||||
void slotScheduleSync( const QString & );
|
||||
// slot to scheule an ETag job
|
||||
void slotScheduleETagJob ( const QString &alias, RequestEtagJob *job);
|
||||
void slotEtagJobDestroyed (QObject*);
|
||||
void slotRunOneEtagJob();
|
||||
|
||||
private slots:
|
||||
|
||||
// slot to take the next folder from queue and start syncing.
|
||||
void slotStartScheduledFolderSync();
|
||||
void slotEtagPollTimerTimeout();
|
||||
|
||||
private:
|
||||
// finds all folder configuration files
|
||||
@@ -153,6 +162,9 @@ private:
|
||||
QSignalMapper *_folderWatcherSignalMapper;
|
||||
QString _currentSyncFolder;
|
||||
bool _syncEnabled;
|
||||
QTimer _etagPollTimer;
|
||||
QPointer<RequestEtagJob> _currentEtagJob; // alias of Folder running the current RequestEtagJob
|
||||
|
||||
QMap<QString, FolderWatcher*> _folderWatchers;
|
||||
QPointer<SocketApi> _socketApi;
|
||||
|
||||
|
||||
@@ -186,13 +186,26 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
painter->drawPixmap(QPoint(warnRect.left(), warnRect.top()),pm );
|
||||
}
|
||||
|
||||
if ((option.state & QStyle::State_Selected)
|
||||
&& (option.state & QStyle::State_Active)
|
||||
// Hack: Windows Vista's light blue is not contrasting enough for white
|
||||
&& !qApp->style()->inherits("QWindowsVistaStyle")) {
|
||||
painter->setPen(option.palette.color(QPalette::HighlightedText));
|
||||
auto palette = option.palette;
|
||||
|
||||
if (qApp->style()->inherits("QWindowsVistaStyle")) {
|
||||
// Hack: Windows Vista's light blue is not contrasting enough for white
|
||||
|
||||
// (code from QWindowsVistaStyle::drawControl for CE_ItemViewItem)
|
||||
palette.setColor(QPalette::All, QPalette::HighlightedText, palette.color(QPalette::Active, QPalette::Text));
|
||||
palette.setColor(QPalette::All, QPalette::Highlight, palette.base().color().darker(108));
|
||||
}
|
||||
|
||||
|
||||
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
|
||||
? QPalette::Normal : QPalette::Disabled;
|
||||
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
|
||||
if (option.state & QStyle::State_Selected) {
|
||||
painter->setPen(palette.color(cg, QPalette::HighlightedText));
|
||||
} else {
|
||||
painter->setPen(option.palette.color(QPalette::Text));
|
||||
painter->setPen(palette.color(cg, QPalette::Text));
|
||||
}
|
||||
QString elidedAlias = aliasFm.elidedText(aliasText, Qt::ElideRight, aliasRect.width());
|
||||
painter->setFont(aliasFont);
|
||||
@@ -272,7 +285,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
pBarOpt.maximum = 100;
|
||||
pBarOpt.progress = overallPercent;
|
||||
pBarOpt.orientation = Qt::Horizontal;
|
||||
pBarOpt.palette = option.palette;
|
||||
pBarOpt.palette = palette;
|
||||
pBarOpt.rect = pBRect;
|
||||
|
||||
QApplication::style()->drawControl( QStyle::CE_ProgressBar, &pBarOpt, painter );
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
||||
#include "mirall/folderwatcher.h"
|
||||
#include "mirall/folderwatcher_win.h"
|
||||
@@ -23,52 +24,123 @@
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
void WatcherThread::run()
|
||||
void WatcherThread::watchChanges(size_t fileNotifyBufferSize,
|
||||
bool* increaseBufferSize)
|
||||
{
|
||||
_handle = FindFirstChangeNotification((wchar_t*)_path.utf16(),
|
||||
true, // recursive watch
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE);
|
||||
*increaseBufferSize = false;
|
||||
|
||||
_handle = CreateFileW(
|
||||
(wchar_t*)_path.utf16(),
|
||||
FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification function failed, stopping watcher!";
|
||||
FindCloseChangeNotification(_handle);
|
||||
DWORD errorCode = GetLastError();
|
||||
qDebug() << Q_FUNC_INFO << "Failed to create handle for" << _path << ", error:" << errorCode;
|
||||
_handle = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_handle == NULL)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification returned null, stopping watcher!";
|
||||
FindCloseChangeNotification(_handle);
|
||||
_handle = 0;
|
||||
return;
|
||||
}
|
||||
// QVarLengthArray ensures the stack-buffer is aligned like double and qint64.
|
||||
QVarLengthArray<char, 4096*10> fileNotifyBuffer;
|
||||
fileNotifyBuffer.resize(fileNotifyBufferSize);
|
||||
|
||||
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;
|
||||
const size_t fileNameBufferSize = 4096;
|
||||
TCHAR fileNameBuffer[fileNameBufferSize];
|
||||
|
||||
forever {
|
||||
FILE_NOTIFY_INFORMATION *pFileNotifyBuffer =
|
||||
(FILE_NOTIFY_INFORMATION*)fileNotifyBuffer.data();
|
||||
DWORD dwBytesReturned = 0;
|
||||
SecureZeroMemory(pFileNotifyBuffer, fileNotifyBufferSize);
|
||||
if(ReadDirectoryChangesW( _handle, (LPVOID)pFileNotifyBuffer,
|
||||
fileNotifyBufferSize, true,
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE,
|
||||
&dwBytesReturned, NULL, NULL))
|
||||
{
|
||||
FILE_NOTIFY_INFORMATION *curEntry = pFileNotifyBuffer;
|
||||
forever {
|
||||
size_t len = curEntry->FileNameLength / 2;
|
||||
QString file = _path + "\\" + QString::fromWCharArray(curEntry->FileName, len);
|
||||
|
||||
// Unless the file was removed or renamed, get its full long name
|
||||
// TODO: We could still try expanding the path in the tricky cases...
|
||||
QString longfile = file;
|
||||
if (curEntry->Action != FILE_ACTION_REMOVED
|
||||
&& curEntry->Action != FILE_ACTION_RENAMED_OLD_NAME) {
|
||||
size_t longNameSize = GetLongPathNameW(reinterpret_cast<LPCWSTR>(file.utf16()), fileNameBuffer, fileNameBufferSize);
|
||||
if (longNameSize > 0) {
|
||||
longfile = QString::fromUtf16(reinterpret_cast<const ushort *>(fileNameBuffer), longNameSize);
|
||||
} else {
|
||||
qDebug() << Q_FUNC_INFO << "Error converting file name to full length, keeping original name.";
|
||||
}
|
||||
}
|
||||
longfile = QDir::cleanPath(longfile);
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Found change in" << longfile << "action:" << curEntry->Action;
|
||||
emit changed(longfile);
|
||||
|
||||
if (curEntry->NextEntryOffset == 0) {
|
||||
break;
|
||||
}
|
||||
curEntry = (FILE_NOTIFY_INFORMATION*)(
|
||||
(char*)curEntry + curEntry->NextEntryOffset);
|
||||
}
|
||||
// qDebug() << Q_FUNC_INFO << "Change detected in" << _path << "from" << QThread::currentThread ();
|
||||
emit changed(_path);
|
||||
break;
|
||||
default:
|
||||
qDebug() << Q_FUNC_INFO << "Error while watching";
|
||||
} else {
|
||||
DWORD errorCode = GetLastError();
|
||||
switch(errorCode) {
|
||||
case ERROR_NOTIFY_ENUM_DIR:
|
||||
qDebug() << Q_FUNC_INFO << "The buffer for changes overflowed! Triggering a generic change and resizing";
|
||||
emit changed(_path);
|
||||
*increaseBufferSize = true;
|
||||
break;
|
||||
default:
|
||||
qDebug() << Q_FUNC_INFO << "General error" << errorCode << "while watching. Exiting.";
|
||||
break;
|
||||
}
|
||||
CloseHandle(_handle);
|
||||
_handle = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WatcherThread::run()
|
||||
{
|
||||
// If this buffer fills up before we've extracted its data we will lose
|
||||
// change information. Therefore start big.
|
||||
size_t bufferSize = 4096*10;
|
||||
size_t maxBuffer = 64*1024;
|
||||
|
||||
forever {
|
||||
bool increaseBufferSize = false;
|
||||
watchChanges(bufferSize, &increaseBufferSize);
|
||||
|
||||
if (increaseBufferSize) {
|
||||
bufferSize = qMin(bufferSize*2, maxBuffer);
|
||||
} else {
|
||||
// Other errors shouldn't actually happen,
|
||||
// so sleep a bit to avoid running into the same error case in a
|
||||
// tight loop.
|
||||
sleep(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WatcherThread::~WatcherThread()
|
||||
{
|
||||
if (_handle)
|
||||
FindCloseChangeNotification(_handle);
|
||||
if (_handle) {
|
||||
CloseHandle(_handle);
|
||||
_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p, const QString& path)
|
||||
|
||||
@@ -33,6 +33,8 @@ public:
|
||||
|
||||
protected:
|
||||
void run();
|
||||
void watchChanges(size_t fileNotifyBufferSize,
|
||||
bool* increaseBufferSize);
|
||||
|
||||
signals:
|
||||
void changed(const QString &path);
|
||||
|
||||
@@ -254,9 +254,9 @@ void FolderWizardRemotePath::slotAddRemoteFolder()
|
||||
|
||||
QInputDialog *dlg = new QInputDialog(this);
|
||||
|
||||
dlg->setWindowTitle(tr("Add Remote Folder"));
|
||||
dlg->setLabelText(tr("Enter the name of the new folder:"));
|
||||
dlg->setTextValue(parent);
|
||||
dlg->setWindowTitle(tr("Create Remote Folder"));
|
||||
dlg->setLabelText(tr("Enter the name of the new folder to be created below '%1':")
|
||||
.arg(parent));
|
||||
dlg->open(this, SLOT(slotCreateRemoteFolder(QString)));
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
@@ -265,7 +265,14 @@ void FolderWizardRemotePath::slotCreateRemoteFolder(const QString &folder)
|
||||
{
|
||||
if( folder.isEmpty() ) return;
|
||||
|
||||
MkColJob *job = new MkColJob(AccountManager::instance()->account(), folder, this);
|
||||
QTreeWidgetItem *current = _ui.folderTreeWidget->currentItem();
|
||||
QString fullPath;
|
||||
if (current) {
|
||||
fullPath = current->data(0, Qt::UserRole).toString();
|
||||
}
|
||||
fullPath += "/" + folder;
|
||||
|
||||
MkColJob *job = new MkColJob(AccountManager::instance()->account(), fullPath, this);
|
||||
/* check the owncloud configuration file and query the ownCloud */
|
||||
connect(job, SIGNAL(finished(QNetworkReply::NetworkError)),
|
||||
SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError)));
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="addFolderButton">
|
||||
<property name="text">
|
||||
<string>Add Folder</string>
|
||||
<string>Create Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "mirall/networkjobs.h"
|
||||
#include "mirall/account.h"
|
||||
#include "mirall/owncloudpropagator.h"
|
||||
|
||||
#include "creds/credentialsfactory.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
@@ -50,12 +51,7 @@ AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QO
|
||||
, _path(path)
|
||||
{
|
||||
_timer.setSingleShot(true);
|
||||
if (!AbstractNetworkJob::preOc7WasDetected) {
|
||||
_timer.setInterval(15*1000); // default to 15 seconds.
|
||||
} else {
|
||||
qDebug() << "Pre-oc7 server detected, adjusting timeout values";
|
||||
_timer.setInterval(60*1000); // long PROPFINDs in oc6 might take too long
|
||||
}
|
||||
_timer.setInterval(OwncloudPropagator::httpTimeout() * 1000); // default to 5 minutes.
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
|
||||
|
||||
connect(this, SIGNAL(networkActivity()), SLOT(resetTimeout()));
|
||||
@@ -170,8 +166,8 @@ void AbstractNetworkJob::slotFinished()
|
||||
bool discard = finished();
|
||||
AbstractCredentials *creds = _account->credentials();
|
||||
if (!creds->stillValid(_reply) &&! _ignoreCredentialFailure
|
||||
&& _account->state() != Account::InvalidCredidential) {
|
||||
_account->setState(Account::InvalidCredidential);
|
||||
&& _account->state() != Account::InvalidCredential) {
|
||||
_account->setState(Account::InvalidCredential);
|
||||
|
||||
// invalidate & forget token/password
|
||||
// but try to re-sign in.
|
||||
|
||||
@@ -259,16 +259,17 @@ void ownCloudGui::slotComputeOverallSyncStatus()
|
||||
// create the tray blob message, check if we have an defined state
|
||||
if( overallResult.status() != SyncResult::Undefined ) {
|
||||
QStringList allStatusStrings;
|
||||
foreach(Folder* folder, map.values()) {
|
||||
qDebug() << "Folder in overallStatus Message: " << folder << " with name " << folder->alias();
|
||||
QString folderMessage = folderMan->statusToString(folder->syncResult().status(), folder->syncPaused());
|
||||
allStatusStrings += tr("Folder %1: %2").arg(folder->alias(), folderMessage);
|
||||
}
|
||||
if( map.count() > 0 ) {
|
||||
foreach(Folder* folder, map.values()) {
|
||||
qDebug() << "Folder in overallStatus Message: " << folder << " with name " << folder->alias();
|
||||
QString folderMessage = folderMan->statusToString(folder->syncResult().status(), folder->syncPaused());
|
||||
allStatusStrings += tr("Folder %1: %2").arg(folder->alias(), folderMessage);
|
||||
}
|
||||
|
||||
if( ! allStatusStrings.isEmpty() )
|
||||
trayMessage = allStatusStrings.join(QLatin1String("\n"));
|
||||
else
|
||||
} else {
|
||||
trayMessage = tr("No sync folders configured.");
|
||||
}
|
||||
|
||||
QIcon statusIcon = Theme::instance()->syncStateIcon( overallResult.status(), true);
|
||||
_tray->setIcon( statusIcon );
|
||||
@@ -466,20 +467,21 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
|
||||
{
|
||||
Q_UNUSED(folder);
|
||||
|
||||
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
||||
_actionStatus->setText( tr("Discovering '%1'")
|
||||
.arg( progress._currentDiscoveredFolder ));
|
||||
} else if (progress._totalSize == 0 ) {
|
||||
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
|
||||
_actionStatus->setText( tr("Syncing %1 of %2 (%3 left)")
|
||||
.arg( currentFile ).arg( progress._totalFileCount )
|
||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
|
||||
} else {
|
||||
QString totalSizeStr = Utility::octetsToString( progress._totalSize );
|
||||
_actionStatus->setText( tr("Syncing %1 (%2 left)")
|
||||
.arg( totalSizeStr )
|
||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
|
||||
}
|
||||
if (!progress._currentDiscoveredFolder.isEmpty()) {
|
||||
_actionStatus->setText( tr("Discovering '%1'")
|
||||
.arg( progress._currentDiscoveredFolder ));
|
||||
} else if (progress._totalSize == 0 ) {
|
||||
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
|
||||
quint64 totalFileCount = qMax(progress._totalFileCount, currentFile);
|
||||
_actionStatus->setText( tr("Syncing %1 of %2 (%3 left)")
|
||||
.arg( currentFile ).arg( totalFileCount )
|
||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
|
||||
} else {
|
||||
QString totalSizeStr = Utility::octetsToString( progress._totalSize );
|
||||
_actionStatus->setText( tr("Syncing %1 (%2 left)")
|
||||
.arg( totalSizeStr )
|
||||
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate(), 2, " ",true) ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -516,7 +518,8 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
|
||||
slotRebuildRecentMenus();
|
||||
}
|
||||
|
||||
if (progress._completedFileCount == progress._totalFileCount
|
||||
if (progress._completedFileCount != ULLONG_MAX
|
||||
&& progress._completedFileCount >= progress._totalFileCount
|
||||
&& progress._currentDiscoveredFolder.isEmpty()) {
|
||||
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
|
||||
}
|
||||
|
||||
@@ -248,13 +248,23 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
||||
|
||||
if (!removedDirectory.isEmpty() && item._file.startsWith(removedDirectory)) {
|
||||
// this is an item in a directory which is going to be removed.
|
||||
PropagateDirectory *delDirJob = dynamic_cast<PropagateDirectory*>(directoriesToRemove.last());
|
||||
|
||||
if (item._instruction == CSYNC_INSTRUCTION_REMOVE) {
|
||||
//already taken care of. (by the removal of the parent directory)
|
||||
|
||||
// increase the number of subjobs that would be there.
|
||||
if( delDirJob ) {
|
||||
delDirJob->increaseAffectedCount();
|
||||
}
|
||||
continue;
|
||||
} else if (item._instruction == CSYNC_INSTRUCTION_NEW && item._isDirectory) {
|
||||
// create a new directory within a deleted directory? That can happen if the directory
|
||||
// etag were not fetched properly on the previous sync because the sync was aborted
|
||||
// while uploading this directory (which is now removed). We can ignore it.
|
||||
if( delDirJob ) {
|
||||
delDirJob->increaseAffectedCount();
|
||||
}
|
||||
continue;
|
||||
} else if (item._instruction == CSYNC_INSTRUCTION_IGNORE) {
|
||||
continue;
|
||||
|
||||
@@ -71,59 +71,6 @@ signals:
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Propagate a directory, and all its sub entries.
|
||||
*/
|
||||
class PropagateDirectory : public PropagatorJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// e.g: create the directory
|
||||
QScopedPointer<PropagatorJob>_firstJob;
|
||||
|
||||
// all the sub files or sub directories.
|
||||
QVector<PropagatorJob *> _subJobs;
|
||||
|
||||
SyncFileItem _item;
|
||||
|
||||
int _current; // index of the current running job
|
||||
int _runningNow; // number of subJob running now
|
||||
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
|
||||
|
||||
|
||||
explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItem &item = SyncFileItem())
|
||||
: PropagatorJob(propagator)
|
||||
, _firstJob(0), _item(item), _current(-1), _runningNow(0), _hasError(SyncFileItem::NoStatus) { }
|
||||
|
||||
virtual ~PropagateDirectory() {
|
||||
qDeleteAll(_subJobs);
|
||||
}
|
||||
|
||||
void append(PropagatorJob *subJob) {
|
||||
_subJobs.append(subJob);
|
||||
}
|
||||
|
||||
virtual void start() Q_DECL_OVERRIDE;
|
||||
virtual void abort() Q_DECL_OVERRIDE {
|
||||
if (_firstJob)
|
||||
_firstJob->abort();
|
||||
foreach (PropagatorJob *j, _subJobs)
|
||||
j->abort();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void startJob(PropagatorJob *next) {
|
||||
connect(next, SIGNAL(finished(SyncFileItem::Status)), this, SLOT(slotSubJobFinished(SyncFileItem::Status)), Qt::QueuedConnection);
|
||||
connect(next, SIGNAL(completed(SyncFileItem)), this, SIGNAL(completed(SyncFileItem)));
|
||||
connect(next, SIGNAL(progress(SyncFileItem,quint64)), this, SIGNAL(progress(SyncFileItem,quint64)));
|
||||
connect(next, SIGNAL(ready()), this, SLOT(slotSubJobReady()));
|
||||
_runningNow++;
|
||||
QMetaObject::invokeMethod(next, "start", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void slotSubJobFinished(SyncFileItem::Status status);
|
||||
void slotSubJobReady();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Abstract class to propagate a single item
|
||||
@@ -148,8 +95,6 @@ protected:
|
||||
_item._errorString = msg;
|
||||
}
|
||||
|
||||
SyncFileItem _item;
|
||||
|
||||
protected slots:
|
||||
void slotRestoreJobCompleted(const SyncFileItem& );
|
||||
|
||||
@@ -160,8 +105,69 @@ public:
|
||||
PropagateItemJob(OwncloudPropagator* propagator, const SyncFileItem &item)
|
||||
: PropagatorJob(propagator), _item(item) {}
|
||||
|
||||
SyncFileItem _item;
|
||||
};
|
||||
|
||||
/*
|
||||
* Propagate a directory, and all its sub entries.
|
||||
*/
|
||||
class PropagateDirectory : public PropagatorJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// e.g: create the directory
|
||||
QScopedPointer<PropagateItemJob>_firstJob;
|
||||
|
||||
// all the sub files or sub directories.
|
||||
QVector<PropagatorJob *> _subJobs;
|
||||
|
||||
SyncFileItem _item;
|
||||
|
||||
int _current; // index of the current running job
|
||||
int _runningNow; // number of subJob running now
|
||||
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
|
||||
|
||||
explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItem &item = SyncFileItem())
|
||||
: PropagatorJob(propagator)
|
||||
, _firstJob(0), _item(item), _current(-1), _runningNow(0), _hasError(SyncFileItem::NoStatus)
|
||||
{ }
|
||||
|
||||
virtual ~PropagateDirectory() {
|
||||
qDeleteAll(_subJobs);
|
||||
}
|
||||
|
||||
void append(PropagatorJob *subJob) {
|
||||
_subJobs.append(subJob);
|
||||
}
|
||||
|
||||
virtual void start() Q_DECL_OVERRIDE;
|
||||
virtual void abort() Q_DECL_OVERRIDE {
|
||||
if (_firstJob)
|
||||
_firstJob->abort();
|
||||
foreach (PropagatorJob *j, _subJobs)
|
||||
j->abort();
|
||||
}
|
||||
|
||||
void increaseAffectedCount() {
|
||||
_firstJob->_item._affectedItems++;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void startJob(PropagatorJob *next) {
|
||||
connect(next, SIGNAL(finished(SyncFileItem::Status)), this, SLOT(slotSubJobFinished(SyncFileItem::Status)), Qt::QueuedConnection);
|
||||
connect(next, SIGNAL(completed(SyncFileItem)), this, SIGNAL(completed(SyncFileItem)));
|
||||
connect(next, SIGNAL(progress(SyncFileItem,quint64)), this, SIGNAL(progress(SyncFileItem,quint64)));
|
||||
connect(next, SIGNAL(ready()), this, SLOT(slotSubJobReady()));
|
||||
_runningNow++;
|
||||
QMetaObject::invokeMethod(next, "start", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void slotSubJobFinished(SyncFileItem::Status status);
|
||||
void slotSubJobReady();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Dummy job that just mark it as completed and ignored.
|
||||
class PropagateIgnoreJob : public PropagateItemJob {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -146,7 +146,7 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
|
||||
}
|
||||
Account *account = _ocWizard->account();
|
||||
account->setUrl(url);
|
||||
// Set fake credentials beforfe we check what credidential it actually is.
|
||||
// Set fake credentials beforfe we check what credential it actually is.
|
||||
account->setCredentials(CredentialsFactory::create("dummy"));
|
||||
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), false, this);
|
||||
job->setIgnoreCredentialFailure(true);
|
||||
@@ -184,17 +184,17 @@ void OwncloudSetupWizard::slotOwnCloudFoundAuth(const QUrl& url, const QVariantM
|
||||
void OwncloudSetupWizard::slotNoOwnCloudFoundAuth(QNetworkReply *reply)
|
||||
{
|
||||
_ocWizard->displayError(tr("Failed to connect to %1 at %2:<br/>%3")
|
||||
.arg(Theme::instance()->appNameGUI())
|
||||
.arg(reply->url().toString())
|
||||
.arg(reply->errorString()));
|
||||
.arg(Theme::instance()->appNameGUI(),
|
||||
reply->url().toString(),
|
||||
reply->errorString()));
|
||||
}
|
||||
|
||||
void OwncloudSetupWizard::slotNoOwnCloudFoundAuthTimeout(const QUrl&url)
|
||||
{
|
||||
_ocWizard->displayError(tr("Failed to connect to %1 at %2:<br/>%3")
|
||||
.arg(Theme::instance()->appNameGUI())
|
||||
.arg(url.toString())
|
||||
.arg("Timeout"));
|
||||
.arg(Theme::instance()->appNameGUI(),
|
||||
url.toString(),
|
||||
"Timeout"));
|
||||
}
|
||||
|
||||
void OwncloudSetupWizard::slotConnectToOCUrl( const QString& url )
|
||||
@@ -228,7 +228,9 @@ void OwncloudSetupWizard::slotConnectionCheck(QNetworkReply* reply)
|
||||
break;
|
||||
|
||||
default:
|
||||
_ocWizard->displayError(tr("Error: Wrong credentials."));
|
||||
_ocWizard->show();
|
||||
_ocWizard->back();
|
||||
_ocWizard->displayError(reply->errorString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -413,7 +415,7 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
||||
Folder *f = folderMan->folderForPath(localFolder);
|
||||
if( f ) {
|
||||
folderMan->setSyncEnabled(false);
|
||||
folderMan->terminateSyncProcess(f->alias());
|
||||
f->slotTerminateSync();
|
||||
f->journalDb()->close();
|
||||
}
|
||||
|
||||
@@ -433,21 +435,23 @@ void OwncloudSetupWizard::slotAssistantFinished( int result )
|
||||
}
|
||||
// 2. Server URL or user changed, requires reinit of folders
|
||||
else if (reinitRequired) {
|
||||
folderMan->removeAllFolderDefinitions();
|
||||
// 2.1: startFromScratch: (Re)move local data, clean slate sync
|
||||
if (startFromScratch) {
|
||||
if (ensureStartFromScratch(localFolder)) {
|
||||
folderMan->addFolderDefinition(Theme::instance()->appName(),
|
||||
localFolder, _remoteFolder, _ocWizard->blacklist() );
|
||||
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
|
||||
if (folderMan->addFolderDefinition(Theme::instance()->appName(),
|
||||
localFolder, _remoteFolder, _ocWizard->blacklist() )) {
|
||||
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
|
||||
}
|
||||
replaceDefaultAccountWith(newAccount);
|
||||
}
|
||||
}
|
||||
// 2.2: Reinit: Remove journal and start a sync
|
||||
else {
|
||||
folderMan->removeAllFolderDefinitions();
|
||||
folderMan->addFolderDefinition(Theme::instance()->appName(),
|
||||
localFolder, _remoteFolder, _ocWizard->blacklist() );
|
||||
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
|
||||
if (folderMan->addFolderDefinition(Theme::instance()->appName(),
|
||||
localFolder, _remoteFolder, _ocWizard->blacklist() )) {
|
||||
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
|
||||
}
|
||||
replaceDefaultAccountWith(newAccount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
#include "ownsql.h"
|
||||
#include "utility.h"
|
||||
@@ -40,26 +41,88 @@ bool SqlDatabase::isOpen()
|
||||
return _db != 0;
|
||||
}
|
||||
|
||||
bool SqlDatabase::open( const QString& filename )
|
||||
bool SqlDatabase::openHelper( const QString& filename, int sqliteFlags )
|
||||
{
|
||||
if(isOpen()) {
|
||||
if( isOpen() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int flag = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_NOMUTEX;
|
||||
SQLITE_DO( sqlite3_open_v2(filename.toUtf8().constData(), &_db, flag, 0) );
|
||||
sqliteFlags |= SQLITE_OPEN_NOMUTEX;
|
||||
|
||||
SQLITE_DO( sqlite3_open_v2(filename.toUtf8().constData(), &_db, sqliteFlags, 0) );
|
||||
|
||||
if( _errId != SQLITE_OK ) {
|
||||
qDebug() << Q_FUNC_INFO << "Error:" << _error << "for" << filename;
|
||||
qDebug() << "Error:" << _error << "for" << filename;
|
||||
close();
|
||||
_db = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_db) {
|
||||
sqlite3_busy_timeout(_db, 5000);
|
||||
if( !_db ) {
|
||||
qDebug() << "Error: no database for" << filename;
|
||||
return false;
|
||||
}
|
||||
|
||||
return isOpen();
|
||||
sqlite3_busy_timeout(_db, 5000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqlDatabase::checkDb()
|
||||
{
|
||||
SqlQuery quick_check("PRAGMA quick_check;", *this);
|
||||
if( !quick_check.exec() ) {
|
||||
qDebug() << "Error running quick_check on database";
|
||||
return false;
|
||||
}
|
||||
|
||||
quick_check.next();
|
||||
QString result = quick_check.stringValue(0);
|
||||
if( result != "ok" ) {
|
||||
qDebug() << "quick_check returned failure:" << result;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqlDatabase::openOrCreateReadWrite( const QString& filename )
|
||||
{
|
||||
if( isOpen() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if( !openHelper(filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !checkDb() ) {
|
||||
qDebug() << "Consistency check failed, removing broken db" << filename;
|
||||
close();
|
||||
QFile::remove(filename);
|
||||
|
||||
return openHelper(filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqlDatabase::openReadOnly( const QString& filename )
|
||||
{
|
||||
if( isOpen() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if( !openHelper(filename, SQLITE_OPEN_READONLY) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !checkDb() ) {
|
||||
qDebug() << "Consistency check failed in readonly mode, giving up" << filename;
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString SqlDatabase::error() const
|
||||
|
||||
@@ -30,7 +30,8 @@ public:
|
||||
explicit SqlDatabase();
|
||||
|
||||
bool isOpen();
|
||||
bool open( const QString& filename );
|
||||
bool openOrCreateReadWrite( const QString& filename );
|
||||
bool openReadOnly( const QString& filename );
|
||||
bool transaction();
|
||||
bool commit();
|
||||
void close();
|
||||
@@ -38,6 +39,9 @@ public:
|
||||
sqlite3* sqliteDb();
|
||||
|
||||
private:
|
||||
bool openHelper( const QString& filename, int sqliteFlags );
|
||||
bool checkDb();
|
||||
|
||||
sqlite3 *_db;
|
||||
QString _error; // last error string
|
||||
int _errId;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <QTime>
|
||||
#include <QQueue>
|
||||
#include <QElapsedTimer>
|
||||
#include <QDebug>
|
||||
|
||||
#include "syncfileitem.h"
|
||||
|
||||
namespace Mirall {
|
||||
@@ -112,12 +114,12 @@ namespace Progress
|
||||
|
||||
void setProgressComplete(const SyncFileItem &item) {
|
||||
_currentItems.remove(item._file);
|
||||
_completedFileCount += item._affectedItems;
|
||||
if (!item._isDirectory) {
|
||||
_completedFileCount++;
|
||||
if (Progress::isSizeDependent(item._instruction)) {
|
||||
_completedSize += item._size;
|
||||
}
|
||||
}
|
||||
if (Progress::isSizeDependent(item._instruction)) {
|
||||
_completedSize += item._size;
|
||||
}
|
||||
}
|
||||
_lastCompletedItem = item;
|
||||
this->updateEstimation();
|
||||
}
|
||||
|
||||
@@ -228,6 +228,7 @@ void PropagateUploadFileQNAM::startNextChunk()
|
||||
quint64 fileSize = _item._size;
|
||||
QMap<QByteArray, QByteArray> headers;
|
||||
headers["OC-Total-Length"] = QByteArray::number(fileSize);
|
||||
headers["OC-Chunk-Size"]= QByteArray::number(quint64(chunkSize()));
|
||||
headers["Content-Type"] = "application/octet-stream";
|
||||
headers["X-OC-Mtime"] = QByteArray::number(qint64(_item._modtime));
|
||||
if (!_item._etag.isEmpty() && _item._etag != "empty_etag" &&
|
||||
@@ -265,7 +266,6 @@ void PropagateUploadFileQNAM::startNextChunk()
|
||||
|
||||
if( isOpen ) {
|
||||
_job = new PUTFileJob(AccountManager::instance()->account(), _propagator->_remoteFolder + path, device, headers);
|
||||
_job->setTimeout(_propagator->httpTimeout() * 1000);
|
||||
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished()));
|
||||
connect(_job, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64)));
|
||||
_job->start();
|
||||
@@ -526,7 +526,7 @@ void GETFileJob::slotMetaDataChanged()
|
||||
}
|
||||
if (start != _resumeStart) {
|
||||
qDebug() << Q_FUNC_INFO << "Wrong content-range: "<< ranges << " while expecting start was" << _resumeStart;
|
||||
if (start == 0) {
|
||||
if (ranges.isEmpty()) {
|
||||
// device don't support range, just stry again from scratch
|
||||
_device->close();
|
||||
if (!_device->open(QIODevice::WriteOnly)) {
|
||||
@@ -679,7 +679,6 @@ void PropagateDownloadFileQNAM::start()
|
||||
url,
|
||||
&_tmpFile, headers);
|
||||
}
|
||||
_job->setTimeout(_propagator->httpTimeout() * 1000);
|
||||
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotGetFinished()));
|
||||
connect(_job, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(slotDownloadProgress(qint64,qint64)));
|
||||
_propagator->_activeJobs ++;
|
||||
@@ -742,6 +741,21 @@ void PropagateDownloadFileQNAM::slotGetFinished()
|
||||
|
||||
_tmpFile.close();
|
||||
_tmpFile.flush();
|
||||
|
||||
/* Check that the size of the GET reply matches the file size. There have been cases
|
||||
* reported that if a server breaks behind a proxy, the GET is still a 200 but is
|
||||
* truncated, as described here: https://github.com/owncloud/mirall/issues/2528
|
||||
*/
|
||||
const QByteArray sizeHeader("Content-Length");
|
||||
quint64 bodySize = job->reply()->rawHeader(sizeHeader).toULongLong();
|
||||
|
||||
if(bodySize > 0 && bodySize != _tmpFile.size() - job->resumeStart() ) {
|
||||
qDebug() << bodySize << _tmpFile.size() << job->resumeStart();
|
||||
_propagator->_anotherSyncNeeded = true;
|
||||
done(SyncFileItem::SoftError, tr("The file could not be downloaded completely."));
|
||||
return;
|
||||
}
|
||||
|
||||
downloadFinished();
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ void ProtocolWidget::slotProgressInfo( const QString& folder, const Progress::In
|
||||
// The sync is restarting, clean the old items
|
||||
cleanIgnoreItems(folder);
|
||||
computeResyncButtonEnabled();
|
||||
} else if (progress._totalFileCount == progress._completedFileCount) {
|
||||
} else if (progress._completedFileCount >= progress._totalFileCount) {
|
||||
//Sync completed
|
||||
computeResyncButtonEnabled();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ void QuotaInfo::slotAccountStateChanged(int state)
|
||||
{
|
||||
switch (state) {
|
||||
case Account::SignedOut: // fall through
|
||||
case Account::InvalidCredidential:
|
||||
case Account::InvalidCredential:
|
||||
case Account::Disconnected:
|
||||
_jobRestartTimer->stop();
|
||||
break;
|
||||
|
||||
@@ -94,6 +94,11 @@ SocketApi::SocketApi(QObject* parent)
|
||||
runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
|
||||
#else
|
||||
runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
|
||||
if (runtimeDir.isEmpty()) {
|
||||
runtimeDir = QDir::tempPath() + QLatin1String("/runtime-")
|
||||
+ QString::fromLocal8Bit(qgetenv("USER"));
|
||||
QDir().mkdir(runtimeDir);
|
||||
}
|
||||
#endif
|
||||
socketPath = runtimeDir + "/" + Theme::instance()->appName() + "/socket";
|
||||
} else {
|
||||
@@ -344,7 +349,12 @@ void SocketApi::broadcastMessage( const QString& verb, const QString& path, cons
|
||||
}
|
||||
if( !path.isEmpty() ) {
|
||||
msg.append(QLatin1Char(':'));
|
||||
msg.append(QDir::toNativeSeparators(path));
|
||||
QFileInfo fi(path);
|
||||
auto canon = fi.canonicalFilePath();
|
||||
if (canon.isEmpty()) { // just in case the file do not exist
|
||||
fi = fi.absoluteFilePath();
|
||||
}
|
||||
msg.append(QDir::toNativeSeparators(canon));
|
||||
}
|
||||
|
||||
// sendMessage already has a debug output
|
||||
@@ -417,7 +427,7 @@ SqlQuery* SocketApi::getSqlQuery( Folder *folder )
|
||||
if( fi.exists() ) {
|
||||
SqlDatabase *db = new SqlDatabase;
|
||||
|
||||
if( db && db->open(dbFileName) ) {
|
||||
if( db && db->openReadOnly(dbFileName) ) {
|
||||
_openDbs.insert(folder, db);
|
||||
|
||||
SqlQuery *query = new SqlQuery(*db);
|
||||
@@ -430,6 +440,8 @@ SqlQuery* SocketApi::getSqlQuery( Folder *folder )
|
||||
}
|
||||
_dbQueries.insert( folder, query);
|
||||
return query;
|
||||
} else {
|
||||
qDebug() << "Unable to open db" << dbFileName;
|
||||
}
|
||||
} else {
|
||||
qDebug() << Q_FUNC_INFO << "Journal to query does not yet exist.";
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <QSslCertificate>
|
||||
#include <QProcess>
|
||||
#include <QElapsedTimer>
|
||||
#include <qtextcodec.h>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
@@ -314,7 +315,16 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
{
|
||||
if( ! file ) return -1;
|
||||
|
||||
QString fileUtf8 = QString::fromUtf8( file->path );
|
||||
QTextCodec::ConverterState utf8State;
|
||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
||||
Q_ASSERT(codec);
|
||||
QString fileUtf8 = codec->toUnicode(file->path, qstrlen(file->path), &utf8State);
|
||||
|
||||
auto instruction = file->instruction;
|
||||
if (utf8State.invalidChars > 0) {
|
||||
qDebug() << "File ignored because of invalid utf-8 sequence: " << file->path;
|
||||
instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
}
|
||||
|
||||
// Gets a default-contructed SyncFileItem or the one from the first walk (=local walk)
|
||||
SyncFileItem item = _syncItemMap.value(fileUtf8);
|
||||
@@ -322,12 +332,12 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
item._originalFile = item._file;
|
||||
|
||||
if (item._instruction == CSYNC_INSTRUCTION_NONE
|
||||
|| (item._instruction == CSYNC_INSTRUCTION_IGNORE && file->instruction != CSYNC_INSTRUCTION_NONE)) {
|
||||
item._instruction = file->instruction;
|
||||
|| (item._instruction == CSYNC_INSTRUCTION_IGNORE && instruction != CSYNC_INSTRUCTION_NONE)) {
|
||||
item._instruction = instruction;
|
||||
item._modtime = file->modtime;
|
||||
} else {
|
||||
if (file->instruction != CSYNC_INSTRUCTION_NONE) {
|
||||
qDebug() << "ERROR: Instruction" << item._instruction << "vs" << file->instruction << "for" << fileUtf8;
|
||||
if (instruction != CSYNC_INSTRUCTION_NONE) {
|
||||
qDebug() << "ERROR: Instruction" << item._instruction << "vs" << instruction << "for" << fileUtf8;
|
||||
Q_ASSERT(!"Instructions are both unequal NONE");
|
||||
return -1;
|
||||
}
|
||||
@@ -380,6 +390,13 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
Q_ASSERT("Non handled error-status");
|
||||
/* No error string */
|
||||
}
|
||||
|
||||
if (item._instruction == CSYNC_INSTRUCTION_IGNORE && utf8State.invalidChars > 0) {
|
||||
item._status = SyncFileItem::NormalError;
|
||||
//item._instruction = CSYNC_INSTRUCTION_ERROR;
|
||||
item._errorString = tr("Filename encoding is not valid");
|
||||
}
|
||||
|
||||
item._isDirectory = file->type == CSYNC_FTW_TYPE_DIR;
|
||||
|
||||
// The etag is already set in the previous sync phases somewhere. Maybe we should remove it there
|
||||
@@ -475,6 +492,9 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
if (Progress::isSizeDependent(file->instruction)) {
|
||||
_progressInfo._totalSize += file->size;
|
||||
}
|
||||
} else if (file->instruction != CSYNC_INSTRUCTION_NONE) {
|
||||
// Added or removed directories certainly count.
|
||||
_progressInfo._totalFileCount++;
|
||||
}
|
||||
_needsUpdate = true;
|
||||
|
||||
@@ -544,6 +564,14 @@ void SyncEngine::startSync()
|
||||
qDebug() << "=====sync with existing DB";
|
||||
}
|
||||
|
||||
qDebug() << "=====Using Qt" << qVersion();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
qDebug() << "=====Using SSL library version"
|
||||
<< QSslSocket::sslLibraryVersionString().toUtf8().data();
|
||||
#endif
|
||||
// Note that this seems to output the OpenSSL build version not runtime version:
|
||||
qDebug() << "=====Using" << ne_version_string();
|
||||
|
||||
fileRecordCount = _journal->getFileRecordCount(); // this creates the DB if it does not exist yet
|
||||
bool isUpdateFrom_1_5 = _journal->isUpdateFrom_1_5();
|
||||
|
||||
@@ -1089,9 +1117,16 @@ void SyncEngine::setSelectiveSyncBlackList(const QStringList& list)
|
||||
bool SyncEngine::estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s)
|
||||
{
|
||||
Q_UNUSED(t);
|
||||
QString pat(fn);
|
||||
if( t == CSYNC_FTW_TYPE_DIR && ! fn.endsWith(QLatin1Char('/'))) {
|
||||
pat.append(QLatin1Char('/'));
|
||||
}
|
||||
|
||||
Q_FOREACH(const SyncFileItem &item, _syncedItems) {
|
||||
//qDebug() << Q_FUNC_INFO << fn << item._file << fn.startsWith(item._file) << item._file.startsWith(fn);
|
||||
if (item._file.startsWith(fn)) {
|
||||
|
||||
if (item._file.startsWith(pat) ||
|
||||
item._file == fn /* the same directory or file */) {
|
||||
qDebug() << Q_FUNC_INFO << "Setting" << fn << " to STATUS_EVAL";
|
||||
s->set(SyncFileStatus::STATUS_EVAL);
|
||||
return true;
|
||||
|
||||
@@ -53,7 +53,10 @@ public:
|
||||
SyncFileItem() : _type(UnknownType), _direction(None), _isDirectory(false),
|
||||
_instruction(CSYNC_INSTRUCTION_NONE), _modtime(0),
|
||||
_size(0), _inode(0), _should_update_etag(false), _hasBlacklistEntry(false),
|
||||
_status(NoStatus), _httpErrorCode(0), _requestDuration(0), _isRestoration(false) {}
|
||||
_status(NoStatus), _httpErrorCode(0), _requestDuration(0), _isRestoration(false),
|
||||
_affectedItems(1)
|
||||
{
|
||||
}
|
||||
|
||||
friend bool operator==(const SyncFileItem& item1, const SyncFileItem& item2) {
|
||||
return item1._file == item2._file;
|
||||
@@ -111,7 +114,8 @@ public:
|
||||
QString _responseTimeStamp;
|
||||
quint64 _requestDuration;
|
||||
bool _isRestoration; // The original operation was forbidden, and this is a restoration
|
||||
|
||||
int _affectedItems; // the number of affected items by the operation on this item.
|
||||
// usually this value is 1, but for removes on dirs, it might be much higher.
|
||||
struct {
|
||||
quint64 _size;
|
||||
time_t _modtime;
|
||||
|
||||
@@ -120,7 +120,7 @@ bool SyncJournalDb::checkConnect()
|
||||
bool isNewDb = !QFile::exists(_dbFile);
|
||||
|
||||
// The database file is created by this call (SQLITE_OPEN_CREATE)
|
||||
if( !_db.open(_dbFile) ) {
|
||||
if( !_db.openOrCreateReadWrite(_dbFile) ) {
|
||||
QString error = _db.error();
|
||||
qDebug() << "Error opening the db: " << error;
|
||||
return false;
|
||||
@@ -158,11 +158,6 @@ bool SyncJournalDb::checkConnect()
|
||||
return sqlFail("Set PRAGMA case_sensitivity", pragma1);
|
||||
}
|
||||
|
||||
// Hide 'em all!
|
||||
FileSystem::setFileHidden(databaseFilePath(), true);
|
||||
FileSystem::setFileHidden(databaseFilePath() + "-wal", true);
|
||||
FileSystem::setFileHidden(databaseFilePath() + "-shm", true);
|
||||
|
||||
/* Because insert are so slow, e do everything in a transaction, and one need to call commit */
|
||||
startTransaction();
|
||||
|
||||
@@ -335,6 +330,11 @@ bool SyncJournalDb::checkConnect()
|
||||
// don't start a new transaction now
|
||||
commitInternal(QString("checkConnect End"), false);
|
||||
|
||||
// Hide 'em all!
|
||||
FileSystem::setFileHidden(databaseFilePath(), true);
|
||||
FileSystem::setFileHidden(databaseFilePath() + "-wal", true);
|
||||
FileSystem::setFileHidden(databaseFilePath() + "-shm", true);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,10 +143,12 @@ private:
|
||||
QList<QString> _avoidReadFromDbOnNextSyncFilter;
|
||||
};
|
||||
|
||||
bool operator==(const SyncJournalDb::DownloadInfo & lhs,
|
||||
const SyncJournalDb::DownloadInfo & rhs);
|
||||
bool operator==(const SyncJournalDb::UploadInfo & lhs,
|
||||
const SyncJournalDb::UploadInfo & rhs);
|
||||
bool OWNCLOUDSYNC_EXPORT
|
||||
operator==(const SyncJournalDb::DownloadInfo & lhs,
|
||||
const SyncJournalDb::DownloadInfo & rhs);
|
||||
bool OWNCLOUDSYNC_EXPORT
|
||||
operator==(const SyncJournalDb::UploadInfo & lhs,
|
||||
const SyncJournalDb::UploadInfo & rhs);
|
||||
|
||||
} // namespace Mirall
|
||||
#endif // SYNCJOURNALDB_H
|
||||
|
||||
@@ -43,8 +43,9 @@ public:
|
||||
int _mode;
|
||||
};
|
||||
|
||||
bool operator==(const SyncJournalFileRecord & lhs,
|
||||
const SyncJournalFileRecord & rhs);
|
||||
bool OWNCLOUDSYNC_EXPORT
|
||||
operator==(const SyncJournalFileRecord & lhs,
|
||||
const SyncJournalFileRecord & rhs);
|
||||
|
||||
class SyncJournalBlacklistRecord
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "theme.h"
|
||||
#include "version.h"
|
||||
#include "config.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <QtCore>
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
@@ -184,11 +185,7 @@ QString Theme::systrayIconFlavor(bool mono) const
|
||||
{
|
||||
QString flavor;
|
||||
if (mono) {
|
||||
#ifdef Q_OS_MAC
|
||||
flavor = QLatin1String("black");
|
||||
#else
|
||||
flavor = QLatin1String("white");
|
||||
#endif
|
||||
flavor = Utility::hasDarkSystray() ? QLatin1String("white") : QLatin1String("black");
|
||||
} else {
|
||||
flavor = QLatin1String("colored");
|
||||
}
|
||||
@@ -230,14 +227,19 @@ QString Theme::gitSHA1() const
|
||||
|
||||
QString Theme::about() const
|
||||
{
|
||||
return tr("<p>Version %1 For more information please visit <a href='%2'>%3</a>.</p>"
|
||||
"<p>Copyright ownCloud, Inc.</p>"
|
||||
"<p>Distributed by %4 and licensed under the GNU General Public License (GPL) Version 2.0.<br/>"
|
||||
"%5 and the %5 logo are registered trademarks of %4 in the "
|
||||
"United States, other countries, or both.</p>")
|
||||
QString re;
|
||||
re = tr("<p>Version %1. For more information please visit <a href='%2'>%3</a>.</p>")
|
||||
.arg(MIRALL_VERSION_STRING).arg("http://" MIRALL_STRINGIFY(APPLICATION_DOMAIN))
|
||||
.arg(MIRALL_STRINGIFY(APPLICATION_DOMAIN)).arg(APPLICATION_VENDOR).arg(APPLICATION_NAME)
|
||||
+gitSHA1();
|
||||
.arg(MIRALL_STRINGIFY(APPLICATION_DOMAIN));
|
||||
|
||||
re += tr("<p>Copyright ownCloud, Incorparated</p>");
|
||||
re += tr("<p>Distributed by %1 and licensed under the GNU General Public License (GPL) Version 2.0.<br/>"
|
||||
"%2 and the %2 logo are registered trademarks of %1 in the "
|
||||
"United States, other countries, or both.</p>")
|
||||
.arg(APPLICATION_VENDOR).arg(APPLICATION_NAME);
|
||||
|
||||
re += gitSHA1();
|
||||
return re;
|
||||
}
|
||||
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define _THEME_H
|
||||
|
||||
#include "mirall/syncresult.h"
|
||||
#include <QObject>
|
||||
|
||||
|
||||
class QIcon;
|
||||
|
||||
@@ -335,6 +335,11 @@ QString Utility::timeToDescriptiveString(QList<QPair<QString,quint32> > &timeMap
|
||||
return retStr;
|
||||
}
|
||||
|
||||
bool Utility::hasDarkSystray()
|
||||
{
|
||||
return hasDarkSystray_private();
|
||||
}
|
||||
|
||||
|
||||
bool Utility::isWindows()
|
||||
{
|
||||
|
||||
@@ -71,7 +71,19 @@ namespace Utility
|
||||
*/
|
||||
OWNCLOUDSYNC_EXPORT QString timeToDescriptiveString(QList<QPair<QString,quint32> > &timeMapping, quint64 msecs, quint8 precision, QString separator, bool specific);
|
||||
OWNCLOUDSYNC_EXPORT QString timeToDescriptiveString(quint64 msecs, quint8 precision, QString separator, bool specific);
|
||||
|
||||
|
||||
/**
|
||||
* @brief hasDarkSystray - determines whether the systray is dark or light.
|
||||
*
|
||||
* Use this to check if the OS has a dark or a light systray.
|
||||
*
|
||||
* The value might change during the execution of the program
|
||||
* (e.g. on OS X 10.10).
|
||||
*
|
||||
* @return bool which is true for systems with dark systray.
|
||||
*/
|
||||
OWNCLOUDSYNC_EXPORT bool hasDarkSystray();
|
||||
|
||||
// convinience OS detection methods
|
||||
OWNCLOUDSYNC_EXPORT bool isWindows();
|
||||
OWNCLOUDSYNC_EXPORT bool isMac();
|
||||
|
||||
@@ -108,3 +108,18 @@ void setLaunchOnStartup_private(const QString &appName, const QString& guiName,
|
||||
CFRelease(urlRef);
|
||||
}
|
||||
|
||||
static bool hasDarkSystray_private()
|
||||
{
|
||||
bool returnValue = false;
|
||||
CFStringRef interfaceStyleKey = CFSTR("AppleInterfaceStyle");
|
||||
CFStringRef interfaceStyle = NULL;
|
||||
CFStringRef darkInterfaceStyle = CFSTR("Dark");
|
||||
interfaceStyle = (CFStringRef)CFPreferencesCopyAppValue(interfaceStyleKey,
|
||||
kCFPreferencesCurrentApplication);
|
||||
if (interfaceStyle != NULL) {
|
||||
returnValue = (kCFCompareEqualTo == CFStringCompare(interfaceStyle, darkInterfaceStyle, 0));
|
||||
CFRelease(interfaceStyle);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,3 +86,8 @@ void setLaunchOnStartup_private(const QString &appName, const QString& guiName,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool hasDarkSystray_private()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,3 +47,8 @@ void setLaunchOnStartup_private(const QString &appName, const QString& guiName,
|
||||
settings.remove(appName);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool hasDarkSystray_private()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ OwncloudSetupPage::OwncloudSetupPage()
|
||||
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(theme->appNameGUI())));
|
||||
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Setup %1 server").arg(theme->appNameGUI())));
|
||||
|
||||
if (!theme->overrideServerUrl().isEmpty()) {
|
||||
_ui.leUrl->setEnabled(false);
|
||||
}
|
||||
|
||||
registerField( QLatin1String("OCUrl*"), _ui.leUrl );
|
||||
|
||||
_ui.resultLayout->addWidget( _progressIndi );
|
||||
@@ -145,6 +149,8 @@ void OwncloudSetupPage::initializePage()
|
||||
_ui.leUrl->setFocus();
|
||||
} else {
|
||||
setCommitPage(true);
|
||||
// Hack: setCommitPage() changes caption, but after an error this page could still be visible
|
||||
setButtonText(QWizard::CommitButton, tr("&Next >"));
|
||||
validatePage();
|
||||
setVisible(false);
|
||||
// because the wizard will call show on us right after this call, we need to hide in the
|
||||
@@ -224,7 +230,7 @@ void OwncloudSetupPage::setErrorString( const QString& err )
|
||||
_ui.errorLabel->setVisible(false);
|
||||
} else {
|
||||
if (_ui.leUrl->text().startsWith("https://")) {
|
||||
QString msg = tr("Could not connect securely. Do you want to connect unencrypted instead (not recommended)?").arg(err);
|
||||
QString msg = tr("<p>Could not connect securely:</p><p>%1</p><p>Do you want to connect unencrypted instead (not recommended)?</p>").arg(err);
|
||||
QString title = tr("Connection failed");
|
||||
if (QMessageBox::question(this, title, msg, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
QUrl url(_ui.leUrl->text());
|
||||
|
||||
@@ -71,18 +71,7 @@ bool OwncloudWizardResultPage::isComplete() const
|
||||
|
||||
void OwncloudWizardResultPage::initializePage()
|
||||
{
|
||||
const QString localFolder = wizard()->property("localFolder").toString();
|
||||
QString text;
|
||||
if( _remoteFolder == QLatin1String("/") || _remoteFolder.isEmpty() ) {
|
||||
text = tr("Your entire account is synced to the local folder <i>%1</i>")
|
||||
.arg(QDir::toNativeSeparators(localFolder));
|
||||
} else {
|
||||
text = tr("%1 folder <i>%1</i> is synced to local folder <i>%2</i>")
|
||||
.arg(Theme::instance()->appNameGUI())
|
||||
.arg(_remoteFolder).arg(QDir::toNativeSeparators(localFolder));
|
||||
}
|
||||
_ui.localFolderLabel->setText( text );
|
||||
|
||||
_ui.localFolderLabel->setText( QString::null );
|
||||
}
|
||||
|
||||
void OwncloudWizardResultPage::setRemoteFolder(const QString &remoteFolder)
|
||||
|
||||
@@ -27,8 +27,8 @@ endif(UNIX AND NOT APPLE)
|
||||
|
||||
owncloud_add_test(CSyncSqlite "")
|
||||
owncloud_add_test(NetrcParser ../src/owncloudcmd/netrcparser.cpp)
|
||||
owncloud_add_test(OwnSql ../src/mirall/ownsql.cpp)
|
||||
owncloud_add_test(SyncJournalDB ../src/mirall/syncjournaldb.cpp)
|
||||
owncloud_add_test(OwnSql "")
|
||||
owncloud_add_test(SyncJournalDB "")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
#include "mirall/folderwatcher_linux.h"
|
||||
#include "mirall/folderwatcher.h"
|
||||
#include "mirall/utility.h"
|
||||
|
||||
using namespace Mirall;
|
||||
@@ -21,9 +21,12 @@ class TestFolderWatcher : public QObject
|
||||
|
||||
public slots:
|
||||
void slotFolderChanged( const QString& path ) {
|
||||
qDebug() << "COMPARE: " << path << _checkMark;
|
||||
QVERIFY(_checkMark == path);
|
||||
_checkMark.clear();
|
||||
if (_skipNotifications.contains(path)) {
|
||||
return;
|
||||
}
|
||||
if (_requiredNotifications.contains(path)) {
|
||||
_receivedNotifications.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
void slotEnd() { // in case something goes wrong...
|
||||
@@ -36,7 +39,16 @@ private:
|
||||
FolderWatcher *_watcher;
|
||||
QEventLoop _loop;
|
||||
QTimer _timer;
|
||||
QString _checkMark;
|
||||
QSet<QString> _requiredNotifications;
|
||||
QSet<QString> _receivedNotifications;
|
||||
QSet<QString> _skipNotifications;
|
||||
|
||||
void processAndWait()
|
||||
{
|
||||
_loop.processEvents();
|
||||
Utility::usleep(200000);
|
||||
_loop.processEvents();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void initTestCase() {
|
||||
@@ -52,68 +64,95 @@ private slots:
|
||||
rootDir.mkpath(_root + "/a2/b3/c3");
|
||||
Utility::writeRandomFile( _root+"/a1/random.bin");
|
||||
Utility::writeRandomFile( _root+"/a1/b2/todelete.bin");
|
||||
Utility::writeRandomFile( _root+"/a2/movefile");
|
||||
Utility::writeRandomFile( _root+"/a2/renamefile");
|
||||
Utility::writeRandomFile( _root+"/a1/movefile");
|
||||
|
||||
_watcher = new FolderWatcher(_root);
|
||||
QObject::connect(_watcher, SIGNAL(folderChanged(QString)), this, SLOT(slotFolderChanged(QString)));
|
||||
_timer.singleShot(3000, this, SLOT(slotEnd()));
|
||||
_timer.singleShot(5000, this, SLOT(slotEnd()));
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
_receivedNotifications.clear();
|
||||
_requiredNotifications.clear();
|
||||
_skipNotifications.clear();
|
||||
}
|
||||
|
||||
void checkNotifications()
|
||||
{
|
||||
processAndWait();
|
||||
QCOMPARE(_receivedNotifications, _requiredNotifications);
|
||||
}
|
||||
|
||||
void testACreate() { // create a new file
|
||||
QString cmd;
|
||||
_checkMark = _root;
|
||||
_requiredNotifications.insert(_root);
|
||||
cmd = QString("echo \"xyz\" > %1/foo.txt").arg(_root);
|
||||
qDebug() << "Command: " << cmd;
|
||||
system(cmd.toLocal8Bit());
|
||||
|
||||
_loop.processEvents();
|
||||
QVERIFY(_checkMark.isEmpty()); // the slot clears the checkmark.
|
||||
checkNotifications();
|
||||
}
|
||||
|
||||
void testATouch() { // touch an existing file.
|
||||
_requiredNotifications.insert(_root+"/a1");
|
||||
#ifdef Q_OS_WIN
|
||||
Utility::writeRandomFile(QString("%1/a1/random.bin").arg(_root));
|
||||
#else
|
||||
QString cmd;
|
||||
cmd = QString("/usr/bin/touch %1/a1/random.bin").arg(_root);
|
||||
_checkMark = _root+"/a1";
|
||||
qDebug() << "Command: " << cmd;
|
||||
system(cmd.toLocal8Bit());
|
||||
#endif
|
||||
|
||||
_loop.processEvents();
|
||||
QVERIFY(_checkMark.isEmpty()); // the slot clears the checkmark.
|
||||
checkNotifications();
|
||||
}
|
||||
|
||||
void testCreateADir() {
|
||||
_checkMark = _root+"/a1/b1";
|
||||
_requiredNotifications.insert(_root+"/a1/b1");
|
||||
_skipNotifications.insert(_root + "/a1/b1/new_dir");
|
||||
QDir dir;
|
||||
dir.mkdir( _root + "/a1/b1/new_dir");
|
||||
QVERIFY(QFile::exists(_root + "/a1/b1/new_dir"));
|
||||
_loop.processEvents();
|
||||
QVERIFY(_checkMark.isEmpty()); // the slot clears the checkmark.
|
||||
|
||||
checkNotifications();
|
||||
}
|
||||
|
||||
void testRemoveADir() {
|
||||
_checkMark = _root+"/a1/b3";
|
||||
_requiredNotifications.insert(_root+"/a1/b3");
|
||||
QDir dir;
|
||||
QVERIFY(dir.rmdir(_root+"/a1/b3/c3"));
|
||||
_loop.processEvents();
|
||||
QVERIFY(_checkMark.isEmpty()); // the slot clears the checkmark.
|
||||
|
||||
checkNotifications();
|
||||
}
|
||||
|
||||
void testRemoveAFile() {
|
||||
_checkMark = _root+"/a1/b2";
|
||||
_requiredNotifications.insert(_root+"/a1/b2");
|
||||
QVERIFY(QFile::exists(_root+"/a1/b2/todelete.bin"));
|
||||
QFile::remove(_root+"/a1/b2/todelete.bin");
|
||||
QVERIFY(!QFile::exists(_root+"/a1/b2/todelete.bin"));
|
||||
_loop.processEvents();
|
||||
QVERIFY(_checkMark.isEmpty()); // the slot clears the checkmark.
|
||||
|
||||
checkNotifications();
|
||||
}
|
||||
|
||||
void testRenameAFile() {
|
||||
_requiredNotifications.insert(_root+"/a2");
|
||||
QVERIFY(QFile::exists(_root+"/a2/renamefile"));
|
||||
QFile::rename(_root+"/a2/renamefile", _root+"/a2/renamefile.renamed" );
|
||||
QVERIFY(QFile::exists(_root+"/a2/renamefile.renamed"));
|
||||
|
||||
checkNotifications();
|
||||
}
|
||||
|
||||
void testMoveAFile() {
|
||||
_checkMark = _root+"/a2";
|
||||
QVERIFY(QFile::exists(_root+"/a2/movefile"));
|
||||
QFile::rename(_root+"/a2/movefile", _root+"/a2/movefile.renamed" );
|
||||
_requiredNotifications.insert(_root+"/a1");
|
||||
_requiredNotifications.insert(_root+"/a2");
|
||||
QVERIFY(QFile::exists(_root+"/a1/movefile"));
|
||||
QFile::rename(_root+"/a1/movefile", _root+"/a2/movefile.renamed" );
|
||||
QVERIFY(QFile::exists(_root+"/a2/movefile.renamed"));
|
||||
_loop.processEvents();
|
||||
QVERIFY(_checkMark.isEmpty()); // the slot clears the checkmark.
|
||||
|
||||
checkNotifications();
|
||||
}
|
||||
|
||||
void cleanupTestCase() {
|
||||
|
||||
@@ -42,7 +42,7 @@ private slots:
|
||||
void testOpenDb() {
|
||||
QFileInfo fi( testdbC );
|
||||
QVERIFY( !fi.exists() ); // must not exist
|
||||
_db.open(testdbC);
|
||||
_db.openOrCreateReadWrite(testdbC);
|
||||
fi.refresh();
|
||||
QVERIFY(fi.exists());
|
||||
|
||||
|
||||