Comparar commits
114 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 5aa1629440 | |||
| fe984b61d7 | |||
| 6b899be895 | |||
| 641785298f | |||
| 1f78ea0fd1 | |||
| 2fd9767892 | |||
| 69a1e46d0c | |||
| e020a5327e | |||
| 1b04489887 | |||
| 36a19703db | |||
| f3a345a23b | |||
| 826459eae7 | |||
| c2c36b85cb | |||
| 7b2f8ae6f7 | |||
| d600fdc89b | |||
| 8c5ea8dc90 | |||
| 0eddcd6384 | |||
| 9f2ae5dd17 | |||
| 766d9ae1ac | |||
| 21128ed762 | |||
| 5000d40619 | |||
| 0d321050a6 | |||
| fc7aaf792b | |||
| f6355e15a3 | |||
| d80d5a8ee4 | |||
| e0a36ab313 | |||
| 9d3e78ed54 | |||
| b6079bfe4f | |||
| f75106fd8e | |||
| 57fe7b800f | |||
| 089ecf8222 | |||
| c2fa9b5bbf | |||
| 86522cbbf0 | |||
| d54f8adac5 | |||
| d35ecafa0b | |||
| 2ca807280a | |||
| 91b6b88883 | |||
| f36d4562a1 | |||
| 67ecca492b | |||
| 84c925dc58 | |||
| e1a01c75d9 | |||
| 6a4adbc87e | |||
| 89974ab1d4 | |||
| 8d0c313486 | |||
| aab0cdf12a | |||
| a89520043e | |||
| 6382a142cd | |||
| 02c403e360 | |||
| 5f2b1999f6 | |||
| bd2bcad3ba | |||
| 598a7cec5d | |||
| 46d934bd95 | |||
| e8c8943a30 | |||
| f1e2e42d99 | |||
| 95c479aa07 | |||
| 035442b6da | |||
| 98efb07535 | |||
| bc04f79959 | |||
| e10c97573f | |||
| 383479fbfd | |||
| fca5f1b210 | |||
| 0cea3d85f5 | |||
| 85b8ab178e | |||
| ea9d17b41d | |||
| b7eb37dc03 | |||
| 98bfa8d5de | |||
| ff701bd473 | |||
| 31aaf956f5 | |||
| a221ac1e4d | |||
| 2b274e9460 | |||
| aa5d3055be | |||
| 3e1690ff7a | |||
| 826a675f32 | |||
| 323ebf9bf2 | |||
| e4bf3ec19a | |||
| f2721aff1d | |||
| 29bd8658bb | |||
| 8b9ca63eeb | |||
| 6f1b03c560 | |||
| 3bd3ffb8e2 | |||
| a810d69daa | |||
| 8496817db2 | |||
| 3d06f4b7c9 | |||
| b228488eb7 | |||
| b7809ded23 | |||
| dfb121236c | |||
| f286493c90 | |||
| c2cb729fee | |||
| 904cd46f75 | |||
| 7fd00b2cd5 | |||
| 2d110540ee | |||
| 907918dca3 | |||
| 5ffaf3a90f | |||
| 1040e7b57b | |||
| 65c49e1de6 | |||
| 4abaee7736 | |||
| 3cdcd8dea0 | |||
| cb19ebc9e3 | |||
| 37adaa7872 | |||
| 9d93afb2a1 | |||
| d5a481f132 | |||
| 7c24ed769e | |||
| 65110f7a91 | |||
| c33abd468d | |||
| 584b205bd5 | |||
| b75f50d62c | |||
| 14457e93e6 | |||
| 9c0ecad420 | |||
| 85b5fdb3d3 | |||
| f2c6669224 | |||
| d8f9bf3a0b | |||
| d5fa8faa91 | |||
| d1a1b95926 | |||
| ee2a67e332 |
+8
-1
@@ -1,6 +1,9 @@
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(VERSION 2.8.0)
|
||||
if(POLICY CMP0020)
|
||||
cmake_policy(SET CMP0020 NEW)
|
||||
endif()
|
||||
|
||||
project(client)
|
||||
|
||||
@@ -57,7 +60,7 @@ endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(DefineInstallationPaths)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
|
||||
@@ -166,6 +169,9 @@ find_package(SQLite3 3.8.0 REQUIRED)
|
||||
# On some OS, we want to use our own, not the system sqlite
|
||||
if (USE_OUR_OWN_SQLITE3)
|
||||
include_directories(BEFORE ${SQLITE3_INCLUDE_DIR})
|
||||
if (WIN32)
|
||||
add_definitions(-DSQLITE_API=__declspec\(dllimport\))
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(ZLIB)
|
||||
@@ -180,6 +186,7 @@ add_definitions(-DUNICODE)
|
||||
add_definitions(-D_UNICODE)
|
||||
if( WIN32 )
|
||||
add_definitions( -D__USE_MINGW_ANSI_STDIO=1 )
|
||||
add_definitions( -DNOMINMAX )
|
||||
endif( WIN32 )
|
||||
|
||||
# Handle Translations, pick all client_* files from trans directory.
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
version 2.2.4 (release 2016-09-27)
|
||||
* Dolphin Plugin: Use the Application name for the socket path (#5172)
|
||||
* SyncEngine: Fix renaming of folder when file are changed (#5195)
|
||||
* Selective Sync: Fix HTTP request loop and show error in view (#5154)
|
||||
* ConnectionValidator: properly handle error in status.php request (#5188)
|
||||
* Discovery: Set thread priority to low (#5017)
|
||||
* ExcludeFiles: Fix when the folder casing is not the same in the settings and in the FS
|
||||
* ShareLink: Ensure the password line edit is enabled (#5117)
|
||||
|
||||
version 2.2.3 (release 2016-08-08)
|
||||
* SyncEngine: Fix detection of backup (#5104)
|
||||
* Fix bug with overriding URL in config (#5016)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Toon opmerkingen bij deze uitgave"
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Toon opmerkingen bij deze versie"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Gevonden ${APPLICATION_EXECUTABLE} proces(sen) moet worden gestopt.$\nWilt u dat het installatieprogramma dat voor u doet?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Stoppen ${APPLICATION_EXECUTABLE} processen."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Het te stoppen proces is niet gevonden!"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar notas de lançamento"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Encontrados ${APPLICATION_EXECUTABLE} processo(s) em execução que precisa(m) de ser interrompido(s).$\nDeseja que o instalador o(s) termine por si?"
|
||||
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 $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Não foi encontrado o 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 $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Não desinstale"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar las notas de la versión"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "El/los proceso/s ${APPLICATION_EXECUTABLE} debe/n ser detenidos.$\n¿Quiere que el instalador lo haga por usted?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Deteniendo el/los proceso/s ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso para finalizar no encontrado!"
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso a finalizar no encontrado!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} se encuentra instalada en el sistema. Se recomienda de instalar la versión actual antes de instalar la nueva. Seleccione la operacion deseada y haga click en Siguiente para continuar."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "No desinstalar"
|
||||
|
||||
@@ -2,21 +2,23 @@
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||
else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||
else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||
endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||
endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif()
|
||||
|
||||
if(DEFINED MIRALL_FATAL_WARNINGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
endif(DEFINED MIRALL_FATAL_WARNINGS)
|
||||
if(DEFINED MIRALL_FATAL_WARNINGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
endif(DEFINED MIRALL_FATAL_WARNINGS)
|
||||
endif()
|
||||
|
||||
@@ -81,6 +81,13 @@ set(csync_HDRS
|
||||
# Statically include sqlite
|
||||
if (USE_OUR_OWN_SQLITE3)
|
||||
list(APPEND csync_SRCS ${SQLITE3_SOURCE})
|
||||
if (WIN32)
|
||||
# We want to export sqlite symbols from the ocsync DLL without
|
||||
# having to patch both sqlite3.h and the amalgation sqlite3.c,
|
||||
# so do the import/export magic manually through the build system.
|
||||
remove_definitions(-DSQLITE_API=__declspec\(dllimport\))
|
||||
add_definitions(-DSQLITE_API=__declspec\(dllexport\))
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
@@ -91,6 +98,12 @@ include_directories(
|
||||
add_library(${CSYNC_LIBRARY} SHARED ${csync_SRCS})
|
||||
#add_library(${CSYNC_LIBRARY}_static STATIC ${csync_SRCS})
|
||||
|
||||
generate_export_header( ${CSYNC_LIBRARY}
|
||||
BASE_NAME ${CSYNC_LIBRARY}
|
||||
EXPORT_MACRO_NAME OCSYNC_EXPORT
|
||||
EXPORT_FILE_NAME ocsynclib.h
|
||||
)
|
||||
|
||||
target_link_libraries(${CSYNC_LIBRARY} ${CSYNC_LINK_LIBRARIES})
|
||||
#target_link_libraries(${CSYNC_LIBRARY}_static ${CSYNC_LINK_LIBRARIES})
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
+32
-32
@@ -33,10 +33,10 @@
|
||||
#define _CSYNC_H
|
||||
|
||||
#include "std/c_private.h"
|
||||
#include "ocsynclib.h"
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <config_csync.h>
|
||||
|
||||
@@ -229,14 +229,14 @@ struct csync_vio_file_stat_s {
|
||||
char *original_name; // only set if locale conversion fails
|
||||
};
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_file_stat_new(void);
|
||||
csync_vio_file_stat_t *csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat);
|
||||
csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_file_stat_new(void);
|
||||
csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat);
|
||||
|
||||
void csync_vio_file_stat_destroy(csync_vio_file_stat_t *fstat);
|
||||
void OCSYNC_EXPORT csync_vio_file_stat_destroy(csync_vio_file_stat_t *fstat);
|
||||
|
||||
void csync_vio_file_stat_set_file_id( csync_vio_file_stat_t* dst, const char* src );
|
||||
void OCSYNC_EXPORT csync_vio_file_stat_set_file_id( csync_vio_file_stat_t* dst, const char* src );
|
||||
|
||||
void csync_vio_set_file_id(char* dst, const char *src );
|
||||
void OCSYNC_EXPORT csync_vio_set_file_id(char* dst, const char *src );
|
||||
|
||||
|
||||
/**
|
||||
@@ -317,7 +317,7 @@ typedef const char* (*csync_checksum_hook) (
|
||||
*
|
||||
* @param csync The context variable to allocate.
|
||||
*/
|
||||
void csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
void OCSYNC_EXPORT csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
|
||||
/**
|
||||
* @brief Initialize the file synchronizer.
|
||||
@@ -326,7 +326,7 @@ void csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
*
|
||||
* @param ctx The context to initialize.
|
||||
*/
|
||||
void csync_init(CSYNC *ctx);
|
||||
void OCSYNC_EXPORT csync_init(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Update detection
|
||||
@@ -335,7 +335,7 @@ void csync_init(CSYNC *ctx);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_update(CSYNC *ctx);
|
||||
int OCSYNC_EXPORT csync_update(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Reconciliation
|
||||
@@ -344,7 +344,7 @@ int csync_update(CSYNC *ctx);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_reconcile(CSYNC *ctx);
|
||||
int OCSYNC_EXPORT csync_reconcile(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Re-initializes the csync context
|
||||
@@ -353,7 +353,7 @@ int csync_reconcile(CSYNC *ctx);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_commit(CSYNC *ctx);
|
||||
int OCSYNC_EXPORT csync_commit(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Destroy the csync context
|
||||
@@ -364,7 +364,7 @@ int csync_commit(CSYNC *ctx);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_destroy(CSYNC *ctx);
|
||||
int OCSYNC_EXPORT csync_destroy(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Get the userdata saved in the context.
|
||||
@@ -386,7 +386,7 @@ void *csync_get_userdata(CSYNC *ctx);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_userdata(CSYNC *ctx, void *userdata);
|
||||
int OCSYNC_EXPORT csync_set_userdata(CSYNC *ctx, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Get the authentication callback set.
|
||||
@@ -396,7 +396,7 @@ int csync_set_userdata(CSYNC *ctx, void *userdata);
|
||||
* @return The authentication callback set or NULL if an error
|
||||
* occurred.
|
||||
*/
|
||||
csync_auth_callback csync_get_auth_callback(CSYNC *ctx);
|
||||
csync_auth_callback OCSYNC_EXPORT csync_get_auth_callback(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Set the authentication callback.
|
||||
@@ -407,7 +407,7 @@ csync_auth_callback csync_get_auth_callback(CSYNC *ctx);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
|
||||
int OCSYNC_EXPORT csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
|
||||
|
||||
/**
|
||||
* @brief Set the log level.
|
||||
@@ -416,14 +416,14 @@ int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb);
|
||||
*
|
||||
* @return 0 on success, < 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_log_level(int level);
|
||||
int OCSYNC_EXPORT csync_set_log_level(int level);
|
||||
|
||||
/**
|
||||
* @brief Get the log verbosity
|
||||
*
|
||||
* @return The log verbosity, -1 on error.
|
||||
*/
|
||||
int csync_get_log_level(void);
|
||||
int OCSYNC_EXPORT csync_get_log_level(void);
|
||||
|
||||
/**
|
||||
* @brief Get the logging callback set.
|
||||
@@ -431,7 +431,7 @@ int csync_get_log_level(void);
|
||||
* @return The logging callback set or NULL if an error
|
||||
* occurred.
|
||||
*/
|
||||
csync_log_callback csync_get_log_callback(void);
|
||||
csync_log_callback OCSYNC_EXPORT csync_get_log_callback(void);
|
||||
|
||||
/**
|
||||
* @brief Set the logging callback.
|
||||
@@ -440,14 +440,14 @@ csync_log_callback csync_get_log_callback(void);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_log_callback(csync_log_callback cb);
|
||||
int OCSYNC_EXPORT csync_set_log_callback(csync_log_callback cb);
|
||||
|
||||
/**
|
||||
* @brief get the userdata set for the logging callback.
|
||||
*
|
||||
* @return The userdata or NULL.
|
||||
*/
|
||||
void *csync_get_log_userdata(void);
|
||||
void OCSYNC_EXPORT *csync_get_log_userdata(void);
|
||||
|
||||
/**
|
||||
* @brief Set the userdata passed to the logging callback.
|
||||
@@ -456,13 +456,13 @@ void *csync_get_log_userdata(void);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_set_log_userdata(void *data);
|
||||
int OCSYNC_EXPORT csync_set_log_userdata(void *data);
|
||||
|
||||
/* Used for special modes or debugging */
|
||||
CSYNC_STATUS csync_get_status(CSYNC *ctx);
|
||||
CSYNC_STATUS OCSYNC_EXPORT csync_get_status(CSYNC *ctx);
|
||||
|
||||
/* Used for special modes or debugging */
|
||||
int csync_set_status(CSYNC *ctx, int status);
|
||||
int OCSYNC_EXPORT csync_set_status(CSYNC *ctx, int status);
|
||||
|
||||
typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*);
|
||||
|
||||
@@ -475,7 +475,7 @@ typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*);
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
|
||||
int OCSYNC_EXPORT csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
|
||||
|
||||
/**
|
||||
* @brief Walk the remote file tree and call a visitor function for each file.
|
||||
@@ -486,7 +486,7 @@ int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int fi
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
|
||||
int OCSYNC_EXPORT csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
|
||||
|
||||
/**
|
||||
* @brief Get the csync status string.
|
||||
@@ -495,7 +495,7 @@ int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int f
|
||||
*
|
||||
* @return A const pointer to a string with more precise status info.
|
||||
*/
|
||||
const char *csync_get_status_string(CSYNC *ctx);
|
||||
const char OCSYNC_EXPORT *csync_get_status_string(CSYNC *ctx);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
/**
|
||||
@@ -505,7 +505,7 @@ const char *csync_get_status_string(CSYNC *ctx);
|
||||
*
|
||||
* @return 0 on success, or an iconv error number.
|
||||
*/
|
||||
int csync_set_iconv_codec(const char *from);
|
||||
int OCSYNC_EXPORT csync_set_iconv_codec(const char *from);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -513,24 +513,24 @@ int csync_set_iconv_codec(const char *from);
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*/
|
||||
void csync_request_abort(CSYNC *ctx);
|
||||
void OCSYNC_EXPORT csync_request_abort(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Clears the abort flag. Can be called from another thread.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*/
|
||||
void csync_resume(CSYNC *ctx);
|
||||
void OCSYNC_EXPORT csync_resume(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Checks for the abort flag, to be used from the modules.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
*/
|
||||
int csync_abort_requested(CSYNC *ctx);
|
||||
int OCSYNC_EXPORT csync_abort_requested(CSYNC *ctx);
|
||||
|
||||
char *csync_normalize_etag(const char *);
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
char OCSYNC_EXPORT *csync_normalize_etag(const char *);
|
||||
time_t OCSYNC_EXPORT oc_httpdate_parse( const char *date );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "c_private.h"
|
||||
@@ -37,6 +36,12 @@
|
||||
#include "csync_exclude.h"
|
||||
#include "csync_misc.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.exclude"
|
||||
#include "csync_log.h"
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef _CSYNC_EXCLUDE_H
|
||||
#define _CSYNC_EXCLUDE_H
|
||||
|
||||
#include "ocsynclib.h"
|
||||
|
||||
enum csync_exclude_type_e {
|
||||
CSYNC_NOT_EXCLUDED = 0,
|
||||
CSYNC_FILE_SILENTLY_EXCLUDED,
|
||||
@@ -35,7 +37,7 @@ enum csync_exclude_type_e {
|
||||
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
|
||||
|
||||
#ifdef WITH_UNIT_TESTING
|
||||
int _csync_exclude_add(c_strlist_t **inList, const char *string);
|
||||
int OCSYNC_EXPORT _csync_exclude_add(c_strlist_t **inList, const char *string);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -46,7 +48,7 @@ int _csync_exclude_add(c_strlist_t **inList, const char *string);
|
||||
*
|
||||
* @return 0 on success, -1 if an error occurred with errno set.
|
||||
*/
|
||||
int csync_exclude_load(const char *fname, c_strlist_t **list);
|
||||
int OCSYNC_EXPORT csync_exclude_load(const char *fname, c_strlist_t **list);
|
||||
|
||||
/**
|
||||
* @brief Check if the given path should be excluded in a traversal situation.
|
||||
@@ -72,7 +74,7 @@ CSYNC_EXCLUDE_TYPE csync_excluded_traversal(c_strlist_t *excludes, const char *p
|
||||
* @param filetype
|
||||
* @return
|
||||
*/
|
||||
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
|
||||
CSYNC_EXCLUDE_TYPE OCSYNC_EXPORT csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
|
||||
#endif /* _CSYNC_EXCLUDE_H */
|
||||
|
||||
/**
|
||||
|
||||
+1
-42
@@ -23,12 +23,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/utime.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include "csync_private.h"
|
||||
#include "csync_log.h"
|
||||
@@ -37,46 +31,11 @@ CSYNC_THREAD int csync_log_level;
|
||||
CSYNC_THREAD csync_log_callback csync_log_cb;
|
||||
CSYNC_THREAD void *csync_log_userdata;
|
||||
|
||||
static int current_timestring(int hires, char *buf, size_t len)
|
||||
{
|
||||
char tbuf[64];
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
t = (time_t) tv.tv_sec;
|
||||
|
||||
tm = localtime(&t);
|
||||
if (tm == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hires) {
|
||||
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
|
||||
snprintf(buf, len, "%s.%06ld", tbuf, (long) tv.tv_usec);
|
||||
} else {
|
||||
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
|
||||
snprintf(buf, len, "%s", tbuf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void csync_log_stderr(int verbosity,
|
||||
const char *function,
|
||||
const char *buffer)
|
||||
{
|
||||
char date[64] = {0};
|
||||
int rc;
|
||||
|
||||
rc = current_timestring(1, date, sizeof(date));
|
||||
if (rc == 0) {
|
||||
fprintf(stderr, "[%s, %d] %s:", date+5, verbosity, function);
|
||||
} else {
|
||||
fprintf(stderr, "[%d] %s", verbosity, function);
|
||||
}
|
||||
|
||||
fprintf(stderr, "[%d] %s", verbosity, function);
|
||||
fprintf(stderr, " %s\n", buffer);
|
||||
}
|
||||
static void csync_log_function(int verbosity,
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
# include <shlobj.h>
|
||||
#else /* _WIN32 */
|
||||
# include <pwd.h>
|
||||
# include <unistd.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "c_lib.h"
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#endif
|
||||
|
||||
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags);
|
||||
int csync_fnmatch(const char *pattern, const char *name, int flags);
|
||||
|
||||
/**
|
||||
* @brief csync_errno_to_status - errno to csync status code
|
||||
|
||||
@@ -224,9 +224,6 @@ struct _csync_treewalk_context_s
|
||||
};
|
||||
typedef struct _csync_treewalk_context_s _csync_treewalk_context;
|
||||
|
||||
|
||||
time_t oc_httpdate_parse( const char *date );
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
*
|
||||
* @todo Add an argument to set the algorithm to use.
|
||||
*/
|
||||
int csync_reconcile_updates(CSYNC *ctx);
|
||||
int OCSYNC_EXPORT csync_reconcile_updates(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* }@
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
extern "C" {
|
||||
#include "csync_private.h"
|
||||
#include "csync_rename.h"
|
||||
}
|
||||
|
||||
#include <map>
|
||||
@@ -93,5 +94,9 @@ char* csync_rename_adjust_path_source(CSYNC* ctx, const char* path)
|
||||
return c_strdup(path);
|
||||
}
|
||||
|
||||
bool csync_rename_count(CSYNC *ctx) {
|
||||
csync_rename_s* d = csync_rename_s::get(ctx);
|
||||
return d->folder_renamed_from.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Return the final destination path of a given patch in case of renames */
|
||||
char *csync_rename_adjust_path(CSYNC *ctx, const char *path);
|
||||
char OCSYNC_EXPORT *csync_rename_adjust_path(CSYNC *ctx, const char *path);
|
||||
/* Return the source of a given path in case of renames */
|
||||
char *csync_rename_adjust_path_source(CSYNC *ctx, const char *path);
|
||||
void csync_rename_destroy(CSYNC *ctx);
|
||||
void csync_rename_record(CSYNC *ctx, const char *from, const char *to);
|
||||
char OCSYNC_EXPORT *csync_rename_adjust_path_source(CSYNC *ctx, const char *path);
|
||||
void OCSYNC_EXPORT csync_rename_destroy(CSYNC *ctx);
|
||||
void OCSYNC_EXPORT csync_rename_record(CSYNC *ctx, const char *from, const char *to);
|
||||
/* Return the amount of renamed item recorded */
|
||||
bool OCSYNC_EXPORT csync_rename_count(CSYNC *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -53,7 +52,7 @@
|
||||
|
||||
#define sqlite_open(A, B) sqlite3_open_v2(A,B, SQLITE_OPEN_READONLY+SQLITE_OPEN_NOMUTEX, NULL)
|
||||
|
||||
#define SQLTM_TIME 150000
|
||||
#define SQLTM_TIME 150
|
||||
#define SQLTM_COUNT 10
|
||||
|
||||
#define SQLITE_BUSY_HANDLED(F) if(1) { \
|
||||
@@ -61,7 +60,7 @@
|
||||
do { rc = F ; \
|
||||
if( (rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED) ) { \
|
||||
n++; \
|
||||
usleep(SQLTM_TIME); \
|
||||
csync_sleep(SQLTM_TIME); \
|
||||
} \
|
||||
}while( (n < SQLTM_COUNT) && ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED))); \
|
||||
}
|
||||
@@ -519,8 +518,7 @@ c_strlist_t *csync_statedb_query(sqlite3 *db,
|
||||
/* compile SQL program into a virtual machine, reattempteing if busy */
|
||||
do {
|
||||
if (busy_count) {
|
||||
/* sleep 100 msec */
|
||||
usleep(100000);
|
||||
csync_sleep(100);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "sqlite3_prepare: BUSY counter: %zu", busy_count);
|
||||
}
|
||||
err = sqlite3_prepare(db, statement, -1, &stmt, &tail);
|
||||
@@ -547,8 +545,7 @@ c_strlist_t *csync_statedb_query(sqlite3 *db,
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Busy counter has reached its maximum. Aborting this sql statement");
|
||||
break;
|
||||
}
|
||||
/* sleep 100 msec */
|
||||
usleep(100000);
|
||||
csync_sleep(100);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "sqlite3_step: BUSY counter: %zu", busy_count);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
#include "csync_time.h"
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.time"
|
||||
#include "csync_log.h"
|
||||
|
||||
@@ -45,7 +50,13 @@
|
||||
|
||||
int csync_gettime(struct timespec *tp)
|
||||
{
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
#if defined(_WIN32)
|
||||
__int64 wintime;
|
||||
GetSystemTimeAsFileTime((FILETIME*)&wintime);
|
||||
wintime -= 116444736000000000ll; //1jan1601 to 1jan1970
|
||||
tp->tv_sec = wintime / 10000000ll; //seconds
|
||||
tp->tv_nsec = wintime % 10000000ll * 100; //nano-seconds
|
||||
#elif defined(HAVE_CLOCK_GETTIME)
|
||||
return clock_gettime(CSYNC_CLOCK, tp);
|
||||
#else
|
||||
struct timeval tv;
|
||||
@@ -62,4 +73,11 @@ int csync_gettime(struct timespec *tp)
|
||||
|
||||
#undef CSYNC_CLOCK
|
||||
|
||||
/* vim: set ts=8 sw=2 et cindent: */
|
||||
void csync_sleep(unsigned int msecs)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Sleep(msecs);
|
||||
#else
|
||||
usleep(msecs * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -26,5 +26,6 @@
|
||||
#include "csync_private.h"
|
||||
|
||||
int csync_gettime(struct timespec *tp);
|
||||
void csync_sleep(unsigned int msecs);
|
||||
|
||||
#endif /* _CSYNC_TIME_H */
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
#include "csync_private.h"
|
||||
|
||||
const char *csync_instruction_str(enum csync_instructions_e instr);
|
||||
const char OCSYNC_EXPORT *csync_instruction_str(enum csync_instructions_e instr);
|
||||
|
||||
void csync_memstat_check(void);
|
||||
void OCSYNC_EXPORT csync_memstat_check(void);
|
||||
|
||||
bool csync_file_locked_or_open( const char *dir, const char *fname);
|
||||
bool OCSYNC_EXPORT csync_file_locked_or_open( const char *dir, const char *fname);
|
||||
#endif /* _CSYNC_UTIL_H */
|
||||
|
||||
@@ -26,6 +26,12 @@ set(cstdlib_SRCS
|
||||
c_time.c
|
||||
)
|
||||
|
||||
if(NOT HAVE_ASPRINTF AND NOT HAVE___MINGW_ASPRINTF)
|
||||
list(APPEND cstdlib_SRCS
|
||||
asprintf.c
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CSTDLIB_PUBLIC_INCLUDE_DIRS}
|
||||
${CSTDLIB_PRIVATE_INCLUDE_DIRS}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
https://raw.githubusercontent.com/littlstar/asprintf.c/20ce5207a4ecb24017b5a17e6cd7d006e3047146/asprintf.c
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Little Star Media, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* `asprintf.c' - asprintf
|
||||
*
|
||||
* copyright (c) 2014 joseph werle <joseph.werle@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "asprintf.h"
|
||||
|
||||
int
|
||||
asprintf (char **str, const char *fmt, ...) {
|
||||
int size = 0;
|
||||
va_list args;
|
||||
|
||||
// init variadic argumens
|
||||
va_start(args, fmt);
|
||||
|
||||
// format and get size
|
||||
size = vasprintf(str, fmt, args);
|
||||
|
||||
// toss args
|
||||
va_end(args);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
vasprintf (char **str, const char *fmt, va_list args) {
|
||||
int size = 0;
|
||||
va_list tmpa;
|
||||
|
||||
// copy
|
||||
va_copy(tmpa, args);
|
||||
|
||||
// apply variadic arguments to
|
||||
// sprintf with format to get size
|
||||
size = vsnprintf(NULL, size, fmt, tmpa);
|
||||
|
||||
// toss args
|
||||
va_end(tmpa);
|
||||
|
||||
// return -1 to be compliant if
|
||||
// size is less than 0
|
||||
if (size < 0) { return -1; }
|
||||
|
||||
// alloc with size plus 1 for `\0'
|
||||
*str = (char *) malloc(size + 1);
|
||||
|
||||
// return -1 to be compliant
|
||||
// if pointer is `NULL'
|
||||
if (NULL == *str) { return -1; }
|
||||
|
||||
// format string with original
|
||||
// variadic arguments and set new size
|
||||
size = vsprintf(*str, fmt, args);
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
https://raw.githubusercontent.com/littlstar/asprintf.c/20ce5207a4ecb24017b5a17e6cd7d006e3047146/asprintf.h
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Little Star Media, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* `asprintf.h' - asprintf.c
|
||||
*
|
||||
* copyright (c) 2014 joseph werle <joseph.werle@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
#ifndef ASPRINTF_H
|
||||
#define ASPRINTF_H 1
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Sets `char **' pointer to be a buffer
|
||||
* large enough to hold the formatted string
|
||||
* accepting a `va_list' args of variadic
|
||||
* arguments.
|
||||
*/
|
||||
|
||||
int
|
||||
vasprintf (char **, const char *, va_list);
|
||||
|
||||
/**
|
||||
* Sets `char **' pointer to be a buffer
|
||||
* large enough to hold the formatted
|
||||
* string accepting `n' arguments of
|
||||
* variadic arguments.
|
||||
*/
|
||||
|
||||
int
|
||||
asprintf (char **, const char *, ...);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -31,14 +31,17 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <wchar.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef __MINGW32__
|
||||
#define EDQUOT 0
|
||||
#define ENODATA 0
|
||||
#ifndef S_IRGRP
|
||||
@@ -65,6 +68,8 @@
|
||||
#define nlink_t int
|
||||
#define getuid() 0
|
||||
#define geteuid() 0
|
||||
#elif defined(_WIN32)
|
||||
#define mode_t int
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
@@ -89,8 +94,12 @@ typedef struct stat csync_stat_t;
|
||||
#define ENODATA EBADF
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_ASPRINTF) && defined(HAVE___MINGW_ASPRINTF)
|
||||
#if !defined(HAVE_ASPRINTF)
|
||||
#if defined(HAVE___MINGW_ASPRINTF)
|
||||
#define asprintf __mingw_asprintf
|
||||
#else
|
||||
#include "asprintf.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRERROR_R
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
#include "c_path.h"
|
||||
#include "c_time.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
struct timespec c_tspecdiff(struct timespec time1, struct timespec time0) {
|
||||
struct timespec ret;
|
||||
int xsec = 0;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#define _C_TIME_H
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/**
|
||||
* @brief Calculate time difference
|
||||
|
||||
@@ -21,12 +21,10 @@
|
||||
#ifndef _CSYNC_VIO_LOCAL_H
|
||||
#define _CSYNC_VIO_LOCAL_H
|
||||
|
||||
#include <sys/time.h>
|
||||
csync_vio_handle_t OCSYNC_EXPORT *csync_vio_local_opendir(const char *name);
|
||||
int OCSYNC_EXPORT csync_vio_local_closedir(csync_vio_handle_t *dhandle);
|
||||
csync_vio_file_stat_t OCSYNC_EXPORT *csync_vio_local_readdir(csync_vio_handle_t *dhandle);
|
||||
|
||||
csync_vio_handle_t *csync_vio_local_opendir(const char *name);
|
||||
int csync_vio_local_closedir(csync_vio_handle_t *dhandle);
|
||||
csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle);
|
||||
|
||||
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf);
|
||||
int OCSYNC_EXPORT csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf);
|
||||
|
||||
#endif /* _CSYNC_VIO_LOCAL_H */
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "config_csync.h"
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ assertLocalAndRemoteDir( '', 0);
|
||||
printInfo( "Testing with a .sys.admin#recall#" );
|
||||
system("echo 'dir/file2.dat' > ". $tmpdir . ".sys.admin\#recall\#");
|
||||
system("echo 'dir/file3.dat' >> ". $tmpdir . ".sys.admin\#recall\#");
|
||||
system("echo 'nonexistant' >> ". $tmpdir . ".sys.admin\#recall\#");
|
||||
system("echo '/tmp/t_recall/file4.dat' >> ". $tmpdir . ".sys.admin\#recall\#");
|
||||
glob_put( "$tmpdir/.sys.admin\#recall\#", "" );
|
||||
|
||||
csync();
|
||||
@@ -68,6 +70,10 @@ assert( -e glob(localDir().'dir/file3_.sys.admin#recall#-*.dat' ) );
|
||||
assert( -e glob(localDir().'dir/file2.dat' ) );
|
||||
assert( -e glob(localDir().'dir/file3.dat' ) );
|
||||
|
||||
assert( !-e glob(localDir().'nonexistant*' ) );
|
||||
assert( !-e glob('/tmp/t_recall/file4_.sys.admin#recall#-*.dat' ) );
|
||||
assert( -e glob('/tmp/t_recall/file4.dat' ) );
|
||||
|
||||
#Remove the recall file
|
||||
unlink(localDir() . ".sys.admin#recall#");
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
@@ -199,12 +199,6 @@ the database by comparing the files and their modification times. This process
|
||||
ensures that both server and client are synchronized using the appropriate NTP
|
||||
time before restarting the client following a database removal.
|
||||
|
||||
Pressing ``F5`` while in the Account Settings Dialog enables you to "reset" the
|
||||
journal. This function can be used to recreate the journal database.
|
||||
|
||||
.. note:: We recommend that you use this function only when advised to do so by
|
||||
ownCloud support staff.
|
||||
|
||||
Custom WebDAV Properties
|
||||
------------------------
|
||||
|
||||
|
||||
+2
-1
@@ -42,7 +42,8 @@ repositories`_ to see all the Linux client repos.
|
||||
echo 'deb-src
|
||||
http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Debian_8.0/ /' >> /etc/apt/sources.list.d/owncloud-client.list
|
||||
|
||||
2. Install the dependencies using the following commands for your specific Linux distribution:
|
||||
2. Install the dependencies using the following commands for your specific Linux
|
||||
distribution. Make sure the repositories for source packages are enabled.
|
||||
|
||||
* Debian/Ubuntu: ``apt-get update; apt-get build-dep owncloud-client``
|
||||
* openSUSE/SLES: ``zypper ref; zypper si -d owncloud-client``
|
||||
|
||||
@@ -292,6 +292,129 @@ X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
|
||||
GenericName[oc]=Dorsièr de Sincronizacion
|
||||
|
||||
@@ -4,6 +4,7 @@ if( UNIX AND NOT APPLE )
|
||||
|
||||
configure_file(syncstate.py syncstate.py COPYONLY)
|
||||
configure_file(syncstate.py syncstate_nemo.py COPYONLY)
|
||||
configure_file(syncstate.py syncstate_caja.py COPYONLY)
|
||||
|
||||
# Call the setupappname.sh script to set the custom app name.
|
||||
set (cmd "${CMAKE_CURRENT_SOURCE_DIR}/setappname.sh")
|
||||
@@ -18,9 +19,17 @@ if( UNIX AND NOT APPLE )
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
ERROR_VARIABLE errors OUTPUT_VARIABLE out)
|
||||
|
||||
# Create a caja plugin script from the nautilus one.
|
||||
# cajacmd copies the syncstate.py and performs string replacement.
|
||||
set (cajacmd "${CMAKE_CURRENT_SOURCE_DIR}/createcajaplugin.sh")
|
||||
execute_process(COMMAND ${cajacmd}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
ERROR_VARIABLE errors OUTPUT_VARIABLE out)
|
||||
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${DATADIR}/nautilus-python/extensions)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${DATADIR}/nemo-python/extensions RENAME syncstate.py)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${DATADIR}/nautilus-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${DATADIR}/nemo-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_caja.py DESTINATION ${DATADIR}/caja-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
||||
|
||||
|
||||
|
||||
|
||||
Arquivo executável
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this script creates a plugin for caja, just by replacing
|
||||
# all occurences of Nautilus with Caja (case sensitive).
|
||||
|
||||
sed -i.org -e 's/Nautilus/Caja/g' syncstate_caja.py
|
||||
sed -i.org -e 's/nautilus/caja/g' syncstate_caja.py
|
||||
+17
-161
@@ -1,165 +1,21 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
Copyright (c) 2011 Morgan Leborgne
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
+23
-20
@@ -1,24 +1,27 @@
|
||||
/*
|
||||
*
|
||||
* This file is part of QProgressIndicator,
|
||||
* an open-source recent files menu widget
|
||||
*
|
||||
* Copyright (C) 2009 - 2010 Morgan Leborgne
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with QRecentFilesMenu. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2011 Morgan Leborgne
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "QProgressIndicator.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
+27
-24
@@ -1,24 +1,27 @@
|
||||
/*
|
||||
*
|
||||
* This file is part of QProgressIndicator,
|
||||
* an open-source recent files menu widget
|
||||
*
|
||||
* Copyright (C) 2009 - 2010 Morgan Leborgne
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with QRecentFilesMenu. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2011 Morgan Leborgne
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QPROGRESSINDICATOR_H
|
||||
#define QPROGRESSINDICATOR_H
|
||||
|
||||
@@ -64,8 +67,8 @@ public:
|
||||
*/
|
||||
const QColor & color() const { return m_color; }
|
||||
|
||||
virtual QSize sizeHint() const Q_DECL_OVERRIDE;
|
||||
int heightForWidth(int w) const Q_DECL_OVERRIDE;
|
||||
virtual QSize sizeHint() const;
|
||||
int heightForWidth(int w) const;
|
||||
public slots:
|
||||
/*! Starts the spin animation.
|
||||
\sa stopAnimation isAnimated
|
||||
@@ -95,8 +98,8 @@ public slots:
|
||||
*/
|
||||
void setColor(const QColor & color);
|
||||
protected:
|
||||
virtual void timerEvent(QTimerEvent * event) Q_DECL_OVERRIDE;
|
||||
virtual void paintEvent(QPaintEvent * event) Q_DECL_OVERRIDE;
|
||||
virtual void timerEvent(QTimerEvent * event);
|
||||
virtual void paintEvent(QPaintEvent * event);
|
||||
private:
|
||||
int m_angle;
|
||||
int m_timerId;
|
||||
|
||||
+1
-1
@@ -11,4 +11,4 @@ Qt 4.4.x.
|
||||
|
||||
## License
|
||||
|
||||
LGPL
|
||||
MIT
|
||||
|
||||
externo
+3732
-2679
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+421
-267
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+29
-1
@@ -29,6 +29,7 @@
|
||||
#include "syncengine.h"
|
||||
#include "syncjournaldb.h"
|
||||
#include "config.h"
|
||||
#include "connectionvalidator.h"
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
@@ -41,10 +42,14 @@
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace OCC;
|
||||
|
||||
|
||||
static void nullMessageHandler(QtMsgType, const char *) {}
|
||||
|
||||
struct CmdOptions {
|
||||
QString source_dir;
|
||||
QString target_url;
|
||||
@@ -68,6 +73,8 @@ struct CmdOptions {
|
||||
// So we have to use a global variable
|
||||
CmdOptions *opts = 0;
|
||||
|
||||
const qint64 timeoutToUseMsec = qMax(1000, ConnectionValidator::DefaultCallingIntervalMsec - 5*1000);
|
||||
|
||||
class EchoDisabler
|
||||
{
|
||||
public:
|
||||
@@ -295,6 +302,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
parseOptions( app.arguments(), &options );
|
||||
|
||||
csync_set_log_level(options.silent ? 1 : 11);
|
||||
if (options.silent) {
|
||||
qInstallMsgHandler(nullMessageHandler);
|
||||
}
|
||||
|
||||
AccountPtr account = Account::create();
|
||||
|
||||
if( !account ) {
|
||||
@@ -388,13 +400,29 @@ int main(int argc, char **argv) {
|
||||
account->setCredentials(cred);
|
||||
account->setSslErrorHandler(sslErrorHandler);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
//obtain capabilities using event loop
|
||||
QEventLoop loop;
|
||||
|
||||
JsonApiJob *job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/capabilities"));
|
||||
job->setTimeout(timeoutToUseMsec);
|
||||
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QVariantMap &json) {
|
||||
auto caps = json.value("ocs").toMap().value("data").toMap().value("capabilities");
|
||||
qDebug() << "Server capabilities" << caps;
|
||||
account->setCapabilities(caps.toMap());
|
||||
loop.quit();
|
||||
});
|
||||
job->start();
|
||||
|
||||
loop.exec();
|
||||
#endif
|
||||
|
||||
// much lower age than the default since this utility is usually made to be run right after a change in the tests
|
||||
SyncEngine::minimumFileAgeForUpload = 0;
|
||||
|
||||
int restartCount = 0;
|
||||
restart_sync:
|
||||
|
||||
csync_set_log_level(options.silent ? 1 : 11);
|
||||
|
||||
opts = &options;
|
||||
|
||||
|
||||
@@ -70,9 +70,9 @@ set(client_SRCS
|
||||
activityitemdelegate.cpp
|
||||
selectivesyncdialog.cpp
|
||||
settingsdialog.cpp
|
||||
share.cpp
|
||||
sharedialog.cpp
|
||||
sharelinkwidget.cpp
|
||||
sharemanager.cpp
|
||||
shareusergroupwidget.cpp
|
||||
sharee.cpp
|
||||
socketapi.cpp
|
||||
|
||||
@@ -209,6 +209,13 @@ void AccountManager::saveAccountHelper(Account* acc, QSettings& settings, bool s
|
||||
|
||||
AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
|
||||
{
|
||||
auto urlConfig = settings.value(QLatin1String(urlC));
|
||||
if (!urlConfig.isValid()) {
|
||||
// No URL probably means a corrupted entry in the account settings
|
||||
qDebug() << "No URL for account " << settings.group();
|
||||
return AccountPtr();
|
||||
}
|
||||
|
||||
auto acc = createAccount();
|
||||
|
||||
QString authType = settings.value(QLatin1String(authTypeC)).toString();
|
||||
@@ -220,7 +227,7 @@ AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
|
||||
acc->setUrl(overrideUrl);
|
||||
authType = forceAuth;
|
||||
} else {
|
||||
acc->setUrl(settings.value(QLatin1String(urlC)).toUrl());
|
||||
acc->setUrl(urlConfig.toUrl());
|
||||
}
|
||||
acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString();
|
||||
|
||||
|
||||
@@ -117,6 +117,10 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
|
||||
|
||||
connect(ui->selectiveSyncApply, SIGNAL(clicked()), _model, SLOT(slotApplySelectiveSync()));
|
||||
connect(ui->selectiveSyncCancel, SIGNAL(clicked()), _model, SLOT(resetFolders()));
|
||||
connect(ui->bigFolderApply, SIGNAL(clicked(bool)), _model, SLOT(slotApplySelectiveSync()));
|
||||
connect(ui->bigFolderSyncAll, SIGNAL(clicked(bool)), _model, SLOT(slotSyncAllPendingBigFolders()));
|
||||
connect(ui->bigFolderSyncNone, SIGNAL(clicked(bool)), _model, SLOT(slotSyncNoPendingBigFolders()));
|
||||
|
||||
connect(FolderMan::instance(), SIGNAL(folderListChanged(Folder::Map)), _model, SLOT(resetFolders()));
|
||||
connect(this, SIGNAL(folderChanged()), _model, SLOT(resetFolders()));
|
||||
|
||||
@@ -635,12 +639,13 @@ void AccountSettings::refreshSelectiveSyncStatus()
|
||||
}
|
||||
|
||||
if (msg.isEmpty()) {
|
||||
ui->selectiveSyncNotification->setVisible(false);
|
||||
ui->selectiveSyncNotification->setText(QString());
|
||||
ui->selectiveSyncButtons->setVisible(true);
|
||||
ui->bigFolderUi->setVisible(false);
|
||||
} else {
|
||||
ui->selectiveSyncNotification->setVisible(true);
|
||||
QString wholeMsg = tr("There are new folders that were not synchronized because they are too big: ") + msg;
|
||||
ui->selectiveSyncNotification->setText(wholeMsg);
|
||||
ui->selectiveSyncButtons->setVisible(false);
|
||||
ui->bigFolderUi->setVisible(true);
|
||||
shouldBeVisible = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,44 +154,105 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="selectiveSyncNotification">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: red</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="bigFolderUi" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="selectiveSyncNotification">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: red</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="bigFolderSyncAll">
|
||||
<property name="text">
|
||||
<string>Synchronize all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="bigFolderSyncNone">
|
||||
<property name="text">
|
||||
<string>Synchronize none</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="bigFolderApply">
|
||||
<property name="text">
|
||||
<string>Apply manual changes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectiveSyncCancel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectiveSyncApply">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="selectiveSyncButtons" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectiveSyncCancel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectiveSyncApply">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -336,9 +336,14 @@ void Application::slotownCloudWizardDone( int res )
|
||||
_checkConnectionTimer.start();
|
||||
slotCheckConnection();
|
||||
|
||||
// The very first time an account is configured: enabled autostart
|
||||
// TODO: Doing this every time the account wizard finishes will annoy users.
|
||||
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), true);
|
||||
// If one account is configured: enable autostart
|
||||
bool shouldSetAutoStart = (accountMan->accounts().size() == 1);
|
||||
#ifdef Q_OS_MAC
|
||||
// Don't auto start when not being 'installed'
|
||||
shouldSetAutoStart = shouldSetAutoStart
|
||||
&& QCoreApplication::applicationDirPath().startsWith("/Applications/");
|
||||
#endif
|
||||
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), shouldSetAutoStart);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-11
@@ -123,6 +123,13 @@ Folder::~Folder()
|
||||
void Folder::checkLocalPath()
|
||||
{
|
||||
const QFileInfo fi(_definition.localPath);
|
||||
_canonicalLocalPath = fi.canonicalFilePath();
|
||||
if (_canonicalLocalPath.isEmpty()) {
|
||||
qDebug() << "Broken symlink:" << _definition.localPath;
|
||||
_canonicalLocalPath = _definition.localPath;
|
||||
} else if( !_canonicalLocalPath.endsWith('/') ) {
|
||||
_canonicalLocalPath.append('/');
|
||||
}
|
||||
|
||||
if( fi.isDir() && fi.isReadable() ) {
|
||||
qDebug() << "Checked local path ok";
|
||||
@@ -161,11 +168,7 @@ QString Folder::alias() const
|
||||
|
||||
QString Folder::path() const
|
||||
{
|
||||
QString p(_definition.localPath);
|
||||
if( ! p.endsWith('/') ) {
|
||||
p.append('/');
|
||||
}
|
||||
return p;
|
||||
return _canonicalLocalPath;
|
||||
}
|
||||
|
||||
QString Folder::shortGuiLocalPath() const
|
||||
@@ -198,7 +201,7 @@ void Folder::setIgnoreHiddenFiles(bool ignore)
|
||||
|
||||
QString Folder::cleanPath()
|
||||
{
|
||||
QString cleanedPath = QDir::cleanPath(_definition.localPath);
|
||||
QString cleanedPath = QDir::cleanPath(_canonicalLocalPath);
|
||||
|
||||
if(cleanedPath.length() == 3 && cleanedPath.endsWith(":/"))
|
||||
cleanedPath.remove(2,1);
|
||||
@@ -755,8 +758,6 @@ void Folder::startSync(const QStringList &pathList)
|
||||
|
||||
QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection);
|
||||
|
||||
// disable events until syncing is done
|
||||
// _watcher->setEventsEnabled(false);
|
||||
emit syncStarted();
|
||||
}
|
||||
|
||||
@@ -820,9 +821,6 @@ void Folder::slotSyncFinished(bool success)
|
||||
bubbleUpSyncResult();
|
||||
|
||||
bool anotherSyncNeeded = _engine->isAnotherSyncNeeded();
|
||||
// _watcher->setEventsEnabledDelayed(2000);
|
||||
|
||||
|
||||
|
||||
if (_csyncError) {
|
||||
_syncResult.setStatus(SyncResult::Error);
|
||||
|
||||
@@ -288,6 +288,7 @@ private:
|
||||
|
||||
AccountStatePtr _accountState;
|
||||
FolderDefinition _definition;
|
||||
QString _canonicalLocalPath; // As returned with QFileInfo:canonicalFilePath. Always ends with "/"
|
||||
|
||||
SyncResult _syncResult;
|
||||
QScopedPointer<SyncEngine> _engine;
|
||||
|
||||
@@ -1046,6 +1046,77 @@ void FolderStatusModel::resetFolders()
|
||||
setAccountState(_accountState);
|
||||
}
|
||||
|
||||
void FolderStatusModel::slotSyncAllPendingBigFolders()
|
||||
{
|
||||
for (int i = 0; i < _folders.count(); ++i) {
|
||||
if (!_folders[i]._fetched) {
|
||||
_folders[i]._folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, QStringList());
|
||||
continue;
|
||||
}
|
||||
auto folder = _folders.at(i)._folder;
|
||||
|
||||
bool ok;
|
||||
auto undecidedList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, &ok);
|
||||
if( !ok ) {
|
||||
qDebug() << Q_FUNC_INFO << "Could not read selective sync list from db.";
|
||||
return;
|
||||
}
|
||||
|
||||
// If this folder had no undecided entries, skip it.
|
||||
if (undecidedList.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove all undecided folders from the blacklist
|
||||
auto blackList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
|
||||
if( !ok ) {
|
||||
qDebug() << Q_FUNC_INFO << "Could not read selective sync list from db.";
|
||||
return;
|
||||
}
|
||||
foreach (const auto& undecidedFolder, undecidedList) {
|
||||
blackList.removeAll(undecidedFolder);
|
||||
}
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
|
||||
|
||||
// Add all undecided folders to the white list
|
||||
auto whiteList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, &ok);
|
||||
if( !ok ) {
|
||||
qDebug() << Q_FUNC_INFO << "Could not read selective sync list from db.";
|
||||
return;
|
||||
}
|
||||
whiteList += undecidedList;
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, whiteList);
|
||||
|
||||
// Clear the undecided list
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, QStringList());
|
||||
|
||||
// Trigger a sync
|
||||
if (folder->isBusy()) {
|
||||
folder->slotTerminateSync();
|
||||
}
|
||||
// The part that changed should not be read from the DB on next sync because there might be new folders
|
||||
// (the ones that are no longer in the blacklist)
|
||||
foreach (const auto &it, undecidedList) {
|
||||
folder->journalDb()->avoidReadFromDbOnNextSync(it);
|
||||
}
|
||||
FolderMan::instance()->slotScheduleSync(folder);
|
||||
}
|
||||
|
||||
resetFolders();
|
||||
}
|
||||
|
||||
void FolderStatusModel::slotSyncNoPendingBigFolders()
|
||||
{
|
||||
for (int i = 0; i < _folders.count(); ++i) {
|
||||
auto folder = _folders.at(i)._folder;
|
||||
|
||||
// clear the undecided list
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, QStringList());
|
||||
}
|
||||
|
||||
resetFolders();
|
||||
}
|
||||
|
||||
void FolderStatusModel::slotNewBigFolder()
|
||||
{
|
||||
auto f = qobject_cast<Folder *>(sender());
|
||||
|
||||
@@ -107,6 +107,8 @@ public slots:
|
||||
void slotUpdateFolderState(Folder *);
|
||||
void slotApplySelectiveSync();
|
||||
void resetFolders();
|
||||
void slotSyncAllPendingBigFolders();
|
||||
void slotSyncNoPendingBigFolders();
|
||||
void slotSetProgress(const ProgressInfo &progress);
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "filesystem.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace OCC;
|
||||
|
||||
@@ -30,6 +31,7 @@ LockWatcher::LockWatcher(QObject* parent)
|
||||
|
||||
void LockWatcher::addFile(const QString& path)
|
||||
{
|
||||
qDebug() << "Watching for lock of" << path << "being released";
|
||||
_watchedPaths.insert(path);
|
||||
}
|
||||
|
||||
@@ -39,6 +41,7 @@ void LockWatcher::checkFiles()
|
||||
|
||||
foreach (const QString& path, _watchedPaths) {
|
||||
if (!FileSystem::isFileLocked(path)) {
|
||||
qDebug() << "Lock of" << path << "was released";
|
||||
emit fileUnlocked(path);
|
||||
unlocked.insert(path);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define OCSSHAREJOB_H
|
||||
|
||||
#include "ocsjob.h"
|
||||
#include "share.h"
|
||||
#include "sharemanager.h"
|
||||
#include <QVector>
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
|
||||
+176
-62
@@ -56,6 +56,7 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
||||
_settingsDialog(new SettingsDialog(this)),
|
||||
#endif
|
||||
_logBrowser(0),
|
||||
_contextMenuVisibleOsx(false),
|
||||
_recentActionsMenu(0),
|
||||
_qdbusmenuWorkaround(false),
|
||||
_folderOpenActionMapper(new QSignalMapper(this)),
|
||||
@@ -66,7 +67,7 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
||||
_tray->setParent(this);
|
||||
|
||||
// for the beginning, set the offline icon until the account was verified
|
||||
_tray->setIcon( Theme::instance()->folderOfflineIcon(true));
|
||||
_tray->setIcon( Theme::instance()->folderOfflineIcon(/*systray?*/ true, /*currently visible?*/ false));
|
||||
|
||||
connect(_tray.data(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||
SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)));
|
||||
@@ -92,9 +93,9 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
||||
this,SLOT(slotSyncStateChange(Folder*)));
|
||||
|
||||
connect( AccountManager::instance(), SIGNAL(accountAdded(AccountState*)),
|
||||
SLOT(setupContextMenuIfVisible()));
|
||||
SLOT(updateContextMenuNeeded()));
|
||||
connect( AccountManager::instance(), SIGNAL(accountRemoved(AccountState*)),
|
||||
SLOT(setupContextMenuIfVisible()));
|
||||
SLOT(updateContextMenuNeeded()));
|
||||
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString)),
|
||||
SLOT(slotShowTrayMessage(QString,QString)));
|
||||
@@ -193,7 +194,7 @@ void ownCloudGui::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
|
||||
void ownCloudGui::slotSyncStateChange( Folder* folder )
|
||||
{
|
||||
slotComputeOverallSyncStatus();
|
||||
setupContextMenuIfVisible();
|
||||
updateContextMenuNeeded();
|
||||
|
||||
if( !folder ) {
|
||||
return; // Valid, just a general GUI redraw was needed.
|
||||
@@ -215,7 +216,7 @@ void ownCloudGui::slotSyncStateChange( Folder* folder )
|
||||
void ownCloudGui::slotFoldersChanged()
|
||||
{
|
||||
slotComputeOverallSyncStatus();
|
||||
setupContextMenuIfVisible();
|
||||
updateContextMenuNeeded();
|
||||
}
|
||||
|
||||
void ownCloudGui::slotOpenPath(const QString &path)
|
||||
@@ -225,7 +226,7 @@ void ownCloudGui::slotOpenPath(const QString &path)
|
||||
|
||||
void ownCloudGui::slotAccountStateChanged()
|
||||
{
|
||||
setupContextMenuIfVisible();
|
||||
updateContextMenuNeeded();
|
||||
slotComputeOverallSyncStatus();
|
||||
}
|
||||
|
||||
@@ -261,7 +262,7 @@ void ownCloudGui::slotComputeOverallSyncStatus()
|
||||
}
|
||||
|
||||
if (!problemAccounts.empty()) {
|
||||
_tray->setIcon(Theme::instance()->folderOfflineIcon(true));
|
||||
_tray->setIcon(Theme::instance()->folderOfflineIcon(true, contextMenuVisible()));
|
||||
#ifdef Q_OS_WIN
|
||||
// Windows has a 128-char tray tooltip length limit.
|
||||
QStringList accountNames;
|
||||
@@ -288,11 +289,11 @@ void ownCloudGui::slotComputeOverallSyncStatus()
|
||||
}
|
||||
|
||||
if (allSignedOut) {
|
||||
_tray->setIcon(Theme::instance()->folderOfflineIcon(true));
|
||||
_tray->setIcon(Theme::instance()->folderOfflineIcon(true, contextMenuVisible()));
|
||||
_tray->setToolTip(tr("Please sign in"));
|
||||
return;
|
||||
} else if (allPaused) {
|
||||
_tray->setIcon(Theme::instance()->syncStateIcon(SyncResult::Paused, true));
|
||||
_tray->setIcon(Theme::instance()->syncStateIcon(SyncResult::Paused, true, contextMenuVisible()));
|
||||
_tray->setToolTip(tr("Account synchronization is disabled"));
|
||||
return;
|
||||
}
|
||||
@@ -322,12 +323,12 @@ void ownCloudGui::slotComputeOverallSyncStatus()
|
||||
trayMessage = tr("No sync folders configured.");
|
||||
}
|
||||
|
||||
QIcon statusIcon = Theme::instance()->syncStateIcon( overallResult.status(), true);
|
||||
QIcon statusIcon = Theme::instance()->syncStateIcon( overallResult.status(), true, contextMenuVisible());
|
||||
_tray->setIcon( statusIcon );
|
||||
_tray->setToolTip(trayMessage);
|
||||
} else {
|
||||
// undefined because there are no folders.
|
||||
QIcon icon = Theme::instance()->syncStateIcon(SyncResult::Problem, true);
|
||||
QIcon icon = Theme::instance()->syncStateIcon(SyncResult::Problem, true, contextMenuVisible());
|
||||
_tray->setIcon( icon );
|
||||
_tray->setToolTip(tr("There are no sync folders configured."));
|
||||
}
|
||||
@@ -399,26 +400,160 @@ void ownCloudGui::addAccountContextMenu(AccountStatePtr accountState, QMenu *men
|
||||
|
||||
}
|
||||
|
||||
void ownCloudGui::slotContextMenuAboutToShow()
|
||||
{
|
||||
// For some reason on OS X _contextMenu->isVisible returns always false
|
||||
qDebug() << "";
|
||||
_contextMenuVisibleOsx = true;
|
||||
|
||||
// Update icon in sys tray, as it might change depending on the context menu state
|
||||
slotComputeOverallSyncStatus();
|
||||
}
|
||||
|
||||
void ownCloudGui::slotContextMenuAboutToHide()
|
||||
{
|
||||
// For some reason on OS X _contextMenu->isVisible returns always false
|
||||
qDebug() << "";
|
||||
_contextMenuVisibleOsx = false;
|
||||
|
||||
// Update icon in sys tray, as it might change depending on the context menu state
|
||||
slotComputeOverallSyncStatus();
|
||||
}
|
||||
|
||||
bool ownCloudGui::contextMenuVisible() const
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
return _contextMenuVisibleOsx;
|
||||
#else
|
||||
return _contextMenu->isVisible();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool minimalTrayMenu()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_MINIMAL_TRAY_MENU");
|
||||
return !var.isEmpty();
|
||||
}
|
||||
|
||||
static bool updateWhileVisible()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_TRAY_UPDATE_WHILE_VISIBLE");
|
||||
if (var == "1") {
|
||||
return true;
|
||||
} else if (var == "0") {
|
||||
return false;
|
||||
} else {
|
||||
// triggers bug on OS X: https://bugreports.qt.io/browse/QTBUG-54845
|
||||
// or flickering on Xubuntu
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static QByteArray forceQDBusTrayWorkaround()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_FORCE_QDBUS_TRAY_WORKAROUND");
|
||||
return var;
|
||||
}
|
||||
|
||||
void ownCloudGui::setupContextMenu()
|
||||
{
|
||||
if (_contextMenu) {
|
||||
return;
|
||||
}
|
||||
|
||||
_contextMenu.reset(new QMenu());
|
||||
_contextMenu->setTitle(Theme::instance()->appNameGUI() );
|
||||
|
||||
_recentActionsMenu = new QMenu(tr("Recent Changes"), _contextMenu.data());
|
||||
|
||||
// this must be called only once after creating the context menu, or
|
||||
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
||||
_tray->setContextMenu(_contextMenu.data());
|
||||
|
||||
// The tray menu is surprisingly problematic. Being able to switch to
|
||||
// a minimal version of it is a useful workaround and testing tool.
|
||||
if (minimalTrayMenu()) {
|
||||
if (!_contextMenu) {
|
||||
_contextMenu.reset(new QMenu());
|
||||
_recentActionsMenu = new QMenu(tr("Recent Changes"), _contextMenu.data());
|
||||
_tray->setContextMenu(_contextMenu.data());
|
||||
_contextMenu->addAction(_actionQuit);
|
||||
}
|
||||
_contextMenu->addAction(_actionQuit);
|
||||
return;
|
||||
}
|
||||
|
||||
// Enables workarounds for bugs introduced in Qt 5.5.0
|
||||
// In particular QTBUG-47863 #3672 (tray menu fails to update and
|
||||
// becomes unresponsive) and QTBUG-48068 #3722 (click signal is
|
||||
// emitted several times)
|
||||
// The Qt version check intentionally uses 5.0.0 (where platformMenu()
|
||||
// was introduced) instead of 5.5.0 to avoid issues where the Qt
|
||||
// version used to build is different from the one used at runtime.
|
||||
// If we build with 5.6.1 or newer, we can skip this because the
|
||||
// bugs should be fixed there.
|
||||
#ifdef Q_OS_LINUX
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) && (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
|
||||
if (qVersion() == QByteArray("5.5.0")) {
|
||||
QObject* platformMenu = reinterpret_cast<QObject*>(_tray->contextMenu()->platformMenu());
|
||||
if (platformMenu
|
||||
&& platformMenu->metaObject()->className() == QLatin1String("QDBusPlatformMenu")) {
|
||||
_qdbusmenuWorkaround = true;
|
||||
qDebug() << "Enabled QDBusPlatformMenu workaround";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (forceQDBusTrayWorkaround() == "1") {
|
||||
_qdbusmenuWorkaround = true;
|
||||
} else if (forceQDBusTrayWorkaround() == "0") {
|
||||
_qdbusmenuWorkaround = false;
|
||||
}
|
||||
|
||||
// When the qdbusmenuWorkaround is necessary, we can't do on-demand updates
|
||||
// because the workaround is to hide and show the tray icon.
|
||||
if (_qdbusmenuWorkaround) {
|
||||
connect(&_workaroundBatchTrayUpdate, SIGNAL(timeout()), SLOT(updateContextMenu()));
|
||||
_workaroundBatchTrayUpdate.setInterval(30 * 1000);
|
||||
_workaroundBatchTrayUpdate.setSingleShot(true);
|
||||
} else {
|
||||
// Update the context menu whenever we're about to show it
|
||||
// to the user.
|
||||
#ifdef Q_OS_MAC
|
||||
// https://bugreports.qt.io/browse/QTBUG-54633
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToShow()), SLOT(slotContextMenuAboutToShow()));
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToHide()), SLOT(slotContextMenuAboutToHide()));
|
||||
#else
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToShow()), SLOT(updateContextMenu()));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Populate the context menu now.
|
||||
updateContextMenu();
|
||||
}
|
||||
|
||||
void ownCloudGui::updateContextMenu()
|
||||
{
|
||||
if (minimalTrayMenu()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_qdbusmenuWorkaround) {
|
||||
// To make tray menu updates work with these bugs (see setupContextMenu)
|
||||
// we need to hide and show the tray icon. We don't want to do that
|
||||
// while it's visible!
|
||||
if (contextMenuVisible()) {
|
||||
if (!_workaroundBatchTrayUpdate.isActive()) {
|
||||
_workaroundBatchTrayUpdate.start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
_tray->hide();
|
||||
}
|
||||
|
||||
_contextMenu->clear();
|
||||
slotRebuildRecentMenus();
|
||||
|
||||
// We must call deleteLater because we might be called from the press in one of the actions.
|
||||
foreach (auto menu, _accountMenus) { menu->deleteLater(); }
|
||||
_accountMenus.clear();
|
||||
|
||||
|
||||
auto accountList = AccountManager::instance()->accounts();
|
||||
|
||||
bool isConfigured = (!accountList.isEmpty());
|
||||
@@ -445,47 +580,6 @@ void ownCloudGui::setupContextMenu()
|
||||
}
|
||||
}
|
||||
|
||||
if ( _contextMenu ) {
|
||||
if (_qdbusmenuWorkaround) {
|
||||
_tray->hide();
|
||||
}
|
||||
_contextMenu->clear();
|
||||
} else {
|
||||
_contextMenu.reset(new QMenu());
|
||||
|
||||
// Update the context menu whenever we're about to show it
|
||||
// to the user.
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToShow()), SLOT(setupContextMenu()));
|
||||
|
||||
_recentActionsMenu = new QMenu(tr("Recent Changes"), _contextMenu.data());
|
||||
// this must be called only once after creating the context menu, or
|
||||
// it will trigger a bug in Ubuntu's SNI bridge patch (11.10, 12.04).
|
||||
_tray->setContextMenu(_contextMenu.data());
|
||||
|
||||
// Enables workarounds for bugs introduced in Qt 5.5.0
|
||||
// In particular QTBUG-47863 #3672 (tray menu fails to update and
|
||||
// becomes unresponsive) and QTBUG-48068 #3722 (click signal is
|
||||
// emitted several times)
|
||||
// The Qt version check intentionally uses 5.0.0 (where platformMenu()
|
||||
// was introduced) instead of 5.5.0 to avoid issues where the Qt
|
||||
// version used to build is different from the one used at runtime.
|
||||
#ifdef Q_OS_LINUX
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
QObject* platformMenu = reinterpret_cast<QObject*>(_tray->contextMenu()->platformMenu());
|
||||
if (platformMenu
|
||||
&& platformMenu->metaObject()->className() == QLatin1String("QDBusPlatformMenu")) {
|
||||
_qdbusmenuWorkaround = true;
|
||||
qDebug() << "Enabled QDBusPlatformMenu workaround";
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
_contextMenu->setTitle(Theme::instance()->appNameGUI() );
|
||||
slotRebuildRecentMenus();
|
||||
|
||||
// We must call deleteLater because we might be called from the press in one of the actions.
|
||||
foreach (auto menu, _accountMenus) { menu->deleteLater(); }
|
||||
_accountMenus.clear();
|
||||
if (accountList.count() > 1) {
|
||||
foreach (AccountStatePtr account, accountList) {
|
||||
QMenu* accountMenu = new QMenu(account->account()->displayName(), _contextMenu.data());
|
||||
@@ -558,10 +652,30 @@ void ownCloudGui::setupContextMenu()
|
||||
}
|
||||
}
|
||||
|
||||
void ownCloudGui::setupContextMenuIfVisible()
|
||||
void ownCloudGui::updateContextMenuNeeded()
|
||||
{
|
||||
if (_contextMenu && _contextMenu->isVisible())
|
||||
setupContextMenu();
|
||||
// For the workaround case updating while visible is impossible. Instead
|
||||
// occasionally update the menu when it's invisible.
|
||||
if (_qdbusmenuWorkaround) {
|
||||
if (!_workaroundBatchTrayUpdate.isActive()) {
|
||||
_workaroundBatchTrayUpdate.start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// https://bugreports.qt.io/browse/QTBUG-54845
|
||||
// We cannot update on demand or while visible -> update when invisible.
|
||||
if (!contextMenuVisible()) {
|
||||
updateContextMenu();
|
||||
}
|
||||
#else
|
||||
if (updateWhileVisible() && contextMenuVisible())
|
||||
updateContextMenu();
|
||||
#endif
|
||||
|
||||
// If no update was done here, we might update it on-demand due to
|
||||
// the aboutToShow() signal.
|
||||
}
|
||||
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg)
|
||||
@@ -724,7 +838,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo&
|
||||
|
||||
// Update the "Recent" menu if the context menu is being shown,
|
||||
// otherwise it'll be updated later, when the context menu is opened.
|
||||
if (_contextMenu && _contextMenu->isVisible()) {
|
||||
if (updateWhileVisible() && contextMenuVisible()) {
|
||||
slotRebuildRecentMenus();
|
||||
}
|
||||
}
|
||||
|
||||
+14
-1
@@ -24,6 +24,7 @@
|
||||
#include <QMenu>
|
||||
#include <QSignalMapper>
|
||||
#include <QSize>
|
||||
#include <QTimer>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
@@ -52,12 +53,18 @@ public:
|
||||
static QSize settingsDialogSize() { return QSize(800, 500); }
|
||||
void setupOverlayIcons();
|
||||
|
||||
/// Whether the tray menu is visible
|
||||
bool contextMenuVisible() const;
|
||||
|
||||
signals:
|
||||
void setupProxy();
|
||||
|
||||
public slots:
|
||||
void setupContextMenu();
|
||||
void setupContextMenuIfVisible();
|
||||
void updateContextMenu();
|
||||
void updateContextMenuNeeded();
|
||||
void slotContextMenuAboutToShow();
|
||||
void slotContextMenuAboutToHide();
|
||||
void slotComputeOverallSyncStatus();
|
||||
void slotShowTrayMessage(const QString &title, const QString &msg);
|
||||
void slotShowOptionalTrayMessage(const QString &title, const QString &msg);
|
||||
@@ -102,9 +109,15 @@ private:
|
||||
QPointer<LogBrowser>_logBrowser;
|
||||
// tray's menu
|
||||
QScopedPointer<QMenu> _contextMenu;
|
||||
|
||||
// Manually tracking whether the context menu is visible, but only works
|
||||
// on OSX because aboutToHide is not reliable everywhere.
|
||||
bool _contextMenuVisibleOsx;
|
||||
|
||||
QMenu *_recentActionsMenu;
|
||||
QVector<QMenu*> _accountMenus;
|
||||
bool _qdbusmenuWorkaround;
|
||||
QTimer _workaroundBatchTrayUpdate;
|
||||
QMap<QString, QPointer<ShareDialog> > _shareDialogs;
|
||||
|
||||
QAction *_actionLogin;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "networkjobs.h"
|
||||
#include "sslerrordialog.h"
|
||||
#include "accountmanager.h"
|
||||
#include "clientproxy.h"
|
||||
|
||||
#include "creds/credentialsfactory.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
@@ -128,7 +129,38 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
|
||||
account->setUrl(url);
|
||||
// Reset the proxy which might had been determined previously in ConnectionValidator::checkServerAndAuth()
|
||||
// when there was a previous account.
|
||||
account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::DefaultProxy));
|
||||
account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::NoProxy));
|
||||
|
||||
// Lookup system proxy in a thread https://github.com/owncloud/client/issues/2993
|
||||
if (ClientProxy::isUsingSystemDefault()) {
|
||||
qDebug() << "Trying to look up system proxy";
|
||||
ClientProxy::lookupSystemProxyAsync(account->url(),
|
||||
this, SLOT(slotSystemProxyLookupDone(QNetworkProxy)));
|
||||
} else {
|
||||
// We want to reset the QNAM proxy so that the global proxy settings are used (via ClientProxy settings)
|
||||
account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::DefaultProxy));
|
||||
// use a queued invocation so we're as asynchronous as with the other code path
|
||||
QMetaObject::invokeMethod(this, "slotContinueDetermineAuth", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void OwncloudSetupWizard::slotSystemProxyLookupDone(const QNetworkProxy &proxy)
|
||||
{
|
||||
if (proxy.type() != QNetworkProxy::NoProxy) {
|
||||
qDebug() << "Setting QNAM proxy to be system proxy" << printQNetworkProxy(proxy);
|
||||
} else {
|
||||
qDebug() << "No system proxy set by OS";
|
||||
}
|
||||
AccountPtr account = _ocWizard->account();
|
||||
account->networkAccessManager()->setProxy(proxy);
|
||||
|
||||
slotContinueDetermineAuth();
|
||||
}
|
||||
|
||||
void OwncloudSetupWizard::slotContinueDetermineAuth()
|
||||
{
|
||||
AccountPtr account = _ocWizard->account();
|
||||
|
||||
// Set fake credentials before we check what credential it actually is.
|
||||
account->setCredentials(CredentialsFactory::create("dummy"));
|
||||
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this);
|
||||
@@ -136,7 +168,7 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
|
||||
connect(job, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotOwnCloudFoundAuth(QUrl,QVariantMap)));
|
||||
connect(job, SIGNAL(instanceNotFound(QNetworkReply*)), SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*)));
|
||||
connect(job, SIGNAL(timeout(const QUrl&)), SLOT(slotNoOwnCloudFoundAuthTimeout(const QUrl&)));
|
||||
job->setTimeout(10*1000);
|
||||
job->setTimeout((account->url().scheme() == "https") ? 30*1000 : 10*1000);
|
||||
job->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ signals:
|
||||
|
||||
private slots:
|
||||
void slotDetermineAuthType(const QString&);
|
||||
void slotSystemProxyLookupDone(const QNetworkProxy &proxy);
|
||||
void slotContinueDetermineAuth();
|
||||
void slotOwnCloudFoundAuth(const QUrl&, const QVariantMap&);
|
||||
void slotNoOwnCloudFoundAuth(QNetworkReply *reply);
|
||||
void slotNoOwnCloudFoundAuthTimeout(const QUrl&url);
|
||||
|
||||
@@ -46,6 +46,7 @@ ShareDialog::ShareDialog(QPointer<AccountState> accountState,
|
||||
_userGroupWidget(NULL),
|
||||
_progressIndicator(NULL)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setObjectName("SharingDialog"); // required as group for saveGeometry call
|
||||
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
#include "account.h"
|
||||
#include "capabilities.h"
|
||||
|
||||
#include "share.h"
|
||||
#include "sharemanager.h"
|
||||
|
||||
#include "QProgressIndicator.h"
|
||||
#include <QBuffer>
|
||||
#include <QClipboard>
|
||||
#include <QFileInfo>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
@@ -490,13 +491,20 @@ void ShareLinkWidget::slotPushButtonMailLinkPressed()
|
||||
{
|
||||
QString fileName = _sharePath.mid(_sharePath.lastIndexOf('/') + 1);
|
||||
|
||||
QDesktopServices::openUrl(QUrl(QString(
|
||||
"mailto: "
|
||||
"?subject=I shared %1 with you"
|
||||
"&body=%2").arg(
|
||||
fileName,
|
||||
_shareUrl),
|
||||
QUrl::TolerantMode));
|
||||
if (!QDesktopServices::openUrl(QUrl(QString(
|
||||
"mailto: "
|
||||
"?subject=I shared %1 with you"
|
||||
"&body=%2").arg(
|
||||
fileName,
|
||||
_shareUrl),
|
||||
QUrl::TolerantMode))) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Could not open email client"),
|
||||
tr("There was an error when launching the email client to "
|
||||
"create a new message. Maybe no default email client is "
|
||||
"configured?"));
|
||||
}
|
||||
}
|
||||
|
||||
void ShareLinkWidget::slotCheckBoxEditingClicked()
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "share.h"
|
||||
#include "sharemanager.h"
|
||||
#include "ocssharejob.h"
|
||||
#include "account.h"
|
||||
|
||||
@@ -30,9 +30,9 @@ Q_DECLARE_METATYPE(CreateShare)
|
||||
|
||||
namespace OCC {
|
||||
|
||||
Share::Share(AccountPtr account,
|
||||
const QString& id,
|
||||
const QString& path,
|
||||
Share::Share(AccountPtr account,
|
||||
const QString& id,
|
||||
const QString& path,
|
||||
const ShareType shareType,
|
||||
const Permissions permissions,
|
||||
const QSharedPointer<Sharee> shareWith)
|
||||
@@ -100,7 +100,7 @@ void Share::slotDeleted()
|
||||
|
||||
void Share::slotOcsError(int statusCode, const QString &message)
|
||||
{
|
||||
emit serverError(statusCode, message);
|
||||
emit serverError(statusCode, message);
|
||||
}
|
||||
|
||||
QUrl LinkShare::getLink() const
|
||||
@@ -229,7 +229,7 @@ void ShareManager::slotLinkShareCreated(const QVariantMap &reply)
|
||||
if (code == 403) {
|
||||
emit linkShareRequiresPassword(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Parse share
|
||||
auto data = reply.value("ocs").toMap().value("data").toMap();
|
||||
@@ -329,7 +329,7 @@ void ShareManager::slotSharesFetched(const QVariantMap &reply)
|
||||
newShare = parseShare(data);
|
||||
}
|
||||
|
||||
shares.append(QSharedPointer<Share>(newShare));
|
||||
shares.append(QSharedPointer<Share>(newShare));
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Sending " << shares.count() << "shares";
|
||||
@@ -371,7 +371,7 @@ QSharedPointer<Share> ShareManager::parseShare(const QVariantMap &data)
|
||||
QSharedPointer<Sharee> sharee(new Sharee(data.value("share_with").toString(),
|
||||
data.value("share_with_displayname").toString(),
|
||||
(Sharee::Type)data.value("share_type").toInt()));
|
||||
|
||||
|
||||
return QSharedPointer<Share>(new Share(_account,
|
||||
data.value("id").toString(),
|
||||
data.value("path").toString(),
|
||||
@@ -11,8 +11,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHARE_H
|
||||
#define SHARE_H
|
||||
#ifndef SHAREMANAGER_H
|
||||
#define SHAREMANAGER_H
|
||||
|
||||
#include "accountfwd.h"
|
||||
#include "sharee.h"
|
||||
@@ -127,7 +127,7 @@ private slots:
|
||||
class LinkShare : public Share {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
explicit LinkShare(AccountPtr account,
|
||||
const QString& id,
|
||||
const QString& path,
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
* In case of a server error the serverError signal is emitted.
|
||||
*/
|
||||
void setPublicUpload(bool publicUpload);
|
||||
|
||||
|
||||
/*
|
||||
* Set the password
|
||||
*
|
||||
@@ -276,7 +276,6 @@ private:
|
||||
AccountPtr _account;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // SHARE_H
|
||||
#endif // SHAREMANAGER_H
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "capabilities.h"
|
||||
|
||||
#include "thumbnailjob.h"
|
||||
#include "share.h"
|
||||
#include "sharee.h"
|
||||
#include "sharemanager.h"
|
||||
|
||||
#include "QProgressIndicator.h"
|
||||
#include <QBuffer>
|
||||
|
||||
@@ -267,6 +267,12 @@
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rSelectiveSync">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
project(libsync)
|
||||
set(CMAKE_AUTOMOC TRUE)
|
||||
include(GenerateExportHeader)
|
||||
|
||||
configure_file( version.h.in "${CMAKE_CURRENT_BINARY_DIR}/version.h" )
|
||||
|
||||
|
||||
@@ -129,7 +129,6 @@ SystemProxyRunnable::SystemProxyRunnable(const QUrl &url) : QObject(), QRunnable
|
||||
|
||||
void SystemProxyRunnable::run()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Starting system proxy lookup";
|
||||
qRegisterMetaType<QNetworkProxy>("QNetworkProxy");
|
||||
QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery(QNetworkProxyQuery(_url));
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
QUrl _url;
|
||||
};
|
||||
|
||||
QString printQNetworkProxy(const QNetworkProxy &proxy);
|
||||
OWNCLOUDSYNC_EXPORT QString printQNetworkProxy(const QNetworkProxy &proxy);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -611,7 +611,12 @@ void ConfigFile::setPromptDeleteFiles(bool promptDeleteFiles)
|
||||
bool ConfigFile::monoIcons() const
|
||||
{
|
||||
QSettings settings(configFile(), QSettings::IniFormat);
|
||||
return settings.value(QLatin1String(monoIconsC), false).toBool();
|
||||
bool monoDefault = false; // On Mac we want bw by default
|
||||
#ifdef Q_OS_MAC
|
||||
// OEM themes are not obliged to ship mono icons
|
||||
monoDefault = (0 == (strcmp("ownCloud",APPLICATION_NAME)));
|
||||
#endif
|
||||
return settings.value(QLatin1String(monoIconsC), monoDefault).toBool();
|
||||
}
|
||||
|
||||
void ConfigFile::setMonoIcons(bool useMonoIcons)
|
||||
|
||||
@@ -106,7 +106,7 @@ void ConnectionValidator::slotCheckServerAndAuth()
|
||||
checkJob->setTimeout(timeoutToUseMsec);
|
||||
checkJob->setIgnoreCredentialFailure(true);
|
||||
connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap)));
|
||||
connect(checkJob, SIGNAL(networkError(QNetworkReply*)), SLOT(slotNoStatusFound(QNetworkReply*)));
|
||||
connect(checkJob, SIGNAL(instanceNotFound(QNetworkReply*)), SLOT(slotNoStatusFound(QNetworkReply*)));
|
||||
connect(checkJob, SIGNAL(timeout(QUrl)), SLOT(slotJobTimeout(QUrl)));
|
||||
checkJob->start();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "discoveryphase.h"
|
||||
#include <csync_private.h>
|
||||
#include <csync_rename.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
#include <QUrl>
|
||||
@@ -51,7 +52,7 @@ static bool findPathInList(const QStringList &list, const QString &path)
|
||||
return pathSlash.startsWith(*it);
|
||||
}
|
||||
|
||||
bool DiscoveryJob::isInSelectiveSyncBlackList(const QString& path) const
|
||||
bool DiscoveryJob::isInSelectiveSyncBlackList(const char *path) const
|
||||
{
|
||||
if (_selectiveSyncBlackList.isEmpty()) {
|
||||
// If there is no black list, everything is allowed
|
||||
@@ -59,13 +60,25 @@ bool DiscoveryJob::isInSelectiveSyncBlackList(const QString& path) const
|
||||
}
|
||||
|
||||
// Block if it is in the black list
|
||||
return findPathInList(_selectiveSyncBlackList, path);
|
||||
if (findPathInList(_selectiveSyncBlackList, QString::fromUtf8(path))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Also try to adjust the path if there was renames
|
||||
if (csync_rename_count(_csync_ctx)) {
|
||||
QScopedPointer<char, QScopedPointerPodDeleter> adjusted(
|
||||
csync_rename_adjust_path_source(_csync_ctx, path));
|
||||
if (strcmp(adjusted.data(), path) != 0) {
|
||||
return findPathInList(_selectiveSyncBlackList, QString::fromUtf8(adjusted.data()));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int DiscoveryJob::isInSelectiveSyncBlackListCallback(void *data, const char *path)
|
||||
{
|
||||
return static_cast<DiscoveryJob*>(data)->isInSelectiveSyncBlackList(QString::fromUtf8(path));
|
||||
return static_cast<DiscoveryJob*>(data)->isInSelectiveSyncBlackList(path);
|
||||
}
|
||||
|
||||
bool DiscoveryJob::checkSelectiveSyncNewFolder(const QString& path)
|
||||
@@ -192,7 +205,8 @@ int get_errno_from_http_errcode( int err, const QString & reason ) {
|
||||
new_errno = EIO;
|
||||
break;
|
||||
case 503: /* Service Unavailable */
|
||||
if (reason == "Storage not available") {
|
||||
// https://github.com/owncloud/core/pull/26145/files
|
||||
if (reason == "Storage not available" || reason == "Storage is temporarily not available") {
|
||||
new_errno = ERRNO_STORAGE_UNAVAILABLE;
|
||||
} else {
|
||||
new_errno = ERRNO_SERVICE_UNAVAILABLE;
|
||||
|
||||
@@ -174,7 +174,7 @@ class DiscoveryJob : public QObject {
|
||||
* return true if the given path should be ignored,
|
||||
* false if the path should be synced
|
||||
*/
|
||||
bool isInSelectiveSyncBlackList(const QString &path) const;
|
||||
bool isInSelectiveSyncBlackList(const char* path) const;
|
||||
static int isInSelectiveSyncBlackListCallback(void *, const char *);
|
||||
bool checkSelectiveSyncNewFolder(const QString &path);
|
||||
static int checkSelectiveSyncNewFolderCallback(void*, const char*);
|
||||
|
||||
@@ -76,13 +76,22 @@ bool ExcludedFiles::isExcluded(
|
||||
return true;
|
||||
}
|
||||
|
||||
QFileInfo fi(filePath);
|
||||
if( excludeHidden ) {
|
||||
if( fi.isHidden() || fi.fileName().startsWith(QLatin1Char('.')) ) {
|
||||
return true;
|
||||
QString path = filePath;
|
||||
// Check all path subcomponents, but to *not* check the base path:
|
||||
// We do want to be able to sync with a hidden folder as the target.
|
||||
while (path.size() > basePath.size()) {
|
||||
QFileInfo fi(path);
|
||||
if( fi.isHidden() || fi.fileName().startsWith(QLatin1Char('.')) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the parent path
|
||||
path = fi.absolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
QFileInfo fi(filePath);
|
||||
csync_ftw_type_e type = CSYNC_FTW_TYPE_FILE;
|
||||
if (fi.isDir()) {
|
||||
type = CSYNC_FTW_TYPE_DIR;
|
||||
|
||||
@@ -29,10 +29,11 @@
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
// We use some internals of csync:
|
||||
|
||||
@@ -384,6 +384,8 @@ void OwncloudPropagator::start(const SyncFileItemVector& items)
|
||||
// will delete directories, so defer execution
|
||||
directoriesToRemove.prepend(current);
|
||||
removedDirectory = item->_file + "/";
|
||||
} else if (item->_instruction == CSYNC_INSTRUCTION_NEW || item->_instruction == CSYNC_INSTRUCTION_SYNC){
|
||||
directories.top().second->appendSyncJob(current);
|
||||
} else {
|
||||
directories.top().second->append(current);
|
||||
}
|
||||
@@ -529,7 +531,7 @@ void OwncloudPropagator::scheduleNextJob()
|
||||
}
|
||||
}
|
||||
if (_activeJobList.count() < maximumActiveJob() + likelyFinishedQuicklyCount) {
|
||||
qDebug() << "Can pump in another request!";
|
||||
qDebug() << "Can pump in another request! activeJobs =" << _activeJobList.count();
|
||||
if (_rootJob->scheduleNextJob()) {
|
||||
QTimer::singleShot(0, this, SLOT(scheduleNextJob()));
|
||||
}
|
||||
@@ -593,7 +595,11 @@ bool PropagateDirectory::scheduleNextJob()
|
||||
_state = Running;
|
||||
|
||||
if (!_firstJob && _subJobs.isEmpty()) {
|
||||
finalize();
|
||||
if (!_scheduledSyncJobs && _syncJobsScheduler) {
|
||||
scheduleSyncJobs();
|
||||
} else {
|
||||
finalize();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -657,17 +663,34 @@ void PropagateDirectory::slotSubJobFinished(SyncFileItem::Status status)
|
||||
// check if we finished
|
||||
if (_jobsFinished >= totalJobs) {
|
||||
Q_ASSERT(!_runningNow); // how can we be finished if there are still jobs running now
|
||||
finalize();
|
||||
if (!_scheduledSyncJobs && _syncJobsScheduler) {
|
||||
scheduleSyncJobs();
|
||||
} else {
|
||||
finalize();
|
||||
}
|
||||
} else {
|
||||
emit ready();
|
||||
}
|
||||
}
|
||||
|
||||
void PropagateDirectory::scheduleSyncJobs() {
|
||||
_scheduledSyncJobs = true;
|
||||
//at this point, scheduler will be destroyed together with _subJobs
|
||||
_subJobs.append(_syncJobsScheduler.data());
|
||||
emit ready();
|
||||
}
|
||||
|
||||
void PropagateDirectory::finalize()
|
||||
{
|
||||
bool ok = true;
|
||||
if (!_item->isEmpty() && _hasError == SyncFileItem::NoStatus) {
|
||||
if( !_item->_renameTarget.isEmpty() ) {
|
||||
if(_item->_instruction == CSYNC_INSTRUCTION_RENAME
|
||||
&& _item->_originalFile != _item->_renameTarget) {
|
||||
// Remove the stale entries from the database.
|
||||
_propagator->_journal->deleteFileRecord(_item->_originalFile, true);
|
||||
}
|
||||
|
||||
_item->_file = _item->_renameTarget;
|
||||
}
|
||||
|
||||
@@ -686,14 +709,14 @@ void PropagateDirectory::finalize()
|
||||
SyncJournalFileRecord record(*_item, _propagator->_localDir + _item->_file);
|
||||
ok = _propagator->_journal->setFileRecordMetadata(record);
|
||||
if (!ok) {
|
||||
_item->_status = SyncFileItem::FatalError;
|
||||
_hasError = _item->_status = SyncFileItem::FatalError;
|
||||
_item->_errorString = tr("Error writing metadata to the database");
|
||||
qWarning() << "Error writing to the database for file" << _item->_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
_state = Finished;
|
||||
emit finished(_item->_status);
|
||||
emit finished(_hasError == SyncFileItem::NoStatus ? SyncFileItem::Success : _hasError);
|
||||
}
|
||||
|
||||
qint64 PropagateDirectory::committedDiskSpace() const
|
||||
@@ -705,6 +728,80 @@ qint64 PropagateDirectory::committedDiskSpace() const
|
||||
return needed;
|
||||
}
|
||||
|
||||
// ================================================================================
|
||||
|
||||
PropagatorJob::JobParallelism PropagateSyncItems::parallelism()
|
||||
{
|
||||
return FullParallelism;
|
||||
}
|
||||
|
||||
|
||||
bool PropagateSyncItems::scheduleNextJob()
|
||||
{
|
||||
if (_state == Finished) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_state == NotYetStarted) {
|
||||
_state = Running;
|
||||
|
||||
if (_syncJobs.isEmpty()) {
|
||||
finalize();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
while (!_syncJobs.isEmpty()) {
|
||||
PropagatorJob *next = _syncJobs.takeFirst();
|
||||
if (next->_state == Finished) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (possiblyRunNextJob(next)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Q_ASSERT(next->_state == Running);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PropagateSyncItems::slotSubJobFinished(SyncFileItem::Status status)
|
||||
{
|
||||
if (status == SyncFileItem::FatalError) {
|
||||
abort();
|
||||
_hasError = status;
|
||||
finalize();
|
||||
return;
|
||||
} else if (status == SyncFileItem::NormalError || status == SyncFileItem::SoftError) {
|
||||
_hasError = status;
|
||||
}
|
||||
|
||||
_jobsFinished++;
|
||||
// We finished processing all the jobs
|
||||
// check if we finished
|
||||
if (_syncJobs.isEmpty() && (_syncJobsCount == _jobsFinished)) {
|
||||
finalize();
|
||||
} else {
|
||||
emit ready();
|
||||
}
|
||||
}
|
||||
|
||||
void PropagateSyncItems::finalize()
|
||||
{
|
||||
_state = Finished;
|
||||
emit finished(_hasError == SyncFileItem::NoStatus ? SyncFileItem::Success : _hasError);
|
||||
}
|
||||
|
||||
qint64 PropagateSyncItems::committedDiskSpace() const
|
||||
{
|
||||
qint64 needed = 0;
|
||||
foreach (PropagatorJob* job, _syncJobs) {
|
||||
needed += job->committedDiskSpace();
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
|
||||
CleanupPollsJob::~CleanupPollsJob()
|
||||
{}
|
||||
|
||||
|
||||
@@ -176,6 +176,59 @@ public slots:
|
||||
virtual void start() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Propagate sync items within a specific folder, and all its sub entries.
|
||||
* @ingroup libsync
|
||||
*/
|
||||
class PropagateSyncItems : public PropagatorJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// all the sub files or sub directories.
|
||||
QList<PropagatorJob *> _syncJobs;
|
||||
|
||||
int _jobsFinished; // number of jobs that have completed
|
||||
int _syncJobsCount; // number of subJobs running right now
|
||||
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
|
||||
|
||||
PropagateSyncItems(OwncloudPropagator *propagator)
|
||||
: PropagatorJob(propagator)
|
||||
, _jobsFinished(0), _syncJobsCount(0), _hasError(SyncFileItem::NoStatus)
|
||||
{ }
|
||||
|
||||
virtual ~PropagateSyncItems() {
|
||||
qDeleteAll(_syncJobs);
|
||||
}
|
||||
|
||||
void append(PropagatorJob *subJob) {
|
||||
_syncJobs.append(subJob);
|
||||
_syncJobsCount++;
|
||||
}
|
||||
|
||||
virtual bool scheduleNextJob() Q_DECL_OVERRIDE;
|
||||
virtual JobParallelism parallelism() Q_DECL_OVERRIDE;
|
||||
virtual void abort() Q_DECL_OVERRIDE {
|
||||
foreach (PropagatorJob *j, _syncJobs)
|
||||
j->abort();
|
||||
}
|
||||
|
||||
void finalize();
|
||||
|
||||
qint64 committedDiskSpace() const Q_DECL_OVERRIDE;
|
||||
|
||||
private slots:
|
||||
bool possiblyRunNextJob(PropagatorJob *next) {
|
||||
if (next->_state == NotYetStarted) {
|
||||
connect(next, SIGNAL(finished(SyncFileItem::Status)), this, SLOT(slotSubJobFinished(SyncFileItem::Status)), Qt::QueuedConnection);
|
||||
connect(next, SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
|
||||
this, SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)));
|
||||
connect(next, SIGNAL(progress(const SyncFileItem &,quint64)), this, SIGNAL(progress(const SyncFileItem &,quint64)));
|
||||
connect(next, SIGNAL(ready()), this, SIGNAL(ready()));
|
||||
}
|
||||
return next->scheduleNextJob();
|
||||
}
|
||||
|
||||
void slotSubJobFinished(SyncFileItem::Status status);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Propagate a directory, and all its sub entries.
|
||||
@@ -187,7 +240,12 @@ public:
|
||||
// e.g: create the directory
|
||||
QScopedPointer<PropagateItemJob>_firstJob;
|
||||
|
||||
// all the sub files or sub directories.
|
||||
// all the new and changed files without conflicts scheduler class
|
||||
// remark: do not QScopedPointer, since this class is either deleted via qDeleteAll(_subJobs) or usual delete,
|
||||
// depending on ownership determined by flag _scheduledSyncJobs
|
||||
QPointer<PropagateSyncItems> _syncJobsScheduler;
|
||||
|
||||
// all the other file operation or sub directories.
|
||||
QVector<PropagatorJob *> _subJobs;
|
||||
|
||||
SyncFileItemPtr _item;
|
||||
@@ -195,13 +253,18 @@ public:
|
||||
int _jobsFinished; // number of jobs that have completed
|
||||
int _runningNow; // number of subJobs running right now
|
||||
SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error
|
||||
bool _scheduledSyncJobs; // verify if already scheduled execution of files sync jobs
|
||||
|
||||
explicit PropagateDirectory(OwncloudPropagator *propagator, const SyncFileItemPtr &item = SyncFileItemPtr(new SyncFileItem))
|
||||
: PropagatorJob(propagator)
|
||||
, _firstJob(0), _item(item), _jobsFinished(0), _runningNow(0), _hasError(SyncFileItem::NoStatus)
|
||||
, _firstJob(0), _syncJobsScheduler(0), _item(item), _jobsFinished(0), _runningNow(0), _hasError(SyncFileItem::NoStatus), _scheduledSyncJobs(false)
|
||||
{ }
|
||||
|
||||
virtual ~PropagateDirectory() {
|
||||
// check whether the owner of the pointer is _subJobs or PropagateDirectory class
|
||||
if (!_scheduledSyncJobs){
|
||||
delete _syncJobsScheduler;
|
||||
}
|
||||
qDeleteAll(_subJobs);
|
||||
}
|
||||
|
||||
@@ -209,11 +272,20 @@ public:
|
||||
_subJobs.append(subJob);
|
||||
}
|
||||
|
||||
void appendSyncJob(PropagatorJob *subJob) {
|
||||
if (!_syncJobsScheduler) {
|
||||
_syncJobsScheduler = new PropagateSyncItems(_propagator);
|
||||
}
|
||||
_syncJobsScheduler->append(subJob);
|
||||
}
|
||||
|
||||
virtual bool scheduleNextJob() Q_DECL_OVERRIDE;
|
||||
virtual JobParallelism parallelism() Q_DECL_OVERRIDE;
|
||||
virtual void abort() Q_DECL_OVERRIDE {
|
||||
if (_firstJob)
|
||||
_firstJob->abort();
|
||||
if (_syncJobsScheduler)
|
||||
_syncJobsScheduler->abort();
|
||||
foreach (PropagatorJob *j, _subJobs)
|
||||
j->abort();
|
||||
}
|
||||
@@ -224,6 +296,8 @@ public:
|
||||
|
||||
void finalize();
|
||||
|
||||
void scheduleSyncJobs();
|
||||
|
||||
qint64 committedDiskSpace() const Q_DECL_OVERRIDE;
|
||||
|
||||
private slots:
|
||||
@@ -242,7 +316,6 @@ private slots:
|
||||
void slotSubJobFinished(SyncFileItem::Status status);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Dummy job that just mark it as completed and ignored
|
||||
* @ingroup libsync
|
||||
|
||||
@@ -49,8 +49,8 @@ QString ownCloudTheme::about() const
|
||||
"Olivier Goffart, Markus Götz and others.</small></p>"
|
||||
"<p>Copyright ownCloud GmbH</p>"
|
||||
"<p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>"
|
||||
"ownCloud and the ownCloud Logo are registered trademarks of ownCloud, "
|
||||
"Inc. in the United States, other countries, or both.</p>"
|
||||
"ownCloud and the ownCloud Logo are registered trademarks of ownCloud GmbH "
|
||||
"in the United States, other countries, or both.</p>"
|
||||
)
|
||||
.arg(MIRALL_VERSION_STRING)
|
||||
.arg("https://" MIRALL_STRINGIFY(APPLICATION_DOMAIN))
|
||||
|
||||
@@ -230,8 +230,12 @@ bool SqlQuery::isPragma()
|
||||
|
||||
bool SqlQuery::exec()
|
||||
{
|
||||
if (!_stmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't do anything for selects, that is how we use the lib :-|
|
||||
if(_stmt && !isSelect() && !isPragma() ) {
|
||||
if( !isSelect() && !isPragma() ) {
|
||||
int rc, n = 0;
|
||||
do {
|
||||
rc = sqlite3_step(_stmt);
|
||||
@@ -376,8 +380,10 @@ void SqlQuery::finish()
|
||||
|
||||
void SqlQuery::reset_and_clear_bindings()
|
||||
{
|
||||
SQLITE_DO(sqlite3_reset(_stmt));
|
||||
SQLITE_DO(sqlite3_clear_bindings(_stmt));
|
||||
if (_stmt) {
|
||||
SQLITE_DO(sqlite3_reset(_stmt));
|
||||
SQLITE_DO(sqlite3_clear_bindings(_stmt));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -147,6 +147,7 @@ void ProgressInfo::reset()
|
||||
_maxBytesPerSecond = 100000.0;
|
||||
_maxFilesPerSecond = 2.0;
|
||||
_updateEstimatesTimer.stop();
|
||||
_lastCompletedItem = SyncFileItem();
|
||||
}
|
||||
|
||||
void ProgressInfo::startEstimateUpdates()
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include <QDebug>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace OCC {
|
||||
|
||||
// Always coming in with forward slashes.
|
||||
@@ -616,30 +620,47 @@ static QString makeRecallFileName(const QString &fn)
|
||||
return recallFileName;
|
||||
}
|
||||
|
||||
static void handleRecallFile(const QString &fn)
|
||||
void handleRecallFile(const QString& filePath, const QString& folderPath, SyncJournalDb& journal)
|
||||
{
|
||||
qDebug() << "handleRecallFile: " << fn;
|
||||
qDebug() << "handleRecallFile: " << filePath;
|
||||
|
||||
FileSystem::setFileHidden(fn, true);
|
||||
FileSystem::setFileHidden(filePath, true);
|
||||
|
||||
QFile file(fn);
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Could not open recall file" << file.errorString();
|
||||
return;
|
||||
}
|
||||
QFileInfo existingFile(fn);
|
||||
QDir thisDir = existingFile.dir();
|
||||
QFileInfo existingFile(filePath);
|
||||
QDir baseDir = existingFile.dir();
|
||||
|
||||
while (!file.atEnd()) {
|
||||
QByteArray line = file.readLine();
|
||||
line.chop(1); // remove trailing \n
|
||||
QString fpath = thisDir.filePath(line);
|
||||
QString rpath = makeRecallFileName(fpath);
|
||||
|
||||
qDebug() << "Copy recall file: " << fpath << " -> " << rpath;
|
||||
QString recalledFile = QDir::cleanPath(baseDir.filePath(line));
|
||||
if (!recalledFile.startsWith(folderPath) || !recalledFile.startsWith(baseDir.path())) {
|
||||
qDebug() << "Ignoring recall of " << recalledFile;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Path of the recalled file in the local folder
|
||||
QString localRecalledFile = recalledFile.mid(folderPath.size());
|
||||
|
||||
SyncJournalFileRecord record = journal.getFileRecord(localRecalledFile);
|
||||
if (!record.isValid()) {
|
||||
qDebug() << "No db entry for recall of" << localRecalledFile;
|
||||
continue;
|
||||
}
|
||||
|
||||
qDebug() << "Recalling" << localRecalledFile << "Checksum:" << record._contentChecksumType << record._contentChecksum;
|
||||
|
||||
QString targetPath = makeRecallFileName(recalledFile);
|
||||
|
||||
qDebug() << "Copy recall file: " << recalledFile << " -> " << targetPath;
|
||||
// Remove the target first, QFile::copy will not overwrite it.
|
||||
FileSystem::remove(rpath);
|
||||
QFile::copy(fpath, rpath);
|
||||
FileSystem::remove(targetPath);
|
||||
QFile::copy(recalledFile, targetPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,8 +817,10 @@ void PropagateDownloadFile::downloadFinished()
|
||||
done(isConflict ? SyncFileItem::Conflict : SyncFileItem::Success);
|
||||
|
||||
// handle the special recall file
|
||||
if(_item->_file == QLatin1String(".sys.admin#recall#") || _item->_file.endsWith("/.sys.admin#recall#")) {
|
||||
handleRecallFile(fn);
|
||||
if(!_item->_remotePerm.contains("S")
|
||||
&& (_item->_file == QLatin1String(".sys.admin#recall#")
|
||||
|| _item->_file.endsWith("/.sys.admin#recall#"))) {
|
||||
handleRecallFile(fn, _propagator->_localDir, *_propagator->_journal);
|
||||
}
|
||||
|
||||
qint64 duration = _stopwatch.elapsed();
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "propagateremotemove.h"
|
||||
#include "propagatorjobs.h"
|
||||
#include "owncloudpropagator_p.h"
|
||||
#include "account.h"
|
||||
#include "syncjournalfilerecord.h"
|
||||
@@ -175,10 +176,45 @@ void PropagateRemoteMove::finalize()
|
||||
done(SyncFileItem::FatalError, tr("Error writing metadata to the database"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_item->_isDirectory) {
|
||||
if (!adjustSelectiveSync(_propagator->_journal, _item->_file, _item->_renameTarget)) {
|
||||
done(SyncFileItem::FatalError, tr("Error writing metadata to the database"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_propagator->_journal->commit("Remote Rename");
|
||||
done(SyncFileItem::Success);
|
||||
}
|
||||
|
||||
bool PropagateRemoteMove::adjustSelectiveSync(SyncJournalDb *journal, const QString &from_, const QString &to_)
|
||||
{
|
||||
bool ok;
|
||||
// We only care about preserving the blacklist. The white list should anyway be empty.
|
||||
// And the undecided list will be repopulated on the next sync, if there is anything too big.
|
||||
QStringList list = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
Q_ASSERT(!from_.endsWith(QLatin1String("/")));
|
||||
Q_ASSERT(!to_.endsWith(QLatin1String("/")));
|
||||
QString from = from_ + QLatin1String("/");
|
||||
QString to = to_ + QLatin1String("/");
|
||||
|
||||
for (auto it = list.begin(); it != list.end(); ++it) {
|
||||
if (it->startsWith(from)) {
|
||||
*it = it->replace(0, from.size(), to);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
journal->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, list);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,12 @@ public:
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
void abort() Q_DECL_OVERRIDE;
|
||||
JobParallelism parallelism() Q_DECL_OVERRIDE { return OCC::PropagatorJob::WaitForFinishedInParentDirectory; }
|
||||
|
||||
/**
|
||||
* Rename the directory in the selective sync list
|
||||
*/
|
||||
static bool adjustSelectiveSync(SyncJournalDb *journal, const QString &from, const QString &to);
|
||||
|
||||
private slots:
|
||||
void slotMoveJobFinished();
|
||||
void finalize();
|
||||
|
||||
@@ -195,6 +195,8 @@ public:
|
||||
: PropagateItemJob(propagator, item), _startChunk(0), _currentChunk(0), _chunkCount(0), _transferId(0), _finished(false), _deleteExisting(false) {}
|
||||
void start() Q_DECL_OVERRIDE;
|
||||
|
||||
bool isLikelyFinishedQuickly() Q_DECL_OVERRIDE { return _item->_size < 100*1024; }
|
||||
|
||||
/**
|
||||
* Whether an existing entity with the same name may be deleted before
|
||||
* the upload.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "propagatorjobs.h"
|
||||
#include "owncloudpropagator_p.h"
|
||||
|
||||
#include "propagateremotemove.h"
|
||||
#include "utility.h"
|
||||
#include "syncjournaldb.h"
|
||||
#include "syncjournalfilerecord.h"
|
||||
@@ -231,6 +231,7 @@ void PropagateLocalRename::start()
|
||||
_propagator->_journal->deleteFileRecord(_item->_originalFile);
|
||||
|
||||
// store the rename file name in the item.
|
||||
const auto oldFile = _item->_file;
|
||||
_item->_file = _item->_renameTarget;
|
||||
|
||||
SyncJournalFileRecord record(*_item, targetFile);
|
||||
@@ -245,9 +246,14 @@ void PropagateLocalRename::start()
|
||||
done(SyncFileItem::FatalError, tr("Error writing metadata to the database"));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!PropagateRemoteMove::adjustSelectiveSync(_propagator->_journal, oldFile, _item->_renameTarget)) {
|
||||
done(SyncFileItem::FatalError, tr("Error writing metadata to the database"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
_propagator->_journal->commit("localRename");
|
||||
|
||||
_propagator->_journal->commit("localRename");
|
||||
|
||||
done(SyncFileItem::Success);
|
||||
}
|
||||
|
||||
@@ -868,6 +868,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||
bool walkOk = true;
|
||||
_seenFiles.clear();
|
||||
_temporarilyUnavailablePaths.clear();
|
||||
_renamedFolders.clear();
|
||||
|
||||
if( csync_walk_local_tree(_csync_ctx, &treewalkLocal, 0) < 0 ) {
|
||||
qDebug() << "Error in local treewalk.";
|
||||
@@ -1162,7 +1163,7 @@ void SyncEngine::checkForPermission()
|
||||
qDebug() << "Moving of " << (*it)->_file << " canceled because no permission to add parent folder";
|
||||
}
|
||||
(*it)->_instruction = CSYNC_INSTRUCTION_ERROR;
|
||||
(*it)->_status = SyncFileItem::NormalError;
|
||||
(*it)->_status = SyncFileItem::SoftError;
|
||||
(*it)->_errorString = tr("Not allowed because you don't have permission to add parent folder");
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +202,6 @@ private:
|
||||
SyncJournalDb *_journal;
|
||||
QPointer<DiscoveryMainThread> _discoveryMainThread;
|
||||
QSharedPointer <OwncloudPropagator> _propagator;
|
||||
QString _lastDeleted; // if the last item was a path and it has been deleted
|
||||
|
||||
// After a sync, only the syncdb entries whose filenames appear in this
|
||||
// set will be kept. See _temporarilyUnavailablePaths.
|
||||
|
||||
@@ -318,7 +318,9 @@ bool SyncJournalDb::checkConnect()
|
||||
createQuery.bindValue(2, MIRALL_VERSION_MINOR);
|
||||
createQuery.bindValue(3, MIRALL_VERSION_PATCH);
|
||||
createQuery.bindValue(4, MIRALL_VERSION_BUILD);
|
||||
createQuery.exec();
|
||||
if (!createQuery.exec()) {
|
||||
return sqlFail("Update version", createQuery);
|
||||
}
|
||||
|
||||
} else {
|
||||
int major = versionQuery.intValue(0);
|
||||
@@ -329,6 +331,15 @@ bool SyncJournalDb::checkConnect()
|
||||
qDebug() << Q_FUNC_INFO << "possibleUpgradeFromMirall_1_8_0_or_1 detected!";
|
||||
forceRemoteDiscovery = true;
|
||||
}
|
||||
|
||||
// There was a bug in versions <2.3.0 that could lead to stale
|
||||
// local files and a remote discovery will fix them.
|
||||
// See #5190 #5242.
|
||||
if( major == 2 && minor < 3) {
|
||||
qDebug() << Q_FUNC_INFO << "upgrade form client < 2.3.0 detected! forcing remote discovery";
|
||||
forceRemoteDiscovery = true;
|
||||
}
|
||||
|
||||
// Not comparing the BUILD id here, correct?
|
||||
if( !(major == MIRALL_VERSION_MAJOR && minor == MIRALL_VERSION_MINOR && patch == MIRALL_VERSION_PATCH) ) {
|
||||
createQuery.prepare("UPDATE version SET major=?1, minor=?2, patch =?3, custom=?4 "
|
||||
@@ -367,60 +378,84 @@ bool SyncJournalDb::checkConnect()
|
||||
}
|
||||
|
||||
_getFileRecordQuery.reset(new SqlQuery(_db));
|
||||
_getFileRecordQuery->prepare(
|
||||
if (_getFileRecordQuery->prepare(
|
||||
"SELECT path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize,"
|
||||
" ignoredChildrenRemote, contentChecksum, contentchecksumtype.name"
|
||||
" FROM metadata"
|
||||
" LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"
|
||||
" WHERE phash=?1" );
|
||||
" WHERE phash=?1" )) {
|
||||
return sqlFail("prepare _getFileRecordQuery", *_getFileRecordQuery);
|
||||
}
|
||||
|
||||
_setFileRecordQuery.reset(new SqlQuery(_db) );
|
||||
_setFileRecordQuery->prepare("INSERT OR REPLACE INTO metadata "
|
||||
if (_setFileRecordQuery->prepare("INSERT OR REPLACE INTO metadata "
|
||||
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, contentChecksum, contentChecksumTypeId) "
|
||||
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16);" );
|
||||
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16);" )) {
|
||||
return sqlFail("prepare _setFileRecordQuery", *_setFileRecordQuery);
|
||||
}
|
||||
|
||||
_setFileRecordChecksumQuery.reset(new SqlQuery(_db) );
|
||||
_setFileRecordChecksumQuery->prepare(
|
||||
if (_setFileRecordChecksumQuery->prepare(
|
||||
"UPDATE metadata"
|
||||
" SET contentChecksum = ?2, contentChecksumTypeId = ?3"
|
||||
" WHERE phash == ?1;");
|
||||
" WHERE phash == ?1;")) {
|
||||
return sqlFail("prepare _setFileRecordChecksumQuery", *_setFileRecordChecksumQuery);
|
||||
}
|
||||
|
||||
_setFileRecordLocalMetadataQuery.reset(new SqlQuery(_db));
|
||||
_setFileRecordLocalMetadataQuery->prepare(
|
||||
if (_setFileRecordLocalMetadataQuery->prepare(
|
||||
"UPDATE metadata"
|
||||
" SET inode=?2, modtime=?3, filesize=?4"
|
||||
" WHERE phash == ?1;");
|
||||
" WHERE phash == ?1;")) {
|
||||
return sqlFail("prepare _setFileRecordLocalMetadataQuery", *_setFileRecordLocalMetadataQuery);
|
||||
}
|
||||
|
||||
_getDownloadInfoQuery.reset(new SqlQuery(_db) );
|
||||
_getDownloadInfoQuery->prepare( "SELECT tmpfile, etag, errorcount FROM "
|
||||
"downloadinfo WHERE path=?1" );
|
||||
if (_getDownloadInfoQuery->prepare( "SELECT tmpfile, etag, errorcount FROM "
|
||||
"downloadinfo WHERE path=?1" )) {
|
||||
return sqlFail("prepare _getDownloadInfoQuery", *_getDownloadInfoQuery);
|
||||
}
|
||||
|
||||
_setDownloadInfoQuery.reset(new SqlQuery(_db) );
|
||||
_setDownloadInfoQuery->prepare( "INSERT OR REPLACE INTO downloadinfo "
|
||||
if (_setDownloadInfoQuery->prepare( "INSERT OR REPLACE INTO downloadinfo "
|
||||
"(path, tmpfile, etag, errorcount) "
|
||||
"VALUES ( ?1 , ?2, ?3, ?4 )" );
|
||||
"VALUES ( ?1 , ?2, ?3, ?4 )" )) {
|
||||
return sqlFail("prepare _setDownloadInfoQuery", *_setDownloadInfoQuery);
|
||||
}
|
||||
|
||||
_deleteDownloadInfoQuery.reset(new SqlQuery(_db) );
|
||||
_deleteDownloadInfoQuery->prepare( "DELETE FROM downloadinfo WHERE path=?1" );
|
||||
if (_deleteDownloadInfoQuery->prepare( "DELETE FROM downloadinfo WHERE path=?1" )) {
|
||||
return sqlFail("prepare _deleteDownloadInfoQuery", *_deleteDownloadInfoQuery);
|
||||
}
|
||||
|
||||
_getUploadInfoQuery.reset(new SqlQuery(_db));
|
||||
_getUploadInfoQuery->prepare( "SELECT chunk, transferid, errorcount, size, modtime FROM "
|
||||
"uploadinfo WHERE path=?1" );
|
||||
if (_getUploadInfoQuery->prepare( "SELECT chunk, transferid, errorcount, size, modtime FROM "
|
||||
"uploadinfo WHERE path=?1" )) {
|
||||
return sqlFail("prepare _getUploadInfoQuery", *_getUploadInfoQuery);
|
||||
}
|
||||
|
||||
_setUploadInfoQuery.reset(new SqlQuery(_db));
|
||||
_setUploadInfoQuery->prepare( "INSERT OR REPLACE INTO uploadinfo "
|
||||
if (_setUploadInfoQuery->prepare( "INSERT OR REPLACE INTO uploadinfo "
|
||||
"(path, chunk, transferid, errorcount, size, modtime) "
|
||||
"VALUES ( ?1 , ?2, ?3 , ?4 , ?5, ?6 )");
|
||||
"VALUES ( ?1 , ?2, ?3 , ?4 , ?5, ?6 )")) {
|
||||
return sqlFail("prepare _setUploadInfoQuery", *_setUploadInfoQuery);
|
||||
}
|
||||
|
||||
_deleteUploadInfoQuery.reset(new SqlQuery(_db));
|
||||
_deleteUploadInfoQuery->prepare("DELETE FROM uploadinfo WHERE path=?1" );
|
||||
if (_deleteUploadInfoQuery->prepare("DELETE FROM uploadinfo WHERE path=?1" )) {
|
||||
return sqlFail("prepare _deleteUploadInfoQuery", *_deleteUploadInfoQuery);
|
||||
}
|
||||
|
||||
|
||||
_deleteFileRecordPhash.reset(new SqlQuery(_db));
|
||||
_deleteFileRecordPhash->prepare("DELETE FROM metadata WHERE phash=?1");
|
||||
if (_deleteFileRecordPhash->prepare("DELETE FROM metadata WHERE phash=?1")) {
|
||||
return sqlFail("prepare _deleteFileRecordPhash", *_deleteFileRecordPhash);
|
||||
}
|
||||
|
||||
_deleteFileRecordRecursively.reset(new SqlQuery(_db));
|
||||
_deleteFileRecordRecursively->prepare("DELETE FROM metadata WHERE path LIKE(?||'/%')");
|
||||
if (_deleteFileRecordRecursively->prepare("DELETE FROM metadata WHERE path LIKE(?||'/%')")) {
|
||||
return sqlFail("prepare _deleteFileRecordRecursively", *_deleteFileRecordRecursively);
|
||||
}
|
||||
|
||||
QString sql( "SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget "
|
||||
"FROM blacklist WHERE path=?1");
|
||||
@@ -430,32 +465,50 @@ bool SyncJournalDb::checkConnect()
|
||||
sql += QLatin1String(" COLLATE NOCASE");
|
||||
}
|
||||
_getErrorBlacklistQuery.reset(new SqlQuery(_db));
|
||||
_getErrorBlacklistQuery->prepare(sql);
|
||||
if (_getErrorBlacklistQuery->prepare(sql)) {
|
||||
return sqlFail("prepare _getErrorBlacklistQuery", *_getErrorBlacklistQuery);
|
||||
}
|
||||
|
||||
_setErrorBlacklistQuery.reset(new SqlQuery(_db));
|
||||
_setErrorBlacklistQuery->prepare("INSERT OR REPLACE INTO blacklist "
|
||||
if (_setErrorBlacklistQuery->prepare("INSERT OR REPLACE INTO blacklist "
|
||||
"(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget) "
|
||||
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)");
|
||||
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)")) {
|
||||
return sqlFail("prepare _setErrorBlacklistQuery", *_setErrorBlacklistQuery);
|
||||
}
|
||||
|
||||
_getSelectiveSyncListQuery.reset(new SqlQuery(_db));
|
||||
_getSelectiveSyncListQuery->prepare("SELECT path FROM selectivesync WHERE type=?1");
|
||||
if (_getSelectiveSyncListQuery->prepare("SELECT path FROM selectivesync WHERE type=?1")) {
|
||||
return sqlFail("prepare _getSelectiveSyncListQuery", *_getSelectiveSyncListQuery);
|
||||
}
|
||||
|
||||
_getChecksumTypeIdQuery.reset(new SqlQuery(_db));
|
||||
_getChecksumTypeIdQuery->prepare("SELECT id FROM checksumtype WHERE name=?1");
|
||||
if (_getChecksumTypeIdQuery->prepare("SELECT id FROM checksumtype WHERE name=?1")) {
|
||||
return sqlFail("prepare _getChecksumTypeIdQuery", *_getChecksumTypeIdQuery);
|
||||
}
|
||||
|
||||
_getChecksumTypeQuery.reset(new SqlQuery(_db));
|
||||
_getChecksumTypeQuery->prepare("SELECT name FROM checksumtype WHERE id=?1");
|
||||
if (_getChecksumTypeQuery->prepare("SELECT name FROM checksumtype WHERE id=?1")) {
|
||||
return sqlFail("prepare _getChecksumTypeQuery", *_getChecksumTypeQuery);
|
||||
}
|
||||
|
||||
_insertChecksumTypeQuery.reset(new SqlQuery(_db));
|
||||
_insertChecksumTypeQuery->prepare("INSERT OR IGNORE INTO checksumtype (name) VALUES (?1)");
|
||||
if (_insertChecksumTypeQuery->prepare("INSERT OR IGNORE INTO checksumtype (name) VALUES (?1)")) {
|
||||
return sqlFail("prepare _insertChecksumTypeQuery", *_insertChecksumTypeQuery);
|
||||
}
|
||||
|
||||
_getDataFingerprintQuery.reset(new SqlQuery(_db));
|
||||
_getDataFingerprintQuery->prepare("SELECT fingerprint FROM datafingerprint");
|
||||
if (_getDataFingerprintQuery->prepare("SELECT fingerprint FROM datafingerprint")) {
|
||||
return sqlFail("prepare _getDataFingerprintQuery", *_getDataFingerprintQuery);
|
||||
}
|
||||
|
||||
_setDataFingerprintQuery1.reset(new SqlQuery(_db));
|
||||
_setDataFingerprintQuery1->prepare("DELETE FROM datafingerprint;");
|
||||
if (_setDataFingerprintQuery1->prepare("DELETE FROM datafingerprint;")) {
|
||||
return sqlFail("prepare _setDataFingerprintQuery1", *_setDataFingerprintQuery1);
|
||||
}
|
||||
_setDataFingerprintQuery2.reset(new SqlQuery(_db));
|
||||
_setDataFingerprintQuery2->prepare("INSERT INTO datafingerprint (fingerprint) VALUES (?1);");
|
||||
if (_setDataFingerprintQuery2->prepare("INSERT INTO datafingerprint (fingerprint) VALUES (?1);")) {
|
||||
return sqlFail("prepare _setDataFingerprintQuery2", *_setDataFingerprintQuery2);
|
||||
}
|
||||
|
||||
// don't start a new transaction now
|
||||
commitInternal(QString("checkConnect End"), false);
|
||||
|
||||
+22
-7
@@ -115,11 +115,11 @@ QIcon Theme::trayFolderIcon( const QString& backend ) const
|
||||
* helper to load a icon from either the icon theme the desktop provides or from
|
||||
* the apps Qt resources.
|
||||
*/
|
||||
QIcon Theme::themeIcon( const QString& name, bool sysTray ) const
|
||||
QIcon Theme::themeIcon( const QString& name, bool sysTray, bool sysTrayMenuVisible ) const
|
||||
{
|
||||
QString flavor;
|
||||
if (sysTray) {
|
||||
flavor = systrayIconFlavor(_mono);
|
||||
flavor = systrayIconFlavor(_mono, sysTrayMenuVisible);
|
||||
} else {
|
||||
flavor = QLatin1String("colored");
|
||||
}
|
||||
@@ -158,6 +158,14 @@ QIcon Theme::themeIcon( const QString& name, bool sysTray ) const
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
|
||||
// This defines the icon as a template and enables automatic macOS color handling
|
||||
// See https://bugreports.qt.io/browse/QTBUG-42109
|
||||
cached.setIsMask(_mono && sysTray && !sysTrayMenuVisible);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return cached;
|
||||
}
|
||||
|
||||
@@ -227,11 +235,18 @@ QString Theme::defaultClientFolder() const
|
||||
return appName();
|
||||
}
|
||||
|
||||
QString Theme::systrayIconFlavor(bool mono) const
|
||||
QString Theme::systrayIconFlavor(bool mono, bool sysTrayMenuVisible ) const
|
||||
{
|
||||
Q_UNUSED(sysTrayMenuVisible)
|
||||
QString flavor;
|
||||
if (mono) {
|
||||
flavor = Utility::hasDarkSystray() ? QLatin1String("white") : QLatin1String("black");
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
if (sysTrayMenuVisible) {
|
||||
flavor = QLatin1String("white");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
flavor = QLatin1String("colored");
|
||||
}
|
||||
@@ -331,7 +346,7 @@ QVariant Theme::customMedia( CustomMediaType type )
|
||||
return re;
|
||||
}
|
||||
|
||||
QIcon Theme::syncStateIcon( SyncResult::Status status, bool sysTray ) const
|
||||
QIcon Theme::syncStateIcon( SyncResult::Status status, bool sysTray, bool sysTrayMenuVisible ) const
|
||||
{
|
||||
// FIXME: Mind the size!
|
||||
QString statusIcon;
|
||||
@@ -363,7 +378,7 @@ QIcon Theme::syncStateIcon( SyncResult::Status status, bool sysTray ) const
|
||||
statusIcon = QLatin1String("state-error");
|
||||
}
|
||||
|
||||
return themeIcon( statusIcon, sysTray );
|
||||
return themeIcon( statusIcon, sysTray, sysTrayMenuVisible );
|
||||
}
|
||||
|
||||
QIcon Theme::folderDisabledIcon( ) const
|
||||
@@ -371,9 +386,9 @@ QIcon Theme::folderDisabledIcon( ) const
|
||||
return themeIcon( QLatin1String("state-pause") );
|
||||
}
|
||||
|
||||
QIcon Theme::folderOfflineIcon(bool systray) const
|
||||
QIcon Theme::folderOfflineIcon(bool sysTray, bool sysTrayMenuVisible ) const
|
||||
{
|
||||
return themeIcon( QLatin1String("state-offline"), systray );
|
||||
return themeIcon( QLatin1String("state-offline"), sysTray, sysTrayMenuVisible );
|
||||
}
|
||||
|
||||
QColor Theme::wizardHeaderTitleColor() const
|
||||
|
||||
@@ -97,10 +97,10 @@ public:
|
||||
/**
|
||||
* get an sync state icon
|
||||
*/
|
||||
virtual QIcon syncStateIcon( SyncResult::Status, bool sysTray = false ) const;
|
||||
virtual QIcon syncStateIcon( SyncResult::Status, bool sysTray = false, bool sysTrayMenuVisible = false) const;
|
||||
|
||||
virtual QIcon folderDisabledIcon() const;
|
||||
virtual QIcon folderOfflineIcon(bool systray = false) const;
|
||||
virtual QIcon folderOfflineIcon(bool sysTray = false, bool sysTrayMenuVisible = false) const;
|
||||
virtual QIcon applicationIcon() const = 0;
|
||||
#endif
|
||||
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
virtual QString enforcedLocale() const { return QString::null; }
|
||||
|
||||
/** colored, white or black */
|
||||
QString systrayIconFlavor(bool mono) const;
|
||||
QString systrayIconFlavor(bool mono, bool sysTrayMenuVisible = false) const;
|
||||
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
/**
|
||||
@@ -304,7 +304,7 @@ public:
|
||||
|
||||
protected:
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
QIcon themeIcon(const QString& name, bool sysTray = false) const;
|
||||
QIcon themeIcon(const QString& name, bool sysTray = false, bool sysTrayMenuVisible = false) const;
|
||||
#endif
|
||||
Theme();
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@ ENDIF()
|
||||
|
||||
owncloud_add_test(FolderWatcher "${FolderWatcher_SRC}")
|
||||
if( UNIX AND NOT APPLE )
|
||||
if(HAVE_QT5 AND NOT BUILD_WITH_QT4)
|
||||
owncloud_add_test(InotifyWatcher "${FolderWatcher_SRC}")
|
||||
endif(HAVE_QT5 AND NOT BUILD_WITH_QT4)
|
||||
endif(UNIX AND NOT APPLE)
|
||||
|
||||
owncloud_add_test(CSyncSqlite "")
|
||||
|
||||
@@ -14,17 +14,21 @@
|
||||
|
||||
#include <QDir>
|
||||
#include <QNetworkReply>
|
||||
#include <QMap>
|
||||
#include <QtTest>
|
||||
|
||||
static const QUrl sRootUrl("owncloud://somehost/owncloud/remote.php/webdav/");
|
||||
|
||||
namespace {
|
||||
QString generateEtag() {
|
||||
inline QString generateEtag() {
|
||||
return QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch(), 16);
|
||||
}
|
||||
inline QByteArray generateFileId() {
|
||||
return QByteArray::number(qrand(), 16);
|
||||
}
|
||||
|
||||
class PathComponents : public QStringList {
|
||||
public:
|
||||
PathComponents(const char *path) : PathComponents{QString::fromUtf8(path)} {}
|
||||
PathComponents(const QString &path) : QStringList{path.split('/', QString::SkipEmptyParts)} { }
|
||||
PathComponents(const QStringList &pathComponents) : QStringList{pathComponents} { }
|
||||
|
||||
@@ -35,7 +39,6 @@ public:
|
||||
QString pathRoot() const { return first(); }
|
||||
QString fileName() const { return last(); }
|
||||
};
|
||||
}
|
||||
|
||||
class FileModifier
|
||||
{
|
||||
@@ -46,6 +49,7 @@ public:
|
||||
virtual void setContents(const QString &relativePath, char contentChar) = 0;
|
||||
virtual void appendByte(const QString &relativePath) = 0;
|
||||
virtual void mkdir(const QString &relativePath) = 0;
|
||||
virtual void rename(const QString &relativePath, const QString &relativeDestinationDirectory) = 0;
|
||||
};
|
||||
|
||||
class DiskFileModifier : public FileModifier
|
||||
@@ -87,6 +91,10 @@ public:
|
||||
void mkdir(const QString &relativePath) override {
|
||||
_rootDir.mkpath(relativePath);
|
||||
}
|
||||
void rename(const QString &from, const QString &to) override {
|
||||
QVERIFY(_rootDir.exists(from));
|
||||
QVERIFY(_rootDir.rename(from, to));
|
||||
}
|
||||
};
|
||||
|
||||
class FileInfo : public FileModifier
|
||||
@@ -127,6 +135,7 @@ public:
|
||||
for (const auto &source : children) {
|
||||
auto &dest = this->children[source.name] = source;
|
||||
dest.parentPath = p;
|
||||
dest.fixupParentPathRecursively();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +167,21 @@ public:
|
||||
createDir(relativePath);
|
||||
}
|
||||
|
||||
void rename(const QString &oldPath, const QString &newPath) override {
|
||||
const PathComponents newPathComponents{newPath};
|
||||
FileInfo *dir = findInvalidatingEtags(newPathComponents.parentDirComponents());
|
||||
Q_ASSERT(dir);
|
||||
Q_ASSERT(dir->isDir);
|
||||
const PathComponents pathComponents{oldPath};
|
||||
FileInfo *parent = findInvalidatingEtags(pathComponents.parentDirComponents());
|
||||
Q_ASSERT(parent);
|
||||
FileInfo fi = parent->children.take(pathComponents.fileName());
|
||||
fi.parentPath = dir->path();
|
||||
fi.name = newPathComponents.fileName();
|
||||
fi.fixupParentPathRecursively();
|
||||
dir->children.insert(newPathComponents.fileName(), std::move(fi));
|
||||
}
|
||||
|
||||
FileInfo *find(const PathComponents &pathComponents, const bool invalidateEtags = false) {
|
||||
if (pathComponents.isEmpty()) {
|
||||
if (invalidateEtags)
|
||||
@@ -219,6 +243,7 @@ public:
|
||||
bool isShared = false;
|
||||
QDateTime lastModified = QDateTime::currentDateTime().addDays(-7);
|
||||
QString etag = generateEtag();
|
||||
QByteArray fileId = generateFileId();
|
||||
qint64 size = 0;
|
||||
char contentChar = 'W';
|
||||
|
||||
@@ -230,6 +255,19 @@ private:
|
||||
FileInfo *findInvalidatingEtags(const PathComponents &pathComponents) {
|
||||
return find(pathComponents, true);
|
||||
}
|
||||
|
||||
void fixupParentPathRecursively() {
|
||||
auto p = path();
|
||||
for (auto it = children.begin(); it != children.end(); ++it) {
|
||||
Q_ASSERT(it.key() == it->name);
|
||||
it->parentPath = p;
|
||||
it->fixupParentPathRecursively();
|
||||
}
|
||||
}
|
||||
|
||||
friend inline QDebug operator<<(QDebug dbg, const FileInfo& fi) {
|
||||
return dbg << "{ " << fi.path() << ": " << fi.children;
|
||||
}
|
||||
};
|
||||
|
||||
class FakePropfindReply : public QNetworkReply
|
||||
@@ -275,6 +313,7 @@ public:
|
||||
xml.writeTextElement(davUri, QStringLiteral("getcontentlength"), QString::number(fileInfo.size));
|
||||
xml.writeTextElement(davUri, QStringLiteral("getetag"), fileInfo.etag);
|
||||
xml.writeTextElement(ocUri, QStringLiteral("permissions"), fileInfo.isShared ? QStringLiteral("SRDNVCKW") : QStringLiteral("RDNVCKW"));
|
||||
xml.writeTextElement(ocUri, QStringLiteral("id"), fileInfo.fileId);
|
||||
xml.writeEndElement(); // prop
|
||||
xml.writeTextElement(davUri, QStringLiteral("status"), "HTTP/1.1 200 OK");
|
||||
xml.writeEndElement(); // propstat
|
||||
@@ -284,6 +323,7 @@ public:
|
||||
Q_ASSERT(request.url().path().startsWith(sRootUrl.path()));
|
||||
QString fileName = request.url().path().mid(sRootUrl.path().length());
|
||||
const FileInfo *fileInfo = remoteRootFileInfo.find(fileName);
|
||||
Q_ASSERT(fileInfo);
|
||||
|
||||
writeFileResponse(*fileInfo);
|
||||
foreach(const FileInfo &childFileInfo, fileInfo->children)
|
||||
@@ -382,7 +422,7 @@ public:
|
||||
}
|
||||
|
||||
Q_INVOKABLE void respond() {
|
||||
// FIXME: setRawHeader("OC-FileId", fileInfo->???);
|
||||
setRawHeader("OC-FileId", fileInfo->fileId);
|
||||
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 201);
|
||||
emit metaDataChanged();
|
||||
emit finished();
|
||||
@@ -419,6 +459,36 @@ public:
|
||||
qint64 readData(char *, qint64) override { return 0; }
|
||||
};
|
||||
|
||||
class FakeMoveReply : public QNetworkReply
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FakeMoveReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, QObject *parent)
|
||||
: QNetworkReply{parent} {
|
||||
setRequest(request);
|
||||
setUrl(request.url());
|
||||
setOperation(op);
|
||||
open(QIODevice::ReadOnly);
|
||||
|
||||
Q_ASSERT(request.url().path().startsWith(sRootUrl.path()));
|
||||
QString fileName = request.url().path().mid(sRootUrl.path().length());
|
||||
QString destPath = request.rawHeader("Destination");
|
||||
Q_ASSERT(destPath.startsWith(sRootUrl.path()));
|
||||
QString dest = destPath.mid(sRootUrl.path().length());
|
||||
remoteRootFileInfo.rename(fileName, dest);
|
||||
QMetaObject::invokeMethod(this, "respond", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Q_INVOKABLE void respond() {
|
||||
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 201);
|
||||
emit metaDataChanged();
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void abort() override { }
|
||||
qint64 readData(char *, qint64) override { return 0; }
|
||||
};
|
||||
|
||||
class FakeGetReply : public QNetworkReply
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -445,6 +515,7 @@ public:
|
||||
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 200);
|
||||
setRawHeader("OC-ETag", fileInfo->etag.toLatin1());
|
||||
setRawHeader("ETag", fileInfo->etag.toLatin1());
|
||||
setRawHeader("OC-FileId", fileInfo->fileId);
|
||||
emit metaDataChanged();
|
||||
if (bytesAvailable())
|
||||
emit readyRead();
|
||||
@@ -513,6 +584,8 @@ protected:
|
||||
return new FakeMkcolReply{_remoteRootFileInfo, op, request, this};
|
||||
else if (verb == QLatin1String("DELETE"))
|
||||
return new FakeDeleteReply{_remoteRootFileInfo, op, request, this};
|
||||
else if (verb == QLatin1String("MOVE"))
|
||||
return new FakeMoveReply{_remoteRootFileInfo, op, request, this};
|
||||
else {
|
||||
qDebug() << verb << outgoingData;
|
||||
Q_UNREACHABLE();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "folderman.h"
|
||||
#include "account.h"
|
||||
#include "accountstate.h"
|
||||
#include "configfile.h"
|
||||
|
||||
using namespace OCC;
|
||||
|
||||
@@ -39,6 +40,7 @@ private slots:
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||
QTemporaryDir dir;
|
||||
ConfigFile::setConfDir(dir.path()); // we don't want to pollute the user's config file
|
||||
QVERIFY(dir.isValid());
|
||||
QDir dir2(dir.path());
|
||||
QVERIFY(dir2.mkpath("sub/ownCloud1/folder/f"));
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <QtTest>
|
||||
#include "syncenginetestutils.h"
|
||||
#include <syncengine.h>
|
||||
|
||||
using namespace OCC;
|
||||
|
||||
@@ -119,6 +120,99 @@ private slots:
|
||||
QVERIFY(itemDidCompleteSuccessfully(completeSpy, "a3.eml"));
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
}
|
||||
|
||||
void testRemoteChangeInMovedFolder() {
|
||||
// issue #5192
|
||||
FakeFolder fakeFolder{FileInfo{ QString(), {
|
||||
FileInfo { QStringLiteral("folder"), {
|
||||
FileInfo{ QStringLiteral("folderA"), { { QStringLiteral("file.txt"), 400 } } },
|
||||
QStringLiteral("folderB")
|
||||
}
|
||||
}}}};
|
||||
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
|
||||
// Edit a file in a moved directory.
|
||||
fakeFolder.remoteModifier().setContents("folder/folderA/file.txt", 'a');
|
||||
fakeFolder.remoteModifier().rename("folder/folderA", "folder/folderB/folderA");
|
||||
fakeFolder.syncOnce();
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
auto oldState = fakeFolder.currentLocalState();
|
||||
QVERIFY(oldState.find("folder/folderB/folderA/file.txt"));
|
||||
QVERIFY(!oldState.find("folder/folderA/file.txt"));
|
||||
|
||||
// This sync should not remove the file
|
||||
fakeFolder.syncOnce();
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
QCOMPARE(fakeFolder.currentLocalState(), oldState);
|
||||
|
||||
}
|
||||
|
||||
void testSelectiveSyncModevFolder() {
|
||||
// issue #5224
|
||||
FakeFolder fakeFolder{FileInfo{ QString(), {
|
||||
FileInfo { QStringLiteral("parentFolder"), {
|
||||
FileInfo{ QStringLiteral("subFolderA"), { { QStringLiteral("fileA.txt"), 400 } } },
|
||||
FileInfo{ QStringLiteral("subFolderB"), { { QStringLiteral("fileB.txt"), 400 } } }
|
||||
}
|
||||
}}}};
|
||||
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
auto expectedServerState = fakeFolder.currentRemoteState();
|
||||
|
||||
// Remove subFolderA with selectiveSync:
|
||||
fakeFolder.syncEngine().journal()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList,
|
||||
{"parentFolder/subFolderA/"});
|
||||
fakeFolder.syncEngine().journal()->avoidReadFromDbOnNextSync("parentFolder/subFolderA/");
|
||||
|
||||
fakeFolder.syncOnce();
|
||||
|
||||
{
|
||||
// Nothing changed on the server
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
|
||||
// The local state should not have subFolderA
|
||||
auto remoteState = fakeFolder.currentRemoteState();
|
||||
remoteState.remove("parentFolder/subFolderA");
|
||||
QCOMPARE(fakeFolder.currentLocalState(), remoteState);
|
||||
}
|
||||
|
||||
// Rename parentFolder on the server
|
||||
fakeFolder.remoteModifier().rename("parentFolder", "parentFolderRenamed");
|
||||
expectedServerState = fakeFolder.currentRemoteState();
|
||||
fakeFolder.syncOnce();
|
||||
|
||||
{
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
|
||||
auto remoteState = fakeFolder.currentRemoteState();
|
||||
// The subFolderA should still be there on the server.
|
||||
QVERIFY(remoteState.find("parentFolderRenamed/subFolderA/fileA.txt"));
|
||||
// But not on the client because of the selective sync
|
||||
remoteState.remove("parentFolderRenamed/subFolderA");
|
||||
QCOMPARE(fakeFolder.currentLocalState(), remoteState);
|
||||
}
|
||||
|
||||
// Rename it again, locally this time.
|
||||
fakeFolder.localModifier().rename("parentFolderRenamed", "parentThirdName");
|
||||
fakeFolder.syncOnce();
|
||||
|
||||
{
|
||||
auto remoteState = fakeFolder.currentRemoteState();
|
||||
// The subFolderA should still be there on the server.
|
||||
QVERIFY(remoteState.find("parentThirdName/subFolderA/fileA.txt"));
|
||||
// But not on the client because of the selective sync
|
||||
remoteState.remove("parentThirdName/subFolderA");
|
||||
QCOMPARE(fakeFolder.currentLocalState(), remoteState);
|
||||
|
||||
expectedServerState = fakeFolder.currentRemoteState();
|
||||
QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)));
|
||||
fakeFolder.syncOnce(); // This sync should do nothing
|
||||
QCOMPARE(completeSpy.count(), 0);
|
||||
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedServerState);
|
||||
QCOMPARE(fakeFolder.currentLocalState(), remoteState);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(TestSyncEngine)
|
||||
|
||||
+65
-65
@@ -522,7 +522,7 @@
|
||||
<context>
|
||||
<name>OCC::CleanupPollsJob</name>
|
||||
<message>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="772"/>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="779"/>
|
||||
<source>Error writing metadata to the database</source>
|
||||
<translation>Error en escriure les metadades a la base de dades</translation>
|
||||
</message>
|
||||
@@ -724,7 +724,7 @@ Continuing the sync as normal will cause all your files to be overwritten by an
|
||||
<message>
|
||||
<location filename="../src/gui/folder.cpp" line="1006"/>
|
||||
<source>Backup detected</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Copia de seguretat detectada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folder.cpp" line="1008"/>
|
||||
@@ -734,7 +734,7 @@ Continuing the sync as normal will cause all your files to be overwritten by an
|
||||
<message>
|
||||
<location filename="../src/gui/folder.cpp" line="1009"/>
|
||||
<source>Keep Local Files as Conflict</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Manté els fitxers locals com a conflicte</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -817,7 +817,7 @@ Continuing the sync as normal will cause all your files to be overwritten by an
|
||||
<message>
|
||||
<location filename="../src/gui/folderman.cpp" line="1190"/>
|
||||
<source>The selected path is not a folder!</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>La ruta seleccionada no és un directori!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderman.cpp" line="1194"/>
|
||||
@@ -892,7 +892,7 @@ Continuing the sync as normal will cause all your files to be overwritten by an
|
||||
<translation>Error en carregar la llista de carpetes del servidor.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="204"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="205"/>
|
||||
<source>Signed out</source>
|
||||
<translation>S'ha desconnectat</translation>
|
||||
</message>
|
||||
@@ -902,96 +902,96 @@ Continuing the sync as normal will cause all your files to be overwritten by an
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="169"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="170"/>
|
||||
<source>Fetching folder list from server...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Obtenint la llista de carpetes del servidor...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="832"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="841"/>
|
||||
<source>Checking for changes in '%1'</source>
|
||||
<translation>S'està comprovant els canvis a '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="867"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="876"/>
|
||||
<source>, '%1'</source>
|
||||
<extracomment>Build a list of file names</extracomment>
|
||||
<translation>, '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="870"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="879"/>
|
||||
<source>'%1'</source>
|
||||
<extracomment>Argument is a file name</extracomment>
|
||||
<translation>'%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="895"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="904"/>
|
||||
<source>Syncing %1</source>
|
||||
<extracomment>Example text: "Syncing 'foo.txt', 'bar.txt'"</extracomment>
|
||||
<translation>S'està sincronitzant %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="897"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="907"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="906"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="916"/>
|
||||
<source>, </source>
|
||||
<translation>, </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="901"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="910"/>
|
||||
<source>download %1/s</source>
|
||||
<extracomment>Example text: "download 24Kb/s" (%1 is replaced by 24Kb (translated))</extracomment>
|
||||
<translation>descarrega %1/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="903"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="912"/>
|
||||
<source>u2193 %1/s</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="910"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="919"/>
|
||||
<source>upload %1/s</source>
|
||||
<extracomment>Example text: "upload 24Kb/s" (%1 is replaced by 24Kb (translated))</extracomment>
|
||||
<translation>pujada %1/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="912"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="921"/>
|
||||
<source>u2191 %1/s</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="917"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="926"/>
|
||||
<source>%1 %2 (%3 of %4)</source>
|
||||
<extracomment>Example text: "uploading foobar.png (2MB of 2MB)"</extracomment>
|
||||
<translation>%1 %2 (%3 de %4)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="921"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="930"/>
|
||||
<source>%1 %2</source>
|
||||
<extracomment>Example text: "uploading foobar.png"</extracomment>
|
||||
<translation>%1 %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="938"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="947"/>
|
||||
<source>%5 left, %1 of %2, file %3 of %4</source>
|
||||
<extracomment>Example text: "5 minutes left, 12 MB of 345 MB, file 6 of 7"</extracomment>
|
||||
<translation>%5 pendent, %1 de %2, fitxer %3 de %4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="944"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="953"/>
|
||||
<source>file %1 of %2</source>
|
||||
<translation>fitxer %1 de %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="984"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="993"/>
|
||||
<source>Waiting...</source>
|
||||
<translation>S'està esperant...</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="986"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="995"/>
|
||||
<source>Waiting for %n other folder(s)...</source>
|
||||
<translation><numerusform>S'està esperant %n altra carpeta...</numerusform><numerusform>S'està esperant %n altres carpetes</numerusform></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="992"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="1001"/>
|
||||
<source>Preparing to sync...</source>
|
||||
<translation>S'està preparant per sincronitzar...</translation>
|
||||
</message>
|
||||
@@ -1006,7 +1006,7 @@ Continuing the sync as normal will cause all your files to be overwritten by an
|
||||
<message>
|
||||
<location filename="../src/gui/folderwizard.cpp" line="544"/>
|
||||
<source>Add Sync Connection</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Afegir una connexió de sincronització</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -1521,7 +1521,7 @@ Els elements que poden ser eliminats s'eliminaran si impedeixen que una car
|
||||
<message>
|
||||
<location filename="../src/gui/notificationwidget.cpp" line="50"/>
|
||||
<source>Created at %1</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Creat el %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/notificationwidget.cpp" line="99"/>
|
||||
@@ -1626,12 +1626,12 @@ privilegis addicionals durant el procés.</translation>
|
||||
<message>
|
||||
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.cpp" line="142"/>
|
||||
<source>Sync the folder '%1'</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Sincronitzar el directori '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.cpp" line="147"/>
|
||||
<source><p><small><strong>Warning:</strong> The local folder is not empty. Pick a resolution!</small></p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><p><small><strong>Atenció:</strong> La carpeta local no està buida. Trieu una resolució!</small></p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.cpp" line="246"/>
|
||||
@@ -1741,7 +1741,7 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/gui/owncloudsetupwizard.cpp" line="181"/>
|
||||
<source>Timeout while trying to connect to %1 at %2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>S'ha esgotat el temps d'espera mentres es conectava a %1 a les %2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/owncloudsetupwizard.cpp" line="192"/>
|
||||
@@ -1916,7 +1916,7 @@ No és aconsellada usar-la.</translation>
|
||||
<context>
|
||||
<name>OCC::PropagateDirectory</name>
|
||||
<message>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="712"/>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="718"/>
|
||||
<source>Error writing metadata to the database</source>
|
||||
<translation>Error en escriure les metadades a la base de dades</translation>
|
||||
</message>
|
||||
@@ -1931,12 +1931,12 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="376"/>
|
||||
<source>The download would reduce free disk space below %1</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>La descàrrega reduïrà l'espai lliure al disc per sota de %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="381"/>
|
||||
<source>Free space on disk is less than %1</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>L'espai lliure del disc dur es inferior a %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="496"/>
|
||||
@@ -1946,7 +1946,7 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="545"/>
|
||||
<source>The file could not be downloaded completely.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>No es pot descarregar el fitxer completament.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="552"/>
|
||||
@@ -1954,17 +1954,17 @@ No és aconsellada usar-la.</translation>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="693"/>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="711"/>
|
||||
<source>File %1 cannot be saved because of a local file name clash!</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="741"/>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="759"/>
|
||||
<source>File has changed since discovery</source>
|
||||
<translation>El fitxer ha canviat des de que es va descobrir</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="791"/>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="809"/>
|
||||
<source>Error writing metadata to the database</source>
|
||||
<translation>Error en escriure les metadades a la base de dades</translation>
|
||||
</message>
|
||||
@@ -2363,7 +2363,7 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/gui/sharedialog.cpp" line="98"/>
|
||||
<source>%1 Sharing</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Compartint amb %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharedialog.cpp" line="73"/>
|
||||
@@ -2378,7 +2378,7 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/gui/sharedialog.cpp" line="101"/>
|
||||
<source>The server does not allow sharing</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>El servidor no permet la compartició de fitxers</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharedialog.cpp" line="113"/>
|
||||
@@ -2450,18 +2450,18 @@ No és aconsellada usar-la.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="366"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="412"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="413"/>
|
||||
<source>Public sh&aring requires a password</source>
|
||||
<translation>La comp&artició pública requereix una contrasenya</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="434"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="435"/>
|
||||
<source>Please Set Password</source>
|
||||
<translation>Establiu la contrasenya</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="498"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="499"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="500"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="501"/>
|
||||
<source>&Share link</source>
|
||||
<translation>Com&parteix l'enllaç</translation>
|
||||
</message>
|
||||
@@ -2871,12 +2871,12 @@ No és aconsellada usar-la.</translation>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1134"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1139"/>
|
||||
<source>Not allowed because you don't have permission to add parent folder</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1141"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1146"/>
|
||||
<source>Not allowed because you don't have permission to add files in that folder</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
@@ -2981,64 +2981,64 @@ No és aconsellada usar-la.</translation>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="787"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="791"/>
|
||||
<source>Unable to read from the sync journal.</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="833"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="837"/>
|
||||
<source>Cannot open the sync journal</source>
|
||||
<translation>No es pot obrir el diari de sincronització</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="889"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="894"/>
|
||||
<source>File name contains at least one invalid character</source>
|
||||
<translation>El nom del fitxer conté al menys un caràcter invàlid</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1093"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1100"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1098"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1105"/>
|
||||
<source>Ignored because of the "choose what to sync" blacklist</source>
|
||||
<translation>S'ignora degut al filtre a «Trieu què sincronitzar»</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1119"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1124"/>
|
||||
<source>Not allowed because you don't have permission to add subfolders to that folder</source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1161"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1166"/>
|
||||
<source>Not allowed to upload this file because it is read-only on the server, restoring</source>
|
||||
<translation>No es permet pujar aquest fitxer perquè només és de lectura en el servidor, es restaura</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1178"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1198"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1183"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1203"/>
|
||||
<source>Not allowed to remove, restoring</source>
|
||||
<translation>No es permet l'eliminació, es restaura</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1211"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1216"/>
|
||||
<source>Local files and share folder removed.</source>
|
||||
<translation>Fitxers locals i carpeta compartida esborrats.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1267"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1272"/>
|
||||
<source>Move not allowed, item restored</source>
|
||||
<translation>No es permet moure'l, l'element es restaura</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1278"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1283"/>
|
||||
<source>Move not allowed because %1 is read-only</source>
|
||||
<translation>No es permet moure perquè %1 només és de lectura</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1279"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1284"/>
|
||||
<source>the destination</source>
|
||||
<translation>el destí</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1279"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1284"/>
|
||||
<source>the source</source>
|
||||
<translation>l'origen</translation>
|
||||
</message>
|
||||
@@ -3048,7 +3048,7 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/gui/synclogdialog.ui" line="14"/>
|
||||
<source>Synchronisation Log</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Registre de sincronització</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -3068,8 +3068,8 @@ No és aconsellada usar-la.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/theme.cpp" line="289"/>
|
||||
<source><p>Copyright ownCloud, Incorporated</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<source><p>Copyright ownCloud GmbH</p></source>
|
||||
<translation><p>Copyright ownCloud GmbH</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/theme.cpp" line="290"/>
|
||||
@@ -3215,7 +3215,7 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/gui/owncloudgui.cpp" line="296"/>
|
||||
<source>Account synchronization is disabled</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>La sincronització del compte està deshabilitada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/owncloudgui.cpp" line="379"/>
|
||||
@@ -3293,8 +3293,8 @@ No és aconsellada usar-la.</translation>
|
||||
<name>OCC::ownCloudTheme</name>
|
||||
<message>
|
||||
<location filename="../src/libsync/owncloudtheme.cpp" line="47"/>
|
||||
<source><p>Version %2. For more information visit <a href="%3">%4</a></p><p><small>By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.</small></p><p>Copyright ownCloud, Inc.</p><p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.</p></source>
|
||||
<translation><p>Versió %2. Per més informació visiteu <a href="%3">%4</a></p><p><small>Per Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz i altres.</small></p><p>Copyright ownCloud, Inc.</p><p>amb llicència GNU General Public License (GPL) versió 2.0<br/>ownCloud i el logo d'ownCloud són marques registrades d'ownCloud, Inc. als Estats Units, altres països, o ambdós.</p></translation>
|
||||
<source><p>Version %2. For more information visit <a href="%3">%4</a></p><p><small>By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.</small></p><p>Copyright ownCloud GmbH</p><p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -3642,7 +3642,7 @@ No és aconsellada usar-la.</translation>
|
||||
<message>
|
||||
<location filename="../src/libsync/progressdispatcher.cpp" line="37"/>
|
||||
<source>Server version downloaded, copied changed local file into conflict file</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>S'ha baixat la versió del servidor i s'ha renomenat el fitxer local com a fitxer de conflicte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/progressdispatcher.cpp" line="39"/>
|
||||
|
||||
+48
-48
@@ -522,7 +522,7 @@
|
||||
<context>
|
||||
<name>OCC::CleanupPollsJob</name>
|
||||
<message>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="772"/>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="779"/>
|
||||
<source>Error writing metadata to the database</source>
|
||||
<translation>Chyba zápisu metadat do databáze</translation>
|
||||
</message>
|
||||
@@ -894,7 +894,7 @@ Pokračováním v synchronizaci způsobí přepsání všech vašich souborů st
|
||||
<translation>Chyba při načítání seznamu adresářů ze serveru.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="204"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="205"/>
|
||||
<source>Signed out</source>
|
||||
<translation>Odhlášeno</translation>
|
||||
</message>
|
||||
@@ -904,96 +904,96 @@ Pokračováním v synchronizaci způsobí přepsání všech vašich souborů st
|
||||
<translation>Přidání adresáře je vypnuto, protože již synchronizujete všechny své soubory. Pokud chcete synchronizovat pouze některé adresáře, odstraňte aktuálně nastavený kořenový adresář.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="169"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="170"/>
|
||||
<source>Fetching folder list from server...</source>
|
||||
<translation>Načítání seznamu adresářů ze serveru...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="832"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="841"/>
|
||||
<source>Checking for changes in '%1'</source>
|
||||
<translation>Kontrola změn v '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="867"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="876"/>
|
||||
<source>, '%1'</source>
|
||||
<extracomment>Build a list of file names</extracomment>
|
||||
<translation>, '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="870"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="879"/>
|
||||
<source>'%1'</source>
|
||||
<extracomment>Argument is a file name</extracomment>
|
||||
<translation>'%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="895"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="904"/>
|
||||
<source>Syncing %1</source>
|
||||
<extracomment>Example text: "Syncing 'foo.txt', 'bar.txt'"</extracomment>
|
||||
<translation>Synchronizuji %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="897"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="907"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="906"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="916"/>
|
||||
<source>, </source>
|
||||
<translation>, </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="901"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="910"/>
|
||||
<source>download %1/s</source>
|
||||
<extracomment>Example text: "download 24Kb/s" (%1 is replaced by 24Kb (translated))</extracomment>
|
||||
<translation>stahování %1/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="903"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="912"/>
|
||||
<source>u2193 %1/s</source>
|
||||
<translation>u2193 %1/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="910"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="919"/>
|
||||
<source>upload %1/s</source>
|
||||
<extracomment>Example text: "upload 24Kb/s" (%1 is replaced by 24Kb (translated))</extracomment>
|
||||
<translation>nahrávání %1/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="912"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="921"/>
|
||||
<source>u2191 %1/s</source>
|
||||
<translation>u2191 %1/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="917"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="926"/>
|
||||
<source>%1 %2 (%3 of %4)</source>
|
||||
<extracomment>Example text: "uploading foobar.png (2MB of 2MB)"</extracomment>
|
||||
<translation>%1 %2 (%3 ze %4)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="921"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="930"/>
|
||||
<source>%1 %2</source>
|
||||
<extracomment>Example text: "uploading foobar.png"</extracomment>
|
||||
<translation>%1 %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="938"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="947"/>
|
||||
<source>%5 left, %1 of %2, file %3 of %4</source>
|
||||
<extracomment>Example text: "5 minutes left, 12 MB of 345 MB, file 6 of 7"</extracomment>
|
||||
<translation>%5 zbývá, %1 ze %2, soubor %3 z %4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="944"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="953"/>
|
||||
<source>file %1 of %2</source>
|
||||
<translation>soubor %1 z %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="984"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="993"/>
|
||||
<source>Waiting...</source>
|
||||
<translation>Chvíli strpení...</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="986"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="995"/>
|
||||
<source>Waiting for %n other folder(s)...</source>
|
||||
<translation><numerusform>Čeká se na %n další adresář...</numerusform><numerusform>Čeká se na %n další adresáře...</numerusform><numerusform>Čeká se na %n dalších adresářů...</numerusform></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="992"/>
|
||||
<location filename="../src/gui/folderstatusmodel.cpp" line="1001"/>
|
||||
<source>Preparing to sync...</source>
|
||||
<translation>Synchronizace se připravuje...</translation>
|
||||
</message>
|
||||
@@ -1918,7 +1918,7 @@ Nedoporučuje se jí používat.</translation>
|
||||
<context>
|
||||
<name>OCC::PropagateDirectory</name>
|
||||
<message>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="712"/>
|
||||
<location filename="../src/libsync/owncloudpropagator.cpp" line="718"/>
|
||||
<source>Error writing metadata to the database</source>
|
||||
<translation>Chyba zápisu metadat do databáze</translation>
|
||||
</message>
|
||||
@@ -1956,17 +1956,17 @@ Nedoporučuje se jí používat.</translation>
|
||||
<translation>Stažený soubor je prázdný, přestože server oznámil, že měl být %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="693"/>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="711"/>
|
||||
<source>File %1 cannot be saved because of a local file name clash!</source>
|
||||
<translation>Soubor %1 nemohl být uložen z důvodu kolize názvu se souborem v místním systému!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="741"/>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="759"/>
|
||||
<source>File has changed since discovery</source>
|
||||
<translation>Soubor se mezitím změnil</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="791"/>
|
||||
<location filename="../src/libsync/propagatedownload.cpp" line="809"/>
|
||||
<source>Error writing metadata to the database</source>
|
||||
<translation>Chyba zápisu metadat do databáze</translation>
|
||||
</message>
|
||||
@@ -2452,18 +2452,18 @@ Nedoporučuje se jí používat.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="366"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="412"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="413"/>
|
||||
<source>Public sh&aring requires a password</source>
|
||||
<translation>Veřejné s&dílení vyžaduje heslo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="434"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="435"/>
|
||||
<source>Please Set Password</source>
|
||||
<translation>Nastavte prosím heslo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="498"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="499"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="500"/>
|
||||
<location filename="../src/gui/sharelinkwidget.cpp" line="501"/>
|
||||
<source>&Share link</source>
|
||||
<translation>&Sdílet odkaz</translation>
|
||||
</message>
|
||||
@@ -2873,12 +2873,12 @@ Nedoporučuje se jí používat.</translation>
|
||||
<translation>Je dostupných pouze %1, pro spuštění je potřeba alespoň %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1134"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1139"/>
|
||||
<source>Not allowed because you don't have permission to add parent folder</source>
|
||||
<translation>Není povoleno, protože nemáte oprávnění vytvořit nadřazený adresář</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1141"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1146"/>
|
||||
<source>Not allowed because you don't have permission to add files in that folder</source>
|
||||
<translation>Není povoleno, protože nemáte oprávnění přidávat soubory do tohoto adresáře</translation>
|
||||
</message>
|
||||
@@ -2983,64 +2983,64 @@ Nedoporučuje se jí používat.</translation>
|
||||
<translation>Nelze načíst blacklist z místní databáze</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="787"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="791"/>
|
||||
<source>Unable to read from the sync journal.</source>
|
||||
<translation>Nelze číst ze žurnálu synchronizace.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="833"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="837"/>
|
||||
<source>Cannot open the sync journal</source>
|
||||
<translation>Nelze otevřít synchronizační žurnál</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="889"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="894"/>
|
||||
<source>File name contains at least one invalid character</source>
|
||||
<translation>Jméno souboru obsahuje aelspoň jeden neplatný znak</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1093"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1100"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1098"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1105"/>
|
||||
<source>Ignored because of the "choose what to sync" blacklist</source>
|
||||
<translation>Ignorováno podle nastavení "vybrat co synchronizovat"</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1119"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1124"/>
|
||||
<source>Not allowed because you don't have permission to add subfolders to that folder</source>
|
||||
<translation>Není povoleno, protože nemáte oprávnění přidávat podadresáře do tohoto adresáře</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1161"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1166"/>
|
||||
<source>Not allowed to upload this file because it is read-only on the server, restoring</source>
|
||||
<translation>Není povoleno nahrát tento soubor, protože je na serveru uložen pouze pro čtení, obnovuji</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1178"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1198"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1183"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1203"/>
|
||||
<source>Not allowed to remove, restoring</source>
|
||||
<translation>Odstranění není povoleno, obnovuji</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1211"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1216"/>
|
||||
<source>Local files and share folder removed.</source>
|
||||
<translation>Místní soubory a sdílený adresář byly odstraněny.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1267"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1272"/>
|
||||
<source>Move not allowed, item restored</source>
|
||||
<translation>Přesun není povolen, položka obnovena</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1278"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1283"/>
|
||||
<source>Move not allowed because %1 is read-only</source>
|
||||
<translation>Přesun není povolen, protože %1 je pouze pro čtení</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1279"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1284"/>
|
||||
<source>the destination</source>
|
||||
<translation>cílové umístění</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1279"/>
|
||||
<location filename="../src/libsync/syncengine.cpp" line="1284"/>
|
||||
<source>the source</source>
|
||||
<translation>zdroj</translation>
|
||||
</message>
|
||||
@@ -3070,8 +3070,8 @@ Nedoporučuje se jí používat.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/theme.cpp" line="289"/>
|
||||
<source><p>Copyright ownCloud, Incorporated</p></source>
|
||||
<translation><p>Copyright ownCloud, Incorporated</p></translation>
|
||||
<source><p>Copyright ownCloud GmbH</p></source>
|
||||
<translation><p>Copyright ownCloud GmbH</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libsync/theme.cpp" line="290"/>
|
||||
@@ -3295,8 +3295,8 @@ Nedoporučuje se jí používat.</translation>
|
||||
<name>OCC::ownCloudTheme</name>
|
||||
<message>
|
||||
<location filename="../src/libsync/owncloudtheme.cpp" line="47"/>
|
||||
<source><p>Version %2. For more information visit <a href="%3">%4</a></p><p><small>By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.</small></p><p>Copyright ownCloud, Inc.</p><p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.</p></source>
|
||||
<translation><p>Verze %2. Pro další informace navštivte <a href="%3">%4</a></p><p><small>Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz a další.</small></p><p>Copyright ownCloud, Inc.</p><p>Licencováno pod GNU General Public License (GPL) Version 2.0<br/>ownCloud a ownCloud logo jsou registrované obchodní známky ownCloud, Inc. ve Spojených státech, ostatních zemích nebo obojí</p></translation>
|
||||
<source><p>Version %2. For more information visit <a href="%3">%4</a></p><p><small>By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.</small></p><p>Copyright ownCloud GmbH</p><p>Licensed under the GNU General Public License (GPL) Version 2.0<br/>ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.</p></source>
|
||||
<translation><p>Verze %2. Pro další informace navštivte <a href="%3">%4</a></p><p><small>Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz a další.</small></p><p>Copyright ownCloud GmbH</p><p>Licencováno pod GNU General Public License (GPL) Version 2.0<br/>ownCloud a ownCloud logo jsou registrované obchodní známky ownCloud, Inc. ve Spojených státech, ostatních zemích nebo obojí</p></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário