Comparar commits
4 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 098b603879 | |||
| 7c3b3d648b | |||
| 778aca386c | |||
| 0758b2cf61 |
@@ -1,21 +1,15 @@
|
||||
sudo: required
|
||||
|
||||
language: cpp
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
branches:
|
||||
only:
|
||||
- coverity_scan
|
||||
|
||||
before_install:
|
||||
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/Ubuntu_14.04/Release.key
|
||||
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/xUbuntu_12.04/Release.key
|
||||
- sudo apt-key add - < Release.key
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y build-dep owncloud-client
|
||||
- sudo apt-get build-dep owncloud-client
|
||||
- checkout=$(git show-ref --head --hash head)
|
||||
- cd ../
|
||||
- wget https://scan.coverity.com/download/linux-64 --post-data "token=$token&project=owncloud%2Fmirall" -O coverity_tool.tgz
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(VERSION 2.8.0)
|
||||
|
||||
@@ -126,17 +125,6 @@ if(OWNCLOUD_5XX_NO_BLACKLIST)
|
||||
add_definitions(-DOWNCLOUD_5XX_NO_BLACKLIST=1)
|
||||
endif()
|
||||
|
||||
# When this option is enabled, a rename that is not allowed will be renamed back
|
||||
# do the original as a restoration step. Withut this option, the restoration will
|
||||
# re-download the file instead.
|
||||
# The default is off because we don't want to rename the files back behind the user's back
|
||||
# Added for IL issue #550
|
||||
option(OWNCLOUD_RESTORE_RENAME "OWNCLOUD_RESTORE_RENAME" OFF)
|
||||
if(OWNCLOUD_RESTORE_RENAME)
|
||||
add_definitions(-DOWNCLOUD_RESTORE_RENAME=1)
|
||||
endif()
|
||||
|
||||
|
||||
if(APPLE)
|
||||
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
|
||||
endif()
|
||||
@@ -163,6 +151,11 @@ endif()
|
||||
|
||||
find_package(ZLIB)
|
||||
|
||||
find_package(LibsnoreQt5 0.6.0)
|
||||
if(LibsnoreQt5_FOUND)
|
||||
find_package(LibsnoreSettingsQt5)
|
||||
endif()
|
||||
|
||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
configure_file(test/test_journal.db "${CMAKE_BINARY_DIR}/test/test_journal.db" COPYONLY)
|
||||
|
||||
@@ -1,38 +1,5 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 2.2.1 (release 2016-05-xx)
|
||||
* Fix out of memory error when too many uploads happen (#4611)
|
||||
* Fix display errors in progress display (#4803 #4856)
|
||||
* LockWatcher: Remember to upload files after they become unlocked (#4865)
|
||||
* Fix overlay icons for files with umlauts (#4884)
|
||||
* Certs: Re-ask for different cert after rejection (#4898, #4911)
|
||||
* Progress: Don't count items without propagation jobs (#4856, #4910)
|
||||
* Utility: Fix for the translation of minutes, second (#4855)
|
||||
* SyncEngine: invalid the blacklist entry when the rename destination change
|
||||
|
||||
version 2.2.0 (release 2016-05-12)
|
||||
* Overlay icons: Refactoring - mainly for performance improvements
|
||||
* Improved error handling with Sync Journal on USB storages (#4632)
|
||||
* Sharing Completion: Improved UI of completion in sharing from desktop. (#3737)
|
||||
* Show server notifications on the client (#3733)
|
||||
* Improved Speed with small files by dynamic parallel request count (#4529)
|
||||
* LockWatcher: Make sure to sync files after apps released exclusive locks on Windows.
|
||||
* Improved handling of Win32 file locks and network files
|
||||
* Workaround Ubuntu 16.04 tray icon bug (#4693)
|
||||
* Removed the Alias field from the folder definition (#4695)
|
||||
* Improved netrc parser (#4691)
|
||||
* Improved user notifications about ignored files and conflicts (#4761, #3222)
|
||||
* Add warnings for old server versions (#4523)
|
||||
* Enable tranportation checksums if the server supports based on server capabilities (#3735)
|
||||
|
||||
* Default Chunk-size changed to 10MB (#4354)
|
||||
* Documentation Improvements, ie. about overlay icons
|
||||
* Translation fixes
|
||||
* Countless other bugfixes
|
||||
* Sqlite Update to recent version
|
||||
* Update of QtKeyChain to support Windows credential store
|
||||
* Packaging of dolphin overlay icon module for bleeding edge distros
|
||||
|
||||
version 2.1.1 (release 2016-02-10)
|
||||
* UI improvements for HiDPI screens, error messages, RTL languages
|
||||
* Fix occurences of "Connection Closed" when a new unauthenticated TCP socket is used
|
||||
|
||||
@@ -15,7 +15,7 @@ with your computer.
|
||||
|
||||
### Binary packages
|
||||
|
||||
* Refer to the download page https://owncloud.org/install/#install-clients
|
||||
* Refer to the download page http://owncloud.org/sync-clients/
|
||||
|
||||
### Source code
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
set( MIRALL_VERSION_MAJOR 2 )
|
||||
set( MIRALL_VERSION_MINOR 3 )
|
||||
set( MIRALL_VERSION_MINOR 2 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_VERSION_YEAR 2016 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
@@ -30,7 +30,7 @@ StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Z
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Zapisuji odinstal tor"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Zapisuji instal tor do registr…"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "DokonŸeno"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Nezd se, §e ${APPLICATION_NAME} je nainstalov na v adres ýi '$INSTDIR'.$\n$\nChcete pokraŸovat (nedoporuŸuje se)?"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Nezd se, §e ${APPLICATION_NAME} je nainstalov na ve slo§ce '$INSTDIR'.$\n$\nChcete pokraŸovat (nedoporuŸuje se)?"
|
||||
StrCpy $UNINSTALL_ABORT "Odinstalace zruçena u§ivatelem"
|
||||
StrCpy $INIT_NO_QUICK_LAUNCH "Z stupce rychl‚ho spuçtØn¡ (nen¡ k dispozici)"
|
||||
StrCpy $INIT_NO_DESKTOP "Z stupce na ploçe (pýep¡çe existuj¡c¡)"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de lançamento"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Existem ${APPLICATION_EXECUTABLE} processo(s) em execução que precisa(m) de ser interrompido(s).$\nDeseja que o instalador o(s) termine automaticamente?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "A terminar os processos de ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Não foi encontrado nenhum processo para terminar!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Está instalada no sistema uma versão antiga de ${APPLICATION_NAME}. É recomendado que desinstale a versão atual antes de instalar a mais recente. Selecione a operação que deseja executar e clique em $\"Seguinte$\" para continuar."
|
||||
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 a mais recente. 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 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 "Uma versão mais recente da aplicação ${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_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á instalada.$\nSelecione a operação que deseja realizar e clique em 'Seguinte' para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Adicionar/Reinstalar Componentes"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
@@ -25,12 +25,12 @@ StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atalho de início rápido"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "A criar atalho de início rápido"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "O essencial de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Atalho de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Atalho do ambiente de trabalho para ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Atalho no ambiente de trabalho de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Atalho de início rápido de ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "A escrever o Desinstalador"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "A escrever chaves de registo do instalador"
|
||||
StrCpy $UNINSTALLER_FINISHED_Detail "Terminado"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Não parece que a aplicação ${APPLICATION_NAME} esteja instalada no diretório '$INSTDIR'.$\n$\nContinuar na mesma (não recomendado)?"
|
||||
StrCpy $UNINSTALL_MESSAGEBOX "Não parece que ${APPLICATION_NAME} esteja instalado no diretório '$INSTDIR'.$\n$\nContinuar na mesma (não recomendado)?"
|
||||
StrCpy $UNINSTALL_ABORT "Desinstalação cancelada pelo utilizador"
|
||||
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)"
|
||||
|
||||
@@ -9,7 +9,6 @@ StrCpy $PageReinstall_NEW_Field_3 "Avinstallera inte"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Redan installerad"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Välj hur du vill installera ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "En nyare version av ${APPLICATION_NAME} är redan installerad! Det rekommenderas inte att du installerar en äldre version. Om du verkligen vill installera denna äldre versionen, är det bättre att du avinstallerar den nuvarande versionen först. Välj den åtgärd du vill utföra och klicka Nästa för att fortsätta."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} är redan installerad.$\n$\nVälj den åtgärd du vill utföra och klicka på Nästa för att fortsätta."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Lägg till/Ominstallera komponenter"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Avinstallera ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Avinstallera ${APPLICATION_NAME}"
|
||||
@@ -41,3 +40,4 @@ StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Detta avinstallationsprogram kräver adm
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Login-service körs inte, avbryter!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Avinstallationsprogrammet körs redan."
|
||||
StrCpy $SectionGroup_Shortcuts "Genvägar"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
--- binary
|
||||
+++ binary
|
||||
@@ -1 +1 @@
|
||||
-Subproject commit 1fb9ddfa9a9a1b4dbc447eee10dbed89172d968a
|
||||
+Subproject commit 01d73965dc8b862d1b2310d3ef801c297b697ec7
|
||||
@@ -98,7 +98,6 @@ enum csync_status_codes_e {
|
||||
CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK,
|
||||
CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST,
|
||||
CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS,
|
||||
CSYNC_STATUS_INDIVIDUAL_TRAILING_SPACE,
|
||||
CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME,
|
||||
CYSNC_STATUS_FILE_LOCKED_OR_OPEN,
|
||||
CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN,
|
||||
|
||||
@@ -229,12 +229,8 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch
|
||||
// distinguish files ending in '.' from files without an ending,
|
||||
// as '.' is a separator that is not stored internally, so let's
|
||||
// not allow to sync those to avoid file loss/ambiguities (#416)
|
||||
if (blen > 1) {
|
||||
if (bname[blen-1]== ' ') {
|
||||
match = CSYNC_FILE_EXCLUDE_TRAILING_SPACE;
|
||||
} else if (bname[blen-1]== '.' ) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
}
|
||||
if (blen > 1 && (bname[blen-1]== ' ' || bname[blen-1]== '.' )) {
|
||||
match = CSYNC_FILE_EXCLUDE_INVALID_CHAR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ enum csync_exclude_type_e {
|
||||
CSYNC_FILE_EXCLUDE_AND_REMOVE,
|
||||
CSYNC_FILE_EXCLUDE_LIST,
|
||||
CSYNC_FILE_EXCLUDE_INVALID_CHAR,
|
||||
CSYNC_FILE_EXCLUDE_TRAILING_SPACE,
|
||||
CSYNC_FILE_EXCLUDE_LONG_FILENAME,
|
||||
CSYNC_FILE_EXCLUDE_HIDDEN,
|
||||
CSYNC_FILE_EXCLUDE_STAT_FAILED
|
||||
|
||||
@@ -270,7 +270,6 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
SAFE_FREE(st);
|
||||
SAFE_FREE(tmp);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
@@ -477,8 +476,6 @@ out:
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_TRAILING_SPACE) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_TRAILING_SPACE; /* File ends with a trailing space. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_LONG_FILENAME) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME; /* File name is too long. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_HIDDEN ) {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
static void setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ static void teardown(void **state) {
|
||||
static void check_csync_init(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
csync_init(csync);
|
||||
|
||||
|
||||
@@ -31,13 +31,6 @@ use strict;
|
||||
|
||||
print "Hello, this is t6, a tester for csync with ownCloud.\n";
|
||||
|
||||
# Checking CURL is installed to avoid misleading errors later...
|
||||
system(("curl", "--help", ">", "/dev/null"));
|
||||
if ($? != 0) {
|
||||
print "CURL is needed for this script, aborting with error\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
initTesting();
|
||||
|
||||
sub createPostUpdateScript($)
|
||||
|
||||
@@ -159,8 +159,8 @@ In order to make setup simple, you can use the provided Dockerfile to build your
|
||||
1. Assuming you are in the root of the ownCloud Client's source tree, you can
|
||||
build an image from this Dockerfile like this::
|
||||
|
||||
cd admin/win/docker
|
||||
docker build . -t owncloud-client-win32:<version>
|
||||
cd admin/win32/docker
|
||||
docker build . -t ownCloud-client-win32:<version>
|
||||
|
||||
Replace ``<version>`` by the version of the client you are building, e.g.
|
||||
|version| for the release of the client that this document describes.
|
||||
@@ -174,8 +174,8 @@ In order to make setup simple, you can use the provided Dockerfile to build your
|
||||
|
||||
2. From within the source tree Run the docker instance::
|
||||
|
||||
docker run owncloud-client-win32:<version> -v "$PWD:/home/jenkins/client" \
|
||||
admin/win/docker/build.sh $(id -u)
|
||||
docker run ownCloud-client-win32:<version> -v "$PWD:/home/jenkins/client" \
|
||||
admin/win32/docker/build.sh $(id -u)
|
||||
|
||||
It will run the build, create an NSIS based installer, as well as run tests.
|
||||
You will find the resulting binary in an newly created ``build-win32`` subfolder.
|
||||
|
||||
@@ -41,7 +41,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'ownCloud Client Manual'
|
||||
copyright = u'2013-2016, The ownCloud developers'
|
||||
copyright = u'2013, The ownCloud developers'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -250,7 +250,7 @@ texinfo_documents = [
|
||||
epub_title = u'ownCloud Client Manual'
|
||||
epub_author = u'The ownCloud developers'
|
||||
epub_publisher = u'The ownCloud developers'
|
||||
epub_copyright = u'2013-2016, The ownCloud developers'
|
||||
epub_copyright = u'2013, The ownCloud developers'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
|
||||
|
Antes Largura: | Altura: | Tamanho: 52 KiB Depois Largura: | Altura: | Tamanho: 86 KiB |
|
Antes Largura: | Altura: | Tamanho: 82 KiB |
|
Antes Largura: | Altura: | Tamanho: 58 KiB Depois Largura: | Altura: | Tamanho: 49 KiB |
|
Antes Largura: | Altura: | Tamanho: 224 KiB Depois Largura: | Altura: | Tamanho: 58 KiB |
|
Antes Largura: | Altura: | Tamanho: 20 KiB Depois Largura: | Altura: | Tamanho: 23 KiB |
|
Antes Largura: | Altura: | Tamanho: 34 KiB Depois Largura: | Altura: | Tamanho: 24 KiB |
@@ -4,16 +4,16 @@ ownCloud Desktop Client Manual
|
||||
==============================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 3
|
||||
|
||||
introduction
|
||||
installing
|
||||
navigating
|
||||
advancedusage
|
||||
autoupdate
|
||||
|
||||
building
|
||||
architecture
|
||||
troubleshooting
|
||||
faq
|
||||
glossary
|
||||
|
||||
glossary
|
||||
@@ -12,22 +12,26 @@ Desktop Sync client enables you to:
|
||||
Your files are always automatically synchronized between your ownCloud server
|
||||
and local PC.
|
||||
|
||||
Because of various technical issues, desktop sync clients older than 1.7 will
|
||||
not allowed to connect and sync with the ownCloud 8.1+ server. It is highly
|
||||
recommended to keep your client updated.
|
||||
|
||||
.. note:: Because of various technical issues, desktop sync clients older than
|
||||
1.7 will not allowed to connect and sync with the ownCloud 8.1+ server. It
|
||||
is highly recommended to keep your client updated.
|
||||
|
||||
Improvements and New Features
|
||||
-----------------------------
|
||||
|
||||
The 2.2 release of the ownCloud desktop sync client has many new features and
|
||||
The 2.1 release of the ownCloud desktop sync client has many new features and
|
||||
improvements. (See the `complete changelog
|
||||
<https://owncloud.org/changelog/desktop/>`_.)
|
||||
|
||||
* Show server notifications on the client
|
||||
* Improved sync speed
|
||||
* Improved handling of Win32 file locks and network files
|
||||
* Improved user notifications about ignored files and conflicts
|
||||
* Add warnings for old server versions
|
||||
* Update of QtKeyChain to support Windows credential store
|
||||
* Packaging of dolphin overlay icon module for bleeding edge distros
|
||||
* Improved appearance on HiDPI screens
|
||||
* Improved error messages
|
||||
* Several fixes/improvements to the sharing dialog
|
||||
* Several fixes/improvements to the server activity tab
|
||||
* Allow changeable upload chunk size in owncloud.cfg
|
||||
* Forget password on explicit sign-out
|
||||
* Windows: Fix deleting and replacing of read-only files
|
||||
* Share with internal ownCloud users from your desktop
|
||||
* Separate views for server activity, sync activity, and errors
|
||||
* Don't re-upload *eml-files if size and checksum are unchanged
|
||||
* Improved upload/download progress indicator
|
||||
|
||||
@@ -62,7 +62,6 @@ This menu provides the following options:
|
||||
* Recent Changes, showing latest activities
|
||||
* Settings
|
||||
* Help menu
|
||||
* Pause synchronizations
|
||||
* An option to log in or log out of all of your accounts at once
|
||||
* Quit ownCloud, logging out and closing the client
|
||||
|
||||
@@ -84,7 +83,7 @@ have the following features:
|
||||
* Connection status, showing which ownCloud server you are connected to, and
|
||||
your ownCloud username.
|
||||
* An **Account** button, which contains a dropdown menu with **Add New**,
|
||||
**Log Out**, and **Remove**.
|
||||
**Log In/Log Out**, and **Remove**.
|
||||
* Used and available space on the server.
|
||||
* Current synchronization status.
|
||||
* **Add Folder Sync Connection** button, which is active only when you have
|
||||
@@ -94,17 +93,26 @@ The little button with three dots (the overflow menu) that sits to the right of
|
||||
the sync status bar offers four additional options:
|
||||
|
||||
* Open Folder
|
||||
* Choose What to Sync (This appears only when your file tree is collapsed, and
|
||||
expands the file tree)
|
||||
* Choose What to Sync
|
||||
* Pause Sync / Resume Sync
|
||||
* Remove folder sync connection
|
||||
|
||||
**Open Folder** opens your local ownCloud sync folder.
|
||||
**Open Folder** opens a file explorer window displaying the client-side folder
|
||||
that is being synced.
|
||||
|
||||
**Choose What to Sync** opens the folder sync tree view. Use this to sync all
|
||||
or only some of the folders in the folder tree.
|
||||
|
||||
**Pause Sync** pauses sync operations without making any changes to your
|
||||
account. It will continue to update file and folder lists, without
|
||||
downloading or updating files. To stop all sync activity use **Remove
|
||||
Folder Sync Connection**.
|
||||
downloading or updating files. To stop all sync activity use **Remove Sync**.
|
||||
|
||||
**Resume Sync** resumes sync operations.
|
||||
|
||||
**Remove Sync** removes the sync connection without removing the account. This
|
||||
stops all sync activity, including file and folder list updates. If you want to
|
||||
synchronize the folder tree again then click the **Add Folder Sync Connection**
|
||||
button, and re-select the folder tree that you want to sync.
|
||||
|
||||
.. figure:: images/client-7.png
|
||||
:alt: Extra options for sync operations
|
||||
@@ -117,10 +125,12 @@ Folder Sync Connection**.
|
||||
Adding New Accounts
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You may configure multiple ownCloud accounts in your desktop sync client. Simply
|
||||
You may configure multiple ownCloud accounts in your desktop sync client.
|
||||
Simply
|
||||
click the **Account** > **Add New** button on any account tab to add a new
|
||||
account, and then follow the account creation wizard. The new account will
|
||||
appear as a new tab in the settings dialog, where you can adjust its settings at
|
||||
appear as a new tab in the settings dialog, where you can adjust its settings
|
||||
at
|
||||
any time. Use **Account** > **Remove** to delete accounts.
|
||||
|
||||
File Manager Overlay Icons
|
||||
@@ -165,7 +175,9 @@ the ``owncloud-client-nautilus`` plugin.) You can create share links, and share
|
||||
with internal ownCloud users the same way as in your ownCloud Web interface.
|
||||
|
||||
.. figure:: images/mac-share.png
|
||||
:alt: Sync client integration in Windows Explorer.
|
||||
:alt: Sync client integration in Finder on Mac OS X.
|
||||
|
||||
*Shared ownCloud files in Finder on Mac OS X*
|
||||
|
||||
Right-click your systray icon, hover over the account you want to use, and
|
||||
left-click "Open folder [folder name] to quickly enter your local ownCloud
|
||||
@@ -194,25 +206,6 @@ such as files not synced.
|
||||
|
||||
.. figure:: images/client-8.png
|
||||
:alt: Activity windows logs all server and client activities.
|
||||
|
||||
Server Notifications
|
||||
--------------------
|
||||
|
||||
Starting with version 2.2.0, the client will display notifications from your
|
||||
ownCloud server that require manual interaction by you. For example, when a
|
||||
user on a remote ownCloud creates a new Federated share for you, you can accept
|
||||
it from your desktop client.
|
||||
|
||||
The desktop client automatically checks for available notifications
|
||||
automatically on a regular basis. Notifications are displayed in the Server
|
||||
Activity tab, and if you have **Show Desktop Notifications** enabled (General
|
||||
tab) you'll also see a systray notification.
|
||||
|
||||
.. figure:: images/client12.png
|
||||
:alt: Activity window with notification.
|
||||
|
||||
This also displays notifications sent to users by the ownCloud admin via the
|
||||
Announcements app.
|
||||
|
||||
General Window
|
||||
--------------
|
||||
|
||||
@@ -40,7 +40,7 @@ logs.
|
||||
|
||||
1. Output of `owncloud --logwindow` or `owncloud --logfile log.txt`
|
||||
(On Windows using `cmd.exe`, you might need to first `cd` into the ownCloud directory)
|
||||
(See also http://doc.owncloud.org/desktop/2.2/troubleshooting.html#client-logfile )
|
||||
(See also http://doc.owncloud.org/desktop/1.8/troubleshooting.html#client-logfile )
|
||||
|
||||
2. Web server error log:
|
||||
|
||||
|
||||
@@ -11,153 +11,11 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
Icon[oc]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
GenericName[ca]=Sincronització de carpetes
|
||||
Name[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
Icon[ca]=@APPLICATION_EXECUTABLE@
|
||||
Comment[da]=@APPLICATION_NAME@ skrivebordsklient til synkronisering
|
||||
GenericName[da]=Mappesynkronisering
|
||||
Name[da]=@APPLICATION_NAME@ skrivebordsklient til synk
|
||||
Icon[da]=@APPLICATION_EXECUTABLE@
|
||||
Comment[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
GenericName[de]=Ordner-Synchronisation
|
||||
Name[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
Icon[de]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
GenericName[ja_JP]=フォルダ同期
|
||||
Name[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
Icon[ja_JP]=@APPLICATION_EXECUTABLE@
|
||||
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
|
||||
GenericName[en_GB]=Folder Sync
|
||||
Name[en_GB]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[en_GB]=@APPLICATION_EXECUTABLE@
|
||||
Comment[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
|
||||
GenericName[es]=Sincronización de carpeta
|
||||
Name[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
|
||||
Icon[es]=@APPLICATION_EXECUTABLE@
|
||||
Comment[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
GenericName[de_DE]=Ordner-Synchronisation
|
||||
Name[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
Icon[de_DE]=@APPLICATION_EXECUTABLE@
|
||||
Comment[fr]=@APPLICATION_NAME@ synchronisation du client
|
||||
GenericName[fr]=Dossier de Synchronisation
|
||||
Name[fr]=@APPLICATION_NAME@ synchronisation du client
|
||||
Icon[fr]=@APPLICATION_EXECUTABLE@
|
||||
Comment[he]=@APPLICATION_NAME@ לקוח סנכון שולחן עבודה
|
||||
GenericName[he]=סנכון תיקייה
|
||||
Name[he]=@APPLICATION_NAME@ לקוח סנכרון שולחן עבודה
|
||||
Icon[he]=@APPLICATION_EXECUTABLE@
|
||||
Comment[id]=Klien sinkronisasi desktop @APPLICATION_NAME@
|
||||
GenericName[id]=Folder Sync
|
||||
Name[id]=Klien sync desktop @APPLICATION_NAME@
|
||||
Icon[id]=@APPLICATION_EXECUTABLE@
|
||||
Comment[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
|
||||
GenericName[is]=Samstilling möppu
|
||||
Name[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
|
||||
Icon[is]=@APPLICATION_EXECUTABLE@
|
||||
Comment[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
|
||||
GenericName[it]=Sincronizzazione cartella
|
||||
Name[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
|
||||
Icon[it]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
GenericName[ko]=폴더 동기화
|
||||
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
|
||||
GenericName[nl]=Mappen sync
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[nl]=@APPLICATION_EXECUTABLE@
|
||||
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
|
||||
GenericName[bg_BG]=Синхронизиране на папката
|
||||
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
|
||||
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
|
||||
Comment[pt_BR]=@APPLICATION_NAME@ cliente de sincronização do computador
|
||||
GenericName[pt_BR]=Sincronização de Pasta
|
||||
Name[pt_BR]=@APPLICATION_NAME@ cliente de sincronização de desktop
|
||||
Icon[pt_BR]=@APPLICATION_EXECUTABLE@
|
||||
Comment[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
GenericName[cs_CZ]=Synchronizace adresáře
|
||||
Name[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
Icon[cs_CZ]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
|
||||
GenericName[ru]=Синхронизация папки
|
||||
Name[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
|
||||
Icon[ru]=@ВЫПОЛНЯЕМОЕ_ПРИЛОЖЕНИЕ@
|
||||
Comment[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
GenericName[sl]=Usklajevanje map
|
||||
Name[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
Icon[sl]=@APPLICATION_EXECUTABLE@
|
||||
Comment[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
GenericName[sq]=Njëkohësim Dosjesh
|
||||
Name[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
Icon[sq]=@APPLICATION_EXECUTABLE@
|
||||
Comment[tr]=@APPLICATION_NAME@ masaüstü senkronizasyon istemcisi
|
||||
GenericName[tr]=Dosya Senkronizasyonu
|
||||
Name[tr]=@APPLICATION_NAME@ masaüstü senkronizasyon istemcisi
|
||||
Icon[tr]=@APPLICATION_EXECUTABLE@
|
||||
Comment[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
|
||||
GenericName[uk]=Синхронізація теки
|
||||
Name[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
|
||||
Icon[uk]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
|
||||
GenericName[ro]=Sincronizare director
|
||||
Name[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
|
||||
Icon[ro]=@APPLICATION_EXECUTABLE@
|
||||
Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
GenericName[zh_CN]=文件夹同步
|
||||
Name[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
Icon[zh_CN]=@APPLICATION_EXECUTABLE@
|
||||
GenericName[zh_TW]=資料夾同步
|
||||
Comment[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
|
||||
GenericName[pt_PT]=Sincronizar Pasta
|
||||
Name[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
|
||||
Icon[pt_PT]=@APPLICATION_EXECUTABLE@
|
||||
Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
|
||||
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
|
||||
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
|
||||
Icon[th_TH]=@APPLICATION_EXECUTABLE@
|
||||
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
|
||||
GenericName[nl]=Mappen sync
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[nl]=@APPLICATION_EXECUTABLE@
|
||||
|
||||
@@ -36,7 +36,8 @@ using namespace std;
|
||||
|
||||
OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud";
|
||||
|
||||
CommunicationSocket socket;
|
||||
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
|
||||
@@ -71,7 +72,8 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
|
||||
|
||||
void OCClientInterface::ShareObject(const std::wstring &path)
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud";
|
||||
|
||||
CommunicationSocket socket;
|
||||
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
|
||||
|
||||
@@ -24,31 +24,11 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#define DEFAULT_BUFLEN 4096
|
||||
#define BUFSIZE 1024
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
std::wstring getUserName() {
|
||||
DWORD len = DEFAULT_BUFLEN;
|
||||
TCHAR buf[DEFAULT_BUFLEN];
|
||||
if (GetUserName(buf, &len)) {
|
||||
return std::wstring(&buf[0], len);
|
||||
} else {
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::wstring CommunicationSocket::DefaultPipePath()
|
||||
{
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud\\";
|
||||
pipename += getUserName();
|
||||
return pipename;
|
||||
}
|
||||
#define DEFAULT_BUFLEN 4096
|
||||
|
||||
CommunicationSocket::CommunicationSocket()
|
||||
: _pipe(INVALID_HANDLE_VALUE)
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
class __declspec(dllexport) CommunicationSocket
|
||||
{
|
||||
public:
|
||||
static std::wstring DefaultPipePath();
|
||||
|
||||
CommunicationSocket();
|
||||
~CommunicationSocket();
|
||||
|
||||
@@ -45,4 +43,4 @@ private:
|
||||
bool _connected;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -31,10 +31,25 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define BUFSIZE 512
|
||||
|
||||
std::wstring getUserName() {
|
||||
DWORD len = BUFSIZE;
|
||||
TCHAR buf[BUFSIZE];
|
||||
if (GetUserName(buf, &len)) {
|
||||
return std::wstring(&buf[0], len);
|
||||
} else {
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
// This code is run in a thread
|
||||
void RemotePathChecker::workerThreadLoop()
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud\\";
|
||||
pipename += getUserName();
|
||||
|
||||
bool connected = false;
|
||||
CommunicationSocket socket;
|
||||
std::unordered_set<std::wstring> asked;
|
||||
|
||||
@@ -28,12 +28,16 @@
|
||||
* \return string PEM
|
||||
*/
|
||||
string x509ToString(BIO *o) {
|
||||
int len = 0;
|
||||
BUF_MEM *bptr;
|
||||
void* data;
|
||||
string ret = "";
|
||||
|
||||
BIO_get_mem_ptr(o, &bptr);
|
||||
int len = bptr->length;
|
||||
void* data = calloc(len+10, sizeof(char));
|
||||
len = bptr->length;
|
||||
data = calloc(len+10, sizeof(char));
|
||||
BIO_read(o, data, len);
|
||||
string ret = std::string(static_cast<char*>(data));
|
||||
ret = strdup((char*)data);
|
||||
free(data);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -45,7 +45,7 @@ qt_wrap_ui(client_UI_SRCS ${client_UI})
|
||||
set(client_SRCS
|
||||
accountmanager.cpp
|
||||
accountsettings.cpp
|
||||
application.cpp
|
||||
ocapplication.cpp
|
||||
folder.cpp
|
||||
folderman.cpp
|
||||
folderstatusmodel.cpp
|
||||
@@ -212,6 +212,10 @@ if(QTKEYCHAIN_FOUND OR QT5KEYCHAIN_FOUND)
|
||||
list(APPEND libsync_LINK_TARGETS ${QTKEYCHAIN_LIBRARY})
|
||||
include_directories(${QTKEYCHAIN_INCLUDE_DIR})
|
||||
endif()
|
||||
if(LibsnoreQt5_FOUND)
|
||||
add_definitions(-DHAVE_LIBSNORE)
|
||||
|
||||
endif()
|
||||
|
||||
# add executable icon on windows and osx
|
||||
include( AddAppIconMacro )
|
||||
@@ -289,6 +293,7 @@ target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} updater )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${OS_SPECIFIC_LINK_LIBRARIES} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} Snore::Libsnore Snore::LibsnoreSettings )
|
||||
|
||||
if(WITH_CRASHREPORTER)
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} crashreporter-handler)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "folderstatusmodel.h"
|
||||
#include "folderstatusdelegate.h"
|
||||
#include "utility.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "configfile.h"
|
||||
#include "account.h"
|
||||
#include "accountstate.h"
|
||||
|
||||
@@ -190,8 +190,7 @@ void AccountState::checkConnectivity()
|
||||
} else {
|
||||
// Check the server and then the auth.
|
||||
|
||||
// Let's try this for all OS and see if it fixes the Qt issues we have on Linux #4720 #3888 #4051
|
||||
//#ifdef Q_OS_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
// There seems to be a bug in Qt on Windows where QNAM sometimes stops
|
||||
// working correctly after the computer woke up from sleep. See #2895 #2899
|
||||
// and #2973.
|
||||
@@ -202,7 +201,7 @@ void AccountState::checkConnectivity()
|
||||
// If we don't reset the ssl config a second CheckServerJob can produce a
|
||||
// ssl config that does not have a sensible certificate chain.
|
||||
account()->setSslConfiguration(QSslConfiguration());
|
||||
//#endif
|
||||
#endif
|
||||
conValidator->checkServerAndAuth();
|
||||
}
|
||||
}
|
||||
@@ -210,7 +209,6 @@ void AccountState::checkConnectivity()
|
||||
void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors)
|
||||
{
|
||||
if (isSignedOut()) {
|
||||
qDebug() << "Signed out, ignoring" << connectionStatusString(status) << _account->url().toString();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,9 +248,6 @@ void ActivityWidget::slotBuildNotificationDisplay(const ActivityList& list)
|
||||
QHash<QString, int> accNotified;
|
||||
QString listAccountName;
|
||||
|
||||
// Whether a new notification widget was added to the notificationLayout.
|
||||
bool newNotificationShown = false;
|
||||
|
||||
foreach( auto activity, list ) {
|
||||
if( _blacklistedNotifications.contains(activity)) {
|
||||
qDebug() << Q_FUNC_INFO << "Activity in blacklist, skip";
|
||||
@@ -274,7 +271,6 @@ void ActivityWidget::slotBuildNotificationDisplay(const ActivityList& list)
|
||||
_ui->_notifyScroll->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
|
||||
#endif
|
||||
_widgetForNotifId[activity.ident()] = widget;
|
||||
newNotificationShown = true;
|
||||
}
|
||||
|
||||
widget->setActivity( activity );
|
||||
@@ -369,10 +365,6 @@ void ActivityWidget::slotBuildNotificationDisplay(const ActivityList& list)
|
||||
const QString log = tr("%1 Notifications - Action Required").arg(Theme::instance()->appNameGUI());
|
||||
emit guiLog( log, msg);
|
||||
}
|
||||
|
||||
if (newNotificationShown) {
|
||||
emit newNotification();
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityWidget::slotSendNotificationRequest(const QString& accountName, const QString& link, const QByteArray& verb)
|
||||
@@ -525,7 +517,6 @@ ActivitySettings::ActivitySettings(QWidget *parent)
|
||||
connect(_activityWidget, SIGNAL(copyToClipboard()), this, SLOT(slotCopyToClipboard()));
|
||||
connect(_activityWidget, SIGNAL(hideActivityTab(bool)), this, SLOT(setActivityTabHidden(bool)));
|
||||
connect(_activityWidget, SIGNAL(guiLog(QString,QString)), this, SIGNAL(guiLog(QString,QString)));
|
||||
connect(_activityWidget, SIGNAL(newNotification()), SLOT(slotShowActivityTab()));
|
||||
|
||||
_protocolWidget = new ProtocolWidget(this);
|
||||
_tab->insertTab(1, _protocolWidget, Theme::instance()->syncStateIcon(SyncResult::Success), tr("Sync Protocol"));
|
||||
@@ -591,13 +582,6 @@ void ActivitySettings::slotShowIssueItemCount(int cnt)
|
||||
_tab->setTabText(_syncIssueTabId, cntText);
|
||||
}
|
||||
|
||||
void ActivitySettings::slotShowActivityTab()
|
||||
{
|
||||
if (_activityTabId != -1) {
|
||||
_tab->setCurrentIndex(_activityTabId);
|
||||
}
|
||||
}
|
||||
|
||||
void ActivitySettings::slotCopyToClipboard()
|
||||
{
|
||||
QString text;
|
||||
|
||||
@@ -41,7 +41,7 @@ class ActivityListModel;
|
||||
namespace Ui {
|
||||
class ActivityWidget;
|
||||
}
|
||||
class Application;
|
||||
class oCApplication;
|
||||
|
||||
/**
|
||||
* @brief The ActivityWidget class
|
||||
@@ -81,7 +81,7 @@ signals:
|
||||
void copyToClipboard();
|
||||
void rowsInserted();
|
||||
void hideActivityTab(bool);
|
||||
void newNotification();
|
||||
void newNotificationList(const ActivityList& list);
|
||||
|
||||
private slots:
|
||||
void slotBuildNotificationDisplay(const ActivityList& list);
|
||||
@@ -143,7 +143,6 @@ private slots:
|
||||
void setActivityTabHidden(bool hidden);
|
||||
void slotRegularNotificationCheck();
|
||||
void slotShowIssueItemCount(int cnt);
|
||||
void slotShowActivityTab();
|
||||
|
||||
signals:
|
||||
void guiLog(const QString&, const QString&);
|
||||
|
||||
@@ -38,12 +38,7 @@ namespace OCC
|
||||
|
||||
class UserAgentWebPage : public QWebPage {
|
||||
public:
|
||||
UserAgentWebPage(QObject *parent) : QWebPage(parent)
|
||||
{
|
||||
if (!qgetenv("OWNCLOUD_SHIBBOLETH_DEBUG").isEmpty()) {
|
||||
settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
|
||||
}
|
||||
}
|
||||
UserAgentWebPage(QObject *parent) : QWebPage(parent) {}
|
||||
QString userAgentForUrl(const QUrl &url ) const {
|
||||
return QWebPage::userAgentForUrl(url) + " " + Utility::userAgentString();
|
||||
}
|
||||
|
||||
@@ -320,7 +320,6 @@ void Folder::slotRunEtagJob()
|
||||
// sync if it's different.
|
||||
|
||||
_requestEtagJob = new RequestEtagJob(account, remotePath(), this);
|
||||
_requestEtagJob->setTimeout(60*1000);
|
||||
// check if the etag is different
|
||||
QObject::connect(_requestEtagJob, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
||||
FolderMan::instance()->slotScheduleETagJob(alias(), _requestEtagJob);
|
||||
@@ -579,10 +578,19 @@ int Folder::slotWipeErrorBlacklist()
|
||||
|
||||
void Folder::slotWatchedPathChanged(const QString& path)
|
||||
{
|
||||
// When no sync is running or it's in the prepare phase, we can
|
||||
// always schedule a new sync.
|
||||
if (! _engine->isSyncRunning() || _syncResult.status() == SyncResult::SyncPrepare) {
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// The folder watcher fires a lot of bogus notifications during
|
||||
// a sync operation, both for actual user files and the database
|
||||
// and log. Therefore we check notifications against operations
|
||||
// the sync is doing to filter out our own changes.
|
||||
bool ownChange = false;
|
||||
#ifdef Q_OS_MAC
|
||||
Q_UNUSED(path)
|
||||
// On OSX the folder watcher does not report changes done by our
|
||||
@@ -592,23 +600,14 @@ void Folder::slotWatchedPathChanged(const QString& path)
|
||||
const auto maxNotificationDelay = 15*1000;
|
||||
qint64 time = _engine->timeSinceFileTouched(path);
|
||||
if (time != -1 && time < maxNotificationDelay) {
|
||||
return;
|
||||
ownChange = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check that the mtime actually changed.
|
||||
if (path.startsWith(this->path())) {
|
||||
auto relativePath = path.mid(this->path().size());
|
||||
auto record = _journal.getFileRecord(relativePath);
|
||||
if (record.isValid() && !FileSystem::fileChanged(path, record._fileSize,
|
||||
Utility::qDateTimeToTime_t(record._modtime))) {
|
||||
qDebug() << "Ignoring spurious notification for file" << relativePath;
|
||||
return; // probably a spurious notification
|
||||
}
|
||||
if (! ownChange) {
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
}
|
||||
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
}
|
||||
|
||||
void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
|
||||
@@ -631,7 +630,7 @@ void Folder::removeFromSettings() const
|
||||
{
|
||||
auto settings = _accountState->settings();
|
||||
settings->beginGroup(QLatin1String("Folders"));
|
||||
settings->remove(FolderMan::escapeAlias(_definition.alias));
|
||||
settings->remove(_definition.alias);
|
||||
}
|
||||
|
||||
bool Folder::isFileExcludedAbsolute(const QString& fullPath) const
|
||||
@@ -916,7 +915,7 @@ void Folder::slotFolderDiscovered(bool, QString folderName)
|
||||
// and hand the result over to the progress dispatcher.
|
||||
void Folder::slotTransmissionProgress(const ProgressInfo &pi)
|
||||
{
|
||||
if( !pi.isUpdatingEstimates() ) {
|
||||
if( !pi.hasStarted() ) {
|
||||
// this is the beginning of a sync, set the warning level to 0
|
||||
_syncResult.setWarnCount(0);
|
||||
}
|
||||
@@ -1002,7 +1001,7 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool *cancel)
|
||||
void Folder::slotAboutToRestoreBackup(bool *restore)
|
||||
{
|
||||
QString msg =
|
||||
tr("This sync would reset the files to an earlier time in the sync folder '%1'.\n"
|
||||
tr("This sync would reset the files to an erlier time in the sync folder '%1'.\n"
|
||||
"This might be because a backup was restored on the server.\n"
|
||||
"Continuing the sync as normal will cause all your files to be overwritten by an older "
|
||||
"file in an earlier state. "
|
||||
|
||||
@@ -29,7 +29,7 @@ class TestFolderMan;
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class SyncResult;
|
||||
class SocketApi;
|
||||
class LockWatcher;
|
||||
@@ -255,7 +255,7 @@ private:
|
||||
|
||||
static FolderMan *_instance;
|
||||
explicit FolderMan(QObject *parent = 0);
|
||||
friend class OCC::Application;
|
||||
friend class OCC::oCApplication;
|
||||
friend class ::TestFolderMan;
|
||||
};
|
||||
|
||||
|
||||
@@ -584,7 +584,7 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list)
|
||||
QStringList sortedSubfolders = list;
|
||||
// skip the parent item (first in the list)
|
||||
sortedSubfolders.erase(sortedSubfolders.begin());
|
||||
Utility::sortFilenames(sortedSubfolders);
|
||||
sortedSubfolders.sort();
|
||||
|
||||
QVarLengthArray<int, 10> undecidedIndexes;
|
||||
|
||||
|
||||
@@ -51,14 +51,6 @@ static void callback(
|
||||
Q_UNUSED(eventFlags)
|
||||
Q_UNUSED(eventIds)
|
||||
|
||||
const FSEventStreamEventFlags c_interestingFlags
|
||||
= kFSEventStreamEventFlagItemCreated // for new folder/file
|
||||
| kFSEventStreamEventFlagItemRemoved // for rm
|
||||
| kFSEventStreamEventFlagItemInodeMetaMod // for mtime change
|
||||
| kFSEventStreamEventFlagItemRenamed // also coming for moves to trash in finder
|
||||
| kFSEventStreamEventFlagItemModified; // for content change
|
||||
//We ignore other flags, e.g. for owner change, xattr change, Finder label change etc
|
||||
|
||||
qDebug() << "FolderWatcherPrivate::callback by OS X";
|
||||
|
||||
QStringList paths;
|
||||
@@ -70,14 +62,8 @@ static void callback(
|
||||
CFIndex pathLength = CFStringGetLength(path);
|
||||
qstring.resize(pathLength);
|
||||
CFStringGetCharacters(path, CFRangeMake(0, pathLength), reinterpret_cast<UniChar *>(qstring.data()));
|
||||
QString fn = qstring.normalized(QString::NormalizationForm_C);
|
||||
|
||||
if (!(eventFlags[i] & c_interestingFlags)) {
|
||||
qDebug() << "Ignoring non-content changes for" << fn;
|
||||
continue;
|
||||
}
|
||||
|
||||
paths.append(fn);
|
||||
paths.append(qstring.normalized(QString::NormalizationForm_C));
|
||||
}
|
||||
|
||||
reinterpret_cast<FolderWatcherPrivate*>(clientCallBackInfo)->doNotifyParent(paths);
|
||||
|
||||
@@ -68,6 +68,13 @@ FolderWizardLocalPath::FolderWizardLocalPath()
|
||||
_ui.localFolderLineEdit->setText( QDir::toNativeSeparators( defaultPath ) );
|
||||
_ui.localFolderLineEdit->setToolTip(tr("Enter the path to the local folder."));
|
||||
|
||||
QString newAlias = Theme::instance()->appName();
|
||||
int count = 0;
|
||||
while (FolderMan::instance()->folder(newAlias)) {
|
||||
// There is already a folder configured with this name and folder names need to be unique
|
||||
newAlias = Theme::instance()->appName() + QString::number(++count);
|
||||
}
|
||||
|
||||
_ui.warnLabel->setTextFormat(Qt::RichText);
|
||||
_ui.warnLabel->hide();
|
||||
}
|
||||
@@ -128,6 +135,14 @@ void FolderWizardLocalPath::slotChooseLocalFolder()
|
||||
if (!dir.isEmpty()) {
|
||||
// set the last directory component name as alias
|
||||
_ui.localFolderLineEdit->setText(QDir::toNativeSeparators(dir));
|
||||
|
||||
QDir pickedDir(dir);
|
||||
QString newAlias = pickedDir.dirName();
|
||||
int count = 0;
|
||||
while (FolderMan::instance()->folder(newAlias)) {
|
||||
// There is already a folder configured with this name and folder names need to be unique
|
||||
newAlias = pickedDir.dirName() + QString::number(++count);
|
||||
}
|
||||
}
|
||||
emit completeChanged();
|
||||
}
|
||||
@@ -308,7 +323,7 @@ void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list)
|
||||
root->setData(0, Qt::UserRole, "/");
|
||||
}
|
||||
QStringList sortedList = list;
|
||||
Utility::sortFilenames(sortedList);
|
||||
sortedList.sort();
|
||||
foreach (QString path, sortedList) {
|
||||
path.remove(webdavFolder);
|
||||
QStringList paths = path.split('/');
|
||||
@@ -488,13 +503,11 @@ FolderWizardSelectiveSync::~FolderWizardSelectiveSync()
|
||||
|
||||
void FolderWizardSelectiveSync::initializePage()
|
||||
{
|
||||
QString alias = wizard()->field(QLatin1String("alias")).toString();
|
||||
QString targetPath = wizard()->property("targetPath").toString();
|
||||
if (targetPath.startsWith('/')) {
|
||||
targetPath = targetPath.mid(1);
|
||||
}
|
||||
QString alias = QFileInfo(targetPath).fileName();
|
||||
if (alias.isEmpty())
|
||||
alias = Theme::instance()->appName();
|
||||
_treeView->setFolderInfo(targetPath, alias);
|
||||
QWizardPage::initializePage();
|
||||
}
|
||||
@@ -507,10 +520,8 @@ bool FolderWizardSelectiveSync::validatePage()
|
||||
|
||||
void FolderWizardSelectiveSync::cleanupPage()
|
||||
{
|
||||
QString alias = wizard()->field(QLatin1String("alias")).toString();
|
||||
QString targetPath = wizard()->property("targetPath").toString();
|
||||
QString alias = QFileInfo(targetPath).fileName();
|
||||
if (alias.isEmpty())
|
||||
alias = Theme::instance()->appName();
|
||||
_treeView->setFolderInfo(targetPath, alias);
|
||||
QWizardPage::cleanupPage();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "theme.h"
|
||||
#include "configfile.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "utility.h"
|
||||
#include "configfile.h"
|
||||
#include "owncloudsetupwizard.h"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "theme.h"
|
||||
#include "utility.h"
|
||||
#include "cocoainitializer.h"
|
||||
@@ -47,24 +47,23 @@ int main(int argc, char **argv)
|
||||
{
|
||||
Q_INIT_RESOURCE(client);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#ifndef Q_OS_MAC
|
||||
// If the font size ratio is set on Windows, we need to
|
||||
// enable the auto pixelRatio in Qt since we don't
|
||||
// want to use sizes relative to the font size everywhere.
|
||||
// This is automatic on OS X, but opt-in on Windows and Linux
|
||||
// https://doc-snapshots.qt.io/qt5-5.6/highdpi.html#qt-support
|
||||
// We do not define it on linux so the behaviour is kept the same
|
||||
// as other Qt apps in the desktop environment. (which may or may
|
||||
// not set this envoronment variable)
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
|
||||
qputenv("QT_DEVICE_PIXEL_RATIO", "auto");
|
||||
#else
|
||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
||||
#endif
|
||||
#endif // !Q_OS_WIN
|
||||
#endif // !Q_OS_MAC
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
Mac::CocoaInitializer cocoaInit; // RIIA
|
||||
#endif
|
||||
OCC::Application app(argc, argv);
|
||||
OCC::oCApplication app(argc, argv);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// The Windows style still has pixelated elements with Qt 5.6,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "theme.h"
|
||||
#include "configfile.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "utility.h"
|
||||
#include "configfile.h"
|
||||
#include "folderman.h"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -91,7 +91,7 @@ QString applicationTrPath()
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
Application::Application(int &argc, char **argv) :
|
||||
oCApplication::oCApplication(int &argc, char **argv) :
|
||||
SharedTools::QtSingleApplication(Theme::instance()->appName() ,argc, argv),
|
||||
_gui(0),
|
||||
_theme(Theme::instance()),
|
||||
@@ -202,7 +202,7 @@ Application::Application(int &argc, char **argv) :
|
||||
connect (this, SIGNAL(aboutToQuit()), SLOT(slotCleanup()));
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
oCApplication::~oCApplication()
|
||||
{
|
||||
// Make sure all folders are gone, otherwise removing the
|
||||
// accounts will remove the associated folders from the settings.
|
||||
@@ -214,7 +214,7 @@ Application::~Application()
|
||||
AccountManager::instance()->shutdown();
|
||||
}
|
||||
|
||||
void Application::slotAccountStateRemoved(AccountState *accountState)
|
||||
void oCApplication::slotAccountStateRemoved(AccountState *accountState)
|
||||
{
|
||||
if (_gui) {
|
||||
disconnect(accountState, SIGNAL(stateChanged(int)),
|
||||
@@ -237,7 +237,7 @@ void Application::slotAccountStateRemoved(AccountState *accountState)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotAccountStateAdded(AccountState *accountState)
|
||||
void oCApplication::slotAccountStateAdded(AccountState *accountState)
|
||||
{
|
||||
connect(accountState, SIGNAL(stateChanged(int)),
|
||||
_gui, SLOT(slotAccountStateChanged()));
|
||||
@@ -251,7 +251,7 @@ void Application::slotAccountStateAdded(AccountState *accountState)
|
||||
_gui->slotTrayMessageIfServerUnsupported(accountState->account().data());
|
||||
}
|
||||
|
||||
void Application::slotCleanup()
|
||||
void oCApplication::slotCleanup()
|
||||
{
|
||||
AccountManager::instance()->save();
|
||||
FolderMan::instance()->unloadAndDeleteAllFolders();
|
||||
@@ -263,7 +263,7 @@ void Application::slotCleanup()
|
||||
// FIXME: This is not ideal yet since a ConnectionValidator might already be running and is in
|
||||
// progress of timing out in some seconds.
|
||||
// Maybe we need 2 validators, one triggered by timer, one by network configuration changes?
|
||||
void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
||||
void oCApplication::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
||||
{
|
||||
if (cnf.state() & QNetworkConfiguration::Active) {
|
||||
//qDebug() << "Trying fast reconnect";
|
||||
@@ -271,7 +271,7 @@ void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotCheckConnection()
|
||||
void oCApplication::slotCheckConnection()
|
||||
{
|
||||
auto list = AccountManager::instance()->accounts();
|
||||
foreach (const auto &accountState , list) {
|
||||
@@ -293,12 +293,12 @@ void Application::slotCheckConnection()
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotCrash()
|
||||
void oCApplication::slotCrash()
|
||||
{
|
||||
Utility::crash();
|
||||
}
|
||||
|
||||
void Application::slotownCloudWizardDone( int res )
|
||||
void oCApplication::slotownCloudWizardDone( int res )
|
||||
{
|
||||
AccountManager *accountMan = AccountManager::instance();
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
@@ -335,7 +335,7 @@ void Application::slotownCloudWizardDone( int res )
|
||||
}
|
||||
}
|
||||
|
||||
void Application::setupLogging()
|
||||
void oCApplication::setupLogging()
|
||||
{
|
||||
// might be called from second instance
|
||||
Logger::instance()->setLogFile(_logFile);
|
||||
@@ -352,12 +352,12 @@ void Application::setupLogging()
|
||||
|
||||
}
|
||||
|
||||
void Application::slotUseMonoIconsChanged(bool)
|
||||
void oCApplication::slotUseMonoIconsChanged(bool)
|
||||
{
|
||||
_gui->slotComputeOverallSyncStatus();
|
||||
}
|
||||
|
||||
void Application::slotParseMessage(const QString &msg, QObject*)
|
||||
void oCApplication::slotParseMessage(const QString &msg, QObject*)
|
||||
{
|
||||
if (msg.startsWith(QLatin1String("MSG_PARSEOPTIONS:"))) {
|
||||
const int lengthOfMsgPrefix = 17;
|
||||
@@ -375,7 +375,7 @@ void Application::slotParseMessage(const QString &msg, QObject*)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::parseOptions(const QStringList &options)
|
||||
void oCApplication::parseOptions(const QStringList &options)
|
||||
{
|
||||
QStringListIterator it(options);
|
||||
// skip file name;
|
||||
@@ -455,7 +455,7 @@ static void displayHelpText(const QString &t)
|
||||
}
|
||||
#endif
|
||||
|
||||
void Application::showHelp()
|
||||
void oCApplication::showHelp()
|
||||
{
|
||||
setHelp();
|
||||
QString helpText;
|
||||
@@ -473,7 +473,7 @@ void Application::showHelp()
|
||||
displayHelpText(helpText);
|
||||
}
|
||||
|
||||
void Application::showVersion()
|
||||
void oCApplication::showVersion()
|
||||
{
|
||||
QString helpText;
|
||||
QTextStream stream(&helpText);
|
||||
@@ -485,7 +485,7 @@ void Application::showVersion()
|
||||
displayHelpText(helpText);
|
||||
}
|
||||
|
||||
void Application::showHint(std::string errorHint)
|
||||
void oCApplication::showHint(std::string errorHint)
|
||||
{
|
||||
static QString binName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
|
||||
std::cerr << errorHint << std::endl;
|
||||
@@ -493,12 +493,12 @@ void Application::showHint(std::string errorHint)
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
bool Application::debugMode()
|
||||
bool oCApplication::debugMode()
|
||||
{
|
||||
return _debugMode;
|
||||
}
|
||||
|
||||
void Application::setHelp()
|
||||
void oCApplication::setHelp()
|
||||
{
|
||||
_helpOnly = true;
|
||||
}
|
||||
@@ -518,7 +518,7 @@ QString substLang(const QString &lang)
|
||||
return lang;
|
||||
}
|
||||
|
||||
void Application::setupTranslations()
|
||||
void oCApplication::setupTranslations()
|
||||
{
|
||||
QStringList uiLanguages;
|
||||
// uiLanguages crashes on Windows with 4.8.0 release builds
|
||||
@@ -582,21 +582,20 @@ void Application::setupTranslations()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Application::giveHelp()
|
||||
bool oCApplication::giveHelp()
|
||||
{
|
||||
return _helpOnly;
|
||||
}
|
||||
|
||||
bool Application::versionOnly()
|
||||
bool oCApplication::versionOnly()
|
||||
{
|
||||
return _versionOnly;
|
||||
}
|
||||
|
||||
void Application::showSettingsDialog()
|
||||
void oCApplication::showSettingsDialog()
|
||||
{
|
||||
_gui->slotShowSettings();
|
||||
}
|
||||
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef APPLICATION_H
|
||||
#define APPLICATION_H
|
||||
#ifndef OCAPPLICATION_H
|
||||
#define OCAPPLICATION_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPointer>
|
||||
@@ -49,12 +49,12 @@ class SslErrorDialog;
|
||||
* @brief The Application class
|
||||
* @ingroup gui
|
||||
*/
|
||||
class Application : public SharedTools::QtSingleApplication
|
||||
class oCApplication : public SharedTools::QtSingleApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Application(int &argc, char **argv);
|
||||
~Application();
|
||||
explicit oCApplication(int &argc, char **argv);
|
||||
~oCApplication();
|
||||
|
||||
bool giveHelp();
|
||||
void showHelp();
|
||||
@@ -11,7 +11,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "owncloudgui.h"
|
||||
#include "theme.h"
|
||||
#include "folderman.h"
|
||||
@@ -47,7 +47,7 @@ namespace OCC {
|
||||
|
||||
const char propertyAccountC[] = "oc_account";
|
||||
|
||||
ownCloudGui::ownCloudGui(Application *parent) :
|
||||
ownCloudGui::ownCloudGui(oCApplication *parent) :
|
||||
QObject(parent),
|
||||
_tray(0),
|
||||
#if defined(Q_OS_MAC)
|
||||
@@ -96,10 +96,10 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
||||
connect( AccountManager::instance(), SIGNAL(accountRemoved(AccountState*)),
|
||||
SLOT(setupContextMenu()));
|
||||
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString)),
|
||||
SLOT(slotShowTrayMessage(QString,QString)));
|
||||
connect( Logger::instance(), SIGNAL(optionalGuiLog(QString,QString)),
|
||||
SLOT(slotShowOptionalTrayMessage(QString,QString)));
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString, Logger::NotificationType)),
|
||||
SLOT(slotShowTrayMessage(QString,QString, Logger::NotificationType)));
|
||||
connect( Logger::instance(), SIGNAL(optionalGuiLog(QString,QString, Logger::NotificationType)),
|
||||
SLOT(slotShowOptionalTrayMessage(QString,QString,Logger::NotificationType)));
|
||||
connect( Logger::instance(), SIGNAL(guiMessage(QString,QString)),
|
||||
SLOT(slotShowGuiMessage(QString,QString)));
|
||||
|
||||
@@ -237,7 +237,8 @@ void ownCloudGui::slotTrayMessageIfServerUnsupported(Account* account)
|
||||
tr("The server on account %1 runs an old and unsupported version %2. "
|
||||
"Using this client with unsupported server versions is untested and "
|
||||
"potentially dangerous. Proceed at your own risk.")
|
||||
.arg(account->displayName(), account->serverVersion()));
|
||||
.arg(account->displayName(), account->serverVersion()),
|
||||
Logger::Critical );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,19 +536,36 @@ void ownCloudGui::setupContextMenu()
|
||||
}
|
||||
|
||||
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg)
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type)
|
||||
{
|
||||
if( _tray )
|
||||
_tray->showMessage(title, msg);
|
||||
else
|
||||
if( _tray ) {
|
||||
QSystemTrayIcon::MessageIcon trayIcon = QSystemTrayIcon::NoIcon;
|
||||
switch( type ) {
|
||||
case Logger::NoIcon:
|
||||
break;
|
||||
case Logger::Information:
|
||||
trayIcon = QSystemTrayIcon::Information;
|
||||
break;
|
||||
case Logger::SoftError:
|
||||
trayIcon = QSystemTrayIcon::Warning;
|
||||
break;
|
||||
case Logger::Error:
|
||||
case Logger::Critical:
|
||||
trayIcon = QSystemTrayIcon::Critical;
|
||||
break;
|
||||
}
|
||||
|
||||
_tray->showMessage(title, msg, trayIcon);
|
||||
} else {
|
||||
qDebug() << "Tray not ready: " << msg;
|
||||
}
|
||||
}
|
||||
|
||||
void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg)
|
||||
void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type)
|
||||
{
|
||||
ConfigFile cfg;
|
||||
if (cfg.optionalDesktopNotifications()) {
|
||||
slotShowTrayMessage(title, msg);
|
||||
slotShowTrayMessage(title, msg, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,7 +703,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo&
|
||||
slotRebuildRecentMenus();
|
||||
}
|
||||
|
||||
if (progress.isUpdatingEstimates()
|
||||
if (progress.hasStarted()
|
||||
&& progress.completedFiles() >= progress.totalFiles()
|
||||
&& progress._currentDiscoveredFolder.isEmpty()) {
|
||||
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "systray.h"
|
||||
#include "connectionvalidator.h"
|
||||
#include "progressdispatcher.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
@@ -32,7 +33,7 @@ class Folder;
|
||||
class SettingsDialog;
|
||||
class SettingsDialogMac;
|
||||
class ShareDialog;
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class LogBrowser;
|
||||
class AccountState;
|
||||
|
||||
@@ -44,7 +45,7 @@ class ownCloudGui : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ownCloudGui(Application *parent = 0);
|
||||
explicit ownCloudGui(oCApplication *parent = 0);
|
||||
|
||||
bool checkAccountExists(bool openSettings);
|
||||
|
||||
@@ -58,8 +59,8 @@ signals:
|
||||
public slots:
|
||||
void setupContextMenu();
|
||||
void slotComputeOverallSyncStatus();
|
||||
void slotShowTrayMessage(const QString &title, const QString &msg);
|
||||
void slotShowOptionalTrayMessage(const QString &title, const QString &msg);
|
||||
void slotShowTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type);
|
||||
void slotShowOptionalTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type);
|
||||
void slotFolderOpenAction( const QString& alias );
|
||||
void slotRebuildRecentMenus();
|
||||
void slotUpdateProgress(const QString &folder, const ProgressInfo& progress);
|
||||
@@ -122,7 +123,7 @@ private:
|
||||
QSignalMapper *_folderOpenActionMapper;
|
||||
QSignalMapper *_recentItemsMapper;
|
||||
|
||||
Application *_app;
|
||||
oCApplication *_app;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -173,7 +173,7 @@ void OwncloudSetupWizard::slotNoOwnCloudFoundAuth(QNetworkReply *reply)
|
||||
|
||||
// Allow the credentials dialog to pop up again for the same URL.
|
||||
// Maybe the user just clicked 'Cancel' by accident or changed his mind.
|
||||
_ocWizard->account()->resetRejectedCertificates();
|
||||
_ocWizard->account()->resetSslCertErrorState();
|
||||
}
|
||||
|
||||
void OwncloudSetupWizard::slotNoOwnCloudFoundAuthTimeout(const QUrl&url)
|
||||
|
||||
@@ -57,15 +57,9 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
|
||||
header << tr("Action");
|
||||
header << tr("Size");
|
||||
|
||||
int timestampColumnExtra = 0;
|
||||
#ifdef Q_OS_WIN
|
||||
timestampColumnExtra = 20; // font metrics are broken on Windows, see #4721
|
||||
#endif
|
||||
|
||||
_ui->_treeWidget->setHeaderLabels( header );
|
||||
int timestampColumnWidth =
|
||||
_ui->_treeWidget->fontMetrics().width(timeString(QDateTime::currentDateTime()))
|
||||
+ timestampColumnExtra;
|
||||
_ui->_treeWidget->fontMetrics().width(timeString(QDateTime::currentDateTime()));
|
||||
_ui->_treeWidget->setColumnWidth(0, timestampColumnWidth);
|
||||
_ui->_treeWidget->setColumnWidth(1, 180);
|
||||
_ui->_treeWidget->setColumnCount(5);
|
||||
@@ -90,8 +84,7 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
|
||||
_issueItemView->setHeaderLabels( header );
|
||||
timestampColumnWidth =
|
||||
ActivityItemDelegate::rowHeight() // icon
|
||||
+ _issueItemView->fontMetrics().width(timeString(QDateTime::currentDateTime()))
|
||||
+ timestampColumnExtra;
|
||||
+ _issueItemView->fontMetrics().width(timeString(QDateTime::currentDateTime()));
|
||||
_issueItemView->setColumnWidth(0, timestampColumnWidth);
|
||||
_issueItemView->setColumnWidth(1, 180);
|
||||
_issueItemView->setColumnCount(4);
|
||||
@@ -219,7 +212,7 @@ QTreeWidgetItem* ProtocolWidget::createCompletedTreewidgetItem(const QString& fo
|
||||
|
||||
void ProtocolWidget::slotProgressInfo( const QString& folder, const ProgressInfo& progress )
|
||||
{
|
||||
if( !progress.isUpdatingEstimates() ) {
|
||||
if( !progress.hasStarted() ) {
|
||||
// The sync is restarting, clean the old items
|
||||
cleanItems(folder);
|
||||
} else if (progress.completedFiles() >= progress.totalFiles()) {
|
||||
|
||||
@@ -31,7 +31,7 @@ class SyncResult;
|
||||
namespace Ui {
|
||||
class ProtocolWidget;
|
||||
}
|
||||
class Application;
|
||||
class oCApplication;
|
||||
|
||||
/**
|
||||
* @brief The ProtocolWidget class
|
||||
|
||||
@@ -222,7 +222,7 @@ void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list)
|
||||
}
|
||||
}
|
||||
|
||||
Utility::sortFilenames(list);
|
||||
list.sort();
|
||||
foreach (QString path, list) {
|
||||
auto size = job ? job->_sizes.value(path) : 0;
|
||||
path.remove(pathToRemove);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Ui {
|
||||
class SettingsDialog;
|
||||
}
|
||||
class AccountSettings;
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class FolderMan;
|
||||
class ownCloudGui;
|
||||
class ActivitySettings;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "ui_sharelinkwidget.h"
|
||||
#include "account.h"
|
||||
#include "capabilities.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
|
||||
#include "share.h"
|
||||
|
||||
@@ -24,7 +23,6 @@
|
||||
#include <QBuffer>
|
||||
#include <QClipboard>
|
||||
#include <QFileInfo>
|
||||
#include <QDesktopServices>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
@@ -55,10 +53,6 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account,
|
||||
_ui->pushButton_copy->setEnabled(false);
|
||||
connect(_ui->pushButton_copy, SIGNAL(clicked(bool)), SLOT(slotPushButtonCopyLinkPressed()));
|
||||
|
||||
_ui->pushButton_mail->setIcon(QIcon::fromTheme("mail-send"));
|
||||
_ui->pushButton_mail->setEnabled(false);
|
||||
connect(_ui->pushButton_mail, SIGNAL(clicked(bool)), SLOT(slotPushButtonMailLinkPressed()));
|
||||
|
||||
// the following progress indicator widgets are added to layouts which makes them
|
||||
// automatically deleted once the dialog dies.
|
||||
_pi_link = new QProgressIndicator();
|
||||
@@ -230,7 +224,6 @@ void ShareLinkWidget::slotSharesFetched(const QList<QSharedPointer<Share>> &shar
|
||||
if (share->getShareType() == Share::TypeLink) {
|
||||
_share = qSharedPointerDynamicCast<LinkShare>(share);
|
||||
_ui->pushButton_copy->show();
|
||||
_ui->pushButton_mail->show();
|
||||
|
||||
_ui->widget_shareLink->show();
|
||||
_ui->checkBox_shareLink->setChecked(true);
|
||||
@@ -275,7 +268,6 @@ void ShareLinkWidget::slotSharesFetched(const QList<QSharedPointer<Share>> &shar
|
||||
}
|
||||
|
||||
setShareLink(_share->getLink().toString());
|
||||
_ui->pushButton_mail->setEnabled(true);
|
||||
_ui->pushButton_copy->setEnabled(true);
|
||||
|
||||
// Connect all shares signals to gui slots
|
||||
@@ -332,7 +324,6 @@ void ShareLinkWidget::setShareLink( const QString& url )
|
||||
if( realUrl.isValid() ) {
|
||||
_shareUrl = url;
|
||||
_ui->pushButton_copy->setEnabled(true);
|
||||
_ui->pushButton_mail->setEnabled(true);
|
||||
} else {
|
||||
_shareUrl.clear();
|
||||
_ui->_labelShareLink->setText(QString::null);
|
||||
@@ -348,7 +339,6 @@ void ShareLinkWidget::slotDeleteShareFetched()
|
||||
_ui->lineEdit_password->clear();
|
||||
_ui->_labelShareLink->clear();
|
||||
_ui->pushButton_copy->setEnabled(false);
|
||||
_ui->pushButton_mail->setEnabled(false);
|
||||
_ui->widget_shareLink->hide();
|
||||
_ui->lineEdit_password->hide();
|
||||
_ui->pushButton_setPassword->setEnabled(false);
|
||||
@@ -378,7 +368,6 @@ void ShareLinkWidget::slotCheckBoxShareLinkClicked()
|
||||
_ui->checkBox_editing->setEnabled(false);
|
||||
_ui->lineEdit_password->setFocus();
|
||||
_ui->pushButton_copy->hide();
|
||||
_ui->pushButton_mail->hide();
|
||||
_ui->widget_shareLink->show();
|
||||
|
||||
slotCheckBoxPasswordClicked();
|
||||
@@ -424,7 +413,6 @@ void ShareLinkWidget::slotCreateShareRequiresPassword(const QString& message)
|
||||
_ui->lineEdit_password->setEnabled(true);
|
||||
_ui->lineEdit_password->setFocus();
|
||||
_ui->pushButton_copy->hide();
|
||||
_ui->pushButton_mail->hide();
|
||||
_ui->widget_shareLink->show();
|
||||
_ui->checkBox_expire->setEnabled(false);
|
||||
_ui->checkBox_editing->setEnabled(false);
|
||||
@@ -485,20 +473,6 @@ void ShareLinkWidget::slotPushButtonCopyLinkPressed()
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShareLinkWidget::slotPushButtonMailLinkPressed()
|
||||
{
|
||||
QString fileName = _sharePath.mid(_sharePath.lastIndexOf('/') + 1);
|
||||
|
||||
QDesktopServices::openUrl(QUrl(QString(
|
||||
"mailto: "
|
||||
"?subject=%1 has shared %2 with you"
|
||||
"&body=%3").arg(
|
||||
_account->credentials()->user(),
|
||||
fileName,
|
||||
_shareUrl),
|
||||
QUrl::TolerantMode));
|
||||
}
|
||||
|
||||
void ShareLinkWidget::slotCheckBoxEditingClicked()
|
||||
{
|
||||
ShareLinkWidget::setPublicUpload(_ui->checkBox_editing->checkState() == Qt::Checked);
|
||||
|
||||
@@ -68,7 +68,6 @@ private slots:
|
||||
void slotPasswordReturnPressed();
|
||||
void slotPasswordChanged(const QString& newText);
|
||||
void slotPushButtonCopyLinkPressed();
|
||||
void slotPushButtonMailLinkPressed();
|
||||
void slotCheckBoxEditingClicked();
|
||||
void slotPublicUploadSet();
|
||||
|
||||
|
||||
@@ -195,13 +195,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_mail">
|
||||
<property name="text">
|
||||
<string>&Mail link</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_copy">
|
||||
<property name="text">
|
||||
|
||||
@@ -72,7 +72,9 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
|
||||
|
||||
_completer->setModel(_completerModel);
|
||||
_completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
_completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
||||
_completer->setFilterMode(Qt::MatchContains);
|
||||
#endif
|
||||
_ui->shareeLineEdit->setCompleter(_completer);
|
||||
|
||||
_manager = new ShareManager(_account, this);
|
||||
|
||||
@@ -56,13 +56,6 @@
|
||||
// The second number should be changed when there are new features.
|
||||
#define MIRALL_SOCKET_API_VERSION "1.0"
|
||||
|
||||
static inline QString removeTrailingSlash(QString path)
|
||||
{
|
||||
Q_ASSERT(path.endsWith(QLatin1Char('/')));
|
||||
path.truncate(path.length()-1);
|
||||
return path;
|
||||
}
|
||||
|
||||
namespace OCC {
|
||||
|
||||
#define DEBUG qDebug() << "SocketApi: "
|
||||
@@ -149,7 +142,7 @@ void SocketApi::slotNewConnection()
|
||||
|
||||
foreach( Folder *f, FolderMan::instance()->map() ) {
|
||||
if (f->canSync()) {
|
||||
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
|
||||
QString message = buildRegisterPathMessage(f->path());
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
}
|
||||
@@ -196,7 +189,7 @@ void SocketApi::slotRegisterPath( const QString& alias )
|
||||
|
||||
Folder *f = FolderMan::instance()->folder(alias);
|
||||
if (f) {
|
||||
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
|
||||
QString message = buildRegisterPathMessage(f->path());
|
||||
foreach(QIODevice *socket, _listeners) {
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
@@ -212,7 +205,7 @@ void SocketApi::slotUnregisterPath( const QString& alias )
|
||||
|
||||
Folder *f = FolderMan::instance()->folder(alias);
|
||||
if (f)
|
||||
broadcastMessage(QLatin1String("UNREGISTER_PATH"), removeTrailingSlash(f->path()), QString::null, true );
|
||||
broadcastMessage(QLatin1String("UNREGISTER_PATH"), f->path(), QString::null, true );
|
||||
|
||||
_registeredAliases.remove(alias);
|
||||
}
|
||||
@@ -232,11 +225,10 @@ void SocketApi::slotUpdateFolderView(Folder *f)
|
||||
f->syncResult().status() == SyncResult::Error ||
|
||||
f->syncResult().status() == SyncResult::SetupError ) {
|
||||
|
||||
QString rootPath = removeTrailingSlash(f->path());
|
||||
broadcastMessage(QLatin1String("STATUS"), rootPath,
|
||||
broadcastMessage(QLatin1String("STATUS"), f->path() ,
|
||||
f->syncEngine().syncFileStatusTracker().fileStatus("").toSocketAPIString());
|
||||
|
||||
broadcastMessage(QLatin1String("UPDATE_VIEW"), rootPath);
|
||||
broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() );
|
||||
} else {
|
||||
qDebug() << "Not sending UPDATE_VIEW for" << f->alias() << "because status() is" << f->syncResult().status();
|
||||
}
|
||||
@@ -310,12 +302,8 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
|
||||
// this can happen in offline mode e.g.: nothing to worry about
|
||||
statusString = QLatin1String("NOP");
|
||||
} else {
|
||||
QString relativePath = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
|
||||
if( relativePath.endsWith(QLatin1Char('/')) ) {
|
||||
relativePath.truncate(relativePath.length()-1);
|
||||
qWarning() << "Removed trailing slash for directory: " << relativePath << "Status pushes won't have one.";
|
||||
}
|
||||
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(relativePath);
|
||||
const QString file = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
|
||||
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
|
||||
|
||||
statusString = fileStatus.toSocketAPIString();
|
||||
}
|
||||
|
||||
@@ -12,9 +12,15 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LIBSNORE
|
||||
#include <libsnore/application.h>
|
||||
#include <libsnore/notification/icon.h>
|
||||
#endif
|
||||
|
||||
#include "systray.h"
|
||||
#include "theme.h"
|
||||
#include <QDebug>
|
||||
#include <QPointer>
|
||||
|
||||
#ifdef USE_FDO_NOTIFICATIONS
|
||||
#include <QDBusConnection>
|
||||
@@ -28,8 +34,54 @@
|
||||
|
||||
namespace OCC {
|
||||
|
||||
void Systray::showMessage(const QString & title, const QString & message, MessageIcon icon, int millisecondsTimeoutHint)
|
||||
Systray::Systray( )
|
||||
{
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::SnoreCore &snore = Snore::SnoreCore::instance();
|
||||
snore.loadPlugins( Snore::SnorePlugin::Backend | Snore::SnorePlugin::SecondaryBackend );
|
||||
snore.setDefaultSettingsValue("Silent", true, Snore::LocalSetting );
|
||||
|
||||
_application = Snore::Application( Theme::instance()->appName(), Theme::instance()->applicationIcon() );
|
||||
_application.hints().setValue( "use-markup", true );
|
||||
_application.hints().setValue( "windows-app-id", Theme::instance()->appName() );
|
||||
_application.hints().setValue( "desktop-entry", Theme::instance()->appNameGUI() );
|
||||
_application.hints().setValue( "tray-icon", qVariantFromValue(QPointer<QSystemTrayIcon>(this)));
|
||||
|
||||
// register the Alerts.
|
||||
Snore::Alert alert( Theme::instance()->appNameGUI(), QIcon() );
|
||||
_alerts.insert( QSystemTrayIcon::NoIcon, alert);
|
||||
_application.addAlert(alert);
|
||||
Snore::Alert alert2( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Success, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Information, alert2);
|
||||
_application.addAlert(alert2);
|
||||
Snore::Alert alert3( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Problem, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Warning, alert3);
|
||||
_application.addAlert(alert3);
|
||||
Snore::Alert alert4( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Error, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Critical, alert4);
|
||||
_application.addAlert(alert4);
|
||||
|
||||
snore.registerApplication( _application );
|
||||
snore.setDefaultApplication( _application );
|
||||
|
||||
// connect( &snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Systray::showMessage(const QString & title, const QString & message, MessageIcon icon,
|
||||
int millisecondsTimeoutHint)
|
||||
{
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::Alert a = _alerts[NoIcon];
|
||||
if( _alerts.contains(icon) ) {
|
||||
a = _alerts[icon];
|
||||
}
|
||||
|
||||
Snore::Notification n( _application , a, title, message, a.icon() );
|
||||
Snore::SnoreCore::instance().broadcastNotification( n );
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef USE_FDO_NOTIFICATIONS
|
||||
if(QDBusInterface(NOTIFICATIONS_SERVICE, NOTIFICATIONS_PATH, NOTIFICATIONS_IFACE).isValid()) {
|
||||
|
||||
@@ -15,8 +15,13 @@
|
||||
#ifndef SYSTRAY_H
|
||||
#define SYSTRAY_H
|
||||
|
||||
#include "logger.h"
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#ifdef HAVE_LIBSNORE
|
||||
#include <libsnore/snore.h>
|
||||
#endif
|
||||
|
||||
class QIcon;
|
||||
|
||||
namespace OCC {
|
||||
@@ -34,8 +39,17 @@ class Systray : public QSystemTrayIcon
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void showMessage(const QString & title, const QString & message, MessageIcon icon = Information, int millisecondsTimeoutHint = 10000);
|
||||
explicit Systray();
|
||||
|
||||
void showMessage(const QString & title, const QString & message, MessageIcon icon = Information,
|
||||
int millisecondsTimeoutHint = 10000);
|
||||
void setToolTip(const QString &tip);
|
||||
|
||||
private:
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::Application _application;
|
||||
QHash<QSystemTrayIcon::MessageIcon, Snore::Alert> _alerts;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -218,7 +218,6 @@ void OCUpdater::slotVersionInfoArrived()
|
||||
{
|
||||
_timeoutWatchdog->stop();
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||
reply->deleteLater();
|
||||
if( reply->error() != QNetworkReply::NoError ) {
|
||||
qDebug() << "Failed to reach version check url: " << reply->errorString();
|
||||
return;
|
||||
@@ -259,7 +258,6 @@ void NSISUpdater::slotWriteFile()
|
||||
void NSISUpdater::slotDownloadFinished()
|
||||
{
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||
reply->deleteLater();
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
setDownloadState(DownloadFailed);
|
||||
return;
|
||||
|
||||
@@ -242,7 +242,6 @@ void AbstractNetworkJob::slotTimeout()
|
||||
reply()->abort();
|
||||
} else {
|
||||
qDebug() << Q_FUNC_INFO << this << "Timeout reply was NULL";
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ Account::Account(QObject *parent)
|
||||
, _capabilities(QVariantMap())
|
||||
, _am(0)
|
||||
, _credentials(0)
|
||||
, _treatSslErrorsAsFailure(false)
|
||||
, _davPath( Theme::instance()->webDavPath() )
|
||||
, _wasMigrated(false)
|
||||
{
|
||||
@@ -328,9 +329,9 @@ void Account::addApprovedCerts(const QList<QSslCertificate> certs)
|
||||
_approvedCerts += certs;
|
||||
}
|
||||
|
||||
void Account::resetRejectedCertificates()
|
||||
void Account::resetSslCertErrorState()
|
||||
{
|
||||
_rejectedCertificates.clear();
|
||||
_treatSslErrorsAsFailure = false;
|
||||
}
|
||||
|
||||
void Account::setSslErrorHandler(AbstractSslErrorHandler *handler)
|
||||
@@ -411,15 +412,8 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
|
||||
<< error.errorString() << "("<< error.error() << ")" << "\n";
|
||||
}
|
||||
|
||||
bool allPreviouslyRejected = true;
|
||||
foreach (const QSslError &error, errors) {
|
||||
if (!_rejectedCertificates.contains(error.certificate())) {
|
||||
allPreviouslyRejected = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If all certs have previously been rejected by the user, don't ask again.
|
||||
if( allPreviouslyRejected ) {
|
||||
if( _treatSslErrorsAsFailure ) {
|
||||
// User decided once not to trust. Honor this decision.
|
||||
qDebug() << out << "Certs not trusted by user decision, returning.";
|
||||
return;
|
||||
}
|
||||
@@ -442,12 +436,7 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
|
||||
// certificate changes.
|
||||
reply->ignoreSslErrors(errors);
|
||||
} else {
|
||||
// Mark all involved certificates as rejected, so we don't ask the user again.
|
||||
foreach (const QSslError &error, errors) {
|
||||
if (!_rejectedCertificates.contains(error.certificate())) {
|
||||
_rejectedCertificates.append(error.certificate());
|
||||
}
|
||||
}
|
||||
_treatSslErrorsAsFailure = true;
|
||||
// if during normal operation, a new certificate was MITM'ed, and the user does not
|
||||
// ACK it, the running request must be aborted and the QNAM must be reset, to not
|
||||
// treat the new cert as granted. See bug #3283
|
||||
|
||||
@@ -133,7 +133,7 @@ public:
|
||||
// Usually when a user explicitly rejects a certificate we don't
|
||||
// ask again. After this call, a dialog will again be shown when
|
||||
// the next unknown certificate is encountered.
|
||||
void resetRejectedCertificates();
|
||||
void resetSslCertErrorState();
|
||||
|
||||
// pluggable handler
|
||||
void setSslErrorHandler(AbstractSslErrorHandler *handler);
|
||||
@@ -216,10 +216,7 @@ private:
|
||||
QuotaInfo *_quotaInfo;
|
||||
QNetworkAccessManager *_am;
|
||||
AbstractCredentials* _credentials;
|
||||
|
||||
/// Certificates that were explicitly rejected by the user
|
||||
QList<QSslCertificate> _rejectedCertificates;
|
||||
|
||||
bool _treatSslErrorsAsFailure;
|
||||
static QString _configFileName;
|
||||
QByteArray _pemCertificate;
|
||||
QString _pemPrivateKey;
|
||||
|
||||
@@ -111,9 +111,9 @@ bool OWNCLOUDSYNC_EXPORT rename(const QString& originFileName,
|
||||
*
|
||||
* @return true if the file's mtime or size are not what is expected.
|
||||
*/
|
||||
bool OWNCLOUDSYNC_EXPORT fileChanged(const QString& fileName,
|
||||
qint64 previousSize,
|
||||
time_t previousMtime);
|
||||
bool fileChanged(const QString& fileName,
|
||||
qint64 previousSize,
|
||||
time_t previousMtime);
|
||||
|
||||
/**
|
||||
* @brief Like !fileChanged() but with verbose logging if the file *did* change.
|
||||
|
||||
@@ -74,14 +74,14 @@ Logger::~Logger() {
|
||||
}
|
||||
|
||||
|
||||
void Logger::postGuiLog(const QString &title, const QString &message)
|
||||
void Logger::postGuiLog(const QString &title, const QString &message, NotificationType type )
|
||||
{
|
||||
emit guiLog(title, message);
|
||||
emit guiLog(title, message, type);
|
||||
}
|
||||
|
||||
void Logger::postOptionalGuiLog(const QString &title, const QString &message)
|
||||
void Logger::postOptionalGuiLog(const QString &title, const QString &message, NotificationType type )
|
||||
{
|
||||
emit optionalGuiLog(title, message);
|
||||
emit optionalGuiLog(title, message, type);
|
||||
}
|
||||
|
||||
void Logger::postGuiMessage(const QString &title, const QString &message)
|
||||
|
||||
@@ -45,6 +45,14 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum NotificationType {
|
||||
NoIcon = 0,
|
||||
Information,
|
||||
SoftError,
|
||||
Error,
|
||||
Critical
|
||||
};
|
||||
|
||||
|
||||
bool isNoop() const;
|
||||
void log(Log log);
|
||||
@@ -57,8 +65,8 @@ public:
|
||||
|
||||
static Logger* instance();
|
||||
|
||||
void postGuiLog(const QString& title, const QString& message);
|
||||
void postOptionalGuiLog(const QString& title, const QString& message);
|
||||
void postGuiLog(const QString& title, const QString& message, NotificationType type = Information);
|
||||
void postOptionalGuiLog(const QString& title, const QString& message, NotificationType type = Information);
|
||||
void postGuiMessage(const QString& title, const QString& message);
|
||||
|
||||
void setLogFile( const QString & name );
|
||||
@@ -68,9 +76,9 @@ public:
|
||||
|
||||
signals:
|
||||
void newLog(const QString&);
|
||||
void guiLog(const QString&, const QString&);
|
||||
void guiLog(const QString&, const QString&, Logger::NotificationType type);
|
||||
void guiMessage(const QString&, const QString&);
|
||||
void optionalGuiLog(const QString&, const QString&);
|
||||
void optionalGuiLog(const QString&, const QString&, Logger::NotificationType type);
|
||||
|
||||
public slots:
|
||||
void enterNextLogFile();
|
||||
|
||||
@@ -542,6 +542,27 @@ void OwncloudPropagator::scheduleNextJob()
|
||||
}
|
||||
}
|
||||
|
||||
void OwncloudPropagator::addTouchedFile(const QString& fn)
|
||||
{
|
||||
QString file = QDir::cleanPath(fn);
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
QMutexLocker lock(&_touchedFilesMutex);
|
||||
_touchedFiles.insert(file, timer);
|
||||
}
|
||||
|
||||
qint64 OwncloudPropagator::timeSinceFileTouched(const QString& fn) const
|
||||
{
|
||||
QMutexLocker lock(&_touchedFilesMutex);
|
||||
if (! _touchedFiles.contains(fn)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _touchedFiles[fn].elapsed();
|
||||
}
|
||||
|
||||
AccountPtr OwncloudPropagator::account() const
|
||||
{
|
||||
return _account;
|
||||
|
||||
@@ -297,12 +297,7 @@ public:
|
||||
|
||||
QAtomicInt _abortRequested; // boolean set by the main thread to abort.
|
||||
|
||||
/** The list of currently active jobs.
|
||||
This list contains the jobs that are currently using ressources and is used purely to
|
||||
know how many jobs there is currently running for the scheduler.
|
||||
Jobs add themself to the list when they do an assynchronous operation.
|
||||
Jobs can be several time on the list (example, when several chunks are uploaded in parallel)
|
||||
*/
|
||||
/* The list of currently active jobs */
|
||||
QList<PropagateItemJob*> _activeJobList;
|
||||
|
||||
/** We detected that another sync is required after this one */
|
||||
@@ -330,6 +325,18 @@ public:
|
||||
/** returns the size of chunks in bytes */
|
||||
static quint64 chunkSize();
|
||||
|
||||
/** Records that a file was touched by a job.
|
||||
*
|
||||
* Thread-safe.
|
||||
*/
|
||||
void addTouchedFile(const QString& fn);
|
||||
|
||||
/** Get the ms since a file was touched, or -1 if it wasn't.
|
||||
*
|
||||
* Thread-safe.
|
||||
*/
|
||||
qint64 timeSinceFileTouched(const QString& fn) const;
|
||||
|
||||
AccountPtr account() const;
|
||||
|
||||
enum DiskSpaceResult
|
||||
@@ -365,24 +372,17 @@ signals:
|
||||
/** Emitted when propagation has problems with a locked file. */
|
||||
void seenLockedFile(const QString &fileName);
|
||||
|
||||
/** Emitted when propagation touches a file.
|
||||
*
|
||||
* Used to track our own file modifications such that notifications
|
||||
* from the file watcher about these can be ignored.
|
||||
*/
|
||||
void touchedFile(const QString &fileName);
|
||||
|
||||
private:
|
||||
|
||||
AccountPtr _account;
|
||||
|
||||
/** Stores the time since a job touched a file. */
|
||||
QHash<QString, QElapsedTimer> _touchedFiles;
|
||||
mutable QMutex _touchedFilesMutex;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
// access to signals which are protected in Qt4
|
||||
friend class PropagateDownloadFileQNAM;
|
||||
friend class PropagateUploadFileQNAM;
|
||||
friend class PropagateLocalMkdir;
|
||||
friend class PropagateLocalRename;
|
||||
friend class PropagateRemoteMove;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -127,65 +127,27 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const ProgressIn
|
||||
emit progressInfo( folder, progress );
|
||||
}
|
||||
|
||||
ProgressInfo::ProgressInfo()
|
||||
void ProgressInfo::start()
|
||||
{
|
||||
connect(&_updateEstimatesTimer, SIGNAL(timeout()), SLOT(updateEstimates()));
|
||||
reset();
|
||||
}
|
||||
|
||||
void ProgressInfo::reset()
|
||||
{
|
||||
_currentItems.clear();
|
||||
_currentDiscoveredFolder.clear();
|
||||
_sizeProgress = Progress();
|
||||
_fileProgress = Progress();
|
||||
_totalSizeOfCompletedJobs = 0;
|
||||
_maxBytesPerSecond = 100000.0;
|
||||
_maxFilesPerSecond = 2.0;
|
||||
_updateEstimatesTimer.stop();
|
||||
}
|
||||
|
||||
void ProgressInfo::startEstimateUpdates()
|
||||
{
|
||||
_updateEstimatesTimer.start(1000);
|
||||
}
|
||||
|
||||
bool ProgressInfo::isUpdatingEstimates() const
|
||||
bool ProgressInfo::hasStarted() const
|
||||
{
|
||||
return _updateEstimatesTimer.isActive();
|
||||
}
|
||||
|
||||
static bool shouldCountProgress(const SyncFileItem &item)
|
||||
{
|
||||
const auto instruction = item._instruction;
|
||||
|
||||
// Don't worry about directories that won't have propagation
|
||||
// jobs associated with them.
|
||||
if (item._isDirectory
|
||||
&& (instruction == CSYNC_INSTRUCTION_NONE
|
||||
|| instruction == CSYNC_INSTRUCTION_SYNC
|
||||
|| instruction == CSYNC_INSTRUCTION_CONFLICT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip any ignored or error files, we do nothing with them.
|
||||
if (instruction == CSYNC_INSTRUCTION_IGNORE
|
||||
|| instruction == CSYNC_INSTRUCTION_ERROR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProgressInfo::adjustTotalsForFile(const SyncFileItem &item)
|
||||
{
|
||||
if (!shouldCountProgress(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fileProgress._total += item._affectedItems;
|
||||
if (isSizeDependent(item)) {
|
||||
_sizeProgress._total += item._size;
|
||||
if (!item._isDirectory) {
|
||||
_fileProgress._total++;
|
||||
if (isSizeDependent(item)) {
|
||||
_sizeProgress._total += item._size;
|
||||
}
|
||||
} else if (item._instruction != CSYNC_INSTRUCTION_NONE) {
|
||||
// Added or removed directories certainly count.
|
||||
_fileProgress._total++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,10 +178,6 @@ quint64 ProgressInfo::completedSize() const
|
||||
|
||||
void ProgressInfo::setProgressComplete(const SyncFileItem &item)
|
||||
{
|
||||
if (!shouldCountProgress(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_currentItems.remove(item._file);
|
||||
_fileProgress.setCompleted(_fileProgress._completed + item._affectedItems);
|
||||
if (ProgressInfo::isSizeDependent(item)) {
|
||||
@@ -231,10 +189,6 @@ void ProgressInfo::setProgressComplete(const SyncFileItem &item)
|
||||
|
||||
void ProgressInfo::setProgressItem(const SyncFileItem &item, quint64 completed)
|
||||
{
|
||||
if (!shouldCountProgress(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_currentItems[item._file]._item = item;
|
||||
_currentItems[item._file]._progress._total = item._size;
|
||||
_currentItems[item._file]._progress.setCompleted(completed);
|
||||
|
||||
@@ -37,27 +37,27 @@ class OWNCLOUDSYNC_EXPORT ProgressInfo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProgressInfo();
|
||||
|
||||
/** Resets for a new sync run.
|
||||
*/
|
||||
void reset();
|
||||
ProgressInfo()
|
||||
: _totalSizeOfCompletedJobs(0)
|
||||
, _maxFilesPerSecond(2.0)
|
||||
, _maxBytesPerSecond(100000.0)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Called when propagation starts.
|
||||
*
|
||||
* isUpdatingEstimates() will return true afterwards.
|
||||
* hasStarted() will return true afterwards.
|
||||
*/
|
||||
void startEstimateUpdates();
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Returns true when startEstimateUpdates() was called.
|
||||
* Returns true when propagation has started (start() was called).
|
||||
*
|
||||
* This is used when the SyncEngine wants to indicate a new sync
|
||||
* is about to start via the transmissionProgress() signal. The
|
||||
* first ProgressInfo will have isUpdatingEstimates() == false.
|
||||
* first ProgressInfo will have hasStarted() == false.
|
||||
*/
|
||||
bool isUpdatingEstimates() const;
|
||||
bool hasStarted() const;
|
||||
|
||||
/**
|
||||
* Increase the file and size totals by the amount indicated in item.
|
||||
|
||||
@@ -592,8 +592,8 @@ void PropagateDownloadFileQNAM::deleteExistingFolder()
|
||||
QString conflictDir = FileSystem::makeConflictFileName(
|
||||
existingDir, Utility::qDateTimeFromTime_t(_item->_modtime));
|
||||
|
||||
emit _propagator->touchedFile(existingDir);
|
||||
emit _propagator->touchedFile(conflictDir);
|
||||
_propagator->addTouchedFile(existingDir);
|
||||
_propagator->addTouchedFile(conflictDir);
|
||||
QString renameError;
|
||||
if (!FileSystem::rename(existingDir, conflictDir, &renameError)) {
|
||||
done(SyncFileItem::NormalError, renameError);
|
||||
@@ -654,6 +654,7 @@ static void preserveGroupOwnership(const QString& fileName, const QFileInfo& fi)
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
|
||||
void PropagateDownloadFileQNAM::transmissionChecksumValidated(const QByteArray &checksumType, const QByteArray &checksum)
|
||||
{
|
||||
const auto theContentChecksumType = contentChecksumType();
|
||||
@@ -753,7 +754,7 @@ void PropagateDownloadFileQNAM::downloadFinished()
|
||||
}
|
||||
|
||||
QString error;
|
||||
emit _propagator->touchedFile(fn);
|
||||
_propagator->addTouchedFile(fn);
|
||||
// The fileChanged() check is done above to generate better error messages.
|
||||
if (!FileSystem::uncheckedRenameReplace(_tmpFile.fileName(), fn, &error)) {
|
||||
qDebug() << Q_FUNC_INFO << QString("Rename failed: %1 => %2").arg(_tmpFile.fileName()).arg(fn);
|
||||
|
||||
@@ -80,8 +80,8 @@ void PropagateRemoteMove::start()
|
||||
QString versionString = _propagator->account()->serverVersion();
|
||||
if (versionString.contains('.') && versionString.split('.')[0].toInt() < 7) {
|
||||
QString originalFile(_propagator->getFilePath(QLatin1String("Shared")));
|
||||
emit _propagator->touchedFile(originalFile);
|
||||
emit _propagator->touchedFile(targetFile);
|
||||
_propagator->addTouchedFile(originalFile);
|
||||
_propagator->addTouchedFile(targetFile);
|
||||
QString renameError;
|
||||
if( FileSystem::rename(targetFile, originalFile, &renameError) ) {
|
||||
done(SyncFileItem::NormalError, tr("This folder must not be renamed. It is renamed back to its original name."));
|
||||
|
||||
@@ -209,6 +209,8 @@ void PropagateUploadFileQNAM::slotComputeContentChecksum()
|
||||
return;
|
||||
}
|
||||
|
||||
_propagator->_activeJobList.removeOne(this);
|
||||
|
||||
const QString filePath = _propagator->getFilePath(_item->_file);
|
||||
|
||||
// remember the modtime before checksumming to be able to detect a file
|
||||
@@ -272,10 +274,6 @@ void PropagateUploadFileQNAM::slotComputeTransmissionChecksum(const QByteArray&
|
||||
|
||||
void PropagateUploadFileQNAM::slotStartUpload(const QByteArray& transmissionChecksumType, const QByteArray& transmissionChecksum)
|
||||
{
|
||||
// Remove ourselfs from the list of active job, before any posible call to done()
|
||||
// When we start chunks, we will add it again, once for every chunks.
|
||||
_propagator->_activeJobList.removeOne(this);
|
||||
|
||||
_transmissionChecksum = transmissionChecksum;
|
||||
_transmissionChecksumType = transmissionChecksumType;
|
||||
|
||||
@@ -400,7 +398,7 @@ qint64 UploadDevice::readData(char* data, qint64 maxlen) {
|
||||
if (isBandwidthLimited()) {
|
||||
maxlen = qMin(maxlen, _bandwidthQuota);
|
||||
if (maxlen <= 0) { // no quota
|
||||
//qDebug() << "no quota";
|
||||
qDebug() << "no quota";
|
||||
return 0;
|
||||
}
|
||||
_bandwidthQuota -= maxlen;
|
||||
@@ -546,16 +544,8 @@ void PropagateUploadFileQNAM::startNextChunk()
|
||||
_transmissionChecksumType, _transmissionChecksum);
|
||||
}
|
||||
|
||||
const QString fileName = _propagator->getFilePath(_item->_file);
|
||||
if (! device->prepareAndOpen(fileName, chunkStart, currentChunkSize)) {
|
||||
if (! device->prepareAndOpen(_propagator->getFilePath(_item->_file), chunkStart, currentChunkSize)) {
|
||||
qDebug() << "ERR: Could not prepare upload device: " << device->errorString();
|
||||
|
||||
// If the file is currently locked, we want to retry the sync
|
||||
// when it becomes available again.
|
||||
if (FileSystem::isFileLocked(fileName)) {
|
||||
emit _propagator->seenLockedFile(fileName);
|
||||
}
|
||||
|
||||
// Soft error because this is likely caused by the user modifying his files while syncing
|
||||
abortWithError( SyncFileItem::SoftError, device->errorString() );
|
||||
delete device;
|
||||
|
||||
@@ -163,7 +163,7 @@ void PropagateLocalMkdir::start()
|
||||
done( SyncFileItem::NormalError, tr("Attention, possible case sensitivity clash with %1").arg(newDirStr) );
|
||||
return;
|
||||
}
|
||||
emit _propagator->touchedFile(newDirStr);
|
||||
_propagator->addTouchedFile(newDirStr);
|
||||
QDir localDir(_propagator->_localDir);
|
||||
if (!localDir.mkpath(_item->_file)) {
|
||||
done( SyncFileItem::NormalError, tr("could not create folder %1").arg(newDirStr) );
|
||||
@@ -217,8 +217,8 @@ void PropagateLocalRename::start()
|
||||
return;
|
||||
}
|
||||
|
||||
emit _propagator->touchedFile(existingFile);
|
||||
emit _propagator->touchedFile(targetFile);
|
||||
_propagator->addTouchedFile(existingFile);
|
||||
_propagator->addTouchedFile(targetFile);
|
||||
QString renameError;
|
||||
if (!FileSystem::rename(existingFile, targetFile, &renameError)) {
|
||||
done(SyncFileItem::NormalError, renameError);
|
||||
|
||||
@@ -95,10 +95,6 @@ SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
|
||||
_excludedFiles.reset(new ExcludedFiles(&_csync_ctx->excludes));
|
||||
_syncFileStatusTracker.reset(new SyncFileStatusTracker(this));
|
||||
|
||||
_clearTouchedFilesTimer.setSingleShot(true);
|
||||
_clearTouchedFilesTimer.setInterval(30*1000);
|
||||
connect(&_clearTouchedFilesTimer, SIGNAL(timeout()), SLOT(slotClearTouchedFiles()));
|
||||
|
||||
_thread.setObjectName("SyncEngine_Thread");
|
||||
}
|
||||
|
||||
@@ -207,12 +203,6 @@ QString SyncEngine::csyncErrorToString(CSYNC_STATUS err)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the item is in the blacklist.
|
||||
* If it should not be sync'ed because of the blacklist, update the item with the error instruction
|
||||
* and proper error message, and return true.
|
||||
* If the item is not in the blacklist, or the blacklist is stale, return false.
|
||||
*/
|
||||
bool SyncEngine::checkErrorBlacklisting( SyncFileItem &item )
|
||||
{
|
||||
if( !_journal ) {
|
||||
@@ -244,9 +234,6 @@ bool SyncEngine::checkErrorBlacklisting( SyncFileItem &item )
|
||||
} else if( item._modtime != entry._lastTryModtime ) {
|
||||
qDebug() << item._file << " is blacklisted, but has changed mtime!";
|
||||
return false;
|
||||
} else if( item._renameTarget != entry._renameTarget) {
|
||||
qDebug() << item._file << " is blacklisted, but rename target changed from" << entry._renameTarget;
|
||||
return false;
|
||||
}
|
||||
} else if( item._direction == SyncFileItem::Down ) {
|
||||
// download, check the etag.
|
||||
@@ -437,9 +424,6 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
case CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS:
|
||||
item->_errorString = tr("Filename contains invalid characters that can not be synced cross platform.");
|
||||
break;
|
||||
case CSYNC_STATUS_INDIVIDUAL_TRAILING_SPACE:
|
||||
item->_errorString = tr("Filename contains trailing spaces.");
|
||||
break;
|
||||
case CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME:
|
||||
item->_errorString = tr("Filename is too long.");
|
||||
break;
|
||||
@@ -555,10 +539,10 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
bool directoryEtagUpdate = isDirectory && file->should_update_metadata;
|
||||
bool localMetadataUpdate = !remote && file->should_update_metadata;
|
||||
if (!directoryEtagUpdate) {
|
||||
item->_isDirectory = isDirectory;
|
||||
if (localMetadataUpdate) {
|
||||
// Hack, we want a local metadata update to happen, but only if the
|
||||
// remote tree doesn't ask us to do some kind of propagation.
|
||||
item->_isDirectory = isDirectory;
|
||||
_syncItemMap.insert(key, item);
|
||||
}
|
||||
emit syncItemDiscovered(*item);
|
||||
@@ -587,7 +571,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
// An upload of an existing file means that the file was left unchanged on the server
|
||||
// This counts as a NONE for detecting if all the files on the server were changed
|
||||
_hasNoneFiles = true;
|
||||
} else if (!isDirectory) {
|
||||
} else if (!item->_isDirectory) {
|
||||
if (std::difftime(file->modtime, file->other.modtime) < 0) {
|
||||
// We are going back on time
|
||||
_backInTimeFiles++;
|
||||
@@ -688,9 +672,6 @@ void SyncEngine::startSync()
|
||||
s_anySyncRunning = true;
|
||||
_syncRunning = true;
|
||||
_anotherSyncNeeded = false;
|
||||
_clearTouchedFilesTimer.stop();
|
||||
|
||||
_progressInfo->reset();
|
||||
|
||||
if (!QDir(_localPath).exists()) {
|
||||
// No _tr, it should only occur in non-mirall
|
||||
@@ -928,7 +909,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||
emit aboutToPropagate(_syncedItems);
|
||||
// it's important to do this before ProgressInfo::start(), to announce start of new sync
|
||||
emit transmissionProgress(*_progressInfo);
|
||||
_progressInfo->startEstimateUpdates();
|
||||
_progressInfo->start();
|
||||
|
||||
// post update phase script: allow to tweak stuff by a custom script in debug mode.
|
||||
if( !qgetenv("OWNCLOUD_POST_UPDATE_SCRIPT").isEmpty() ) {
|
||||
@@ -953,7 +934,6 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||
this, SLOT(slotProgress(const SyncFileItem &,quint64)));
|
||||
connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()), Qt::QueuedConnection);
|
||||
connect(_propagator.data(), SIGNAL(seenLockedFile(QString)), SIGNAL(seenLockedFile(QString)));
|
||||
connect(_propagator.data(), SIGNAL(touchedFile(QString)), SLOT(slotAddTouchedFile(QString)));
|
||||
|
||||
// apply the network limits to the propagator
|
||||
setNetworkLimits(_uploadLimit, _downloadLimit);
|
||||
@@ -1050,8 +1030,6 @@ void SyncEngine::finalize(bool success)
|
||||
|
||||
// Delete the propagator only after emitting the signal.
|
||||
_propagator.clear();
|
||||
|
||||
_clearTouchedFilesTimer.start();
|
||||
}
|
||||
|
||||
void SyncEngine::slotProgress(const SyncFileItem& item, quint64 current)
|
||||
@@ -1266,18 +1244,15 @@ void SyncEngine::checkForPermission()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OWNCLOUD_RESTORE_RENAME /* We don't like the idea of renaming behind user's back, as the user may be working with the files */
|
||||
if (!sourceOK && (!destinationOK || isRename)
|
||||
// (not for directory because that's more complicated with the contents that needs to be adjusted)
|
||||
&& !(*it)->_isDirectory) {
|
||||
#if 0 /* We don't like the idea of renaming behind user's back, as the user may be working with the files */
|
||||
|
||||
if (!sourceOK && !destinationOK) {
|
||||
// Both the source and the destination won't allow move. Move back to the original
|
||||
std::swap((*it)->_file, (*it)->_renameTarget);
|
||||
(*it)->_direction = SyncFileItem::Down;
|
||||
(*it)->_errorString = tr("Move not allowed, item restored");
|
||||
(*it)->_isRestoration = true;
|
||||
qDebug() << "checkForPermission: MOVING BACK" << (*it)->_file;
|
||||
// in case something does wrong, we will not do it next time
|
||||
_journal->avoidRenamesOnNextSync((*it)->_file);
|
||||
} else
|
||||
#endif
|
||||
if (!sourceOK || !destinationOK) {
|
||||
@@ -1373,28 +1348,14 @@ SyncFileItem* SyncEngine::findSyncItem(const QString &fileName) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SyncEngine::slotAddTouchedFile(const QString& fn)
|
||||
{
|
||||
QString file = QDir::cleanPath(fn);
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
_touchedFiles.insert(file, timer);
|
||||
}
|
||||
|
||||
void SyncEngine::slotClearTouchedFiles()
|
||||
{
|
||||
_touchedFiles.clear();
|
||||
}
|
||||
|
||||
qint64 SyncEngine::timeSinceFileTouched(const QString& fn) const
|
||||
{
|
||||
if (! _touchedFiles.contains(fn)) {
|
||||
return -1;
|
||||
// This copy is essential for thread safety.
|
||||
QSharedPointer<OwncloudPropagator> prop = _propagator;
|
||||
if (prop) {
|
||||
return prop->timeSinceFileTouched(fn);
|
||||
}
|
||||
|
||||
return _touchedFiles[fn].elapsed();
|
||||
return -1;
|
||||
}
|
||||
|
||||
AccountPtr SyncEngine::account() const
|
||||
|
||||
@@ -157,12 +157,6 @@ private slots:
|
||||
void slotDiscoveryJobFinished(int updateResult);
|
||||
void slotCleanPollsJobAborted(const QString &error);
|
||||
|
||||
/** Records that a file was touched by a job. */
|
||||
void slotAddTouchedFile(const QString& fn);
|
||||
|
||||
/** Wipes the _touchedFiles hash */
|
||||
void slotClearTouchedFiles();
|
||||
|
||||
private:
|
||||
void handleSyncError(CSYNC *ctx, const char *state);
|
||||
|
||||
@@ -262,12 +256,6 @@ private:
|
||||
CSyncChecksumHook _checksum_hook;
|
||||
|
||||
bool _anotherSyncNeeded;
|
||||
|
||||
/** Stores the time since a job touched a file. */
|
||||
QHash<QString, QElapsedTimer> _touchedFiles;
|
||||
|
||||
/** For clearing the _touchedFiles variable after sync finished */
|
||||
QTimer _clearTouchedFilesTimer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -92,13 +92,15 @@ SyncFileItem SyncFileStatusTracker::rootSyncFileItem()
|
||||
return fakeRootItem;
|
||||
}
|
||||
|
||||
SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& relativePath)
|
||||
SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& systemFileName)
|
||||
{
|
||||
// normalization is required for OS X to match file names properly
|
||||
QString normalizedRelativePath = relativePath.normalized(QString::NormalizationForm_C);
|
||||
Q_ASSERT(!normalizedRelativePath.endsWith(QLatin1Char('/')));
|
||||
QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
|
||||
if( fileName.endsWith(QLatin1Char('/')) ) {
|
||||
fileName.truncate(fileName.length()-1);
|
||||
qDebug() << "Removed trailing slash: " << fileName;
|
||||
}
|
||||
|
||||
if (normalizedRelativePath.isEmpty()) {
|
||||
if( fileName.isEmpty() ) {
|
||||
// This is the root sync folder, it doesn't have an entry in the database and won't be walked by csync, so create one manually.
|
||||
return syncFileItemStatus(rootSyncFileItem());
|
||||
}
|
||||
@@ -109,22 +111,22 @@ SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& relativePath)
|
||||
// update the exclude list at runtime and doing it statically here removes
|
||||
// our ability to notify changes through the fileStatusChanged signal,
|
||||
// it's an acceptable compromize to treat all exclude types the same.
|
||||
if( _syncEngine->excludedFiles().isExcluded(_syncEngine->localPath() + normalizedRelativePath,
|
||||
if( _syncEngine->excludedFiles().isExcluded(_syncEngine->localPath() + fileName,
|
||||
_syncEngine->localPath(),
|
||||
_syncEngine->ignoreHiddenFiles()) ) {
|
||||
return SyncFileStatus(SyncFileStatus::StatusWarning);
|
||||
}
|
||||
|
||||
if ( _dirtyPaths.contains(normalizedRelativePath) )
|
||||
if ( _dirtyPaths.contains(fileName) )
|
||||
return SyncFileStatus::StatusSync;
|
||||
|
||||
SyncFileItem* item = _syncEngine->findSyncItem(normalizedRelativePath);
|
||||
SyncFileItem* item = _syncEngine->findSyncItem(fileName);
|
||||
if (item) {
|
||||
return syncFileItemStatus(*item);
|
||||
}
|
||||
|
||||
// If we're not currently syncing that file, look it up in the database to know if it's shared
|
||||
SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(normalizedRelativePath);
|
||||
SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(fileName);
|
||||
if (rec.isValid()) {
|
||||
return syncFileItemStatus(rec.toSyncFileItem());
|
||||
}
|
||||
@@ -156,7 +158,7 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
|
||||
} else if (showWarningInSocketApi(*item)) {
|
||||
_syncProblems[item->_file] = SyncFileStatus::StatusWarning;
|
||||
}
|
||||
emit fileStatusChanged(getSystemDestination(item->destination()), syncFileItemStatus(*item));
|
||||
emit fileStatusChanged(getSystemDestination(*item), syncFileItemStatus(*item));
|
||||
}
|
||||
|
||||
// Make sure to push any status that might have been resolved indirectly since the last sync
|
||||
@@ -168,7 +170,7 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
|
||||
SyncFileStatus::SyncFileStatusTag severity = it->second;
|
||||
if (severity == SyncFileStatus::StatusError)
|
||||
invalidateParentPaths(path);
|
||||
emit fileStatusChanged(getSystemDestination(path), fileStatus(path));
|
||||
emit fileStatusChanged(_syncEngine->localPath() + path, fileStatus(path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,10 +184,11 @@ void SyncFileStatusTracker::slotItemCompleted(const SyncFileItem &item)
|
||||
} else if (showWarningInSocketApi(item)) {
|
||||
_syncProblems[item._file] = SyncFileStatus::StatusWarning;
|
||||
} else {
|
||||
_syncProblems.erase(item._file);
|
||||
// There is currently no situation where an error status set during discovery/update is fixed by propagation.
|
||||
Q_ASSERT(_syncProblems.find(item._file) == _syncProblems.end());
|
||||
}
|
||||
|
||||
emit fileStatusChanged(getSystemDestination(item.destination()), syncFileItemStatus(item));
|
||||
emit fileStatusChanged(getSystemDestination(item), syncFileItemStatus(item));
|
||||
}
|
||||
|
||||
void SyncFileStatusTracker::slotSyncEngineRunningChanged()
|
||||
@@ -233,19 +236,20 @@ void SyncFileStatusTracker::invalidateParentPaths(const QString& path)
|
||||
QStringList splitPath = path.split('/', QString::SkipEmptyParts);
|
||||
for (int i = 0; i < splitPath.size(); ++i) {
|
||||
QString parentPath = QStringList(splitPath.mid(0, i)).join(QLatin1String("/"));
|
||||
emit fileStatusChanged(getSystemDestination(parentPath), fileStatus(parentPath));
|
||||
emit fileStatusChanged(_syncEngine->localPath() + parentPath, fileStatus(parentPath));
|
||||
}
|
||||
}
|
||||
|
||||
QString SyncFileStatusTracker::getSystemDestination(const QString& relativePath)
|
||||
QString SyncFileStatusTracker::getSystemDestination(const SyncFileItem& item)
|
||||
{
|
||||
QString systemPath = _syncEngine->localPath() + relativePath;
|
||||
// SyncEngine::localPath() has a trailing slash, make sure to remove it if the
|
||||
// destination is empty.
|
||||
if( systemPath.endsWith(QLatin1Char('/')) ) {
|
||||
systemPath.truncate(systemPath.length()-1);
|
||||
QString systemFileName = _syncEngine->localPath() + item.destination();
|
||||
// the trailing slash for directories must be appended as the filenames coming in
|
||||
// from the plugins have that too. Otherwise the matching entry item is not found
|
||||
// in the plugin.
|
||||
if( item._type == SyncFileItem::Type::Directory ) {
|
||||
systemFileName += QLatin1Char('/');
|
||||
}
|
||||
return systemPath;
|
||||
return systemFileName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class OWNCLOUDSYNC_EXPORT SyncFileStatusTracker : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SyncFileStatusTracker(SyncEngine* syncEngine);
|
||||
SyncFileStatus fileStatus(const QString& relativePath);
|
||||
SyncFileStatus fileStatus(const QString& systemFileName);
|
||||
|
||||
public slots:
|
||||
void slotPathTouched(const QString& fileName);
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
SyncFileItem rootSyncFileItem();
|
||||
|
||||
void invalidateParentPaths(const QString& path);
|
||||
QString getSystemDestination(const QString& relativePath);
|
||||
QString getSystemDestination(const SyncFileItem& syncEnginePath);
|
||||
|
||||
SyncEngine* _syncEngine;
|
||||
|
||||
|
||||
@@ -409,7 +409,7 @@ bool SyncJournalDb::checkConnect()
|
||||
_deleteFileRecordRecursively.reset(new SqlQuery(_db));
|
||||
_deleteFileRecordRecursively->prepare("DELETE FROM metadata WHERE path LIKE(?||'/%')");
|
||||
|
||||
QString sql( "SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget "
|
||||
QString sql( "SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration "
|
||||
"FROM blacklist WHERE path=?1");
|
||||
if( Utility::fsCasePreserving() ) {
|
||||
// if the file system is case preserving we have to check the blacklist
|
||||
@@ -421,8 +421,8 @@ bool SyncJournalDb::checkConnect()
|
||||
|
||||
_setErrorBlacklistQuery.reset(new SqlQuery(_db));
|
||||
_setErrorBlacklistQuery->prepare("INSERT OR REPLACE INTO blacklist "
|
||||
"(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget) "
|
||||
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)");
|
||||
"(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration) "
|
||||
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7)");
|
||||
|
||||
_getSelectiveSyncListQuery.reset(new SqlQuery(_db));
|
||||
_getSelectiveSyncListQuery->prepare("SELECT path FROM selectivesync WHERE type=?1");
|
||||
@@ -612,15 +612,6 @@ bool SyncJournalDb::updateErrorBlacklistTableStructure()
|
||||
}
|
||||
commitInternal("update database structure: add lastTryTime, ignoreDuration cols");
|
||||
}
|
||||
if( columns.indexOf(QLatin1String("renameTarget")) == -1 ) {
|
||||
SqlQuery query(_db);
|
||||
query.prepare("ALTER TABLE blacklist ADD COLUMN renameTarget VARCHAR(4096);");
|
||||
if( !query.exec() ) {
|
||||
sqlFail("updateBlacklistTableStructure: Add renameTarget", query);
|
||||
re = false;
|
||||
}
|
||||
commitInternal("update database structure: add lastTryTime, ignoreDuration cols");
|
||||
}
|
||||
|
||||
SqlQuery query(_db);
|
||||
query.prepare("CREATE INDEX IF NOT EXISTS blacklist_index ON blacklist(path collate nocase);");
|
||||
@@ -1233,7 +1224,6 @@ SyncJournalErrorBlacklistRecord SyncJournalDb::errorBlacklistEntry( const QStrin
|
||||
entry._errorString = _getErrorBlacklistQuery->stringValue(3);
|
||||
entry._lastTryTime = _getErrorBlacklistQuery->int64Value(4);
|
||||
entry._ignoreDuration = _getErrorBlacklistQuery->int64Value(5);
|
||||
entry._renameTarget = _getErrorBlacklistQuery->stringValue(6);
|
||||
entry._file = file;
|
||||
}
|
||||
_getErrorBlacklistQuery->reset_and_clear_bindings();
|
||||
@@ -1345,14 +1335,13 @@ void SyncJournalDb::updateErrorBlacklistEntry( const SyncJournalErrorBlacklistRe
|
||||
_setErrorBlacklistQuery->bindValue(5, item._errorString);
|
||||
_setErrorBlacklistQuery->bindValue(6, QString::number(item._lastTryTime));
|
||||
_setErrorBlacklistQuery->bindValue(7, QString::number(item._ignoreDuration));
|
||||
_setErrorBlacklistQuery->bindValue(8, item._renameTarget);
|
||||
if( !_setErrorBlacklistQuery->exec() ) {
|
||||
QString bug = _setErrorBlacklistQuery->error();
|
||||
qDebug() << "SQL exec blacklistitem insert or replace failed: "<< bug;
|
||||
}
|
||||
qDebug() << "set blacklist entry for " << item._file << item._retryCount
|
||||
<< item._errorString << item._lastTryTime << item._ignoreDuration
|
||||
<< item._lastTryModtime << item._lastTryEtag << item._renameTarget ;
|
||||
<< item._lastTryModtime << item._lastTryEtag;
|
||||
_setErrorBlacklistQuery->reset_and_clear_bindings();
|
||||
|
||||
}
|
||||
|
||||
@@ -151,7 +151,6 @@ SyncJournalErrorBlacklistRecord SyncJournalErrorBlacklistRecord::update(
|
||||
// The factor of 5 feels natural: 25s, 2 min, 10 min, ~1h, ~5h, ~24h
|
||||
entry._ignoreDuration = old._ignoreDuration * 5;
|
||||
entry._file = item._file;
|
||||
entry._renameTarget = item._renameTarget;
|
||||
|
||||
if( item._httpErrorCode == 403 ) {
|
||||
qDebug() << "Probably firewall error: " << item._httpErrorCode << ", blacklisting up to 1h only";
|
||||
|
||||
@@ -89,7 +89,6 @@ public:
|
||||
time_t _ignoreDuration;
|
||||
|
||||
QString _file;
|
||||
QString _renameTarget;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
#else
|
||||
#include <QStandardPaths>
|
||||
#endif
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
||||
#include <QCollator>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <sys/statvfs.h>
|
||||
@@ -310,22 +306,17 @@ namespace {
|
||||
QString description(quint64 value) const
|
||||
{
|
||||
return QCoreApplication::translate(
|
||||
"Utility", name, 0, QCoreApplication::UnicodeUTF8,
|
||||
"Utiliy", name, 0, QCoreApplication::UnicodeUTF8,
|
||||
value);
|
||||
}
|
||||
};
|
||||
// QTBUG-3945 and issue #4855: QT_TRANSLATE_NOOP does not work with plural form because lupdate
|
||||
// limitation unless we fake more arguments
|
||||
// (it must be in the form ("context", "source", "comment", n)
|
||||
#undef QT_TRANSLATE_NOOP
|
||||
#define QT_TRANSLATE_NOOP(ctx, str, ...) str
|
||||
Q_DECL_CONSTEXPR Period periods[] = {
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n year(s)" , 0, _) , 365*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n month(s)", 0, _) , 30*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n day(s)", 0, _) , 24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n hour(s)", 0, _) , 3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n minute(s)", 0, _) , 60*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n second(s)", 0, _ ), 1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln year(s)") , 365*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln month(s)") , 30*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln day(s)") , 24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln hour(s)") , 3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln minute(s)") , 60*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln second(s)") , 1000LL },
|
||||
{ 0, 0 }
|
||||
};
|
||||
} // anonymous namespace
|
||||
@@ -550,18 +541,4 @@ quint64 Utility::StopWatch::durationOfLap( const QString& lapName ) const
|
||||
return _lapTimes.value(lapName, 0);
|
||||
}
|
||||
|
||||
void Utility::sortFilenames(QStringList& fileNames)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
||||
QCollator collator;
|
||||
collator.setNumericMode(true);
|
||||
collator.setCaseSensitivity(Qt::CaseInsensitive);
|
||||
qSort(fileNames.begin(), fileNames.end(), collator);
|
||||
#elif QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
fileNames.sort(Qt::CaseInsensitive);
|
||||
#else
|
||||
fileNames.sort();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -136,11 +136,6 @@ namespace Utility
|
||||
quint64 durationOfLap( const QString& lapName ) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sort a QStringList in a way that's appropriate for filenames
|
||||
*/
|
||||
OWNCLOUDSYNC_EXPORT void sortFilenames(QStringList& fileNames);
|
||||
|
||||
}
|
||||
/** @} */ // \addtogroup
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ macro(owncloud_add_test test_class additional_cpp)
|
||||
string(TOLOWER "${OWNCLOUD_TEST_CLASS}" OWNCLOUD_TEST_CLASS_LOWERCASE)
|
||||
|
||||
add_executable(${OWNCLOUD_TEST_CLASS}Test test${OWNCLOUD_TEST_CLASS_LOWERCASE}.cpp ${additional_cpp})
|
||||
qt5_use_modules(${OWNCLOUD_TEST_CLASS}Test Test Sql Xml Network)
|
||||
qt5_use_modules(${OWNCLOUD_TEST_CLASS}Test Test Sql Xml Network Gui Widgets)
|
||||
|
||||
target_link_libraries(${OWNCLOUD_TEST_CLASS}Test
|
||||
updater
|
||||
|
||||
@@ -150,10 +150,5 @@ using namespace OCC;
|
||||
}
|
||||
};
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
QTEST_MAIN(TestChecksumValidator)
|
||||
#else
|
||||
QTEST_GUILESS_MAIN(TestChecksumValidator)
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(TestChecksumValidator)
|
||||
#include "testchecksumvalidator.moc"
|
||||
|
||||
@@ -100,5 +100,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestConcatUrl)
|
||||
QTEST_MAIN(TestConcatUrl)
|
||||
#include "testconcaturl.moc"
|
||||
|
||||
@@ -85,5 +85,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestCSyncSqlite)
|
||||
QTEST_MAIN(TestCSyncSqlite)
|
||||
#include "testcsyncsqlite.moc"
|
||||
|
||||
@@ -26,24 +26,24 @@ private slots:
|
||||
bool excludeHidden = true;
|
||||
bool keepHidden = false;
|
||||
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "/a", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b~", "/a", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", "/a", excludeHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "b", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b~", "b~", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", ".b", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", ".b", excludeHidden));
|
||||
|
||||
QString path(BIN_PATH);
|
||||
path.append("/sync-exclude.lst");
|
||||
excluded.addExcludeFilePath(path);
|
||||
excluded.reloadExcludes();
|
||||
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/b~", "/a", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.Trashes", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/foo_conflict-bar", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", "/a", excludeHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "b", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/b~", "b~", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", ".b", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.Trashes", ".Trashes", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/foo_conflict-bar", "foo_conflict-bar", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", ".b", excludeHidden));
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestExcludedFiles)
|
||||
QTEST_MAIN(TestExcludedFiles)
|
||||
#include "testexcludedfiles.moc"
|
||||
|
||||
@@ -87,5 +87,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestFileSystem)
|
||||
QTEST_MAIN(TestFileSystem)
|
||||
#include "testfilesystem.moc"
|
||||
|
||||
@@ -41,5 +41,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestFolder)
|
||||
QTEST_MAIN(TestFolder)
|
||||
#include "testfolder.moc"
|
||||
|
||||
@@ -118,5 +118,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestFolderMan)
|
||||
QTEST_MAIN(TestFolderMan)
|
||||
#include "testfolderman.moc"
|
||||
|
||||
@@ -170,10 +170,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
QTEST_MAIN(TestFolderWatcher)
|
||||
#else
|
||||
QTEST_GUILESS_MAIN(TestFolderWatcher)
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(TestFolderWatcher)
|
||||
#include "testfolderwatcher.moc"
|
||||
|
||||