Comparar commits
4 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 098b603879 | |||
| 7c3b3d648b | |||
| 778aca386c | |||
| 0758b2cf61 |
@@ -1,21 +1,15 @@
|
||||
sudo: required
|
||||
|
||||
language: cpp
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
branches:
|
||||
only:
|
||||
- coverity_scan
|
||||
|
||||
before_install:
|
||||
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/Ubuntu_14.04/Release.key
|
||||
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/xUbuntu_12.04/Release.key
|
||||
- sudo apt-key add - < Release.key
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y build-dep owncloud-client
|
||||
- sudo apt-get build-dep owncloud-client
|
||||
- checkout=$(git show-ref --head --hash head)
|
||||
- cd ../
|
||||
- wget https://scan.coverity.com/download/linux-64 --post-data "token=$token&project=owncloud%2Fmirall" -O coverity_tool.tgz
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(VERSION 2.8.0)
|
||||
|
||||
@@ -126,17 +125,6 @@ if(OWNCLOUD_5XX_NO_BLACKLIST)
|
||||
add_definitions(-DOWNCLOUD_5XX_NO_BLACKLIST=1)
|
||||
endif()
|
||||
|
||||
# When this option is enabled, a rename that is not allowed will be renamed back
|
||||
# do the original as a restoration step. Withut this option, the restoration will
|
||||
# re-download the file instead.
|
||||
# The default is off because we don't want to rename the files back behind the user's back
|
||||
# Added for IL issue #550
|
||||
option(OWNCLOUD_RESTORE_RENAME "OWNCLOUD_RESTORE_RENAME" OFF)
|
||||
if(OWNCLOUD_RESTORE_RENAME)
|
||||
add_definitions(-DOWNCLOUD_RESTORE_RENAME=1)
|
||||
endif()
|
||||
|
||||
|
||||
if(APPLE)
|
||||
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
|
||||
endif()
|
||||
@@ -163,6 +151,11 @@ endif()
|
||||
|
||||
find_package(ZLIB)
|
||||
|
||||
find_package(LibsnoreQt5 0.6.0)
|
||||
if(LibsnoreQt5_FOUND)
|
||||
find_package(LibsnoreSettingsQt5)
|
||||
endif()
|
||||
|
||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
configure_file(test/test_journal.db "${CMAKE_BINARY_DIR}/test/test_journal.db" COPYONLY)
|
||||
|
||||
@@ -1,38 +1,5 @@
|
||||
ChangeLog
|
||||
=========
|
||||
version 2.2.1 (release 2016-05-xx)
|
||||
* Fix out of memory error when too many uploads happen (#4611)
|
||||
* Fix display errors in progress display (#4803 #4856)
|
||||
* LockWatcher: Remember to upload files after they become unlocked (#4865)
|
||||
* Fix overlay icons for files with umlauts (#4884)
|
||||
* Certs: Re-ask for different cert after rejection (#4898, #4911)
|
||||
* Progress: Don't count items without propagation jobs (#4856, #4910)
|
||||
* Utility: Fix for the translation of minutes, second (#4855)
|
||||
* SyncEngine: invalid the blacklist entry when the rename destination change
|
||||
|
||||
version 2.2.0 (release 2016-05-12)
|
||||
* Overlay icons: Refactoring - mainly for performance improvements
|
||||
* Improved error handling with Sync Journal on USB storages (#4632)
|
||||
* Sharing Completion: Improved UI of completion in sharing from desktop. (#3737)
|
||||
* Show server notifications on the client (#3733)
|
||||
* Improved Speed with small files by dynamic parallel request count (#4529)
|
||||
* LockWatcher: Make sure to sync files after apps released exclusive locks on Windows.
|
||||
* Improved handling of Win32 file locks and network files
|
||||
* Workaround Ubuntu 16.04 tray icon bug (#4693)
|
||||
* Removed the Alias field from the folder definition (#4695)
|
||||
* Improved netrc parser (#4691)
|
||||
* Improved user notifications about ignored files and conflicts (#4761, #3222)
|
||||
* Add warnings for old server versions (#4523)
|
||||
* Enable tranportation checksums if the server supports based on server capabilities (#3735)
|
||||
|
||||
* Default Chunk-size changed to 10MB (#4354)
|
||||
* Documentation Improvements, ie. about overlay icons
|
||||
* Translation fixes
|
||||
* Countless other bugfixes
|
||||
* Sqlite Update to recent version
|
||||
* Update of QtKeyChain to support Windows credential store
|
||||
* Packaging of dolphin overlay icon module for bleeding edge distros
|
||||
|
||||
version 2.1.1 (release 2016-02-10)
|
||||
* UI improvements for HiDPI screens, error messages, RTL languages
|
||||
* Fix occurences of "Connection Closed" when a new unauthenticated TCP socket is used
|
||||
|
||||
@@ -15,7 +15,7 @@ with your computer.
|
||||
|
||||
### Binary packages
|
||||
|
||||
* Refer to the download page https://owncloud.org/install/#install-clients
|
||||
* Refer to the download page http://owncloud.org/sync-clients/
|
||||
|
||||
### Source code
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set( MIRALL_VERSION_MAJOR 2 )
|
||||
set( MIRALL_VERSION_MINOR 2 )
|
||||
set( MIRALL_VERSION_PATCH 3 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_VERSION_YEAR 2016 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
--- binary
|
||||
+++ binary
|
||||
@@ -1 +1 @@
|
||||
-Subproject commit 1fb9ddfa9a9a1b4dbc447eee10dbed89172d968a
|
||||
+Subproject commit 01d73965dc8b862d1b2310d3ef801c297b697ec7
|
||||
@@ -44,18 +44,6 @@
|
||||
static
|
||||
#endif
|
||||
int _csync_exclude_add(c_strlist_t **inList, const char *string) {
|
||||
size_t i = 0;
|
||||
|
||||
// We never want duplicates, so check whether the string is already
|
||||
// in the list first.
|
||||
if (*inList) {
|
||||
for (i = 0; i < (*inList)->count; ++i) {
|
||||
char *pattern = (*inList)->vector[i];
|
||||
if (c_streq(pattern, string)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c_strlist_add_grow(inList, string);
|
||||
}
|
||||
|
||||
@@ -151,10 +139,8 @@ int csync_exclude_load(const char *fname, c_strlist_t **list) {
|
||||
buf[i] = '\0';
|
||||
if (*entry != '#') {
|
||||
const char *unescaped = csync_exclude_expand_escapes(entry);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", unescaped);
|
||||
rc = _csync_exclude_add(list, unescaped);
|
||||
if( rc == 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", unescaped);
|
||||
}
|
||||
SAFE_FREE(unescaped);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
|
||||
@@ -472,7 +472,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE
|
||||
|| excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
|
||||
/* store into result list. */
|
||||
if (c_rbtree_insert(ctx->remote.tree, (void *) st) < 0) {
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -269,8 +269,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
tmp = csync_statedb_get_stat_by_hash(ctx, h);
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
csync_file_stat_free(st);
|
||||
csync_file_stat_free(tmp);
|
||||
SAFE_FREE(st);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
@@ -357,7 +356,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
enum csync_vio_file_type_e tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
|
||||
/* tmp might point to malloc mem, so free it here before reusing tmp */
|
||||
csync_file_stat_free(tmp);
|
||||
SAFE_FREE(tmp);
|
||||
|
||||
/* check if it's a file and has been renamed */
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
@@ -366,7 +365,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
tmp = csync_statedb_get_stat_by_inode(ctx, fs->inode);
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
@@ -422,7 +421,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
tmp = csync_statedb_get_stat_by_file_id(ctx, fs->file_id);
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
@@ -451,7 +450,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
|
||||
if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY && ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncNewFolderHook) {
|
||||
if (ctx->callbacks.checkSelectiveSyncNewFolderHook(ctx->callbacks.update_callback_userdata, path)) {
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -461,7 +460,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
}
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb" );
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
@@ -523,14 +522,14 @@ out:
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
if (c_rbtree_insert(ctx->local.tree, (void *) st) < 0) {
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
if (c_rbtree_insert(ctx->remote.tree, (void *) st) < 0) {
|
||||
csync_file_stat_free(st);
|
||||
SAFE_FREE(st);
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ void csync_vio_file_stat_destroy(csync_vio_file_stat_t *file_stat) {
|
||||
SAFE_FREE(file_stat->directDownloadUrl);
|
||||
SAFE_FREE(file_stat->directDownloadCookies);
|
||||
SAFE_FREE(file_stat->name);
|
||||
SAFE_FREE(file_stat->original_name);
|
||||
SAFE_FREE(file_stat);
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
|
||||
return file_stat;
|
||||
|
||||
err:
|
||||
csync_vio_file_stat_destroy(file_stat);
|
||||
SAFE_FREE(file_stat);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -159,8 +159,8 @@ In order to make setup simple, you can use the provided Dockerfile to build your
|
||||
1. Assuming you are in the root of the ownCloud Client's source tree, you can
|
||||
build an image from this Dockerfile like this::
|
||||
|
||||
cd admin/win/docker
|
||||
docker build . -t owncloud-client-win32:<version>
|
||||
cd admin/win32/docker
|
||||
docker build . -t ownCloud-client-win32:<version>
|
||||
|
||||
Replace ``<version>`` by the version of the client you are building, e.g.
|
||||
|version| for the release of the client that this document describes.
|
||||
@@ -174,8 +174,8 @@ In order to make setup simple, you can use the provided Dockerfile to build your
|
||||
|
||||
2. From within the source tree Run the docker instance::
|
||||
|
||||
docker run -v "$PWD:/home/user/client" owncloud-client-win32:<version> \
|
||||
/home/user/client/admin/win/docker/build.sh client/ $(id -u)
|
||||
docker run ownCloud-client-win32:<version> -v "$PWD:/home/jenkins/client" \
|
||||
admin/win32/docker/build.sh $(id -u)
|
||||
|
||||
It will run the build, create an NSIS based installer, as well as run tests.
|
||||
You will find the resulting binary in an newly created ``build-win32`` subfolder.
|
||||
|
||||
@@ -41,7 +41,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'ownCloud Client Manual'
|
||||
copyright = u'2013-2016, The ownCloud developers'
|
||||
copyright = u'2013, The ownCloud developers'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -250,7 +250,7 @@ texinfo_documents = [
|
||||
epub_title = u'ownCloud Client Manual'
|
||||
epub_author = u'The ownCloud developers'
|
||||
epub_publisher = u'The ownCloud developers'
|
||||
epub_copyright = u'2013-2016, The ownCloud developers'
|
||||
epub_copyright = u'2013, The ownCloud developers'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
|
||||
|
Antes Largura: | Altura: | Tamanho: 52 KiB Depois Largura: | Altura: | Tamanho: 86 KiB |
|
Antes Largura: | Altura: | Tamanho: 82 KiB |
|
Antes Largura: | Altura: | Tamanho: 58 KiB Depois Largura: | Altura: | Tamanho: 49 KiB |
|
Antes Largura: | Altura: | Tamanho: 224 KiB Depois Largura: | Altura: | Tamanho: 58 KiB |
|
Antes Largura: | Altura: | Tamanho: 20 KiB Depois Largura: | Altura: | Tamanho: 23 KiB |
|
Antes Largura: | Altura: | Tamanho: 34 KiB Depois Largura: | Altura: | Tamanho: 24 KiB |
@@ -4,16 +4,16 @@ ownCloud Desktop Client Manual
|
||||
==============================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 3
|
||||
|
||||
introduction
|
||||
installing
|
||||
navigating
|
||||
advancedusage
|
||||
autoupdate
|
||||
|
||||
building
|
||||
architecture
|
||||
troubleshooting
|
||||
faq
|
||||
glossary
|
||||
|
||||
glossary
|
||||
@@ -12,22 +12,26 @@ Desktop Sync client enables you to:
|
||||
Your files are always automatically synchronized between your ownCloud server
|
||||
and local PC.
|
||||
|
||||
Because of various technical issues, desktop sync clients older than 1.7 will
|
||||
not allowed to connect and sync with the ownCloud 8.1+ server. It is highly
|
||||
recommended to keep your client updated.
|
||||
|
||||
.. note:: Because of various technical issues, desktop sync clients older than
|
||||
1.7 will not allowed to connect and sync with the ownCloud 8.1+ server. It
|
||||
is highly recommended to keep your client updated.
|
||||
|
||||
Improvements and New Features
|
||||
-----------------------------
|
||||
|
||||
The 2.2 release of the ownCloud desktop sync client has many new features and
|
||||
The 2.1 release of the ownCloud desktop sync client has many new features and
|
||||
improvements. (See the `complete changelog
|
||||
<https://owncloud.org/changelog/desktop/>`_.)
|
||||
|
||||
* Show server notifications on the client
|
||||
* Improved sync speed
|
||||
* Improved handling of Win32 file locks and network files
|
||||
* Improved user notifications about ignored files and conflicts
|
||||
* Add warnings for old server versions
|
||||
* Update of QtKeyChain to support Windows credential store
|
||||
* Packaging of dolphin overlay icon module for bleeding edge distros
|
||||
* Improved appearance on HiDPI screens
|
||||
* Improved error messages
|
||||
* Several fixes/improvements to the sharing dialog
|
||||
* Several fixes/improvements to the server activity tab
|
||||
* Allow changeable upload chunk size in owncloud.cfg
|
||||
* Forget password on explicit sign-out
|
||||
* Windows: Fix deleting and replacing of read-only files
|
||||
* Share with internal ownCloud users from your desktop
|
||||
* Separate views for server activity, sync activity, and errors
|
||||
* Don't re-upload *eml-files if size and checksum are unchanged
|
||||
* Improved upload/download progress indicator
|
||||
|
||||
@@ -62,7 +62,6 @@ This menu provides the following options:
|
||||
* Recent Changes, showing latest activities
|
||||
* Settings
|
||||
* Help menu
|
||||
* Pause synchronizations
|
||||
* An option to log in or log out of all of your accounts at once
|
||||
* Quit ownCloud, logging out and closing the client
|
||||
|
||||
@@ -84,7 +83,7 @@ have the following features:
|
||||
* Connection status, showing which ownCloud server you are connected to, and
|
||||
your ownCloud username.
|
||||
* An **Account** button, which contains a dropdown menu with **Add New**,
|
||||
**Log Out**, and **Remove**.
|
||||
**Log In/Log Out**, and **Remove**.
|
||||
* Used and available space on the server.
|
||||
* Current synchronization status.
|
||||
* **Add Folder Sync Connection** button, which is active only when you have
|
||||
@@ -94,17 +93,26 @@ The little button with three dots (the overflow menu) that sits to the right of
|
||||
the sync status bar offers four additional options:
|
||||
|
||||
* Open Folder
|
||||
* Choose What to Sync (This appears only when your file tree is collapsed, and
|
||||
expands the file tree)
|
||||
* Choose What to Sync
|
||||
* Pause Sync / Resume Sync
|
||||
* Remove folder sync connection
|
||||
|
||||
**Open Folder** opens your local ownCloud sync folder.
|
||||
**Open Folder** opens a file explorer window displaying the client-side folder
|
||||
that is being synced.
|
||||
|
||||
**Choose What to Sync** opens the folder sync tree view. Use this to sync all
|
||||
or only some of the folders in the folder tree.
|
||||
|
||||
**Pause Sync** pauses sync operations without making any changes to your
|
||||
account. It will continue to update file and folder lists, without
|
||||
downloading or updating files. To stop all sync activity use **Remove
|
||||
Folder Sync Connection**.
|
||||
downloading or updating files. To stop all sync activity use **Remove Sync**.
|
||||
|
||||
**Resume Sync** resumes sync operations.
|
||||
|
||||
**Remove Sync** removes the sync connection without removing the account. This
|
||||
stops all sync activity, including file and folder list updates. If you want to
|
||||
synchronize the folder tree again then click the **Add Folder Sync Connection**
|
||||
button, and re-select the folder tree that you want to sync.
|
||||
|
||||
.. figure:: images/client-7.png
|
||||
:alt: Extra options for sync operations
|
||||
@@ -117,10 +125,12 @@ Folder Sync Connection**.
|
||||
Adding New Accounts
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You may configure multiple ownCloud accounts in your desktop sync client. Simply
|
||||
You may configure multiple ownCloud accounts in your desktop sync client.
|
||||
Simply
|
||||
click the **Account** > **Add New** button on any account tab to add a new
|
||||
account, and then follow the account creation wizard. The new account will
|
||||
appear as a new tab in the settings dialog, where you can adjust its settings at
|
||||
appear as a new tab in the settings dialog, where you can adjust its settings
|
||||
at
|
||||
any time. Use **Account** > **Remove** to delete accounts.
|
||||
|
||||
File Manager Overlay Icons
|
||||
@@ -165,7 +175,9 @@ the ``owncloud-client-nautilus`` plugin.) You can create share links, and share
|
||||
with internal ownCloud users the same way as in your ownCloud Web interface.
|
||||
|
||||
.. figure:: images/mac-share.png
|
||||
:alt: Sync client integration in Windows Explorer.
|
||||
:alt: Sync client integration in Finder on Mac OS X.
|
||||
|
||||
*Shared ownCloud files in Finder on Mac OS X*
|
||||
|
||||
Right-click your systray icon, hover over the account you want to use, and
|
||||
left-click "Open folder [folder name] to quickly enter your local ownCloud
|
||||
@@ -194,25 +206,6 @@ such as files not synced.
|
||||
|
||||
.. figure:: images/client-8.png
|
||||
:alt: Activity windows logs all server and client activities.
|
||||
|
||||
Server Notifications
|
||||
--------------------
|
||||
|
||||
Starting with version 2.2.0, the client will display notifications from your
|
||||
ownCloud server that require manual interaction by you. For example, when a
|
||||
user on a remote ownCloud creates a new Federated share for you, you can accept
|
||||
it from your desktop client.
|
||||
|
||||
The desktop client automatically checks for available notifications
|
||||
automatically on a regular basis. Notifications are displayed in the Server
|
||||
Activity tab, and if you have **Show Desktop Notifications** enabled (General
|
||||
tab) you'll also see a systray notification.
|
||||
|
||||
.. figure:: images/client12.png
|
||||
:alt: Activity window with notification.
|
||||
|
||||
This also displays notifications sent to users by the ownCloud admin via the
|
||||
Announcements app.
|
||||
|
||||
General Window
|
||||
--------------
|
||||
|
||||
@@ -11,218 +11,11 @@ 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
|
||||
Icon[oc]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
|
||||
GenericName[ar]=مزامنة المجلد
|
||||
Name[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
|
||||
Icon[ar]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
GenericName[ca]=Sincronització de carpetes
|
||||
Name[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
Icon[ca]=@APPLICATION_EXECUTABLE@
|
||||
Comment[da]=@APPLICATION_NAME@ skrivebordsklient til synkronisering
|
||||
GenericName[da]=Mappesynkronisering
|
||||
Name[da]=@APPLICATION_NAME@ skrivebordsklient til synk
|
||||
Icon[da]=@APPLICATION_EXECUTABLE@
|
||||
Comment[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
GenericName[de]=Ordner-Synchronisation
|
||||
Name[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
Icon[de]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
GenericName[ja_JP]=フォルダ同期
|
||||
Name[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
Icon[ja_JP]=@APPLICATION_EXECUTABLE@
|
||||
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
|
||||
GenericName[en_GB]=Folder Sync
|
||||
Name[en_GB]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[en_GB]=@APPLICATION_EXECUTABLE@
|
||||
Comment[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
|
||||
GenericName[es]=Sincronización de carpeta
|
||||
Name[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
|
||||
Icon[es]=@APPLICATION_EXECUTABLE@
|
||||
Comment[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
GenericName[de_DE]=Ordner-Synchronisation
|
||||
Name[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
Icon[de_DE]=@APPLICATION_EXECUTABLE@
|
||||
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
|
||||
GenericName[bg_BG]=Синхронизиране на папката
|
||||
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
|
||||
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
|
||||
Comment[fr]=@APPLICATION_NAME@ synchronisation du client
|
||||
GenericName[fr]=Dossier de Synchronisation
|
||||
Name[fr]=@APPLICATION_NAME@ synchronisation du client
|
||||
Icon[fr]=@APPLICATION_EXECUTABLE@
|
||||
Comment[he]=@APPLICATION_NAME@ לקוח סנכון שולחן עבודה
|
||||
GenericName[he]=סנכון תיקייה
|
||||
Name[he]=@APPLICATION_NAME@ לקוח סנכרון שולחן עבודה
|
||||
Icon[he]=@APPLICATION_EXECUTABLE@
|
||||
Comment[id]=Klien sinkronisasi desktop @APPLICATION_NAME@
|
||||
GenericName[id]=Folder Sync
|
||||
Name[id]=Klien sync desktop @APPLICATION_NAME@
|
||||
Icon[id]=@APPLICATION_EXECUTABLE@
|
||||
Comment[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
|
||||
GenericName[is]=Samstilling möppu
|
||||
Name[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
|
||||
Icon[is]=@APPLICATION_EXECUTABLE@
|
||||
Comment[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
|
||||
GenericName[it]=Sincronizzazione cartella
|
||||
Name[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
|
||||
Icon[it]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
GenericName[ko]=폴더 동기화
|
||||
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
|
||||
GenericName[hu_HU]=Könyvtár szinkronizálás
|
||||
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkr. kliens
|
||||
Icon[hu_HU]=@APPLICATION_EXECUTABLE@
|
||||
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
|
||||
GenericName[nl]=Mappen sync
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[nl]=@APPLICATION_EXECUTABLE@
|
||||
Icon[pl]=@APPLICATION_EXECUTABLE@
|
||||
Comment[pt_BR]=@APPLICATION_NAME@ cliente de sincronização do computador
|
||||
GenericName[pt_BR]=Sincronização de Pasta
|
||||
Name[pt_BR]=@APPLICATION_NAME@ cliente de sincronização de desktop
|
||||
Icon[pt_BR]=@APPLICATION_EXECUTABLE@
|
||||
Comment[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
GenericName[cs_CZ]=Synchronizace adresáře
|
||||
Name[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
Icon[cs_CZ]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
|
||||
GenericName[ru]=Синхронизация папки
|
||||
Name[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
|
||||
Icon[ru]=@ВЫПОЛНЯЕМОЕ_ПРИЛОЖЕНИЕ@
|
||||
Comment[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
GenericName[sl]=Usklajevanje map
|
||||
Name[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
Icon[sl]=@APPLICATION_EXECUTABLE@
|
||||
Comment[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
GenericName[sq]=Njëkohësim Dosjesh
|
||||
Name[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
Icon[sq]=@APPLICATION_EXECUTABLE@
|
||||
Comment[sv]=@APPLICATION_NAME@ desktop synkroniseringsklient
|
||||
GenericName[sv]=Mappsynk
|
||||
Name[sv]=@APPLICATION_NAME@ desktop synk-klient
|
||||
Icon[sv]=@APPLICATION_EXECUTABLE@
|
||||
Comment[tr]=@APPLICATION_NAME@ masaüstü senkronizasyon istemcisi
|
||||
GenericName[tr]=Dosya Senkronizasyonu
|
||||
Name[tr]=@APPLICATION_NAME@ masaüstü senkronizasyon istemcisi
|
||||
Icon[tr]=@APPLICATION_EXECUTABLE@
|
||||
Comment[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
|
||||
GenericName[uk]=Синхронізація теки
|
||||
Name[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
|
||||
Icon[uk]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
|
||||
GenericName[ro]=Sincronizare director
|
||||
Name[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
|
||||
Icon[ro]=@APPLICATION_EXECUTABLE@
|
||||
Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
GenericName[zh_CN]=文件夹同步
|
||||
Name[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
Icon[zh_CN]=@APPLICATION_EXECUTABLE@
|
||||
GenericName[zh_TW]=資料夾同步
|
||||
Comment[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
|
||||
GenericName[pt_PT]=Sincronizar Pasta
|
||||
Name[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
|
||||
Icon[pt_PT]=@APPLICATION_EXECUTABLE@
|
||||
Comment[lb]=@APPLICATION_NAME@ Desktop Synchronisatioun Client
|
||||
GenericName[lb]=Dossier Dync
|
||||
Name[lb]=@APPLICATION_NAME@ Desktop Sync Client
|
||||
Icon[lb]=@APPLICATION_EXECUTABLE@
|
||||
Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
|
||||
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
|
||||
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
|
||||
Icon[th_TH]=@APPLICATION_EXECUTABLE@
|
||||
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
|
||||
GenericName[nl]=Mappen sync
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[nl]=@APPLICATION_EXECUTABLE@
|
||||
|
||||
@@ -36,7 +36,8 @@ using namespace std;
|
||||
|
||||
OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud";
|
||||
|
||||
CommunicationSocket socket;
|
||||
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
|
||||
@@ -71,7 +72,8 @@ OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
|
||||
|
||||
void OCClientInterface::ShareObject(const std::wstring &path)
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud";
|
||||
|
||||
CommunicationSocket socket;
|
||||
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
|
||||
|
||||
@@ -24,31 +24,11 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#define DEFAULT_BUFLEN 4096
|
||||
#define BUFSIZE 1024
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
std::wstring getUserName() {
|
||||
DWORD len = DEFAULT_BUFLEN;
|
||||
TCHAR buf[DEFAULT_BUFLEN];
|
||||
if (GetUserName(buf, &len)) {
|
||||
return std::wstring(&buf[0], len);
|
||||
} else {
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::wstring CommunicationSocket::DefaultPipePath()
|
||||
{
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud\\";
|
||||
pipename += getUserName();
|
||||
return pipename;
|
||||
}
|
||||
#define DEFAULT_BUFLEN 4096
|
||||
|
||||
CommunicationSocket::CommunicationSocket()
|
||||
: _pipe(INVALID_HANDLE_VALUE)
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
class __declspec(dllexport) CommunicationSocket
|
||||
{
|
||||
public:
|
||||
static std::wstring DefaultPipePath();
|
||||
|
||||
CommunicationSocket();
|
||||
~CommunicationSocket();
|
||||
|
||||
@@ -45,4 +43,4 @@ private:
|
||||
bool _connected;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -31,10 +31,25 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define BUFSIZE 512
|
||||
|
||||
std::wstring getUserName() {
|
||||
DWORD len = BUFSIZE;
|
||||
TCHAR buf[BUFSIZE];
|
||||
if (GetUserName(buf, &len)) {
|
||||
return std::wstring(&buf[0], len);
|
||||
} else {
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
// This code is run in a thread
|
||||
void RemotePathChecker::workerThreadLoop()
|
||||
{
|
||||
auto pipename = CommunicationSocket::DefaultPipePath();
|
||||
auto pipename = std::wstring(L"\\\\.\\pipe\\");
|
||||
pipename += L"ownCloud\\";
|
||||
pipename += getUserName();
|
||||
|
||||
bool connected = false;
|
||||
CommunicationSocket socket;
|
||||
std::unordered_set<std::wstring> asked;
|
||||
|
||||
@@ -28,12 +28,16 @@
|
||||
* \return string PEM
|
||||
*/
|
||||
string x509ToString(BIO *o) {
|
||||
int len = 0;
|
||||
BUF_MEM *bptr;
|
||||
void* data;
|
||||
string ret = "";
|
||||
|
||||
BIO_get_mem_ptr(o, &bptr);
|
||||
int len = bptr->length;
|
||||
void* data = calloc(len+10, sizeof(char));
|
||||
len = bptr->length;
|
||||
data = calloc(len+10, sizeof(char));
|
||||
BIO_read(o, data, len);
|
||||
string ret = std::string(static_cast<char*>(data));
|
||||
ret = strdup((char*)data);
|
||||
free(data);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -443,27 +443,16 @@ restart_sync:
|
||||
QObject::connect(&engine, SIGNAL(finished(bool)), &app, SLOT(quit()));
|
||||
QObject::connect(&engine, SIGNAL(transmissionProgress(ProgressInfo)), &cmd, SLOT(transmissionProgressSlot()));
|
||||
|
||||
|
||||
// Exclude lists
|
||||
|
||||
bool hasUserExcludeFile = !options.exclude.isEmpty();
|
||||
QString systemExcludeFile = ConfigFile::excludeFileFromSystem();
|
||||
|
||||
// Always try to load the user-provided exclude list if one is specified
|
||||
if ( hasUserExcludeFile ) {
|
||||
engine.excludedFiles().addExcludeFilePath(ConfigFile::excludeFileFromSystem());
|
||||
if( QFile::exists(options.exclude) )
|
||||
engine.excludedFiles().addExcludeFilePath(options.exclude);
|
||||
}
|
||||
// Load the system list if available, or if there's no user-provided list
|
||||
if ( !hasUserExcludeFile || QFile::exists(systemExcludeFile) ) {
|
||||
engine.excludedFiles().addExcludeFilePath(systemExcludeFile);
|
||||
}
|
||||
|
||||
if (!engine.excludedFiles().reloadExcludes()) {
|
||||
// Always make sure at least one list has been loaded
|
||||
qFatal("Cannot load system exclude list or list supplied via --exclude");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Have to be done async, else, an error before exec() does not terminate the event loop.
|
||||
QMetaObject::invokeMethod(&engine, "startSync", Qt::QueuedConnection);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ qt_wrap_ui(client_UI_SRCS ${client_UI})
|
||||
set(client_SRCS
|
||||
accountmanager.cpp
|
||||
accountsettings.cpp
|
||||
application.cpp
|
||||
ocapplication.cpp
|
||||
folder.cpp
|
||||
folderman.cpp
|
||||
folderstatusmodel.cpp
|
||||
@@ -212,6 +212,10 @@ if(QTKEYCHAIN_FOUND OR QT5KEYCHAIN_FOUND)
|
||||
list(APPEND libsync_LINK_TARGETS ${QTKEYCHAIN_LIBRARY})
|
||||
include_directories(${QTKEYCHAIN_INCLUDE_DIR})
|
||||
endif()
|
||||
if(LibsnoreQt5_FOUND)
|
||||
add_definitions(-DHAVE_LIBSNORE)
|
||||
|
||||
endif()
|
||||
|
||||
# add executable icon on windows and osx
|
||||
include( AddAppIconMacro )
|
||||
@@ -289,6 +293,7 @@ target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} updater )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} ${OS_SPECIFIC_LINK_LIBRARIES} )
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} Snore::Libsnore Snore::LibsnoreSettings )
|
||||
|
||||
if(WITH_CRASHREPORTER)
|
||||
target_link_libraries( ${APPLICATION_EXECUTABLE} crashreporter-handler)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "folderstatusmodel.h"
|
||||
#include "folderstatusdelegate.h"
|
||||
#include "utility.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "configfile.h"
|
||||
#include "account.h"
|
||||
#include "accountstate.h"
|
||||
@@ -159,13 +159,7 @@ void AccountSettings::createAccountToolbox()
|
||||
|
||||
void AccountSettings::slotOpenAccountWizard()
|
||||
{
|
||||
if (
|
||||
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
|
||||
qgetenv("QT_QPA_PLATFORMTHEME") == "appmenu-qt5" ||
|
||||
// We can't call isSystemTrayAvailable with appmenu-qt5 because it breaks the systemtray
|
||||
// (issue #4693, #4944)
|
||||
#endif
|
||||
QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
if (QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
topLevelWidget()->close();
|
||||
}
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
@@ -190,8 +190,7 @@ void AccountState::checkConnectivity()
|
||||
} else {
|
||||
// Check the server and then the auth.
|
||||
|
||||
// Let's try this for all OS and see if it fixes the Qt issues we have on Linux #4720 #3888 #4051
|
||||
//#ifdef Q_OS_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
// There seems to be a bug in Qt on Windows where QNAM sometimes stops
|
||||
// working correctly after the computer woke up from sleep. See #2895 #2899
|
||||
// and #2973.
|
||||
@@ -202,7 +201,7 @@ void AccountState::checkConnectivity()
|
||||
// If we don't reset the ssl config a second CheckServerJob can produce a
|
||||
// ssl config that does not have a sensible certificate chain.
|
||||
account()->setSslConfiguration(QSslConfiguration());
|
||||
//#endif
|
||||
#endif
|
||||
conValidator->checkServerAndAuth();
|
||||
}
|
||||
}
|
||||
@@ -210,7 +209,6 @@ void AccountState::checkConnectivity()
|
||||
void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors)
|
||||
{
|
||||
if (isSignedOut()) {
|
||||
qDebug() << "Signed out, ignoring" << connectionStatusString(status) << _account->url().toString();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class ActivityListModel;
|
||||
namespace Ui {
|
||||
class ActivityWidget;
|
||||
}
|
||||
class Application;
|
||||
class oCApplication;
|
||||
|
||||
/**
|
||||
* @brief The ActivityWidget class
|
||||
|
||||
@@ -38,12 +38,7 @@ namespace OCC
|
||||
|
||||
class UserAgentWebPage : public QWebPage {
|
||||
public:
|
||||
UserAgentWebPage(QObject *parent) : QWebPage(parent)
|
||||
{
|
||||
if (!qgetenv("OWNCLOUD_SHIBBOLETH_DEBUG").isEmpty()) {
|
||||
settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
|
||||
}
|
||||
}
|
||||
UserAgentWebPage(QObject *parent) : QWebPage(parent) {}
|
||||
QString userAgentForUrl(const QUrl &url ) const {
|
||||
return QWebPage::userAgentForUrl(url) + " " + Utility::userAgentString();
|
||||
}
|
||||
|
||||
@@ -46,6 +46,14 @@
|
||||
|
||||
namespace OCC {
|
||||
|
||||
static void csyncLogCatcher(int /*verbosity*/,
|
||||
const char */*function*/,
|
||||
const char *buffer,
|
||||
void */*userdata*/)
|
||||
{
|
||||
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
|
||||
}
|
||||
|
||||
|
||||
Folder::Folder(const FolderDefinition& definition,
|
||||
AccountState* accountState,
|
||||
@@ -113,8 +121,6 @@ Folder::Folder(const FolderDefinition& definition,
|
||||
|
||||
Folder::~Folder()
|
||||
{
|
||||
// Reset then engine first as it will abort and try to access members of the Folder
|
||||
_engine.reset();
|
||||
}
|
||||
|
||||
void Folder::checkLocalPath()
|
||||
@@ -314,7 +320,6 @@ void Folder::slotRunEtagJob()
|
||||
// sync if it's different.
|
||||
|
||||
_requestEtagJob = new RequestEtagJob(account, remotePath(), this);
|
||||
_requestEtagJob->setTimeout(60*1000);
|
||||
// check if the etag is different
|
||||
QObject::connect(_requestEtagJob, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
||||
FolderMan::instance()->slotScheduleETagJob(alias(), _requestEtagJob);
|
||||
@@ -573,10 +578,19 @@ int Folder::slotWipeErrorBlacklist()
|
||||
|
||||
void Folder::slotWatchedPathChanged(const QString& path)
|
||||
{
|
||||
// When no sync is running or it's in the prepare phase, we can
|
||||
// always schedule a new sync.
|
||||
if (! _engine->isSyncRunning() || _syncResult.status() == SyncResult::SyncPrepare) {
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// The folder watcher fires a lot of bogus notifications during
|
||||
// a sync operation, both for actual user files and the database
|
||||
// and log. Therefore we check notifications against operations
|
||||
// the sync is doing to filter out our own changes.
|
||||
bool ownChange = false;
|
||||
#ifdef Q_OS_MAC
|
||||
Q_UNUSED(path)
|
||||
// On OSX the folder watcher does not report changes done by our
|
||||
@@ -586,23 +600,14 @@ void Folder::slotWatchedPathChanged(const QString& path)
|
||||
const auto maxNotificationDelay = 15*1000;
|
||||
qint64 time = _engine->timeSinceFileTouched(path);
|
||||
if (time != -1 && time < maxNotificationDelay) {
|
||||
return;
|
||||
ownChange = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check that the mtime actually changed.
|
||||
if (path.startsWith(this->path())) {
|
||||
auto relativePath = path.mid(this->path().size());
|
||||
auto record = _journal.getFileRecord(relativePath);
|
||||
if (record.isValid() && !FileSystem::fileChanged(path, record._fileSize,
|
||||
Utility::qDateTimeToTime_t(record._modtime))) {
|
||||
qDebug() << "Ignoring spurious notification for file" << relativePath;
|
||||
return; // probably a spurious notification
|
||||
}
|
||||
if (! ownChange) {
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
}
|
||||
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit scheduleToSync(this);
|
||||
}
|
||||
|
||||
void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
|
||||
@@ -625,7 +630,7 @@ void Folder::removeFromSettings() const
|
||||
{
|
||||
auto settings = _accountState->settings();
|
||||
settings->beginGroup(QLatin1String("Folders"));
|
||||
settings->remove(FolderMan::escapeAlias(_definition.alias));
|
||||
settings->remove(_definition.alias);
|
||||
}
|
||||
|
||||
bool Folder::isFileExcludedAbsolute(const QString& fullPath) const
|
||||
@@ -689,10 +694,6 @@ void Folder::wipe()
|
||||
|
||||
bool Folder::setIgnoredFiles()
|
||||
{
|
||||
// Note: Doing this on each sync run and on Folder construction is
|
||||
// unnecessary, because _engine->excludedFiles() persists between
|
||||
// sync runs. This is not a big problem because ExcludedFiles maintains
|
||||
// a QSet of files to load.
|
||||
ConfigFile cfg;
|
||||
QString systemList = cfg.excludeFile(ConfigFile::SystemScope);
|
||||
if( QFile::exists(systemList) ) {
|
||||
@@ -724,6 +725,8 @@ void Folder::startSync(const QStringList &pathList)
|
||||
if (proxyDirty()) {
|
||||
setProxyDirty(false);
|
||||
}
|
||||
csync_set_log_callback( csyncLogCatcher );
|
||||
csync_set_log_level( Logger::instance()->isNoop() ? 0 : 11 );
|
||||
|
||||
if (isBusy()) {
|
||||
qCritical() << "* ERROR csync is still running and new sync requested.";
|
||||
@@ -912,7 +915,7 @@ void Folder::slotFolderDiscovered(bool, QString folderName)
|
||||
// and hand the result over to the progress dispatcher.
|
||||
void Folder::slotTransmissionProgress(const ProgressInfo &pi)
|
||||
{
|
||||
if( !pi.isUpdatingEstimates() ) {
|
||||
if( !pi.hasStarted() ) {
|
||||
// this is the beginning of a sync, set the warning level to 0
|
||||
_syncResult.setWarnCount(0);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class TestFolderMan;
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class SyncResult;
|
||||
class SocketApi;
|
||||
class LockWatcher;
|
||||
@@ -255,7 +255,7 @@ private:
|
||||
|
||||
static FolderMan *_instance;
|
||||
explicit FolderMan(QObject *parent = 0);
|
||||
friend class OCC::Application;
|
||||
friend class OCC::oCApplication;
|
||||
friend class ::TestFolderMan;
|
||||
};
|
||||
|
||||
|
||||
@@ -51,14 +51,6 @@ static void callback(
|
||||
Q_UNUSED(eventFlags)
|
||||
Q_UNUSED(eventIds)
|
||||
|
||||
const FSEventStreamEventFlags c_interestingFlags
|
||||
= kFSEventStreamEventFlagItemCreated // for new folder/file
|
||||
| kFSEventStreamEventFlagItemRemoved // for rm
|
||||
| kFSEventStreamEventFlagItemInodeMetaMod // for mtime change
|
||||
| kFSEventStreamEventFlagItemRenamed // also coming for moves to trash in finder
|
||||
| kFSEventStreamEventFlagItemModified; // for content change
|
||||
//We ignore other flags, e.g. for owner change, xattr change, Finder label change etc
|
||||
|
||||
qDebug() << "FolderWatcherPrivate::callback by OS X";
|
||||
|
||||
QStringList paths;
|
||||
@@ -70,14 +62,8 @@ static void callback(
|
||||
CFIndex pathLength = CFStringGetLength(path);
|
||||
qstring.resize(pathLength);
|
||||
CFStringGetCharacters(path, CFRangeMake(0, pathLength), reinterpret_cast<UniChar *>(qstring.data()));
|
||||
QString fn = qstring.normalized(QString::NormalizationForm_C);
|
||||
|
||||
if (!(eventFlags[i] & c_interestingFlags)) {
|
||||
qDebug() << "Ignoring non-content changes for" << fn;
|
||||
continue;
|
||||
}
|
||||
|
||||
paths.append(fn);
|
||||
paths.append(qstring.normalized(QString::NormalizationForm_C));
|
||||
}
|
||||
|
||||
reinterpret_cast<FolderWatcherPrivate*>(clientCallBackInfo)->doNotifyParent(paths);
|
||||
|
||||
@@ -68,6 +68,13 @@ FolderWizardLocalPath::FolderWizardLocalPath()
|
||||
_ui.localFolderLineEdit->setText( QDir::toNativeSeparators( defaultPath ) );
|
||||
_ui.localFolderLineEdit->setToolTip(tr("Enter the path to the local folder."));
|
||||
|
||||
QString newAlias = Theme::instance()->appName();
|
||||
int count = 0;
|
||||
while (FolderMan::instance()->folder(newAlias)) {
|
||||
// There is already a folder configured with this name and folder names need to be unique
|
||||
newAlias = Theme::instance()->appName() + QString::number(++count);
|
||||
}
|
||||
|
||||
_ui.warnLabel->setTextFormat(Qt::RichText);
|
||||
_ui.warnLabel->hide();
|
||||
}
|
||||
@@ -128,6 +135,14 @@ void FolderWizardLocalPath::slotChooseLocalFolder()
|
||||
if (!dir.isEmpty()) {
|
||||
// set the last directory component name as alias
|
||||
_ui.localFolderLineEdit->setText(QDir::toNativeSeparators(dir));
|
||||
|
||||
QDir pickedDir(dir);
|
||||
QString newAlias = pickedDir.dirName();
|
||||
int count = 0;
|
||||
while (FolderMan::instance()->folder(newAlias)) {
|
||||
// There is already a folder configured with this name and folder names need to be unique
|
||||
newAlias = pickedDir.dirName() + QString::number(++count);
|
||||
}
|
||||
}
|
||||
emit completeChanged();
|
||||
}
|
||||
@@ -488,13 +503,11 @@ FolderWizardSelectiveSync::~FolderWizardSelectiveSync()
|
||||
|
||||
void FolderWizardSelectiveSync::initializePage()
|
||||
{
|
||||
QString alias = wizard()->field(QLatin1String("alias")).toString();
|
||||
QString targetPath = wizard()->property("targetPath").toString();
|
||||
if (targetPath.startsWith('/')) {
|
||||
targetPath = targetPath.mid(1);
|
||||
}
|
||||
QString alias = QFileInfo(targetPath).fileName();
|
||||
if (alias.isEmpty())
|
||||
alias = Theme::instance()->appName();
|
||||
_treeView->setFolderInfo(targetPath, alias);
|
||||
QWizardPage::initializePage();
|
||||
}
|
||||
@@ -507,10 +520,8 @@ bool FolderWizardSelectiveSync::validatePage()
|
||||
|
||||
void FolderWizardSelectiveSync::cleanupPage()
|
||||
{
|
||||
QString alias = wizard()->field(QLatin1String("alias")).toString();
|
||||
QString targetPath = wizard()->property("targetPath").toString();
|
||||
QString alias = QFileInfo(targetPath).fileName();
|
||||
if (alias.isEmpty())
|
||||
alias = Theme::instance()->appName();
|
||||
_treeView->setFolderInfo(targetPath, alias);
|
||||
QWizardPage::cleanupPage();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "theme.h"
|
||||
#include "configfile.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "utility.h"
|
||||
#include "configfile.h"
|
||||
#include "owncloudsetupwizard.h"
|
||||
@@ -161,4 +161,12 @@ void GeneralSettings::slotIgnoreFilesEditor()
|
||||
}
|
||||
}
|
||||
|
||||
void GeneralSettings::slotOpenAccountWizard()
|
||||
{
|
||||
if (QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
topLevelWidget()->close();
|
||||
}
|
||||
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), 0);
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -44,6 +44,7 @@ private slots:
|
||||
void slotToggleOptionalDesktopNotifications(bool);
|
||||
void slotUpdateInfo();
|
||||
void slotIgnoreFilesEditor();
|
||||
void slotOpenAccountWizard();
|
||||
|
||||
private:
|
||||
void loadMiscSettings();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "theme.h"
|
||||
#include "utility.h"
|
||||
#include "cocoainitializer.h"
|
||||
@@ -47,26 +47,23 @@ int main(int argc, char **argv)
|
||||
{
|
||||
Q_INIT_RESOURCE(client);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#ifndef Q_OS_MAC
|
||||
// If the font size ratio is set on Windows, we need to
|
||||
// enable the auto pixelRatio in Qt since we don't
|
||||
// want to use sizes relative to the font size everywhere.
|
||||
// This is automatic on OS X, but opt-in on Windows and Linux
|
||||
// https://doc-snapshots.qt.io/qt5-5.6/highdpi.html#qt-support
|
||||
// We do not define it on linux so the behaviour is kept the same
|
||||
// as other Qt apps in the desktop environment. (which may or may
|
||||
// not set this envoronment variable)
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
|
||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
|
||||
qputenv("QT_DEVICE_PIXEL_RATIO", "auto");
|
||||
#else
|
||||
qputenv("QT_DEVICE_PIXEL_RATIO", "auto"); // See #4840, #4994
|
||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
||||
#endif
|
||||
#endif // !Q_OS_WIN
|
||||
#endif // !Q_OS_MAC
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
Mac::CocoaInitializer cocoaInit; // RIIA
|
||||
#endif
|
||||
OCC::Application app(argc, argv);
|
||||
OCC::oCApplication app(argc, argv);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// The Windows style still has pixelated elements with Qt 5.6,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "theme.h"
|
||||
#include "configfile.h"
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "utility.h"
|
||||
#include "configfile.h"
|
||||
#include "folderman.h"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -91,7 +91,7 @@ QString applicationTrPath()
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
Application::Application(int &argc, char **argv) :
|
||||
oCApplication::oCApplication(int &argc, char **argv) :
|
||||
SharedTools::QtSingleApplication(Theme::instance()->appName() ,argc, argv),
|
||||
_gui(0),
|
||||
_theme(Theme::instance()),
|
||||
@@ -139,7 +139,6 @@ Application::Application(int &argc, char **argv) :
|
||||
setupTranslations();
|
||||
|
||||
// Setup global excludes
|
||||
qDebug() << "Loading global exclude list";
|
||||
ConfigFile cfg;
|
||||
ExcludedFiles& excludes = ExcludedFiles::instance();
|
||||
excludes.addExcludeFilePath( cfg.excludeFile(ConfigFile::SystemScope) );
|
||||
@@ -203,7 +202,7 @@ Application::Application(int &argc, char **argv) :
|
||||
connect (this, SIGNAL(aboutToQuit()), SLOT(slotCleanup()));
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
oCApplication::~oCApplication()
|
||||
{
|
||||
// Make sure all folders are gone, otherwise removing the
|
||||
// accounts will remove the associated folders from the settings.
|
||||
@@ -215,7 +214,7 @@ Application::~Application()
|
||||
AccountManager::instance()->shutdown();
|
||||
}
|
||||
|
||||
void Application::slotAccountStateRemoved(AccountState *accountState)
|
||||
void oCApplication::slotAccountStateRemoved(AccountState *accountState)
|
||||
{
|
||||
if (_gui) {
|
||||
disconnect(accountState, SIGNAL(stateChanged(int)),
|
||||
@@ -238,7 +237,7 @@ void Application::slotAccountStateRemoved(AccountState *accountState)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotAccountStateAdded(AccountState *accountState)
|
||||
void oCApplication::slotAccountStateAdded(AccountState *accountState)
|
||||
{
|
||||
connect(accountState, SIGNAL(stateChanged(int)),
|
||||
_gui, SLOT(slotAccountStateChanged()));
|
||||
@@ -252,7 +251,7 @@ void Application::slotAccountStateAdded(AccountState *accountState)
|
||||
_gui->slotTrayMessageIfServerUnsupported(accountState->account().data());
|
||||
}
|
||||
|
||||
void Application::slotCleanup()
|
||||
void oCApplication::slotCleanup()
|
||||
{
|
||||
AccountManager::instance()->save();
|
||||
FolderMan::instance()->unloadAndDeleteAllFolders();
|
||||
@@ -264,7 +263,7 @@ void Application::slotCleanup()
|
||||
// FIXME: This is not ideal yet since a ConnectionValidator might already be running and is in
|
||||
// progress of timing out in some seconds.
|
||||
// Maybe we need 2 validators, one triggered by timer, one by network configuration changes?
|
||||
void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
||||
void oCApplication::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
||||
{
|
||||
if (cnf.state() & QNetworkConfiguration::Active) {
|
||||
//qDebug() << "Trying fast reconnect";
|
||||
@@ -272,7 +271,7 @@ void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotCheckConnection()
|
||||
void oCApplication::slotCheckConnection()
|
||||
{
|
||||
auto list = AccountManager::instance()->accounts();
|
||||
foreach (const auto &accountState , list) {
|
||||
@@ -294,12 +293,12 @@ void Application::slotCheckConnection()
|
||||
}
|
||||
}
|
||||
|
||||
void Application::slotCrash()
|
||||
void oCApplication::slotCrash()
|
||||
{
|
||||
Utility::crash();
|
||||
}
|
||||
|
||||
void Application::slotownCloudWizardDone( int res )
|
||||
void oCApplication::slotownCloudWizardDone( int res )
|
||||
{
|
||||
AccountManager *accountMan = AccountManager::instance();
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
@@ -336,15 +335,7 @@ void Application::slotownCloudWizardDone( int res )
|
||||
}
|
||||
}
|
||||
|
||||
static void csyncLogCatcher(int /*verbosity*/,
|
||||
const char */*function*/,
|
||||
const char *buffer,
|
||||
void */*userdata*/)
|
||||
{
|
||||
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
|
||||
}
|
||||
|
||||
void Application::setupLogging()
|
||||
void oCApplication::setupLogging()
|
||||
{
|
||||
// might be called from second instance
|
||||
Logger::instance()->setLogFile(_logFile);
|
||||
@@ -359,17 +350,14 @@ void Application::setupLogging()
|
||||
.arg(property("ui_lang").toString())
|
||||
.arg(_theme->version());
|
||||
|
||||
// Setup CSYNC logging to forward to our own logger
|
||||
csync_set_log_callback( csyncLogCatcher );
|
||||
csync_set_log_level( Logger::instance()->isNoop() ? 0 : 11 );
|
||||
}
|
||||
|
||||
void Application::slotUseMonoIconsChanged(bool)
|
||||
void oCApplication::slotUseMonoIconsChanged(bool)
|
||||
{
|
||||
_gui->slotComputeOverallSyncStatus();
|
||||
}
|
||||
|
||||
void Application::slotParseMessage(const QString &msg, QObject*)
|
||||
void oCApplication::slotParseMessage(const QString &msg, QObject*)
|
||||
{
|
||||
if (msg.startsWith(QLatin1String("MSG_PARSEOPTIONS:"))) {
|
||||
const int lengthOfMsgPrefix = 17;
|
||||
@@ -387,7 +375,7 @@ void Application::slotParseMessage(const QString &msg, QObject*)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::parseOptions(const QStringList &options)
|
||||
void oCApplication::parseOptions(const QStringList &options)
|
||||
{
|
||||
QStringListIterator it(options);
|
||||
// skip file name;
|
||||
@@ -467,7 +455,7 @@ static void displayHelpText(const QString &t)
|
||||
}
|
||||
#endif
|
||||
|
||||
void Application::showHelp()
|
||||
void oCApplication::showHelp()
|
||||
{
|
||||
setHelp();
|
||||
QString helpText;
|
||||
@@ -485,7 +473,7 @@ void Application::showHelp()
|
||||
displayHelpText(helpText);
|
||||
}
|
||||
|
||||
void Application::showVersion()
|
||||
void oCApplication::showVersion()
|
||||
{
|
||||
QString helpText;
|
||||
QTextStream stream(&helpText);
|
||||
@@ -497,7 +485,7 @@ void Application::showVersion()
|
||||
displayHelpText(helpText);
|
||||
}
|
||||
|
||||
void Application::showHint(std::string errorHint)
|
||||
void oCApplication::showHint(std::string errorHint)
|
||||
{
|
||||
static QString binName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
|
||||
std::cerr << errorHint << std::endl;
|
||||
@@ -505,12 +493,12 @@ void Application::showHint(std::string errorHint)
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
bool Application::debugMode()
|
||||
bool oCApplication::debugMode()
|
||||
{
|
||||
return _debugMode;
|
||||
}
|
||||
|
||||
void Application::setHelp()
|
||||
void oCApplication::setHelp()
|
||||
{
|
||||
_helpOnly = true;
|
||||
}
|
||||
@@ -530,7 +518,7 @@ QString substLang(const QString &lang)
|
||||
return lang;
|
||||
}
|
||||
|
||||
void Application::setupTranslations()
|
||||
void oCApplication::setupTranslations()
|
||||
{
|
||||
QStringList uiLanguages;
|
||||
// uiLanguages crashes on Windows with 4.8.0 release builds
|
||||
@@ -594,21 +582,20 @@ void Application::setupTranslations()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Application::giveHelp()
|
||||
bool oCApplication::giveHelp()
|
||||
{
|
||||
return _helpOnly;
|
||||
}
|
||||
|
||||
bool Application::versionOnly()
|
||||
bool oCApplication::versionOnly()
|
||||
{
|
||||
return _versionOnly;
|
||||
}
|
||||
|
||||
void Application::showSettingsDialog()
|
||||
void oCApplication::showSettingsDialog()
|
||||
{
|
||||
_gui->slotShowSettings();
|
||||
}
|
||||
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef APPLICATION_H
|
||||
#define APPLICATION_H
|
||||
#ifndef OCAPPLICATION_H
|
||||
#define OCAPPLICATION_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPointer>
|
||||
@@ -49,12 +49,12 @@ class SslErrorDialog;
|
||||
* @brief The Application class
|
||||
* @ingroup gui
|
||||
*/
|
||||
class Application : public SharedTools::QtSingleApplication
|
||||
class oCApplication : public SharedTools::QtSingleApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Application(int &argc, char **argv);
|
||||
~Application();
|
||||
explicit oCApplication(int &argc, char **argv);
|
||||
~oCApplication();
|
||||
|
||||
bool giveHelp();
|
||||
void showHelp();
|
||||
@@ -11,7 +11,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
#include "ocapplication.h"
|
||||
#include "owncloudgui.h"
|
||||
#include "theme.h"
|
||||
#include "folderman.h"
|
||||
@@ -47,7 +47,7 @@ namespace OCC {
|
||||
|
||||
const char propertyAccountC[] = "oc_account";
|
||||
|
||||
ownCloudGui::ownCloudGui(Application *parent) :
|
||||
ownCloudGui::ownCloudGui(oCApplication *parent) :
|
||||
QObject(parent),
|
||||
_tray(0),
|
||||
#if defined(Q_OS_MAC)
|
||||
@@ -96,10 +96,10 @@ ownCloudGui::ownCloudGui(Application *parent) :
|
||||
connect( AccountManager::instance(), SIGNAL(accountRemoved(AccountState*)),
|
||||
SLOT(setupContextMenu()));
|
||||
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString)),
|
||||
SLOT(slotShowTrayMessage(QString,QString)));
|
||||
connect( Logger::instance(), SIGNAL(optionalGuiLog(QString,QString)),
|
||||
SLOT(slotShowOptionalTrayMessage(QString,QString)));
|
||||
connect( Logger::instance(), SIGNAL(guiLog(QString,QString, Logger::NotificationType)),
|
||||
SLOT(slotShowTrayMessage(QString,QString, Logger::NotificationType)));
|
||||
connect( Logger::instance(), SIGNAL(optionalGuiLog(QString,QString, Logger::NotificationType)),
|
||||
SLOT(slotShowOptionalTrayMessage(QString,QString,Logger::NotificationType)));
|
||||
connect( Logger::instance(), SIGNAL(guiMessage(QString,QString)),
|
||||
SLOT(slotShowGuiMessage(QString,QString)));
|
||||
|
||||
@@ -237,7 +237,8 @@ void ownCloudGui::slotTrayMessageIfServerUnsupported(Account* account)
|
||||
tr("The server on account %1 runs an old and unsupported version %2. "
|
||||
"Using this client with unsupported server versions is untested and "
|
||||
"potentially dangerous. Proceed at your own risk.")
|
||||
.arg(account->displayName(), account->serverVersion()));
|
||||
.arg(account->displayName(), account->serverVersion()),
|
||||
Logger::Critical );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,19 +536,36 @@ void ownCloudGui::setupContextMenu()
|
||||
}
|
||||
|
||||
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg)
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type)
|
||||
{
|
||||
if( _tray )
|
||||
_tray->showMessage(title, msg);
|
||||
else
|
||||
if( _tray ) {
|
||||
QSystemTrayIcon::MessageIcon trayIcon = QSystemTrayIcon::NoIcon;
|
||||
switch( type ) {
|
||||
case Logger::NoIcon:
|
||||
break;
|
||||
case Logger::Information:
|
||||
trayIcon = QSystemTrayIcon::Information;
|
||||
break;
|
||||
case Logger::SoftError:
|
||||
trayIcon = QSystemTrayIcon::Warning;
|
||||
break;
|
||||
case Logger::Error:
|
||||
case Logger::Critical:
|
||||
trayIcon = QSystemTrayIcon::Critical;
|
||||
break;
|
||||
}
|
||||
|
||||
_tray->showMessage(title, msg, trayIcon);
|
||||
} else {
|
||||
qDebug() << "Tray not ready: " << msg;
|
||||
}
|
||||
}
|
||||
|
||||
void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg)
|
||||
void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type)
|
||||
{
|
||||
ConfigFile cfg;
|
||||
if (cfg.optionalDesktopNotifications()) {
|
||||
slotShowTrayMessage(title, msg);
|
||||
slotShowTrayMessage(title, msg, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,7 +703,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo&
|
||||
slotRebuildRecentMenus();
|
||||
}
|
||||
|
||||
if (progress.isUpdatingEstimates()
|
||||
if (progress.hasStarted()
|
||||
&& progress.completedFiles() >= progress.totalFiles()
|
||||
&& progress._currentDiscoveredFolder.isEmpty()) {
|
||||
QTimer::singleShot(2000, this, SLOT(slotDisplayIdle()));
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "systray.h"
|
||||
#include "connectionvalidator.h"
|
||||
#include "progressdispatcher.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
@@ -32,7 +33,7 @@ class Folder;
|
||||
class SettingsDialog;
|
||||
class SettingsDialogMac;
|
||||
class ShareDialog;
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class LogBrowser;
|
||||
class AccountState;
|
||||
|
||||
@@ -44,7 +45,7 @@ class ownCloudGui : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ownCloudGui(Application *parent = 0);
|
||||
explicit ownCloudGui(oCApplication *parent = 0);
|
||||
|
||||
bool checkAccountExists(bool openSettings);
|
||||
|
||||
@@ -58,8 +59,8 @@ signals:
|
||||
public slots:
|
||||
void setupContextMenu();
|
||||
void slotComputeOverallSyncStatus();
|
||||
void slotShowTrayMessage(const QString &title, const QString &msg);
|
||||
void slotShowOptionalTrayMessage(const QString &title, const QString &msg);
|
||||
void slotShowTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type);
|
||||
void slotShowOptionalTrayMessage(const QString &title, const QString &msg, Logger::NotificationType type);
|
||||
void slotFolderOpenAction( const QString& alias );
|
||||
void slotRebuildRecentMenus();
|
||||
void slotUpdateProgress(const QString &folder, const ProgressInfo& progress);
|
||||
@@ -122,7 +123,7 @@ private:
|
||||
QSignalMapper *_folderOpenActionMapper;
|
||||
QSignalMapper *_recentItemsMapper;
|
||||
|
||||
Application *_app;
|
||||
oCApplication *_app;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -173,7 +173,7 @@ void OwncloudSetupWizard::slotNoOwnCloudFoundAuth(QNetworkReply *reply)
|
||||
|
||||
// Allow the credentials dialog to pop up again for the same URL.
|
||||
// Maybe the user just clicked 'Cancel' by accident or changed his mind.
|
||||
_ocWizard->account()->resetRejectedCertificates();
|
||||
_ocWizard->account()->resetSslCertErrorState();
|
||||
}
|
||||
|
||||
void OwncloudSetupWizard::slotNoOwnCloudFoundAuthTimeout(const QUrl&url)
|
||||
|
||||
@@ -57,15 +57,9 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
|
||||
header << tr("Action");
|
||||
header << tr("Size");
|
||||
|
||||
int timestampColumnExtra = 0;
|
||||
#ifdef Q_OS_WIN
|
||||
timestampColumnExtra = 20; // font metrics are broken on Windows, see #4721
|
||||
#endif
|
||||
|
||||
_ui->_treeWidget->setHeaderLabels( header );
|
||||
int timestampColumnWidth =
|
||||
_ui->_treeWidget->fontMetrics().width(timeString(QDateTime::currentDateTime()))
|
||||
+ timestampColumnExtra;
|
||||
_ui->_treeWidget->fontMetrics().width(timeString(QDateTime::currentDateTime()));
|
||||
_ui->_treeWidget->setColumnWidth(0, timestampColumnWidth);
|
||||
_ui->_treeWidget->setColumnWidth(1, 180);
|
||||
_ui->_treeWidget->setColumnCount(5);
|
||||
@@ -90,8 +84,7 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
|
||||
_issueItemView->setHeaderLabels( header );
|
||||
timestampColumnWidth =
|
||||
ActivityItemDelegate::rowHeight() // icon
|
||||
+ _issueItemView->fontMetrics().width(timeString(QDateTime::currentDateTime()))
|
||||
+ timestampColumnExtra;
|
||||
+ _issueItemView->fontMetrics().width(timeString(QDateTime::currentDateTime()));
|
||||
_issueItemView->setColumnWidth(0, timestampColumnWidth);
|
||||
_issueItemView->setColumnWidth(1, 180);
|
||||
_issueItemView->setColumnCount(4);
|
||||
@@ -121,9 +114,17 @@ void ProtocolWidget::hideEvent(QHideEvent *ev)
|
||||
|
||||
void ProtocolWidget::cleanItems(const QString& folder)
|
||||
{
|
||||
int itemCnt = _ui->_treeWidget->topLevelItemCount();
|
||||
|
||||
// Limit the number of items
|
||||
while(itemCnt > 2000) {
|
||||
delete _ui->_treeWidget->takeTopLevelItem(itemCnt - 1);
|
||||
itemCnt--;
|
||||
}
|
||||
|
||||
// The issue list is a state, clear it and let the next sync fill it
|
||||
// with ignored files and propagation errors.
|
||||
int itemCnt = _issueItemView->topLevelItemCount();
|
||||
itemCnt = _issueItemView->topLevelItemCount();
|
||||
for( int cnt = itemCnt-1; cnt >=0 ; cnt-- ) {
|
||||
QTreeWidgetItem *item = _issueItemView->topLevelItem(cnt);
|
||||
QString itemFolder = item->data(2, Qt::UserRole).toString();
|
||||
@@ -211,7 +212,7 @@ QTreeWidgetItem* ProtocolWidget::createCompletedTreewidgetItem(const QString& fo
|
||||
|
||||
void ProtocolWidget::slotProgressInfo( const QString& folder, const ProgressInfo& progress )
|
||||
{
|
||||
if( !progress.isUpdatingEstimates() ) {
|
||||
if( !progress.hasStarted() ) {
|
||||
// The sync is restarting, clean the old items
|
||||
cleanItems(folder);
|
||||
} else if (progress.completedFiles() >= progress.totalFiles()) {
|
||||
@@ -231,12 +232,6 @@ void ProtocolWidget::slotItemCompleted(const QString &folder, const SyncFileItem
|
||||
_issueItemView->insertTopLevelItem(0, line);
|
||||
emit issueItemCountUpdated(_issueItemView->topLevelItemCount());
|
||||
} else {
|
||||
// Limit the number of items
|
||||
int itemCnt = _ui->_treeWidget->topLevelItemCount();
|
||||
while(itemCnt > 2000) {
|
||||
delete _ui->_treeWidget->takeTopLevelItem(itemCnt - 1);
|
||||
itemCnt--;
|
||||
}
|
||||
_ui->_treeWidget->insertTopLevelItem(0, line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class SyncResult;
|
||||
namespace Ui {
|
||||
class ProtocolWidget;
|
||||
}
|
||||
class Application;
|
||||
class oCApplication;
|
||||
|
||||
/**
|
||||
* @brief The ProtocolWidget class
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Ui {
|
||||
class SettingsDialog;
|
||||
}
|
||||
class AccountSettings;
|
||||
class Application;
|
||||
class oCApplication;
|
||||
class FolderMan;
|
||||
class ownCloudGui;
|
||||
class ActivitySettings;
|
||||
|
||||
@@ -72,7 +72,9 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
|
||||
|
||||
_completer->setModel(_completerModel);
|
||||
_completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
_completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
||||
_completer->setFilterMode(Qt::MatchContains);
|
||||
#endif
|
||||
_ui->shareeLineEdit->setCompleter(_completer);
|
||||
|
||||
_manager = new ShareManager(_account, this);
|
||||
|
||||
@@ -56,13 +56,6 @@
|
||||
// The second number should be changed when there are new features.
|
||||
#define MIRALL_SOCKET_API_VERSION "1.0"
|
||||
|
||||
static inline QString removeTrailingSlash(QString path)
|
||||
{
|
||||
Q_ASSERT(path.endsWith(QLatin1Char('/')));
|
||||
path.truncate(path.length()-1);
|
||||
return path;
|
||||
}
|
||||
|
||||
namespace OCC {
|
||||
|
||||
#define DEBUG qDebug() << "SocketApi: "
|
||||
@@ -149,7 +142,7 @@ void SocketApi::slotNewConnection()
|
||||
|
||||
foreach( Folder *f, FolderMan::instance()->map() ) {
|
||||
if (f->canSync()) {
|
||||
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
|
||||
QString message = buildRegisterPathMessage(f->path());
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
}
|
||||
@@ -196,7 +189,7 @@ void SocketApi::slotRegisterPath( const QString& alias )
|
||||
|
||||
Folder *f = FolderMan::instance()->folder(alias);
|
||||
if (f) {
|
||||
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
|
||||
QString message = buildRegisterPathMessage(f->path());
|
||||
foreach(QIODevice *socket, _listeners) {
|
||||
sendMessage(socket, message);
|
||||
}
|
||||
@@ -212,7 +205,7 @@ void SocketApi::slotUnregisterPath( const QString& alias )
|
||||
|
||||
Folder *f = FolderMan::instance()->folder(alias);
|
||||
if (f)
|
||||
broadcastMessage(QLatin1String("UNREGISTER_PATH"), removeTrailingSlash(f->path()), QString::null, true );
|
||||
broadcastMessage(QLatin1String("UNREGISTER_PATH"), f->path(), QString::null, true );
|
||||
|
||||
_registeredAliases.remove(alias);
|
||||
}
|
||||
@@ -232,11 +225,10 @@ void SocketApi::slotUpdateFolderView(Folder *f)
|
||||
f->syncResult().status() == SyncResult::Error ||
|
||||
f->syncResult().status() == SyncResult::SetupError ) {
|
||||
|
||||
QString rootPath = removeTrailingSlash(f->path());
|
||||
broadcastMessage(QLatin1String("STATUS"), rootPath,
|
||||
broadcastMessage(QLatin1String("STATUS"), f->path() ,
|
||||
f->syncEngine().syncFileStatusTracker().fileStatus("").toSocketAPIString());
|
||||
|
||||
broadcastMessage(QLatin1String("UPDATE_VIEW"), rootPath);
|
||||
broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() );
|
||||
} else {
|
||||
qDebug() << "Not sending UPDATE_VIEW for" << f->alias() << "because status() is" << f->syncResult().status();
|
||||
}
|
||||
@@ -310,12 +302,8 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
|
||||
// this can happen in offline mode e.g.: nothing to worry about
|
||||
statusString = QLatin1String("NOP");
|
||||
} else {
|
||||
QString relativePath = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
|
||||
if( relativePath.endsWith(QLatin1Char('/')) ) {
|
||||
relativePath.truncate(relativePath.length()-1);
|
||||
qWarning() << "Removed trailing slash for directory: " << relativePath << "Status pushes won't have one.";
|
||||
}
|
||||
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(relativePath);
|
||||
const QString file = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
|
||||
SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
|
||||
|
||||
statusString = fileStatus.toSocketAPIString();
|
||||
}
|
||||
|
||||
@@ -12,9 +12,15 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LIBSNORE
|
||||
#include <libsnore/application.h>
|
||||
#include <libsnore/notification/icon.h>
|
||||
#endif
|
||||
|
||||
#include "systray.h"
|
||||
#include "theme.h"
|
||||
#include <QDebug>
|
||||
#include <QPointer>
|
||||
|
||||
#ifdef USE_FDO_NOTIFICATIONS
|
||||
#include <QDBusConnection>
|
||||
@@ -28,8 +34,54 @@
|
||||
|
||||
namespace OCC {
|
||||
|
||||
void Systray::showMessage(const QString & title, const QString & message, MessageIcon icon, int millisecondsTimeoutHint)
|
||||
Systray::Systray( )
|
||||
{
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::SnoreCore &snore = Snore::SnoreCore::instance();
|
||||
snore.loadPlugins( Snore::SnorePlugin::Backend | Snore::SnorePlugin::SecondaryBackend );
|
||||
snore.setDefaultSettingsValue("Silent", true, Snore::LocalSetting );
|
||||
|
||||
_application = Snore::Application( Theme::instance()->appName(), Theme::instance()->applicationIcon() );
|
||||
_application.hints().setValue( "use-markup", true );
|
||||
_application.hints().setValue( "windows-app-id", Theme::instance()->appName() );
|
||||
_application.hints().setValue( "desktop-entry", Theme::instance()->appNameGUI() );
|
||||
_application.hints().setValue( "tray-icon", qVariantFromValue(QPointer<QSystemTrayIcon>(this)));
|
||||
|
||||
// register the Alerts.
|
||||
Snore::Alert alert( Theme::instance()->appNameGUI(), QIcon() );
|
||||
_alerts.insert( QSystemTrayIcon::NoIcon, alert);
|
||||
_application.addAlert(alert);
|
||||
Snore::Alert alert2( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Success, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Information, alert2);
|
||||
_application.addAlert(alert2);
|
||||
Snore::Alert alert3( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Problem, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Warning, alert3);
|
||||
_application.addAlert(alert3);
|
||||
Snore::Alert alert4( Theme::instance()->appNameGUI(), Theme::instance()->syncStateIcon(SyncResult::Error, false ));
|
||||
_alerts.insert( QSystemTrayIcon::Critical, alert4);
|
||||
_application.addAlert(alert4);
|
||||
|
||||
snore.registerApplication( _application );
|
||||
snore.setDefaultApplication( _application );
|
||||
|
||||
// connect( &snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Systray::showMessage(const QString & title, const QString & message, MessageIcon icon,
|
||||
int millisecondsTimeoutHint)
|
||||
{
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::Alert a = _alerts[NoIcon];
|
||||
if( _alerts.contains(icon) ) {
|
||||
a = _alerts[icon];
|
||||
}
|
||||
|
||||
Snore::Notification n( _application , a, title, message, a.icon() );
|
||||
Snore::SnoreCore::instance().broadcastNotification( n );
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef USE_FDO_NOTIFICATIONS
|
||||
if(QDBusInterface(NOTIFICATIONS_SERVICE, NOTIFICATIONS_PATH, NOTIFICATIONS_IFACE).isValid()) {
|
||||
|
||||
@@ -15,8 +15,13 @@
|
||||
#ifndef SYSTRAY_H
|
||||
#define SYSTRAY_H
|
||||
|
||||
#include "logger.h"
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#ifdef HAVE_LIBSNORE
|
||||
#include <libsnore/snore.h>
|
||||
#endif
|
||||
|
||||
class QIcon;
|
||||
|
||||
namespace OCC {
|
||||
@@ -34,8 +39,17 @@ class Systray : public QSystemTrayIcon
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void showMessage(const QString & title, const QString & message, MessageIcon icon = Information, int millisecondsTimeoutHint = 10000);
|
||||
explicit Systray();
|
||||
|
||||
void showMessage(const QString & title, const QString & message, MessageIcon icon = Information,
|
||||
int millisecondsTimeoutHint = 10000);
|
||||
void setToolTip(const QString &tip);
|
||||
|
||||
private:
|
||||
#ifdef HAVE_LIBSNORE
|
||||
Snore::Application _application;
|
||||
QHash<QSystemTrayIcon::MessageIcon, Snore::Alert> _alerts;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -218,7 +218,6 @@ void OCUpdater::slotVersionInfoArrived()
|
||||
{
|
||||
_timeoutWatchdog->stop();
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||
reply->deleteLater();
|
||||
if( reply->error() != QNetworkReply::NoError ) {
|
||||
qDebug() << "Failed to reach version check url: " << reply->errorString();
|
||||
return;
|
||||
@@ -259,7 +258,6 @@ void NSISUpdater::slotWriteFile()
|
||||
void NSISUpdater::slotDownloadFinished()
|
||||
{
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||
reply->deleteLater();
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
setDownloadState(DownloadFailed);
|
||||
return;
|
||||
|
||||
@@ -242,7 +242,6 @@ void AbstractNetworkJob::slotTimeout()
|
||||
reply()->abort();
|
||||
} else {
|
||||
qDebug() << Q_FUNC_INFO << this << "Timeout reply was NULL";
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ namespace OCC {
|
||||
Account::Account(QObject *parent)
|
||||
: QObject(parent)
|
||||
, _capabilities(QVariantMap())
|
||||
, _am(0)
|
||||
, _credentials(0)
|
||||
, _treatSslErrorsAsFailure(false)
|
||||
, _davPath( Theme::instance()->webDavPath() )
|
||||
, _wasMigrated(false)
|
||||
{
|
||||
@@ -53,6 +56,8 @@ AccountPtr Account::create()
|
||||
|
||||
Account::~Account()
|
||||
{
|
||||
delete _credentials;
|
||||
delete _am;
|
||||
}
|
||||
|
||||
QString Account::davPath() const
|
||||
@@ -113,14 +118,14 @@ bool Account::changed(AccountPtr other, bool ignoreUrlProtocol) const
|
||||
changes = (_url == other->_url);
|
||||
}
|
||||
|
||||
changes |= _credentials->changed(other->credentials());
|
||||
changes |= _credentials->changed(other->_credentials);
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
AbstractCredentials *Account::credentials() const
|
||||
{
|
||||
return _credentials.data();
|
||||
return _credentials;
|
||||
}
|
||||
|
||||
void Account::setCredentials(AbstractCredentials *cred)
|
||||
@@ -131,27 +136,29 @@ void Account::setCredentials(AbstractCredentials *cred)
|
||||
jar = _am->cookieJar();
|
||||
jar->setParent(0);
|
||||
|
||||
_am = QSharedPointer<QNetworkAccessManager>();
|
||||
_am->deleteLater();
|
||||
}
|
||||
|
||||
if (_credentials) {
|
||||
credentials()->deleteLater();
|
||||
}
|
||||
|
||||
// The order for these two is important! Reading the credential's
|
||||
// settings accesses the account as well as account->_credentials,
|
||||
// so deleteLater must be used.
|
||||
_credentials = QSharedPointer<AbstractCredentials>(cred, &QObject::deleteLater);
|
||||
// settings accesses the account as well as account->_credentials
|
||||
_credentials = cred;
|
||||
cred->setAccount(this);
|
||||
|
||||
_am = QSharedPointer<QNetworkAccessManager>(_credentials->getQNAM(), &QObject::deleteLater);
|
||||
|
||||
_am = _credentials->getQNAM();
|
||||
if (jar) {
|
||||
_am->setCookieJar(jar);
|
||||
}
|
||||
connect(_am.data(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
||||
connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
||||
SLOT(slotHandleSslErrors(QNetworkReply*,QList<QSslError>)));
|
||||
connect(_am.data(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
|
||||
connect(_am, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
|
||||
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
|
||||
connect(_credentials.data(), SIGNAL(fetched()),
|
||||
connect(_credentials, SIGNAL(fetched()),
|
||||
SLOT(slotCredentialsFetched()));
|
||||
connect(_credentials.data(), SIGNAL(asked()),
|
||||
connect(_credentials, SIGNAL(asked()),
|
||||
SLOT(slotCredentialsAsked()));
|
||||
}
|
||||
|
||||
@@ -190,21 +197,18 @@ void Account::resetNetworkAccessManager()
|
||||
|
||||
qDebug() << "Resetting QNAM";
|
||||
QNetworkCookieJar* jar = _am->cookieJar();
|
||||
|
||||
// Use a QSharedPointer to allow locking the life of the QNAM on the stack.
|
||||
// Make it call deleteLater to make sure that we can return to any QNAM stack frames safely.
|
||||
_am = QSharedPointer<QNetworkAccessManager>(_credentials->getQNAM(), &QObject::deleteLater);
|
||||
|
||||
_am->deleteLater();
|
||||
_am = _credentials->getQNAM();
|
||||
_am->setCookieJar(jar); // takes ownership of the old cookie jar
|
||||
connect(_am.data(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
||||
connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
||||
SLOT(slotHandleSslErrors(QNetworkReply*,QList<QSslError>)));
|
||||
connect(_am.data(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
|
||||
connect(_am, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
|
||||
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
|
||||
}
|
||||
|
||||
QNetworkAccessManager *Account::networkAccessManager()
|
||||
{
|
||||
return _am.data();
|
||||
return _am;
|
||||
}
|
||||
|
||||
QNetworkReply *Account::headRequest(const QString &relPath)
|
||||
@@ -325,9 +329,9 @@ void Account::addApprovedCerts(const QList<QSslCertificate> certs)
|
||||
_approvedCerts += certs;
|
||||
}
|
||||
|
||||
void Account::resetRejectedCertificates()
|
||||
void Account::resetSslCertErrorState()
|
||||
{
|
||||
_rejectedCertificates.clear();
|
||||
_treatSslErrorsAsFailure = false;
|
||||
}
|
||||
|
||||
void Account::setSslErrorHandler(AbstractSslErrorHandler *handler)
|
||||
@@ -408,15 +412,8 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
|
||||
<< error.errorString() << "("<< error.error() << ")" << "\n";
|
||||
}
|
||||
|
||||
bool allPreviouslyRejected = true;
|
||||
foreach (const QSslError &error, errors) {
|
||||
if (!_rejectedCertificates.contains(error.certificate())) {
|
||||
allPreviouslyRejected = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If all certs have previously been rejected by the user, don't ask again.
|
||||
if( allPreviouslyRejected ) {
|
||||
if( _treatSslErrorsAsFailure ) {
|
||||
// User decided once not to trust. Honor this decision.
|
||||
qDebug() << out << "Certs not trusted by user decision, returning.";
|
||||
return;
|
||||
}
|
||||
@@ -427,12 +424,6 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
|
||||
return;
|
||||
}
|
||||
|
||||
// SslDialogErrorHandler::handleErrors will run an event loop that might execute
|
||||
// the deleteLater() of the QNAM before we have the chance of unwinding our stack.
|
||||
// Keep a ref here on our stackframe to make sure that it doesn't get deleted before
|
||||
// handleErrors returns.
|
||||
QSharedPointer<QNetworkAccessManager> qnamLock = _am;
|
||||
|
||||
if (_sslErrorHandler->handleErrors(errors, reply->sslConfiguration(), &approvedCerts, sharedFromThis())) {
|
||||
QSslSocket::addDefaultCaCertificates(approvedCerts);
|
||||
addApprovedCerts(approvedCerts);
|
||||
@@ -445,12 +436,7 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
|
||||
// certificate changes.
|
||||
reply->ignoreSslErrors(errors);
|
||||
} else {
|
||||
// Mark all involved certificates as rejected, so we don't ask the user again.
|
||||
foreach (const QSslError &error, errors) {
|
||||
if (!_rejectedCertificates.contains(error.certificate())) {
|
||||
_rejectedCertificates.append(error.certificate());
|
||||
}
|
||||
}
|
||||
_treatSslErrorsAsFailure = true;
|
||||
// if during normal operation, a new certificate was MITM'ed, and the user does not
|
||||
// ACK it, the running request must be aborted and the QNAM must be reset, to not
|
||||
// treat the new cert as granted. See bug #3283
|
||||
@@ -462,12 +448,12 @@ void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors
|
||||
|
||||
void Account::slotCredentialsFetched()
|
||||
{
|
||||
emit credentialsFetched(_credentials.data());
|
||||
emit credentialsFetched(_credentials);
|
||||
}
|
||||
|
||||
void Account::slotCredentialsAsked()
|
||||
{
|
||||
emit credentialsAsked(_credentials.data());
|
||||
emit credentialsAsked(_credentials);
|
||||
}
|
||||
|
||||
void Account::handleInvalidCredentials()
|
||||
|
||||
@@ -133,7 +133,7 @@ public:
|
||||
// Usually when a user explicitly rejects a certificate we don't
|
||||
// ask again. After this call, a dialog will again be shown when
|
||||
// the next unknown certificate is encountered.
|
||||
void resetRejectedCertificates();
|
||||
void resetSslCertErrorState();
|
||||
|
||||
// pluggable handler
|
||||
void setSslErrorHandler(AbstractSslErrorHandler *handler);
|
||||
@@ -214,12 +214,9 @@ private:
|
||||
QString _serverVersion;
|
||||
QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
|
||||
QuotaInfo *_quotaInfo;
|
||||
QSharedPointer<QNetworkAccessManager> _am;
|
||||
QSharedPointer<AbstractCredentials> _credentials;
|
||||
|
||||
/// Certificates that were explicitly rejected by the user
|
||||
QList<QSslCertificate> _rejectedCertificates;
|
||||
|
||||
QNetworkAccessManager *_am;
|
||||
AbstractCredentials* _credentials;
|
||||
bool _treatSslErrorsAsFailure;
|
||||
static QString _configFileName;
|
||||
QByteArray _pemCertificate;
|
||||
QString _pemPrivateKey;
|
||||
|
||||
@@ -42,7 +42,7 @@ ExcludedFiles& ExcludedFiles::instance()
|
||||
|
||||
void ExcludedFiles::addExcludeFilePath(const QString& path)
|
||||
{
|
||||
_excludeFiles.insert(path);
|
||||
_excludeFiles.append(path);
|
||||
}
|
||||
|
||||
bool ExcludedFiles::reloadExcludes()
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
#include "owncloudlib.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
extern "C" {
|
||||
#include "std/c_string.h"
|
||||
@@ -67,7 +66,7 @@ private:
|
||||
// This is a pointer to the csync exclude list, its is owned by this class
|
||||
// but the pointer can be in a csync_context so that it can itself also query the list.
|
||||
c_strlist_t** _excludesPtr;
|
||||
QSet<QString> _excludeFiles;
|
||||
QStringList _excludeFiles;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -496,16 +496,16 @@ QString FileSystem::fileSystemForPath(const QString & path)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define BUFSIZE qint64(500*1024) // 500 KiB
|
||||
#define BUFSIZE 1024*1024*10
|
||||
|
||||
static QByteArray readToCrypto( const QString& filename, QCryptographicHash::Algorithm algo )
|
||||
{
|
||||
QFile file(filename);
|
||||
const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
|
||||
QByteArray buf(bufSize, Qt::Uninitialized);
|
||||
const qint64 bufSize = BUFSIZE;
|
||||
QByteArray buf(bufSize,0);
|
||||
QByteArray arr;
|
||||
QCryptographicHash crypto( algo );
|
||||
|
||||
QFile file(filename);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
qint64 size;
|
||||
while (!file.atEnd()) {
|
||||
@@ -532,11 +532,11 @@ QByteArray FileSystem::calcSha1( const QString& filename )
|
||||
#ifdef ZLIB_FOUND
|
||||
QByteArray FileSystem::calcAdler32( const QString& filename )
|
||||
{
|
||||
QFile file(filename);
|
||||
const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
|
||||
QByteArray buf(bufSize, Qt::Uninitialized);
|
||||
|
||||
unsigned int adler = adler32(0L, Z_NULL, 0);
|
||||
const qint64 bufSize = BUFSIZE;
|
||||
QByteArray buf(bufSize, 0);
|
||||
|
||||
QFile file(filename);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
qint64 size;
|
||||
while (!file.atEnd()) {
|
||||
|
||||
@@ -111,9 +111,9 @@ bool OWNCLOUDSYNC_EXPORT rename(const QString& originFileName,
|
||||
*
|
||||
* @return true if the file's mtime or size are not what is expected.
|
||||
*/
|
||||
bool OWNCLOUDSYNC_EXPORT fileChanged(const QString& fileName,
|
||||
qint64 previousSize,
|
||||
time_t previousMtime);
|
||||
bool fileChanged(const QString& fileName,
|
||||
qint64 previousSize,
|
||||
time_t previousMtime);
|
||||
|
||||
/**
|
||||
* @brief Like !fileChanged() but with verbose logging if the file *did* change.
|
||||
|
||||
@@ -74,14 +74,14 @@ Logger::~Logger() {
|
||||
}
|
||||
|
||||
|
||||
void Logger::postGuiLog(const QString &title, const QString &message)
|
||||
void Logger::postGuiLog(const QString &title, const QString &message, NotificationType type )
|
||||
{
|
||||
emit guiLog(title, message);
|
||||
emit guiLog(title, message, type);
|
||||
}
|
||||
|
||||
void Logger::postOptionalGuiLog(const QString &title, const QString &message)
|
||||
void Logger::postOptionalGuiLog(const QString &title, const QString &message, NotificationType type )
|
||||
{
|
||||
emit optionalGuiLog(title, message);
|
||||
emit optionalGuiLog(title, message, type);
|
||||
}
|
||||
|
||||
void Logger::postGuiMessage(const QString &title, const QString &message)
|
||||
|
||||
@@ -45,6 +45,14 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum NotificationType {
|
||||
NoIcon = 0,
|
||||
Information,
|
||||
SoftError,
|
||||
Error,
|
||||
Critical
|
||||
};
|
||||
|
||||
|
||||
bool isNoop() const;
|
||||
void log(Log log);
|
||||
@@ -57,8 +65,8 @@ public:
|
||||
|
||||
static Logger* instance();
|
||||
|
||||
void postGuiLog(const QString& title, const QString& message);
|
||||
void postOptionalGuiLog(const QString& title, const QString& message);
|
||||
void postGuiLog(const QString& title, const QString& message, NotificationType type = Information);
|
||||
void postOptionalGuiLog(const QString& title, const QString& message, NotificationType type = Information);
|
||||
void postGuiMessage(const QString& title, const QString& message);
|
||||
|
||||
void setLogFile( const QString & name );
|
||||
@@ -68,9 +76,9 @@ public:
|
||||
|
||||
signals:
|
||||
void newLog(const QString&);
|
||||
void guiLog(const QString&, const QString&);
|
||||
void guiLog(const QString&, const QString&, Logger::NotificationType type);
|
||||
void guiMessage(const QString&, const QString&);
|
||||
void optionalGuiLog(const QString&, const QString&);
|
||||
void optionalGuiLog(const QString&, const QString&, Logger::NotificationType type);
|
||||
|
||||
public slots:
|
||||
void enterNextLogFile();
|
||||
|
||||
@@ -297,12 +297,7 @@ public:
|
||||
|
||||
QAtomicInt _abortRequested; // boolean set by the main thread to abort.
|
||||
|
||||
/** The list of currently active jobs.
|
||||
This list contains the jobs that are currently using ressources and is used purely to
|
||||
know how many jobs there is currently running for the scheduler.
|
||||
Jobs add themself to the list when they do an assynchronous operation.
|
||||
Jobs can be several time on the list (example, when several chunks are uploaded in parallel)
|
||||
*/
|
||||
/* The list of currently active jobs */
|
||||
QList<PropagateItemJob*> _activeJobList;
|
||||
|
||||
/** We detected that another sync is required after this one */
|
||||
@@ -388,7 +383,6 @@ private:
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
// access to signals which are protected in Qt4
|
||||
friend class PropagateDownloadFileQNAM;
|
||||
friend class PropagateUploadFileQNAM;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -127,65 +127,27 @@ void ProgressDispatcher::setProgressInfo(const QString& folder, const ProgressIn
|
||||
emit progressInfo( folder, progress );
|
||||
}
|
||||
|
||||
ProgressInfo::ProgressInfo()
|
||||
void ProgressInfo::start()
|
||||
{
|
||||
connect(&_updateEstimatesTimer, SIGNAL(timeout()), SLOT(updateEstimates()));
|
||||
reset();
|
||||
}
|
||||
|
||||
void ProgressInfo::reset()
|
||||
{
|
||||
_currentItems.clear();
|
||||
_currentDiscoveredFolder.clear();
|
||||
_sizeProgress = Progress();
|
||||
_fileProgress = Progress();
|
||||
_totalSizeOfCompletedJobs = 0;
|
||||
_maxBytesPerSecond = 100000.0;
|
||||
_maxFilesPerSecond = 2.0;
|
||||
_updateEstimatesTimer.stop();
|
||||
}
|
||||
|
||||
void ProgressInfo::startEstimateUpdates()
|
||||
{
|
||||
_updateEstimatesTimer.start(1000);
|
||||
}
|
||||
|
||||
bool ProgressInfo::isUpdatingEstimates() const
|
||||
bool ProgressInfo::hasStarted() const
|
||||
{
|
||||
return _updateEstimatesTimer.isActive();
|
||||
}
|
||||
|
||||
static bool shouldCountProgress(const SyncFileItem &item)
|
||||
{
|
||||
const auto instruction = item._instruction;
|
||||
|
||||
// Don't worry about directories that won't have propagation
|
||||
// jobs associated with them.
|
||||
if (item._isDirectory
|
||||
&& (instruction == CSYNC_INSTRUCTION_NONE
|
||||
|| instruction == CSYNC_INSTRUCTION_SYNC
|
||||
|| instruction == CSYNC_INSTRUCTION_CONFLICT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip any ignored or error files, we do nothing with them.
|
||||
if (instruction == CSYNC_INSTRUCTION_IGNORE
|
||||
|| instruction == CSYNC_INSTRUCTION_ERROR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProgressInfo::adjustTotalsForFile(const SyncFileItem &item)
|
||||
{
|
||||
if (!shouldCountProgress(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fileProgress._total += item._affectedItems;
|
||||
if (isSizeDependent(item)) {
|
||||
_sizeProgress._total += item._size;
|
||||
if (!item._isDirectory) {
|
||||
_fileProgress._total++;
|
||||
if (isSizeDependent(item)) {
|
||||
_sizeProgress._total += item._size;
|
||||
}
|
||||
} else if (item._instruction != CSYNC_INSTRUCTION_NONE) {
|
||||
// Added or removed directories certainly count.
|
||||
_fileProgress._total++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,10 +178,6 @@ quint64 ProgressInfo::completedSize() const
|
||||
|
||||
void ProgressInfo::setProgressComplete(const SyncFileItem &item)
|
||||
{
|
||||
if (!shouldCountProgress(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_currentItems.remove(item._file);
|
||||
_fileProgress.setCompleted(_fileProgress._completed + item._affectedItems);
|
||||
if (ProgressInfo::isSizeDependent(item)) {
|
||||
@@ -231,10 +189,6 @@ void ProgressInfo::setProgressComplete(const SyncFileItem &item)
|
||||
|
||||
void ProgressInfo::setProgressItem(const SyncFileItem &item, quint64 completed)
|
||||
{
|
||||
if (!shouldCountProgress(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_currentItems[item._file]._item = item;
|
||||
_currentItems[item._file]._progress._total = item._size;
|
||||
_currentItems[item._file]._progress.setCompleted(completed);
|
||||
|
||||
@@ -37,27 +37,27 @@ class OWNCLOUDSYNC_EXPORT ProgressInfo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProgressInfo();
|
||||
|
||||
/** Resets for a new sync run.
|
||||
*/
|
||||
void reset();
|
||||
ProgressInfo()
|
||||
: _totalSizeOfCompletedJobs(0)
|
||||
, _maxFilesPerSecond(2.0)
|
||||
, _maxBytesPerSecond(100000.0)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Called when propagation starts.
|
||||
*
|
||||
* isUpdatingEstimates() will return true afterwards.
|
||||
* hasStarted() will return true afterwards.
|
||||
*/
|
||||
void startEstimateUpdates();
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Returns true when startEstimateUpdates() was called.
|
||||
* Returns true when propagation has started (start() was called).
|
||||
*
|
||||
* This is used when the SyncEngine wants to indicate a new sync
|
||||
* is about to start via the transmissionProgress() signal. The
|
||||
* first ProgressInfo will have isUpdatingEstimates() == false.
|
||||
* first ProgressInfo will have hasStarted() == false.
|
||||
*/
|
||||
bool isUpdatingEstimates() const;
|
||||
bool hasStarted() const;
|
||||
|
||||
/**
|
||||
* Increase the file and size totals by the amount indicated in item.
|
||||
|
||||
@@ -654,6 +654,7 @@ static void preserveGroupOwnership(const QString& fileName, const QFileInfo& fi)
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
|
||||
void PropagateDownloadFileQNAM::transmissionChecksumValidated(const QByteArray &checksumType, const QByteArray &checksum)
|
||||
{
|
||||
const auto theContentChecksumType = contentChecksumType();
|
||||
|
||||
@@ -97,9 +97,7 @@ void PUTFileJob::start() {
|
||||
}
|
||||
|
||||
void PUTFileJob::slotTimeout() {
|
||||
qDebug() << "Timeout" << (reply() ? reply()->request().url() : path());
|
||||
if (!reply())
|
||||
return;
|
||||
qDebug() << "Timeout" << reply()->request().url();
|
||||
_errorString = tr("Connection Timeout");
|
||||
reply()->abort();
|
||||
}
|
||||
@@ -211,6 +209,8 @@ void PropagateUploadFileQNAM::slotComputeContentChecksum()
|
||||
return;
|
||||
}
|
||||
|
||||
_propagator->_activeJobList.removeOne(this);
|
||||
|
||||
const QString filePath = _propagator->getFilePath(_item->_file);
|
||||
|
||||
// remember the modtime before checksumming to be able to detect a file
|
||||
@@ -234,8 +234,6 @@ void PropagateUploadFileQNAM::slotComputeContentChecksum()
|
||||
|
||||
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
|
||||
SLOT(slotComputeTransmissionChecksum(QByteArray,QByteArray)));
|
||||
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
|
||||
computeChecksum, SLOT(deleteLater()));
|
||||
computeChecksum->start(filePath);
|
||||
}
|
||||
|
||||
@@ -270,18 +268,12 @@ void PropagateUploadFileQNAM::slotComputeTransmissionChecksum(const QByteArray&
|
||||
|
||||
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
|
||||
SLOT(slotStartUpload(QByteArray,QByteArray)));
|
||||
connect(computeChecksum, SIGNAL(done(QByteArray,QByteArray)),
|
||||
computeChecksum, SLOT(deleteLater()));
|
||||
const QString filePath = _propagator->getFilePath(_item->_file);
|
||||
computeChecksum->start(filePath);
|
||||
}
|
||||
|
||||
void PropagateUploadFileQNAM::slotStartUpload(const QByteArray& transmissionChecksumType, const QByteArray& transmissionChecksum)
|
||||
{
|
||||
// Remove ourselfs from the list of active job, before any posible call to done()
|
||||
// When we start chunks, we will add it again, once for every chunks.
|
||||
_propagator->_activeJobList.removeOne(this);
|
||||
|
||||
_transmissionChecksum = transmissionChecksum;
|
||||
_transmissionChecksumType = transmissionChecksumType;
|
||||
|
||||
@@ -406,7 +398,7 @@ qint64 UploadDevice::readData(char* data, qint64 maxlen) {
|
||||
if (isBandwidthLimited()) {
|
||||
maxlen = qMin(maxlen, _bandwidthQuota);
|
||||
if (maxlen <= 0) { // no quota
|
||||
//qDebug() << "no quota";
|
||||
qDebug() << "no quota";
|
||||
return 0;
|
||||
}
|
||||
_bandwidthQuota -= maxlen;
|
||||
@@ -552,16 +544,8 @@ void PropagateUploadFileQNAM::startNextChunk()
|
||||
_transmissionChecksumType, _transmissionChecksum);
|
||||
}
|
||||
|
||||
const QString fileName = _propagator->getFilePath(_item->_file);
|
||||
if (! device->prepareAndOpen(fileName, chunkStart, currentChunkSize)) {
|
||||
if (! device->prepareAndOpen(_propagator->getFilePath(_item->_file), chunkStart, currentChunkSize)) {
|
||||
qDebug() << "ERR: Could not prepare upload device: " << device->errorString();
|
||||
|
||||
// If the file is currently locked, we want to retry the sync
|
||||
// when it becomes available again.
|
||||
if (FileSystem::isFileLocked(fileName)) {
|
||||
emit _propagator->seenLockedFile(fileName);
|
||||
}
|
||||
|
||||
// Soft error because this is likely caused by the user modifying his files while syncing
|
||||
abortWithError( SyncFileItem::SoftError, device->errorString() );
|
||||
delete device;
|
||||
@@ -779,8 +763,6 @@ void PropagateUploadFileQNAM::slotPutFinished()
|
||||
<< _stopWatch.durationOfLap(QLatin1String("ContentChecksum"))
|
||||
<< _stopWatch.durationOfLap(QLatin1String("TransmissionChecksum"))
|
||||
<< _item->_requestDuration;
|
||||
// The job might stay alive for the whole sync, release this tiny bit of memory.
|
||||
_stopWatch.reset();
|
||||
|
||||
finalize(*_item);
|
||||
}
|
||||
|
||||
@@ -101,10 +101,10 @@ SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
|
||||
SyncEngine::~SyncEngine()
|
||||
{
|
||||
abort();
|
||||
_thread.quit();
|
||||
_thread.wait();
|
||||
_excludedFiles.reset();
|
||||
csync_destroy(_csync_ctx);
|
||||
_thread.quit();
|
||||
_thread.wait();
|
||||
}
|
||||
|
||||
//Convert an error code from csync to a user readable string.
|
||||
@@ -203,12 +203,6 @@ QString SyncEngine::csyncErrorToString(CSYNC_STATUS err)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the item is in the blacklist.
|
||||
* If it should not be sync'ed because of the blacklist, update the item with the error instruction
|
||||
* and proper error message, and return true.
|
||||
* If the item is not in the blacklist, or the blacklist is stale, return false.
|
||||
*/
|
||||
bool SyncEngine::checkErrorBlacklisting( SyncFileItem &item )
|
||||
{
|
||||
if( !_journal ) {
|
||||
@@ -240,9 +234,6 @@ bool SyncEngine::checkErrorBlacklisting( SyncFileItem &item )
|
||||
} else if( item._modtime != entry._lastTryModtime ) {
|
||||
qDebug() << item._file << " is blacklisted, but has changed mtime!";
|
||||
return false;
|
||||
} else if( item._renameTarget != entry._renameTarget) {
|
||||
qDebug() << item._file << " is blacklisted, but rename target changed from" << entry._renameTarget;
|
||||
return false;
|
||||
}
|
||||
} else if( item._direction == SyncFileItem::Down ) {
|
||||
// download, check the etag.
|
||||
@@ -548,10 +539,10 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
bool directoryEtagUpdate = isDirectory && file->should_update_metadata;
|
||||
bool localMetadataUpdate = !remote && file->should_update_metadata;
|
||||
if (!directoryEtagUpdate) {
|
||||
item->_isDirectory = isDirectory;
|
||||
if (localMetadataUpdate) {
|
||||
// Hack, we want a local metadata update to happen, but only if the
|
||||
// remote tree doesn't ask us to do some kind of propagation.
|
||||
item->_isDirectory = isDirectory;
|
||||
_syncItemMap.insert(key, item);
|
||||
}
|
||||
emit syncItemDiscovered(*item);
|
||||
@@ -580,7 +571,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
||||
// An upload of an existing file means that the file was left unchanged on the server
|
||||
// This counts as a NONE for detecting if all the files on the server were changed
|
||||
_hasNoneFiles = true;
|
||||
} else if (!isDirectory) {
|
||||
} else if (!item->_isDirectory) {
|
||||
if (std::difftime(file->modtime, file->other.modtime) < 0) {
|
||||
// We are going back on time
|
||||
_backInTimeFiles++;
|
||||
@@ -682,8 +673,6 @@ void SyncEngine::startSync()
|
||||
_syncRunning = true;
|
||||
_anotherSyncNeeded = false;
|
||||
|
||||
_progressInfo->reset();
|
||||
|
||||
if (!QDir(_localPath).exists()) {
|
||||
// No _tr, it should only occur in non-mirall
|
||||
emit csyncError("Unable to find local sync folder.");
|
||||
@@ -920,7 +909,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
|
||||
emit aboutToPropagate(_syncedItems);
|
||||
// it's important to do this before ProgressInfo::start(), to announce start of new sync
|
||||
emit transmissionProgress(*_progressInfo);
|
||||
_progressInfo->startEstimateUpdates();
|
||||
_progressInfo->start();
|
||||
|
||||
// post update phase script: allow to tweak stuff by a custom script in debug mode.
|
||||
if( !qgetenv("OWNCLOUD_POST_UPDATE_SCRIPT").isEmpty() ) {
|
||||
@@ -1255,18 +1244,15 @@ void SyncEngine::checkForPermission()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OWNCLOUD_RESTORE_RENAME /* We don't like the idea of renaming behind user's back, as the user may be working with the files */
|
||||
if (!sourceOK && (!destinationOK || isRename)
|
||||
// (not for directory because that's more complicated with the contents that needs to be adjusted)
|
||||
&& !(*it)->_isDirectory) {
|
||||
#if 0 /* We don't like the idea of renaming behind user's back, as the user may be working with the files */
|
||||
|
||||
if (!sourceOK && !destinationOK) {
|
||||
// Both the source and the destination won't allow move. Move back to the original
|
||||
std::swap((*it)->_file, (*it)->_renameTarget);
|
||||
(*it)->_direction = SyncFileItem::Down;
|
||||
(*it)->_errorString = tr("Move not allowed, item restored");
|
||||
(*it)->_isRestoration = true;
|
||||
qDebug() << "checkForPermission: MOVING BACK" << (*it)->_file;
|
||||
// in case something does wrong, we will not do it next time
|
||||
_journal->avoidRenamesOnNextSync((*it)->_file);
|
||||
} else
|
||||
#endif
|
||||
if (!sourceOK || !destinationOK) {
|
||||
@@ -1379,13 +1365,13 @@ AccountPtr SyncEngine::account() const
|
||||
|
||||
void SyncEngine::abort()
|
||||
{
|
||||
// Sets a flag for the update phase
|
||||
csync_request_abort(_csync_ctx);
|
||||
qDebug() << Q_FUNC_INFO << _discoveryMainThread;
|
||||
// Aborts the discovery phase job
|
||||
if (_discoveryMainThread) {
|
||||
_discoveryMainThread->abort();
|
||||
}
|
||||
// Sets a flag for the update phase
|
||||
csync_request_abort(_csync_ctx);
|
||||
// For the propagator
|
||||
if(_propagator) {
|
||||
_propagator->abort();
|
||||
|
||||
@@ -76,6 +76,7 @@ SyncFileStatusTracker::SyncFileStatusTracker(SyncEngine *syncEngine)
|
||||
SLOT(slotAboutToPropagate(SyncFileItemVector&)));
|
||||
connect(syncEngine, SIGNAL(itemCompleted(const SyncFileItem&, const PropagatorJob&)),
|
||||
SLOT(slotItemCompleted(const SyncFileItem&)));
|
||||
connect(syncEngine, SIGNAL(started()), SLOT(slotClearDirtyPaths()));
|
||||
connect(syncEngine, SIGNAL(started()), SLOT(slotSyncEngineRunningChanged()));
|
||||
connect(syncEngine, SIGNAL(finished(bool)), SLOT(slotSyncEngineRunningChanged()));
|
||||
}
|
||||
@@ -91,13 +92,15 @@ SyncFileItem SyncFileStatusTracker::rootSyncFileItem()
|
||||
return fakeRootItem;
|
||||
}
|
||||
|
||||
SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& relativePath)
|
||||
SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& systemFileName)
|
||||
{
|
||||
// normalization is required for OS X to match file names properly
|
||||
QString normalizedRelativePath = relativePath.normalized(QString::NormalizationForm_C);
|
||||
Q_ASSERT(!normalizedRelativePath.endsWith(QLatin1Char('/')));
|
||||
QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
|
||||
if( fileName.endsWith(QLatin1Char('/')) ) {
|
||||
fileName.truncate(fileName.length()-1);
|
||||
qDebug() << "Removed trailing slash: " << fileName;
|
||||
}
|
||||
|
||||
if (normalizedRelativePath.isEmpty()) {
|
||||
if( fileName.isEmpty() ) {
|
||||
// This is the root sync folder, it doesn't have an entry in the database and won't be walked by csync, so create one manually.
|
||||
return syncFileItemStatus(rootSyncFileItem());
|
||||
}
|
||||
@@ -108,22 +111,22 @@ SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& relativePath)
|
||||
// update the exclude list at runtime and doing it statically here removes
|
||||
// our ability to notify changes through the fileStatusChanged signal,
|
||||
// it's an acceptable compromize to treat all exclude types the same.
|
||||
if( _syncEngine->excludedFiles().isExcluded(_syncEngine->localPath() + normalizedRelativePath,
|
||||
if( _syncEngine->excludedFiles().isExcluded(_syncEngine->localPath() + fileName,
|
||||
_syncEngine->localPath(),
|
||||
_syncEngine->ignoreHiddenFiles()) ) {
|
||||
return SyncFileStatus(SyncFileStatus::StatusWarning);
|
||||
}
|
||||
|
||||
if ( _dirtyPaths.contains(normalizedRelativePath) )
|
||||
if ( _dirtyPaths.contains(fileName) )
|
||||
return SyncFileStatus::StatusSync;
|
||||
|
||||
SyncFileItem* item = _syncEngine->findSyncItem(normalizedRelativePath);
|
||||
SyncFileItem* item = _syncEngine->findSyncItem(fileName);
|
||||
if (item) {
|
||||
return syncFileItemStatus(*item);
|
||||
}
|
||||
|
||||
// If we're not currently syncing that file, look it up in the database to know if it's shared
|
||||
SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(normalizedRelativePath);
|
||||
SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(fileName);
|
||||
if (rec.isValid()) {
|
||||
return syncFileItemStatus(rec.toSyncFileItem());
|
||||
}
|
||||
@@ -155,18 +158,9 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
|
||||
} else if (showWarningInSocketApi(*item)) {
|
||||
_syncProblems[item->_file] = SyncFileStatus::StatusWarning;
|
||||
}
|
||||
_dirtyPaths.remove(item->destination());
|
||||
emit fileStatusChanged(getSystemDestination(item->destination()), syncFileItemStatus(*item));
|
||||
emit fileStatusChanged(getSystemDestination(*item), syncFileItemStatus(*item));
|
||||
}
|
||||
|
||||
// Some metadata status won't trigger files to be synced, make sure that we
|
||||
// push the OK status for dirty files that don't need to be propagated.
|
||||
// Swap into a copy since fileStatus() reads _dirtyPaths to determine the status
|
||||
QSet<QString> oldDirtyPaths;
|
||||
std::swap(_dirtyPaths, oldDirtyPaths);
|
||||
for (auto it = oldDirtyPaths.begin(); it != oldDirtyPaths.end(); ++it)
|
||||
emit fileStatusChanged(getSystemDestination(*it), fileStatus(*it));
|
||||
|
||||
// Make sure to push any status that might have been resolved indirectly since the last sync
|
||||
// (like an error file being deleted from disk)
|
||||
for (auto it = _syncProblems.begin(); it != _syncProblems.end(); ++it)
|
||||
@@ -176,7 +170,7 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
|
||||
SyncFileStatus::SyncFileStatusTag severity = it->second;
|
||||
if (severity == SyncFileStatus::StatusError)
|
||||
invalidateParentPaths(path);
|
||||
emit fileStatusChanged(getSystemDestination(path), fileStatus(path));
|
||||
emit fileStatusChanged(_syncEngine->localPath() + path, fileStatus(path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,10 +184,11 @@ void SyncFileStatusTracker::slotItemCompleted(const SyncFileItem &item)
|
||||
} else if (showWarningInSocketApi(item)) {
|
||||
_syncProblems[item._file] = SyncFileStatus::StatusWarning;
|
||||
} else {
|
||||
_syncProblems.erase(item._file);
|
||||
// There is currently no situation where an error status set during discovery/update is fixed by propagation.
|
||||
Q_ASSERT(_syncProblems.find(item._file) == _syncProblems.end());
|
||||
}
|
||||
|
||||
emit fileStatusChanged(getSystemDestination(item.destination()), syncFileItemStatus(item));
|
||||
emit fileStatusChanged(getSystemDestination(item), syncFileItemStatus(item));
|
||||
}
|
||||
|
||||
void SyncFileStatusTracker::slotSyncEngineRunningChanged()
|
||||
@@ -201,6 +196,13 @@ void SyncFileStatusTracker::slotSyncEngineRunningChanged()
|
||||
emit fileStatusChanged(_syncEngine->localPath(), syncFileItemStatus(rootSyncFileItem()));
|
||||
}
|
||||
|
||||
void SyncFileStatusTracker::slotClearDirtyPaths()
|
||||
{
|
||||
// We just assume that during a sync all dirty statuses will be resolved
|
||||
// one way or the other.
|
||||
_dirtyPaths.clear();
|
||||
}
|
||||
|
||||
SyncFileStatus SyncFileStatusTracker::syncFileItemStatus(const SyncFileItem& item)
|
||||
{
|
||||
// Hack to know if the item was taken from the sync engine (Sync), or from the database (UpToDate)
|
||||
@@ -234,19 +236,20 @@ void SyncFileStatusTracker::invalidateParentPaths(const QString& path)
|
||||
QStringList splitPath = path.split('/', QString::SkipEmptyParts);
|
||||
for (int i = 0; i < splitPath.size(); ++i) {
|
||||
QString parentPath = QStringList(splitPath.mid(0, i)).join(QLatin1String("/"));
|
||||
emit fileStatusChanged(getSystemDestination(parentPath), fileStatus(parentPath));
|
||||
emit fileStatusChanged(_syncEngine->localPath() + parentPath, fileStatus(parentPath));
|
||||
}
|
||||
}
|
||||
|
||||
QString SyncFileStatusTracker::getSystemDestination(const QString& relativePath)
|
||||
QString SyncFileStatusTracker::getSystemDestination(const SyncFileItem& item)
|
||||
{
|
||||
QString systemPath = _syncEngine->localPath() + relativePath;
|
||||
// SyncEngine::localPath() has a trailing slash, make sure to remove it if the
|
||||
// destination is empty.
|
||||
if( systemPath.endsWith(QLatin1Char('/')) ) {
|
||||
systemPath.truncate(systemPath.length()-1);
|
||||
QString systemFileName = _syncEngine->localPath() + item.destination();
|
||||
// the trailing slash for directories must be appended as the filenames coming in
|
||||
// from the plugins have that too. Otherwise the matching entry item is not found
|
||||
// in the plugin.
|
||||
if( item._type == SyncFileItem::Type::Directory ) {
|
||||
systemFileName += QLatin1Char('/');
|
||||
}
|
||||
return systemPath;
|
||||
return systemFileName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class OWNCLOUDSYNC_EXPORT SyncFileStatusTracker : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SyncFileStatusTracker(SyncEngine* syncEngine);
|
||||
SyncFileStatus fileStatus(const QString& relativePath);
|
||||
SyncFileStatus fileStatus(const QString& systemFileName);
|
||||
|
||||
public slots:
|
||||
void slotPathTouched(const QString& fileName);
|
||||
@@ -47,13 +47,14 @@ private slots:
|
||||
void slotAboutToPropagate(SyncFileItemVector& items);
|
||||
void slotItemCompleted(const SyncFileItem& item);
|
||||
void slotSyncEngineRunningChanged();
|
||||
void slotClearDirtyPaths();
|
||||
|
||||
private:
|
||||
SyncFileStatus syncFileItemStatus(const SyncFileItem& item);
|
||||
SyncFileItem rootSyncFileItem();
|
||||
|
||||
void invalidateParentPaths(const QString& path);
|
||||
QString getSystemDestination(const QString& relativePath);
|
||||
QString getSystemDestination(const SyncFileItem& syncEnginePath);
|
||||
|
||||
SyncEngine* _syncEngine;
|
||||
|
||||
|
||||
@@ -409,7 +409,7 @@ bool SyncJournalDb::checkConnect()
|
||||
_deleteFileRecordRecursively.reset(new SqlQuery(_db));
|
||||
_deleteFileRecordRecursively->prepare("DELETE FROM metadata WHERE path LIKE(?||'/%')");
|
||||
|
||||
QString sql( "SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget "
|
||||
QString sql( "SELECT lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration "
|
||||
"FROM blacklist WHERE path=?1");
|
||||
if( Utility::fsCasePreserving() ) {
|
||||
// if the file system is case preserving we have to check the blacklist
|
||||
@@ -421,8 +421,8 @@ bool SyncJournalDb::checkConnect()
|
||||
|
||||
_setErrorBlacklistQuery.reset(new SqlQuery(_db));
|
||||
_setErrorBlacklistQuery->prepare("INSERT OR REPLACE INTO blacklist "
|
||||
"(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration, renameTarget) "
|
||||
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)");
|
||||
"(path, lastTryEtag, lastTryModtime, retrycount, errorstring, lastTryTime, ignoreDuration) "
|
||||
"VALUES ( ?1, ?2, ?3, ?4, ?5, ?6, ?7)");
|
||||
|
||||
_getSelectiveSyncListQuery.reset(new SqlQuery(_db));
|
||||
_getSelectiveSyncListQuery->prepare("SELECT path FROM selectivesync WHERE type=?1");
|
||||
@@ -612,15 +612,6 @@ bool SyncJournalDb::updateErrorBlacklistTableStructure()
|
||||
}
|
||||
commitInternal("update database structure: add lastTryTime, ignoreDuration cols");
|
||||
}
|
||||
if( columns.indexOf(QLatin1String("renameTarget")) == -1 ) {
|
||||
SqlQuery query(_db);
|
||||
query.prepare("ALTER TABLE blacklist ADD COLUMN renameTarget VARCHAR(4096);");
|
||||
if( !query.exec() ) {
|
||||
sqlFail("updateBlacklistTableStructure: Add renameTarget", query);
|
||||
re = false;
|
||||
}
|
||||
commitInternal("update database structure: add lastTryTime, ignoreDuration cols");
|
||||
}
|
||||
|
||||
SqlQuery query(_db);
|
||||
query.prepare("CREATE INDEX IF NOT EXISTS blacklist_index ON blacklist(path collate nocase);");
|
||||
@@ -1233,7 +1224,6 @@ SyncJournalErrorBlacklistRecord SyncJournalDb::errorBlacklistEntry( const QStrin
|
||||
entry._errorString = _getErrorBlacklistQuery->stringValue(3);
|
||||
entry._lastTryTime = _getErrorBlacklistQuery->int64Value(4);
|
||||
entry._ignoreDuration = _getErrorBlacklistQuery->int64Value(5);
|
||||
entry._renameTarget = _getErrorBlacklistQuery->stringValue(6);
|
||||
entry._file = file;
|
||||
}
|
||||
_getErrorBlacklistQuery->reset_and_clear_bindings();
|
||||
@@ -1345,14 +1335,13 @@ void SyncJournalDb::updateErrorBlacklistEntry( const SyncJournalErrorBlacklistRe
|
||||
_setErrorBlacklistQuery->bindValue(5, item._errorString);
|
||||
_setErrorBlacklistQuery->bindValue(6, QString::number(item._lastTryTime));
|
||||
_setErrorBlacklistQuery->bindValue(7, QString::number(item._ignoreDuration));
|
||||
_setErrorBlacklistQuery->bindValue(8, item._renameTarget);
|
||||
if( !_setErrorBlacklistQuery->exec() ) {
|
||||
QString bug = _setErrorBlacklistQuery->error();
|
||||
qDebug() << "SQL exec blacklistitem insert or replace failed: "<< bug;
|
||||
}
|
||||
qDebug() << "set blacklist entry for " << item._file << item._retryCount
|
||||
<< item._errorString << item._lastTryTime << item._ignoreDuration
|
||||
<< item._lastTryModtime << item._lastTryEtag << item._renameTarget ;
|
||||
<< item._lastTryModtime << item._lastTryEtag;
|
||||
_setErrorBlacklistQuery->reset_and_clear_bindings();
|
||||
|
||||
}
|
||||
|
||||
@@ -151,7 +151,6 @@ SyncJournalErrorBlacklistRecord SyncJournalErrorBlacklistRecord::update(
|
||||
// The factor of 5 feels natural: 25s, 2 min, 10 min, ~1h, ~5h, ~24h
|
||||
entry._ignoreDuration = old._ignoreDuration * 5;
|
||||
entry._file = item._file;
|
||||
entry._renameTarget = item._renameTarget;
|
||||
|
||||
if( item._httpErrorCode == 403 ) {
|
||||
qDebug() << "Probably firewall error: " << item._httpErrorCode << ", blacklisting up to 1h only";
|
||||
|
||||
@@ -89,7 +89,6 @@ public:
|
||||
time_t _ignoreDuration;
|
||||
|
||||
QString _file;
|
||||
QString _renameTarget;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
|
||||
@@ -306,22 +306,17 @@ namespace {
|
||||
QString description(quint64 value) const
|
||||
{
|
||||
return QCoreApplication::translate(
|
||||
"Utility", name, 0, QCoreApplication::UnicodeUTF8,
|
||||
"Utiliy", name, 0, QCoreApplication::UnicodeUTF8,
|
||||
value);
|
||||
}
|
||||
};
|
||||
// QTBUG-3945 and issue #4855: QT_TRANSLATE_NOOP does not work with plural form because lupdate
|
||||
// limitation unless we fake more arguments
|
||||
// (it must be in the form ("context", "source", "comment", n)
|
||||
#undef QT_TRANSLATE_NOOP
|
||||
#define QT_TRANSLATE_NOOP(ctx, str, ...) str
|
||||
Q_DECL_CONSTEXPR Period periods[] = {
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n year(s)" , 0, _) , 365*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n month(s)", 0, _) , 30*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n day(s)", 0, _) , 24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n hour(s)", 0, _) , 3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n minute(s)", 0, _) , 60*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%n second(s)", 0, _ ), 1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln year(s)") , 365*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln month(s)") , 30*24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln day(s)") , 24*3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln hour(s)") , 3600*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln minute(s)") , 60*1000LL },
|
||||
{ QT_TRANSLATE_NOOP("Utility", "%Ln second(s)") , 1000LL },
|
||||
{ 0, 0 }
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace Utility
|
||||
|
||||
class OWNCLOUDSYNC_EXPORT StopWatch {
|
||||
private:
|
||||
QMap<QString, quint64> _lapTimes;
|
||||
QHash<QString, quint64> _lapTimes;
|
||||
QDateTime _startTime;
|
||||
QElapsedTimer _timer;
|
||||
public:
|
||||
|
||||
@@ -11,7 +11,7 @@ macro(owncloud_add_test test_class additional_cpp)
|
||||
string(TOLOWER "${OWNCLOUD_TEST_CLASS}" OWNCLOUD_TEST_CLASS_LOWERCASE)
|
||||
|
||||
add_executable(${OWNCLOUD_TEST_CLASS}Test test${OWNCLOUD_TEST_CLASS_LOWERCASE}.cpp ${additional_cpp})
|
||||
qt5_use_modules(${OWNCLOUD_TEST_CLASS}Test Test Sql Xml Network)
|
||||
qt5_use_modules(${OWNCLOUD_TEST_CLASS}Test Test Sql Xml Network Gui Widgets)
|
||||
|
||||
target_link_libraries(${OWNCLOUD_TEST_CLASS}Test
|
||||
updater
|
||||
|
||||
@@ -150,10 +150,5 @@ using namespace OCC;
|
||||
}
|
||||
};
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
QTEST_MAIN(TestChecksumValidator)
|
||||
#else
|
||||
QTEST_GUILESS_MAIN(TestChecksumValidator)
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(TestChecksumValidator)
|
||||
#include "testchecksumvalidator.moc"
|
||||
|
||||
@@ -100,5 +100,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestConcatUrl)
|
||||
QTEST_MAIN(TestConcatUrl)
|
||||
#include "testconcaturl.moc"
|
||||
|
||||
@@ -85,5 +85,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestCSyncSqlite)
|
||||
QTEST_MAIN(TestCSyncSqlite)
|
||||
#include "testcsyncsqlite.moc"
|
||||
|
||||
@@ -26,25 +26,24 @@ private slots:
|
||||
bool excludeHidden = true;
|
||||
bool keepHidden = false;
|
||||
|
||||
bool x = excluded.isExcluded("/a/b", "/a", keepHidden);
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "/a", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b~", "/a", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", "/a", excludeHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "b", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b~", "b~", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", ".b", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", ".b", excludeHidden));
|
||||
|
||||
QString path(BIN_PATH);
|
||||
path.append("/sync-exclude.lst");
|
||||
excluded.addExcludeFilePath(path);
|
||||
excluded.reloadExcludes();
|
||||
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/b~", "/a", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.Trashes", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/foo_conflict-bar", "/a", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", "/a", excludeHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/b", "b", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/b~", "b~", keepHidden));
|
||||
QVERIFY(!excluded.isExcluded("/a/.b", ".b", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.Trashes", ".Trashes", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/foo_conflict-bar", "foo_conflict-bar", keepHidden));
|
||||
QVERIFY(excluded.isExcluded("/a/.b", ".b", excludeHidden));
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestExcludedFiles)
|
||||
QTEST_MAIN(TestExcludedFiles)
|
||||
#include "testexcludedfiles.moc"
|
||||
|
||||
@@ -87,5 +87,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestFileSystem)
|
||||
QTEST_MAIN(TestFileSystem)
|
||||
#include "testfilesystem.moc"
|
||||
|
||||
@@ -41,5 +41,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestFolder)
|
||||
QTEST_MAIN(TestFolder)
|
||||
#include "testfolder.moc"
|
||||
|
||||
@@ -118,5 +118,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestFolderMan)
|
||||
QTEST_MAIN(TestFolderMan)
|
||||
#include "testfolderman.moc"
|
||||
|
||||
@@ -170,10 +170,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
QTEST_MAIN(TestFolderWatcher)
|
||||
#else
|
||||
QTEST_GUILESS_MAIN(TestFolderWatcher)
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(TestFolderWatcher)
|
||||
#include "testfolderwatcher.moc"
|
||||
|
||||
@@ -69,5 +69,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestInotifyWatcher)
|
||||
QTEST_MAIN(TestInotifyWatcher)
|
||||
#include "testinotifywatcher.moc"
|
||||
|
||||
@@ -72,5 +72,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestNetrcParser)
|
||||
QTEST_MAIN(TestNetrcParser)
|
||||
#include "testnetrcparser.moc"
|
||||
|
||||
@@ -78,5 +78,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestOwncloudPropagator)
|
||||
QTEST_MAIN(TestOwncloudPropagator)
|
||||
#include "testowncloudpropagator.moc"
|
||||
|
||||
@@ -149,5 +149,5 @@ private:
|
||||
SqlDatabase _db;
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestOwnSql)
|
||||
QTEST_MAIN(TestOwnSql)
|
||||
#include "testownsql.moc"
|
||||
|
||||
@@ -65,5 +65,5 @@ private slots:
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestSyncFileItem)
|
||||
QTEST_MAIN(TestSyncFileItem)
|
||||
#include "testsyncfileitem.moc"
|
||||
|
||||
@@ -171,5 +171,5 @@ private:
|
||||
SyncJournalDb _db;
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestSyncJournalDB)
|
||||
QTEST_MAIN(TestSyncJournalDB)
|
||||
#include "testsyncjournaldb.moc"
|
||||
|
||||
@@ -30,5 +30,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestUpdater)
|
||||
QTEST_MAIN(TestUpdater)
|
||||
#include "testupdater.moc"
|
||||
|
||||
@@ -121,13 +121,11 @@ private slots:
|
||||
// Current requires an X-Server
|
||||
return;
|
||||
}
|
||||
// pass the binary name owncloud to the next call. This brakes branding,
|
||||
// but branding is not supposed to work with this.
|
||||
QString ver = versionOfInstalledBinary(BIN_PATH+QLatin1String("/owncloud"));
|
||||
QString ver = versionOfInstalledBinary(BIN_PATH);
|
||||
qDebug() << "Version of installed ownCloud Binary: " << ver;
|
||||
QVERIFY( !ver.isEmpty());
|
||||
|
||||
QRegExp rx( "ownCloud version \\d+\\.\\d+\\.\\d+.*" );
|
||||
QRegExp rx( "ownCloud version \\d+\\.\\d+\\.\\d+.+" );
|
||||
QVERIFY( rx.exactMatch(ver));
|
||||
} else {
|
||||
QVERIFY( versionOfInstalledBinary().isEmpty());
|
||||
@@ -136,29 +134,36 @@ private slots:
|
||||
|
||||
void testTimeAgo()
|
||||
{
|
||||
// Both times in same timezone
|
||||
// Both times in local time
|
||||
QDateTime d1 = QDateTime::fromString("2015-01-24T09:20:30+01:00", Qt::ISODate);
|
||||
QDateTime d2 = QDateTime::fromString("2015-01-23T09:20:30+01:00", Qt::ISODate);
|
||||
QString s = timeAgoInWords(d2, d1);
|
||||
QCOMPARE(s, QLatin1String("1 day(s) ago"));
|
||||
|
||||
// Different timezones
|
||||
//
|
||||
QDateTime earlyTS = QDateTime::fromString("2015-01-24T09:20:30+01:00", Qt::ISODate);
|
||||
QDateTime laterTS = QDateTime::fromString("2015-01-24T09:20:30-01:00", Qt::ISODate);
|
||||
earlyTS.setTimeSpec(Qt::UTC);
|
||||
QDateTime laterTS = earlyTS.toOffsetFromUtc(3600);
|
||||
laterTS.setTimeSpec(Qt::UTC);
|
||||
s = timeAgoInWords(earlyTS, laterTS);
|
||||
QCOMPARE(s, QLatin1String("2 hour(s) ago"));
|
||||
QCOMPARE(s, QLatin1String("1 hour(s) ago"));
|
||||
|
||||
// 'Now' in whatever timezone
|
||||
earlyTS = QDateTime::currentDateTime();
|
||||
|
||||
laterTS.setTimeSpec(Qt::LocalTime);
|
||||
laterTS.setTimeZone( QTimeZone("Pacific/Easter") );
|
||||
laterTS = earlyTS;
|
||||
|
||||
s = timeAgoInWords(earlyTS, laterTS );
|
||||
QCOMPARE(s, QLatin1String("now"));
|
||||
|
||||
earlyTS = earlyTS.addSecs(-6);
|
||||
s = timeAgoInWords(earlyTS, laterTS );
|
||||
QCOMPARE(s, QLatin1String("Less than a minute ago"));
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestUtility)
|
||||
QTEST_MAIN(TestUtility)
|
||||
#include "testutility.moc"
|
||||
|
||||
@@ -441,10 +441,5 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
QTEST_MAIN(TestXmlParse)
|
||||
#else
|
||||
QTEST_GUILESS_MAIN(TestXmlParse)
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(TestXmlParse)
|
||||
#include "testxmlparse.moc"
|
||||
|
||||