Comparar commits

..

108 Commits

Autor SHA1 Mensagem Data
Daniel Molkentin 06ce09651e Merge remote-tracking branch 'origin/master' into libsplit
Conflicts:
	src/gui/folder.cpp
2015-10-20 22:21:37 +02:00
Markus Goetz 98b966d274 OS X: Use Cocoa Pasteboard instead of QClipBoard #3300 2015-10-20 15:42:43 +02:00
Olivier Goffart 674b6f2373 Account Settings: clear the focus of the "Sign In" button when clicked
So that the focus does not go to the "Remove Account" button instead
which would be wierd
2015-10-20 13:56:35 +02:00
Olivier Goffart 407ff0a99d Theme: cache the QIcon::fromTheme
We are calling that every time we draw the folder delegate.
Which is a lot when the sync is runing and the progress bar is moving
2015-10-20 13:24:11 +02:00
Olivier Goffart 0b6d21e3d5 Logger: don't call qFormatLog when unessesary
That's a lot of string operations that can be avoided if the log window
is not shown
2015-10-20 13:22:48 +02:00
Olivier Goffart 557b704069 Fix compilation warning
shibbolethcredentials.h:59:10: warning: 'askFromUser' overrides a member
function but is not marked 'override' [-Winconsistent-missing-override]
2015-10-20 11:35:25 +02:00
Olivier Goffart 4369e31a49 Folder Model: don't try to fetch data if the account is disconnected
Now that it expands automatically, it would do lots of query to the
server when the account is disconnected. (all resulting in 401)
2015-10-19 18:32:34 +02:00
Olivier Goffart 23b5a74c17 Account Settings: Don't expand while clicking on the '...' button 2015-10-19 18:23:56 +02:00
Olivier Goffart ee69ab2021 Account Settings: Don't disable double click expanding for sub folders
The root folder open on simple click,  but the sub folder don't, so keep
this behaviour which is the native behaviour
2015-10-19 18:12:49 +02:00
Olivier Goffart 374f29c4d3 Account Settings: Fix crash for acocunts withour folder
Was broken by  027a865fbc
2015-10-19 18:08:11 +02:00
Markus Goetz 67910e7d60 Discovery: Call it "Checking for changes in" in UI
For #3431
2015-10-19 15:59:16 +02:00
Markus Goetz c80b033466 VERSION.cmake: fixup 2015-10-19 15:57:13 +02:00
Olivier Goffart 671af9f8fe Merge branch 'master' 2015-10-19 15:53:58 +02:00
Olivier Goffart 6ea05ff6e3 Dolphin shell integration: use the owncloud icons 2015-10-19 15:53:40 +02:00
Markus Goetz 00485e133f VERSION.cmake: This is git not rc1 2015-10-19 15:51:33 +02:00
Olivier Goffart c520ee4eab Dolphin Shell Extension: renamove the kf5 in the name 2015-10-19 15:43:42 +02:00
Olivier Goffart 5408ec79f7 Dolphin shell extention: Remove the KDE4 based plugin 2015-10-19 15:42:41 +02:00
Olivier Goffart f8e68ae823 Merge branch 'dolphin-plugin' 2015-10-19 15:41:47 +02:00
Olivier Goffart 184412d88e Dolphin shell integration: Renames the plugins
And put the helper in a shared library so it is shared accross both plugins
2015-10-19 15:40:11 +02:00
Olivier Goffart 82d1d04774 Dolphin shell integration: share code between two plugins 2015-10-19 15:40:11 +02:00
Olivier Goffart 731d4b3d4d Dolphin shell extention: adapt to the change in KDE Frameworks 2015-10-19 15:39:51 +02:00
Markus Goetz ccec186b98 ETagJob: Depth 0 for server >= 8.1 #3730 2015-10-19 15:31:27 +02:00
Olivier Goffart 5cac90b3eb SelectiveSyncTreeView: show the size for the root item (#3755) 2015-10-19 10:58:54 +02:00
Olivier Goffart df135a0bb2 Merge branch '2.0'
Conflicts:
	src/gui/folder.cpp
2015-10-19 10:57:37 +02:00
Markus Goetz b5e75afc17 General settings: Align checkbox #3758 2015-10-15 19:15:50 +02:00
Markus Goetz 027a865fbc Account Settings: Show selective sync buttons after list load
Especially nice when having a slower network.
For #3839
2015-10-15 18:52:16 +02:00
Markus Goetz 132b5f5130 Account Settings: Expand selective sync on show #3585 2015-10-15 17:27:38 +02:00
Markus Goetz c3754e1fdd folderstatusmodel.h: Fix warning 2015-10-15 17:27:29 +02:00
Markus Goetz 963eb1f29b VERSION.cmake: master is 2.1 2015-10-15 16:51:29 +02:00
Christian Kamm c418d67920 Merge remote-tracking branch 'origin/2.0' 2015-10-15 15:54:09 +02:00
Christian Kamm 6e09e3af86 Fix test compile
I regularly fix errors in the copies of the test sources that are
made in build/. Refactoring how these tests work could be worthwhile.
2015-10-15 15:52:58 +02:00
Christian Kamm 67e9a06d30 Progress estimation: Adjust low-transfer detection #3942
Progress estimation is usually based on transfer speed. That makes no
sense when we're doing operations like deletes, that need very little
data transfer but nevertheless take a long time.

This hack attempts to detect this case better and switches to a
different estimate.

We should rewrite this to maintain and update estimates for the
transfer speed, per-file overhead and chunk-assembly overhead each
time an item finishes. Then we could provide more consistent progress
estimates without ad-hoc fixes like this one.

Also, there's an issue where resuming a partial download will lead
to exaggerated transfer speed estimates.
2015-10-15 15:04:11 +02:00
Christian Kamm abd63035c1 ETag: Allow parsing of weak tags #3946 2015-10-15 14:57:34 +02:00
Roeland Douma df2418d9c5 Merge pull request #3661 from rullzer/public_upload
Allow setting of public upload on link shares
2015-10-14 15:34:25 +02:00
Roeland Jago Douma 2fdae6d72f Allow setting op public upload on link shares 2015-10-14 15:30:28 +02:00
Roeland Jago Douma 05471d0acd Also parse capabilitie for public uploads 2015-10-14 15:30:23 +02:00
Christian Kamm 05eee16959 SelectiveSync: Show in-progress label #3524
We now show 'Fetching data...' after a second.

This also increased the timeout to 60s, making the error
condition much less likely.
2015-10-14 13:05:53 +02:00
Roeland Douma a752eadd0f Merge pull request #3923 from owncloud/check_shareapi_available
Provide information about share availablity for files
2015-10-14 12:38:03 +02:00
Roeland Jago Douma 028dc8d6c3 Add SHARE_STATUS socketAPI command
This command allows to retrieve the share status of a file. In other
words if it can be shared.
2015-10-14 12:36:32 +02:00
Roeland Jago Douma 4a7242c8f9 Extended capabilities API
* Naming of capabilities is now a bit more consistent
2015-10-14 11:45:34 +02:00
Christian Kamm efdb29d2f9 AccountSettings: Show disabled 'Add Folder' tooltip on click #3645 2015-10-14 11:34:30 +02:00
Christian Kamm 225da68832 ExcludedFiles: Add test 2015-10-13 15:01:59 +02:00
Christian Kamm 51a2e6c580 Exclusion: Fix confusion with relative and absolute paths 2015-10-13 12:53:38 +02:00
Christian Kamm 7fe03c715d SelectiveSync: Don't adjust removed path 2015-10-13 12:37:27 +02:00
Klaas Freitag 419d18c128 FileSystem: Reuse the FileInfo object that is created in the caller.
With that, a lot of stats can be avoided, ie. in SocketAPI
2015-10-09 13:02:02 +02:00
Klaas Freitag 74a7755ad9 SocketAPI: String concat optimization as learned on QtWS. 2015-10-08 18:26:30 +02:00
Klaas Freitag c1ba927b37 Propagatorjobs: Removed superflous semicolon. 2015-10-08 16:20:42 +02:00
Klaas Freitag cb3a301f2c Merge pull request #3899 from sebasje/sebas/cmake
fix multiarch library path for Debian/Ubuntu
2015-10-06 15:36:43 +02:00
Klaas Freitag 6d6903ef62 Merge pull request #3919 from phil-davis/libsynctypos
libsync comment and message typos for master
2015-10-06 14:49:54 +02:00
Klaas Freitag f5daf50dc4 Merge pull request #3920 from phil-davis/guitypos
GUI comment and message typos for master
2015-10-06 14:46:00 +02:00
Phil Davis b8ccbbc72a GUI comment and message typos for master 2015-10-05 10:06:19 +05:45
Phil Davis f0e17fd9c0 libtypos comment and message typos for master 2015-10-05 09:05:09 +05:45
Klaas Freitag b09f1d591c Merge pull request #3916 from RealRancor/fix_rst_syntax
Fix linkname in architecture.rst.
2015-10-04 17:59:45 +02:00
RealRancor 8fd2b8d829 Fix linkname in architecture.rst. 2015-10-03 21:42:23 +02:00
Christian Kamm d610693af1 SelectiveSync: Apply excludes #3876 2015-10-02 15:56:39 +02:00
Christian Kamm 7d1886684e FolderWatcher: Use csync exclude code #3805
Introduce a global ExcludedFiles instance to avoid loading the global
exclude lists several times.

One could still add per-folder exclude lists by checking these after
the global ones.
2015-10-02 15:56:39 +02:00
Christian Kamm 95fc792745 Tray: Change texts #3657 2015-10-02 15:48:44 +02:00
Christian Kamm efefc2d986 Merge branch '2.0'
Conflicts:
	doc/images/menu.png
	doc/images/settings_network.png
2015-10-02 15:44:50 +02:00
Christian Kamm 9f8d109a7e Network errors: Use exception name, if message is empty #2718 2015-10-02 15:25:34 +02:00
Christian Kamm cf9e5ffb0b Remove dead code
no_recursive_propfind does not exist anymore.
2015-10-02 15:17:19 +02:00
Christian Kamm 1383023b2e Fix the Qt4 build. 2015-10-02 11:05:15 +02:00
Christian Kamm 3812fd0866 Checksums: Prepare 'supported checksums' capability #3735
It currently always returns the empty list and thus has no effect.
2015-10-01 15:00:33 +02:00
Christian Kamm 24c41ed0da Propagation: Try another sync on 423 Locked #3387 2015-10-01 13:05:07 +02:00
Christian Kamm 36e8e9ebf5 Propagator: Download disk space checks #2939
* There's a critical 50 MB threshold under which syncs abort
  (OWNCLOUD_CRITICAL_FREE_SPACE)
* The sync client always keeps 250 MB free
  (OWNCLOUD_FREE_SPACE)
2015-10-01 12:59:05 +02:00
Christian Kamm 12dc372b21 Sync: An initial diskspace check #2939
* Before each sync, check that there are at least
  250 MB of space available and abort otherwise.
* Can be overridden with OWNCLOUD_MIN_FREE_SPACE
2015-10-01 10:25:35 +02:00
Christian Kamm 20ea9015ca Propagation: Make 423 Locked a soft error #3387 2015-09-30 14:00:53 +02:00
Sebastian Kügler a7cf1b04ad Simplify creating the library path
Instead of checking whether the library path ends up somewhere in /usr,
set the architecture prefix, anyway. The library path mechanism is also
used in custom prefixes, without this change, the library gets installed
globally on Debian and Ubuntu, leading to non-standard behaviour and
cross-build problems, as multiple architecture builds of this library
can't be installed alongside each other.

This is the minimal change to correct this behaviour from upstream cmake.
2015-09-29 00:15:39 +02:00
Daniel Molkentin a08a90a718 Merge pull request #3892 from RealRancor/fix_faq
Fix registry key syntax in FAQ.
2015-09-27 20:38:13 +02:00
RealRancor 1cb518cb13 Fix registry key syntax in FAQ. 2015-09-27 20:19:06 +02:00
Sebastian Kügler c9eef1aca2 Include remaining necessary classes in libclient 2015-09-25 16:45:45 +02:00
Sebastian Kügler f8329bf8b5 Add libowncloudclient
This is an option right now, and not used by the desktop client (this
switch can come later).
2015-09-25 04:26:29 +02:00
Sebastian Kügler c3ab89c965 Fix include 2015-09-25 04:24:31 +02:00
Sebastian Kügler 2b4f0e6ea4 Fix includes 2015-09-25 04:24:01 +02:00
Sebastian Kügler 63a67da3b8 Install cross-referenced headers 2015-09-25 04:22:10 +02:00
Sebastian Kügler 9d62c519f8 Include the private header, but only in the .cpp files 2015-09-25 04:21:53 +02:00
Sebastian Kügler 3b1a78e3b4 Do not install private header
This is actually not needed in any of the headers, so we can forego
installing it. We do need the config_ header, and the std/c_private.h
one, though.
2015-09-25 04:20:43 +02:00
Sebastian Kügler 695223527f Install owncloudlib.h 2015-09-25 02:54:10 +02:00
Sebastian Kügler 79d8b0d261 include csync_private.h from csync.h
This allows to remove the private includes, and will make it possible to
merge these headers later on without breaking includes. It's a bit of a
hack, but makes the separation a bit cleaner.
2015-09-25 01:19:09 +02:00
Sebastian Kügler f37a66bd5c Install csync headers
- installs headers for non-osx bundles
- also installs csync_private.h, since it's needed in the owncloud
  client (this is a sign that it warrants rethinking the public API, and
  what's supposed to be private, and why.
2015-09-25 01:12:33 +02:00
Olivier Goffart cac219aca8 Dolphin shell integration: Add a Share with owncloud action 2015-09-10 13:41:45 +02:00
Olivier Goffart a159dfc7ec Dolphin shell integration: Make it work with dolphin master 2015-09-10 13:41:45 +02:00
Daniel Molkentin b7061618b1 Merge pull request #3789 from hh-lohmann/Terminology
/doc/autoupdate.rst: "32-/64-bit" => "32-/64-bit-Windows"
2015-09-10 01:37:10 +02:00
Daniel Molkentin d823809021 Merge pull request #3781 from phil-davis/FSC
Coin the term 'folder sync connection'
2015-09-10 01:35:25 +02:00
hh.lohmann 0329a8be2e /doc/autoupdate.rst: "Migrate to the following directory" => "Edit this Registry key"
Registry keys are no directories; you would not "migrate" to keys if you are just about to switch to them; resembling formulas as "Edit these / this Registry key/s" ease fast reading, for that also ":" instead of "::" at the end (formatting what follows)
2015-09-09 12:33:25 +02:00
hh.lohmann 79f64abfc3 /doc/autoupdate.rst: "32-/64-bit" => "32-/64-bit-Windows"
Should be stated clearly that there are no alternative 32- / 64-bit-ownCloud-Clients, but just a 32-bit-ownCloud-Client that is treated differently in 32- / 64-bit-Windows
2015-09-09 12:10:10 +02:00
Markus Goetz 63636aca9b Merge pull request #3777 from owncloud/individual-it-utf8-patch
fix unicode issue #3753
2015-09-08 16:06:42 +02:00
Phil Davis fdfab07d07 Coin the term 'folder sync connection'
Proposed wording for issue
https://github.com/owncloud/client/issues/3757
2015-09-08 17:22:57 +05:45
Individual IT Services cc5f8e5122 fix unicode issue #3753
fixes the unicode issue #3753

I don't know much CPP and Qt but after some google research I found this http://wiki.qt.io/Strings_and_encodings_in_Qt
it does mention trUtf8() that has done the trick for me on Linux with Gnome 3.16.
Haven't tested it on other systems
2015-09-08 13:59:43 +05:45
Olivier Goffart 21dbf97a02 Merge remote-tracking branch 'origin/2.0' 2015-09-07 10:32:16 +02:00
Olivier Goffart 39bff056a6 Merge remote-tracking branch 'origin/2.0' 2015-09-05 18:14:30 +02:00
Jocelyn Turcotte 128d46e19a Remove *Credentials::_fetchJobInProgress
Now that fetchFromKeychain is solely called from AccountState::slotInvalidCredentials
and that this one already protects the fetch call using _waitingForNewCredentials,
we can remove that extra check.
2015-09-05 16:00:45 +02:00
Jocelyn Turcotte 6d027ebd40 Separate the credential dialog from their fetch #3350
This moves the responsibility of asking the user or not for
credentials from the Credentials classes back to the AccountState.
fetch() now only extract credentials from the keychain, reports
the result to the AccountState which then decides if askFromUser()
should be called or not. The result is once more reported to the
AccounState.

This also replaces the HttpCredentials::queryPassword virtual
which now lets HttpCredentialsGui and HttpCredentialsText do it
the way that they prefer.
2015-09-05 16:00:45 +02:00
Jocelyn Turcotte 89f69209dd Simplify the authentication code paths #3350
The AccountState is now the only class responsible for triggering credentials
fetching from the keychain or from the user.

With the ShibbolethRefresher out of the question it's possible
to remove the invalidateAndFetch virtual and manually call invalidateToken.
This also allows us to move that code from Account to AccountState.
In the end this also allows us to move the fetch() call from the
ConnectionValidator and use the same code path as for invalid credentials.
2015-09-05 16:00:45 +02:00
Jocelyn Turcotte 94a57fe8d5 Get rid of ShibbolethRefresher
This is only for neon and not necessary if we want to show a notification
instead of a login window when the network reports invalid credentials.
2015-09-05 15:45:54 +02:00
Jocelyn Turcotte dcb687929f Show a notification instead of a login window on startup #3350
The original problem is that showing a popup not originated
from the main settings window while it's focused won't be
shown in front to the user.

This try not to highjack the user's attention of the user
by showing a notification when checking the connection for
valid credentials, and require the user to sign in through
the UI. There are still issues with showing that popup from
the tray icon, but the user will most likely be looking for
the popup in that case. The new sign in button directly in
the settings account works properly.
2015-09-01 18:40:20 +02:00
Jocelyn Turcotte 628957de21 Remove the _readPwdFromDeprecatedPlace codepath
This was introduced in 1.6.2 to read the password from earlier versions.
People upgrading from 1.5 to 2.1 will sadly need to re-enter their password.
2015-09-01 18:40:20 +02:00
Jocelyn Turcotte bcfc16c0f6 Add a sign in button in the settings window
It's not obvious for users that they should sign in through
the tray icon, especially if they were automatically signed out.
2015-09-01 18:40:20 +02:00
Olivier Goffart 3ba5e27d02 Merge branch '2.0' 2015-09-01 17:57:56 +02:00
Olivier Goffart 950bc578d0 Merge branch '2.0' 2015-08-31 14:34:04 +02:00
Carla Schroder ccfcdff190 Merge pull request #3665 from owncloud/2-0updates
1st batch of updates for 2.0
2015-08-27 10:28:03 +02:00
Carla Schroder 45835f1cf9 Update navigating.rst 2015-08-27 10:25:19 +02:00
Carla Schroder cf543d1eb0 Update navigating.rst 2015-08-27 10:20:15 +02:00
Carla Schroder 9f24f10186 Update installing.rst 2015-08-27 10:07:54 +02:00
Carla Schroder bc37668e9f 1st batch of updates for 2.0 2015-08-21 13:19:15 -07:00
Daniel Molkentin 22d87218b7 Merge pull request #3601 from individual-it/master
checking if file or folder is to be shared to fix issue #3556
2015-08-18 11:45:31 +02:00
Markus Goetz 62d64acd7b Merge pull request #3589 from owncloud/sharedir
Use SHAREDIR for i18n dir
2015-08-13 16:02:11 +02:00
Individual IT Services c6ff73f3e5 checking if file or folder is to be shared to fix issue #3556 2015-08-12 21:48:04 +05:45
hefee a87602af3f use SHAREDIR for i18n
SHAREDIR is used in src/gui/application.cpp and should also use that in
CMakeLists.txt.
2015-08-11 15:14:59 +02:00
130 arquivos alterados com 2121 adições e 1877 exclusões
+3 -3
Ver Arquivo
@@ -1,10 +1,10 @@
set( MIRALL_VERSION_MAJOR 2 )
set( MIRALL_VERSION_MINOR 0 )
set( MIRALL_VERSION_PATCH 2 )
set( MIRALL_VERSION_MINOR 1 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
set( MIRALL_VERSION_SUFFIX "rc2") #e.g. beta1, beta2, rc1
set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
if( NOT DEFINED MIRALL_VERSION_BUILD )
+1 -7
Ver Arquivo
@@ -134,13 +134,7 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
AND NOT CMAKE_CROSSCOMPILING)
if (EXISTS "/etc/debian_version") # is this a debian system ?
if(CMAKE_LIBRARY_ARCHITECTURE)
if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX
AND "${_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
set(__LAST_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
+13 -9
Ver Arquivo
@@ -88,10 +88,8 @@ configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h)
set(csync_HDRS
${CMAKE_CURRENT_BINARY_DIR}/csync_version.h
${CMAKE_CURRENT_BINARY_DIR}/../config_csync.h
csync.h
vio/csync_vio.h
vio/csync_vio_method.h
vio/csync_vio_module.h
)
# Statically include sqlite
@@ -142,12 +140,18 @@ else()
RUNTIME DESTINATION
${BIN_INSTALL_DIR}/${APPLICATION_EXECUTABLE}
)
INSTALL(
FILES
${csync_HDRS}
DESTINATION
${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}
)
INSTALL(
FILES
std/c_private.h
DESTINATION
${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}/std
)
endif()
# INSTALL(
# FILES
# ${csync_HDRS}
# DESTINATION
# ${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}
# )
+2 -2
Ver Arquivo
@@ -73,8 +73,8 @@ To prevent automatic updates, but allow manual overrides:
1. Edit these Registry keys:
a. (32-bit) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud``
b. (64-bit) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud``
a. (32-bit-Windows) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud``
b. (64-bit-Windows) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud``
2. Add the key ``skipUpdateCheck`` (of type DWORD).
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 39 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 41 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 44 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 59 KiB

@@ -1,256 +0,0 @@
From 3a26dc77f8e988ea99b23c4d5a2c831ecc31c920 Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@woboq.com>
Date: Thu, 17 Jul 2014 13:26:56 +0200
Subject: [PATCH] WIP: add KOverlayIconPlugin
---
.../src/kitemviews/kfileitemmodelrolesupdater.cpp | 35 ++++++++++++-
.../src/kitemviews/kfileitemmodelrolesupdater.h | 9 ++++
lib/konq/CMakeLists.txt | 4 +-
lib/konq/koverlayiconplugin.cpp | 30 ++++++++++++
lib/konq/koverlayiconplugin.desktop | 4 ++
lib/konq/koverlayiconplugin.h | 57 ++++++++++++++++++++++
6 files changed, 137 insertions(+), 2 deletions(-)
create mode 100644 lib/konq/koverlayiconplugin.cpp
create mode 100644 lib/konq/koverlayiconplugin.desktop
create mode 100644 lib/konq/koverlayiconplugin.h
diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
index 0865d40..840a65d 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -28,9 +28,11 @@
#include <KGlobal>
#include <KIO/JobUiDelegate>
#include <KIO/PreviewJob>
+#include <KServiceTypeTrader>
#include "private/kpixmapmodifier.h"
#include "private/kdirectorycontentscounter.h"
+#include <koverlayiconplugin.h>
#include <QApplication>
#include <QPainter>
@@ -129,6 +131,17 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
m_directoryContentsCounter = new KDirectoryContentsCounter(m_model, this);
connect(m_directoryContentsCounter, SIGNAL(result(QString,int)),
this, SLOT(slotDirectoryContentsCountReceived(QString,int)));
+
+
+ const KService::List pluginServices = KServiceTypeTrader::self()->query("KOverlayIconPlugin");
+
+ for (KService::List::ConstIterator it = pluginServices.constBegin(); it != pluginServices.constEnd(); ++it) {
+ KOverlayIconPlugin* plugin = (*it)->createInstance<KOverlayIconPlugin>(this);
+ if (plugin) {
+ m_overlayIconsPlugin.append(plugin);
+ connect(plugin, SIGNAL(overlaysChanged(KUrl,QStringList)), this, SLOT(slotOverlaysChanged(KUrl,QStringList)));
+ }
+ }
}
KFileItemModelRolesUpdater::~KFileItemModelRolesUpdater()
@@ -1075,7 +1088,11 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
data.insert("type", item.mimeComment());
}
- data.insert("iconOverlays", item.overlays());
+ QStringList overlays = item.overlays();
+ foreach(KOverlayIconPlugin *it, m_overlayIconsPlugin) {
+ overlays.append(it->getOverlays(item));
+ }
+ data.insert("iconOverlays", overlays);
#ifdef HAVE_BALOO
if (m_balooFileMonitor) {
@@ -1086,6 +1103,22 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
return data;
}
+void KFileItemModelRolesUpdater::slotOverlaysChanged(const KUrl& url, const QStringList &)
+{
+ KFileItem item = m_model->fileItem(url);
+ if (item.isNull())
+ return;
+ int index = m_model->index(item);
+ QHash <QByteArray, QVariant> data = m_model->data(index);
+ QStringList overlays = item.overlays();
+ foreach(KOverlayIconPlugin *it, m_overlayIconsPlugin) {
+ overlays.append(it->getOverlays(item));
+ }
+ data.insert("iconOverlays", overlays);
+ m_model->setData(index, data);
+}
+
+
void KFileItemModelRolesUpdater::updateAllPreviews()
{
if (m_state == Paused) {
diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
index a9e979a..6d3add0 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
@@ -32,6 +32,7 @@
#include <QSize>
#include <QStringList>
+class KOverlayIconPlugin;
class KDirectoryContentsCounter;
class KFileItemModel;
class KJob;
@@ -180,6 +181,12 @@ private slots:
void slotPreviewJobFinished();
/**
+ * Is invoked when one of the KOverlayIconPlugin emit the signal that an overlay has changed
+ */
+ void slotOverlaysChanged(const KUrl&, const QStringList&);
+
+
+ /**
* Resolves the sort role of the next item in m_pendingSortRole, applies it
* to the model, and invokes itself if there are any pending items left. If
* that is not the case, \a startUpdating() is called.
@@ -331,6 +338,8 @@ private:
KDirectoryContentsCounter* m_directoryContentsCounter;
+ QList<KOverlayIconPlugin*> m_overlayIconsPlugin;
+
#ifdef HAVE_BALOO
Baloo::FileMonitor* m_balooFileMonitor;
#endif
diff --git a/lib/konq/CMakeLists.txt b/lib/konq/CMakeLists.txt
index 8ecbfa9..7381caf 100644
--- a/lib/konq/CMakeLists.txt
+++ b/lib/konq/CMakeLists.txt
@@ -22,6 +22,7 @@ set(konq_LIB_SRCS
konq_historyprovider.cpp
kversioncontrolplugin.cpp # used by dolphin and its version control plugins (deprecated)
kversioncontrolplugin2.cpp # used by dolphin and its version control plugins
+ koverlayiconplugin.cpp
konq_nameandurlinputdialog.cpp # deprecated (functionality has moved to kdelibs)
knewmenu.cpp # deprecated (functionality has moved to kdelibs)
@@ -67,8 +68,9 @@ install( FILES
konq_fileitemcapabilities.h
kversioncontrolplugin.h
kversioncontrolplugin2.h
+ koverlayiconplugin.h
konq_historyprovider.h
konq_historyentry.h
DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel
)
-install( FILES konqpopupmenuplugin.desktop konqdndpopupmenuplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} )
+install( FILES konqpopupmenuplugin.desktop konqdndpopupmenuplugin.desktop koverlayiconplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} )
diff --git a/lib/konq/koverlayiconplugin.cpp b/lib/konq/koverlayiconplugin.cpp
new file mode 100644
index 0000000..6125040
--- /dev/null
+++ b/lib/konq/koverlayiconplugin.cpp
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com> *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public License *
+ * along with this library; see the file COPYING.LIB. If not, write to *
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301, USA. *
+ *****************************************************************************/
+
+#include "koverlayiconplugin.h"
+#include <KFileItem>
+
+KOverlayIconPlugin::KOverlayIconPlugin(QObject* parent) : QObject(parent)
+{
+}
+
+KOverlayIconPlugin::~KOverlayIconPlugin()
+{
+}
+
+#include "koverlayiconplugin.moc"
diff --git a/lib/konq/koverlayiconplugin.desktop b/lib/konq/koverlayiconplugin.desktop
new file mode 100644
index 0000000..65a1170
--- /dev/null
+++ b/lib/konq/koverlayiconplugin.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KOverlayIconPlugin
+Comment=Plugin to add overlay icons in Dolphin
diff --git a/lib/konq/koverlayiconplugin.h b/lib/konq/koverlayiconplugin.h
new file mode 100644
index 0000000..bcdf31b
--- /dev/null
+++ b/lib/konq/koverlayiconplugin.h
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com> *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public License *
+ * along with this library; see the file COPYING.LIB. If not, write to *
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301, USA. *
+ *****************************************************************************/
+
+
+#ifndef OverlayIconPlugin_H
+#define OverlayIconPlugin_H
+
+#include <QtCore/QObject>
+#include <libkonq_export.h>
+
+class KUrl;
+class KFileItem;
+
+/**
+ * @brief Base class for overlay icon plugins.
+ *
+ * Enables the file manager to show custom overlay icons on files.
+ *
+ * To write a custom plugin you need to create a .desktop file for your plugin with
+ * KDE-ServiceTypes=KOverlayIconPlugin
+ */
+class LIBKONQ_EXPORT KOverlayIconPlugin : public QObject {
+ Q_OBJECT
+ void *d;
+public:
+ explicit KOverlayIconPlugin(QObject *parent = 0);
+ ~KOverlayIconPlugin();
+
+ /**
+ * Returns a list of overlay pixmap to add to a file
+ * This can be a path to an icon, or the icon name
+ */
+ virtual QStringList getOverlays(const KFileItem &item) = 0;
+signals:
+
+ /**
+ * Emit this signal when the list of overlay icon changed for a given URL
+ */
+ void overlaysChanged(const KUrl &url, const QStringList &overlays);
+};
+
+#endif
--
2.1.3
+41 -12
Ver Arquivo
@@ -1,17 +1,46 @@
cmake_minimum_required(VERSION 2.6)
project(dolphin-owncloud)
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
include(MacroLibrary)
find_package(LibKonq REQUIRED)
add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
cmake_minimum_required(VERSION 2.8.12)
include(FeatureSummary)
set(QT_MIN_VERSION "5.3.0")
set(KF5_MIN_VERSION "5.16.0")
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Core Network)
find_package(ECM 1.2.0 REQUIRED CONFIG)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS CoreAddons KIO)
set_package_properties(DolphinVcs PROPERTIES
DESCRIPTION "the Dolphin plugin library"
URL "http://dolphin.kde.org/"
TYPE REQUIRED
PURPOSE "Provides plugin interfaces for Dolphin."
)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings)
include(ECMMarkNonGuiExecutable)
include(GenerateExportHeader)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES} )
include_directories( ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ${LIBKONQ_INCLUDE_DIR} )
kde4_add_plugin(ownclouddolphinplugin ownclouddolphinplugin.cpp)
#---HELPER---
add_library(ownclouddolphinpluginhelper SHARED ownclouddolphinpluginhelper.cpp)
target_link_libraries(ownclouddolphinpluginhelper Qt5::Network)
generate_export_header(ownclouddolphinpluginhelper)
install(TARGETS ownclouddolphinpluginhelper LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
target_link_libraries(ownclouddolphinplugin ${KDE4_KIO_LIBS} ${LIBKONQ_LIBRARY})
install(FILES ownclouddolphinplugin.desktop DESTINATION ${SERVICES_INSTALL_DIR})
install(TARGETS ownclouddolphinplugin DESTINATION ${PLUGIN_INSTALL_DIR})
#---OVERLAY PLUGIN---
kcoreaddons_add_plugin(ownclouddolphinoverlayplugin INSTALL_NAMESPACE "kf5/overlayicon"
JSON ownclouddolphinoverlayplugin.json SOURCES ownclouddolphinoverlayplugin.cpp)
target_link_libraries(ownclouddolphinoverlayplugin KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ownclouddolphinpluginhelper)
#---ACTION PLUGIN---
add_library(ownclouddolphinactionplugin MODULE ownclouddolphinactionplugin.cpp)
target_link_libraries(ownclouddolphinactionplugin KF5::CoreAddons KF5::KIOCore KF5::KIOWidgets ownclouddolphinpluginhelper)
install(FILES ownclouddolphinactionplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
install(TARGETS ownclouddolphinactionplugin DESTINATION ${KDE_INSTALL_PLUGINDIR})
+4 -11
Ver Arquivo
@@ -1,18 +1,11 @@
- The patch 0001-KOverlayIconPlugin.patch should be applied to kde-baseapps git repository
(It should apply to both KDE/4.14 or Applications/14.12 branches)
- Recompile and install dolphin
- Recompile and install recent enough version of dolphin and kio (git from oct 2015)
- Build and install the plugin
- After installing, run
kdeinit4 --noincremental
- Make sure to set XDG_DATA_DIRS=$PREFIX/share, QT_PLUGIN_PATH=$PREFIX/lib64/plugins/
- To test that the plugin is well installed
ktraderclient --servicetype KOverlayIconPlugin
It should show the Owncloud plugin
- After installing, run
kdeinit5 --noincremental
- restart dolphin (make sure to kill all instances)
@@ -0,0 +1,67 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#include <KPluginFactory>
#include <KPluginLoader>
#include <KIOWidgets/kabstractfileitemactionplugin.h>
#include <QtNetwork/QLocalSocket>
#include <KIOCore/kfileitem.h>
#include <KIOCore/KFileItemListProperties>
#include <QtWidgets/QAction>
#include <QtCore/QTimer>
#include "ownclouddolphinpluginhelper.h"
class OwncloudDolphinPluginAction : public KAbstractFileItemActionPlugin
{
public:
explicit OwncloudDolphinPluginAction(QObject* parent, const QList<QVariant>&)
: KAbstractFileItemActionPlugin(parent) { }
QList<QAction*> actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) Q_DECL_OVERRIDE
{
auto helper = OwncloudDolphinPluginHelper::instance();
QList<QUrl> urls = fileItemInfos.urlList();
if (urls.count() != 1 || !helper->isConnected())
return {};
auto url = urls.first();
if (!url.isLocalFile())
return {};
auto localFile = url.toLocalFile();
const auto paths = helper->paths();
if (!std::any_of(paths.begin(), paths.end(), [&](const QString &s) {
return localFile.startsWith(s);
} ))
return {};
auto act = new QAction(parentWidget);
act->setText(helper->shareActionString());
connect(act, &QAction::triggered, this, [localFile, helper] {
helper->sendCommand("SHARE:"+localFile.toUtf8()+"\n");
} );
return { act };
}
};
K_PLUGIN_FACTORY(OwncloudDolphinPluginActionFactory, registerPlugin<OwncloudDolphinPluginAction>();)
K_EXPORT_PLUGIN(OwncloudDolphinPluginActionFactory("ownclouddolhpinpluginaction"))
#include "ownclouddolphinactionplugin.moc"
@@ -0,0 +1,6 @@
[Desktop Entry]
Type=Service
Name=OwncloudAction
ServiceTypes=KFileItemAction/Plugin
MimeType=application/octet-stream;inode/directory;
X-KDE-Library=ownclouddolphinactionplugin
@@ -0,0 +1,101 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#include <KOverlayIconPlugin>
#include <KPluginFactory>
#include <QtNetwork/QLocalSocket>
#include <KIOCore/kfileitem.h>
#include <QTimer>
#include "ownclouddolphinpluginhelper.h"
class OwncloudDolphinPlugin : public KOverlayIconPlugin
{
Q_PLUGIN_METADATA(IID "com.owncloud.ovarlayiconplugin" FILE "ownclouddolphinoverlayplugin.json");
Q_OBJECT
typedef QHash<QByteArray, QByteArray> StatusMap;
StatusMap m_status;
public:
OwncloudDolphinPlugin() {
auto helper = OwncloudDolphinPluginHelper::instance();
QObject::connect(helper, &OwncloudDolphinPluginHelper::commandRecieved,
this, &OwncloudDolphinPlugin::slotCommandRecieved);
}
QStringList getOverlays(const QUrl& url) override {
auto helper = OwncloudDolphinPluginHelper::instance();
if (!helper->isConnected())
return QStringList();
if (!url.isLocalFile())
return QStringList();
const QByteArray localFile = url.toLocalFile().toUtf8();
helper->sendCommand("RETRIEVE_FILE_STATUS:" + localFile + "\n");
StatusMap::iterator it = m_status.find(localFile);
if (it != m_status.constEnd()) {
return overlaysForString(*it);
}
return QStringList();
}
private:
QStringList overlaysForString(const QByteArray &status) {
QStringList r;
if (status.startsWith("NOP"))
return r;
if (status.startsWith("OK"))
r << "ownCloud_ok";
if (status.startsWith("SYNC") || status.startsWith("NEW"))
r << "owncloud_sync";
if (status.startsWith("IGNORE") || status.startsWith("WARN"))
r << "owncloud_warn";
if (status.startsWith("ERROR"))
r << "owncloud_error";
if (status.contains("+SWM"))
r << "document-share";
return r;
}
void slotCommandRecieved(const QByteArray &line) {
QList<QByteArray> tokens = line.split(':');
if (tokens.count() != 3)
return;
if (tokens[0] != "STATUS" && tokens[0] != "BROADCAST")
return;
if (tokens[2].isEmpty())
return;
const QByteArray name = tokens[2];
QByteArray &status = m_status[name]; // reference to the item in the hash
if (status == tokens[1])
return;
status = tokens[1];
emit overlaysChanged(QUrl::fromLocalFile(QString::fromUtf8(name)), overlaysForString(status));
}
};
#include "ownclouddolphinoverlayplugin.moc"
@@ -0,0 +1,8 @@
{
"KPlugin": {
"Description": "Overlay icon for owncloud",
"ServiceTypes": [
"KOverlayIconPlugin"
]
}
}
@@ -1,131 +0,0 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#include <koverlayiconplugin.h>
#include <KPluginFactory>
#include <KPluginLoader>
#include <kdebug.h>
#include <kfileitem.h>
#include <QtNetwork/QLocalSocket>
class OwncloudDolphinPlugin : public KOverlayIconPlugin
{
Q_OBJECT
QLocalSocket m_socket;
typedef QHash<QByteArray, QByteArray> StatusMap;
StatusMap m_status;
QByteArray m_line;
public:
explicit OwncloudDolphinPlugin(QObject* parent, const QList<QVariant>&) : KOverlayIconPlugin(parent) {
connect(&m_socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
tryConnect();
}
virtual QStringList getOverlays(const KFileItem& item) {
KUrl url = item.url();
if (!url.isLocalFile())
return QStringList();
const QByteArray localFile = url.toLocalFile().toUtf8();
kDebug() << localFile;
tryConnect();
if (m_socket.state() == QLocalSocket::ConnectingState) {
if (!m_socket.waitForConnected(100)) {
kWarning() << "not connected" << m_socket.errorString();
}
}
if (m_socket.state() == QLocalSocket::ConnectedState) {
m_socket.write("RETRIEVE_FILE_STATUS:");
m_socket.write(localFile);
m_socket.write("\n");
}
StatusMap::iterator it = m_status.find(localFile);
if (it != m_status.constEnd()) {
return overlaysForString(*it);
}
return QStringList();
}
private:
void tryConnect() {
if (m_socket.state() != QLocalSocket::UnconnectedState)
return;
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
QString socketPath = runtimeDir + "/" + "ownCloud" + "/socket";
m_socket.connectToServer(socketPath);
}
QStringList overlaysForString(const QByteArray status) {
QStringList r;
if (status.startsWith("NOP"))
return r;
if (status.startsWith("OK"))
r << "dialog-ok";
if (status.startsWith("SYNC") || status.startsWith("NEW"))
r << "view-refresh";
if (status.contains("+SWM"))
r << "document-share";
kDebug() << status << r;
return r;
}
private slots:
void readyRead() {
while (m_socket.bytesAvailable()) {
m_line += m_socket.readLine();
if (!m_line.endsWith("\n"))
continue;
QByteArray line;
qSwap(line, m_line);
line.chop(1);
kDebug() << "got line " << line;
if (line.isEmpty())
continue;
QList<QByteArray> tokens = line.split(':');
if (tokens.count() != 3)
continue;
if (tokens[0] != "STATUS" && tokens[0] != "BROADCAST")
continue;
if (tokens[2].isEmpty())
continue;
const QByteArray name = tokens[2];
QByteArray &status = m_status[name]; // reference to the item in the hash
if (status == tokens[1])
continue;
status = tokens[1];
emit this->overlaysChanged(KUrl::fromLocalFile(QString::fromUtf8(name)), overlaysForString(status));
}
}
};
K_PLUGIN_FACTORY(OwncloudDolphinPluginFactory, registerPlugin<OwncloudDolphinPlugin>();)
K_EXPORT_PLUGIN(OwncloudDolphinPluginFactory("ownclouddolhpinplugin"))
#include "ownclouddolphinplugin.moc"
@@ -1,6 +0,0 @@
[Desktop Entry]
Type=Service
Name=Owncloud
X-KDE-ServiceTypes=KOverlayIconPlugin
MimeType=text/plain;
X-KDE-Library=ownclouddolphinplugin
@@ -0,0 +1,98 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#include <QtNetwork/QLocalSocket>
#include <qcoreevent.h>
#include <QFile>
#include "ownclouddolphinpluginhelper.h"
OwncloudDolphinPluginHelper* OwncloudDolphinPluginHelper::instance()
{
static OwncloudDolphinPluginHelper self;
return &self;
}
OwncloudDolphinPluginHelper::OwncloudDolphinPluginHelper()
{
connect(&_socket, &QLocalSocket::connected, this, &OwncloudDolphinPluginHelper::slotConnected);
connect(&_socket, &QLocalSocket::readyRead, this, &OwncloudDolphinPluginHelper::slotReadyRead);
_connectTimer.start(45 * 1000, Qt::VeryCoarseTimer, this);
tryConnect();
}
void OwncloudDolphinPluginHelper::timerEvent(QTimerEvent *e)
{
if (e->timerId() == _connectTimer.timerId()) {
tryConnect();
return;
}
QObject::timerEvent(e);
}
bool OwncloudDolphinPluginHelper::isConnected() const
{
return _socket.state() == QLocalSocket::ConnectedState;
}
void OwncloudDolphinPluginHelper::sendCommand(const char* data)
{
_socket.write(data);
_socket.flush();
}
void OwncloudDolphinPluginHelper::slotConnected()
{
sendCommand("SHARE_MENU_TITLE:\n");
}
void OwncloudDolphinPluginHelper::tryConnect()
{
if (_socket.state() != QLocalSocket::UnconnectedState) {
return;
}
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
QString socketPath = runtimeDir + QLatin1String("/ownCloud/socket");
_socket.connectToServer(socketPath);
}
void OwncloudDolphinPluginHelper::slotReadyRead()
{
while (_socket.bytesAvailable()) {
_line += _socket.readLine();
if (!_line.endsWith("\n"))
continue;
QByteArray line;
qSwap(line, _line);
line.chop(1);
if (line.isEmpty())
continue;
if (line.startsWith("REGISTER_PATH:")) {
auto col = line.indexOf(':');
QString file = QString::fromUtf8(line.constData() + col + 1, line.size() - col - 1);
_paths.append(file);
continue;
} else if (line.startsWith("SHARE_MENU_TITLE:")) {
auto col = line.indexOf(':');
_shareActionString = QString::fromUtf8(line.constData() + col + 1, line.size() - col - 1);
continue;
}
emit commandRecieved(line);
}
}
@@ -0,0 +1,52 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#pragma once
#include <QObject>
#include <QBasicTimer>
#include <QLocalSocket>
#include "ownclouddolphinpluginhelper_export.h"
class OWNCLOUDDOLPHINPLUGINHELPER_EXPORT OwncloudDolphinPluginHelper : public QObject {
Q_OBJECT
public:
static OwncloudDolphinPluginHelper *instance();
QString shareActionString() const { return _shareActionString; }
bool isConnected() const;
void sendCommand(const char *data);
QVector<QString> paths() const { return _paths; }
signals:
void commandRecieved(const QByteArray &cmd);
protected:
void timerEvent(QTimerEvent*) override;
private:
OwncloudDolphinPluginHelper();
void slotConnected();
void slotReadyRead();
void tryConnect();
QLocalSocket _socket;
QByteArray _line;
QVector<QString> _paths;
QString _shareActionString;
QBasicTimer _connectTimer;
};
@@ -1,267 +0,0 @@
From d452ed613a9e02ed81eec2f3226f28babff240c8 Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@woboq.com>
Date: Thu, 17 Jul 2014 13:26:56 +0200
Subject: [PATCH] WIP: add KOverlayIconPlugin
Conflicts:
dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
lib/konq/CMakeLists.txt
---
.../src/kitemviews/kfileitemmodelrolesupdater.cpp | 38 ++++++++++++++-
.../src/kitemviews/kfileitemmodelrolesupdater.h | 9 ++++
lib/konq/src/CMakeLists.txt | 4 +-
lib/konq/src/koverlayiconplugin.cpp | 30 ++++++++++++
lib/konq/src/koverlayiconplugin.desktop | 4 ++
lib/konq/src/koverlayiconplugin.h | 57 ++++++++++++++++++++++
6 files changed, 140 insertions(+), 2 deletions(-)
create mode 100644 lib/konq/src/koverlayiconplugin.cpp
create mode 100644 lib/konq/src/koverlayiconplugin.desktop
create mode 100644 lib/konq/src/koverlayiconplugin.h
diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
index df521e2..4d94836 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -29,9 +29,11 @@
#include <KJobWidgets>
#include <KIO/JobUiDelegate>
#include <KIO/PreviewJob>
+#include <KServiceTypeTrader>
#include "private/kpixmapmodifier.h"
#include "private/kdirectorycontentscounter.h"
+#include <koverlayiconplugin.h>
#include <QApplication>
#include <QPainter>
@@ -129,6 +131,20 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
m_directoryContentsCounter = new KDirectoryContentsCounter(m_model, this);
connect(m_directoryContentsCounter, &KDirectoryContentsCounter::result,
this, &KFileItemModelRolesUpdater::slotDirectoryContentsCountReceived);
+
+
+ const KService::List pluginServices = KServiceTypeTrader::self()->query("KOverlayIconPlugin");
+
+ for (KService::List::ConstIterator it = pluginServices.constBegin(); it != pluginServices.constEnd(); ++it) {
+ QString error;
+ KOverlayIconPlugin* plugin = (*it)->createInstance<KOverlayIconPlugin>(this, QVariantList(), &error);
+ if (plugin) {
+ m_overlayIconsPlugin.append(plugin);
+ connect(plugin, &KOverlayIconPlugin::overlaysChanged, this, &KFileItemModelRolesUpdater::slotOverlaysChanged);
+ } else {
+ qWarning() << "Could not load plugin " << (*it)->name() << ":" << error;
+ }
+ }
}
KFileItemModelRolesUpdater::~KFileItemModelRolesUpdater()
@@ -1065,7 +1081,11 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
data.insert("type", item.mimeComment());
}
- data.insert("iconOverlays", item.overlays());
+ QStringList overlays = item.overlays();
+ foreach(KOverlayIconPlugin *it, m_overlayIconsPlugin) {
+ overlays.append(it->getOverlays(item));
+ }
+ data.insert("iconOverlays", overlays);
#ifdef HAVE_BALOO
if (m_balooFileMonitor) {
@@ -1076,6 +1096,22 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
return data;
}
+void KFileItemModelRolesUpdater::slotOverlaysChanged(const QUrl& url, const QStringList &)
+{
+ KFileItem item = m_model->fileItem(url);
+ if (item.isNull())
+ return;
+ int index = m_model->index(item);
+ QHash <QByteArray, QVariant> data = m_model->data(index);
+ QStringList overlays = item.overlays();
+ foreach(KOverlayIconPlugin *it, m_overlayIconsPlugin) {
+ overlays.append(it->getOverlays(item));
+ }
+ data.insert("iconOverlays", overlays);
+ m_model->setData(index, data);
+}
+
+
void KFileItemModelRolesUpdater::updateAllPreviews()
{
if (m_state == Paused) {
diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
index 6c82dbe..1e5b98e 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
@@ -32,6 +32,7 @@
#include <QSize>
#include <QStringList>
+class KOverlayIconPlugin;
class KDirectoryContentsCounter;
class KFileItemModel;
class QPixmap;
@@ -183,6 +184,12 @@ private slots:
void slotPreviewJobFinished();
/**
+ * Is invoked when one of the KOverlayIconPlugin emit the signal that an overlay has changed
+ */
+ void slotOverlaysChanged(const QUrl& url, const QStringList&);
+
+
+ /**
* Resolves the sort role of the next item in m_pendingSortRole, applies it
* to the model, and invokes itself if there are any pending items left. If
* that is not the case, \a startUpdating() is called.
@@ -333,6 +340,8 @@ private:
KDirectoryContentsCounter* m_directoryContentsCounter;
+ QList<KOverlayIconPlugin*> m_overlayIconsPlugin;
+
#ifdef HAVE_BALOO
Baloo::FileMonitor* m_balooFileMonitor;
#endif
diff --git a/lib/konq/src/CMakeLists.txt b/lib/konq/src/CMakeLists.txt
index 9c05b9f..0ac0526 100644
--- a/lib/konq/src/CMakeLists.txt
+++ b/lib/konq/src/CMakeLists.txt
@@ -15,6 +15,7 @@ set(konq_LIB_SRCS
konq_historyprovider.cpp # konqueror and konqueror/sidebar
kversioncontrolplugin.cpp # used by dolphin and its version control plugins (deprecated)
kversioncontrolplugin2.cpp # used by dolphin and its version control plugins
+ koverlayiconplugin.cpp
)
add_library(KF5Konq ${konq_LIB_SRCS})
@@ -64,13 +65,14 @@ install(FILES
konq_popupmenuplugin.h
kversioncontrolplugin.h
kversioncontrolplugin2.h
+ koverlayiconplugin.h
${LibKonq_BINARY_DIR}/src/libkonq_export.h
DESTINATION ${KF5_INCLUDE_INSTALL_DIR}
COMPONENT Devel
)
-install(FILES konqpopupmenuplugin.desktop konqdndpopupmenuplugin.desktop
+install(FILES konqpopupmenuplugin.desktop konqdndpopupmenuplugin.desktop koverlayiconplugin.desktop
DESTINATION ${SERVICETYPES_INSTALL_DIR}
)
diff --git a/lib/konq/src/koverlayiconplugin.cpp b/lib/konq/src/koverlayiconplugin.cpp
new file mode 100644
index 0000000..6125040
--- /dev/null
+++ b/lib/konq/src/koverlayiconplugin.cpp
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com> *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public License *
+ * along with this library; see the file COPYING.LIB. If not, write to *
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301, USA. *
+ *****************************************************************************/
+
+#include "koverlayiconplugin.h"
+#include <KFileItem>
+
+KOverlayIconPlugin::KOverlayIconPlugin(QObject* parent) : QObject(parent)
+{
+}
+
+KOverlayIconPlugin::~KOverlayIconPlugin()
+{
+}
+
+#include "koverlayiconplugin.moc"
diff --git a/lib/konq/src/koverlayiconplugin.desktop b/lib/konq/src/koverlayiconplugin.desktop
new file mode 100644
index 0000000..65a1170
--- /dev/null
+++ b/lib/konq/src/koverlayiconplugin.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KOverlayIconPlugin
+Comment=Plugin to add overlay icons in Dolphin
diff --git a/lib/konq/src/koverlayiconplugin.h b/lib/konq/src/koverlayiconplugin.h
new file mode 100644
index 0000000..bfdaa2f
--- /dev/null
+++ b/lib/konq/src/koverlayiconplugin.h
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com> *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License version 2 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public License *
+ * along with this library; see the file COPYING.LIB. If not, write to *
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301, USA. *
+ *****************************************************************************/
+
+
+#ifndef OverlayIconPlugin_H
+#define OverlayIconPlugin_H
+
+#include <QtCore/QObject>
+#include <libkonq_export.h>
+
+class KUrl;
+class KFileItem;
+
+/**
+ * @brief Base class for overlay icon plugins.
+ *
+ * Enables the file manager to show custom overlay icons on files.
+ *
+ * To write a custom plugin you need to create a .desktop file for your plugin with
+ * KDE-ServiceTypes=KOverlayIconPlugin
+ */
+class LIBKONQ_EXPORT KOverlayIconPlugin : public QObject {
+ Q_OBJECT
+ void *d;
+public:
+ explicit KOverlayIconPlugin(QObject *parent = 0);
+ ~KOverlayIconPlugin();
+
+ /**
+ * Returns a list of overlay pixmap to add to a file
+ * This can be a path to an icon, or the icon name
+ */
+ virtual QStringList getOverlays(const KFileItem &item) = 0;
+signals:
+
+ /**
+ * Emit this signal when the list of overlay icon changed for a given URL
+ */
+ void overlaysChanged(const QUrl &url, const QStringList &overlays);
+};
+
+#endif
--
2.2.1
-30
Ver Arquivo
@@ -1,30 +0,0 @@
project(dolphin-owncloud)
cmake_minimum_required(VERSION 2.8)
set(QT_MIN_VERSION "5.3.0")
find_package(ECM 1.2.0 REQUIRED CONFIG)
include(FeatureSummary)
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings)
include(ECMInstallIcons)
include(ECMSetupVersion)
find_package(Qt5 CONFIG REQUIRED Core DBus Test Widgets)
find_package(KF5 REQUIRED Archive Bookmarks CoreAddons Config ConfigWidgets DBusAddons KIO KDELibs4Support Parts Activities)
find_package(KF5Konq REQUIRED)
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
add_library(ownclouddolphinplugin MODULE ownclouddolphinplugin.cpp)
target_link_libraries(ownclouddolphinplugin KF5::Konq)
install(FILES ownclouddolphinplugin.desktop DESTINATION ${SERVICES_INSTALL_DIR})
install(TARGETS ownclouddolphinplugin DESTINATION ${PLUGIN_INSTALL_DIR})
-16
Ver Arquivo
@@ -1,16 +0,0 @@
- The patch 0001-KOverlayIconPlugin.patch should be applied to kde-baseapps git repository
(It should apply to frameworks branch)
- Recompile and install dolphin (frameworks branch)
- Build and install the plugin
- Make sure to set XDG_DATA_DIRS=$PREFIX/share, QT_PLUGIN_PATH=$PREFIX/lib64/plugins/
- After installing, run
kdeinit5 --noincremental
- restart dolphin (make sure to kill all instances)
@@ -1,131 +0,0 @@
/******************************************************************************
* Copyright (C) 2014 by Olivier Goffart <ogoffart@woboq.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
******************************************************************************/
#include <koverlayiconplugin.h>
#include <KPluginFactory>
#include <KPluginLoader>
#include <kdebug.h>
#include <kfileitem.h>
#include <QtNetwork/QLocalSocket>
class OwncloudDolphinPlugin : public KOverlayIconPlugin
{
Q_OBJECT
QLocalSocket m_socket;
typedef QHash<QByteArray, QByteArray> StatusMap;
StatusMap m_status;
QByteArray m_line;
public:
explicit OwncloudDolphinPlugin(QObject* parent, const QList<QVariant>&) : KOverlayIconPlugin(parent) {
connect(&m_socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
tryConnect();
}
virtual QStringList getOverlays(const KFileItem& item) {
auto url = item.url();
if (!url.isLocalFile())
return QStringList();
const QByteArray localFile = url.toLocalFile().toUtf8();
kDebug() << localFile;
tryConnect();
if (m_socket.state() == QLocalSocket::ConnectingState) {
if (!m_socket.waitForConnected(100)) {
kWarning() << "not connected" << m_socket.errorString();
}
}
if (m_socket.state() == QLocalSocket::ConnectedState) {
m_socket.write("RETRIEVE_FILE_STATUS:");
m_socket.write(localFile);
m_socket.write("\n");
}
StatusMap::iterator it = m_status.find(localFile);
if (it != m_status.constEnd()) {
return overlaysForString(*it);
}
return QStringList();
}
private:
void tryConnect() {
if (m_socket.state() != QLocalSocket::UnconnectedState)
return;
QString runtimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
QString socketPath = runtimeDir + "/" + "ownCloud" + "/socket";
m_socket.connectToServer(socketPath);
}
QStringList overlaysForString(const QByteArray status) {
QStringList r;
if (status.startsWith("NOP"))
return r;
if (status.startsWith("OK"))
r << "dialog-ok";
if (status.startsWith("SYNC") || status.startsWith("NEW"))
r << "view-refresh";
if (status.contains("+SWM"))
r << "document-share";
kDebug() << status << r;
return r;
}
private slots:
void readyRead() {
while (m_socket.bytesAvailable()) {
m_line += m_socket.readLine();
if (!m_line.endsWith("\n"))
continue;
QByteArray line;
qSwap(line, m_line);
line.chop(1);
kDebug() << "got line " << line;
if (line.isEmpty())
continue;
QList<QByteArray> tokens = line.split(':');
if (tokens.count() != 3)
continue;
if (tokens[0] != "STATUS" && tokens[0] != "BROADCAST")
continue;
if (tokens[2].isEmpty())
continue;
const QByteArray name = tokens[2];
QByteArray &status = m_status[name]; // reference to the item in the hash
if (status == tokens[1])
continue;
status = tokens[1];
emit this->overlaysChanged(QUrl::fromLocalFile(QString::fromUtf8(name)), overlaysForString(status));
}
}
};
K_PLUGIN_FACTORY(OwncloudDolphinPluginFactory, registerPlugin<OwncloudDolphinPlugin>();)
K_EXPORT_PLUGIN(OwncloudDolphinPluginFactory("ownclouddolhpinplugin"))
#include "ownclouddolphinplugin.moc"
@@ -1,6 +0,0 @@
[Desktop Entry]
Type=Service
Name=Owncloud
X-KDE-ServiceTypes=KOverlayIconPlugin
MimeType=text/plain;
X-KDE-Library=ownclouddolphinplugin
+1
Ver Arquivo
@@ -10,6 +10,7 @@ if (APPLE)
endif()
add_subdirectory(libsync)
add_subdirectory(libclient)
if (NOT BUILD_LIBRARIES_ONLY)
add_subdirectory(gui)
add_subdirectory(cmd)
+7 -5
Ver Arquivo
@@ -42,6 +42,8 @@
#include <termios.h>
#endif
#include <csync_private.h>
using namespace OCC;
struct CmdOptions {
@@ -114,11 +116,11 @@ public:
_sslTrusted(false)
{}
QString queryPassword(bool *ok, const QString&) Q_DECL_OVERRIDE {
if (ok) {
*ok = true;
}
return ::queryPassword(user());
void askFromUser() Q_DECL_OVERRIDE {
_password = ::queryPassword(user());
_ready = true;
persist();
emit asked();
}
void setSSLTrusted( bool isTrusted ) {
+3 -3
Ver Arquivo
@@ -72,7 +72,6 @@ set(client_SRCS
creds/httpcredentialsgui.cpp
creds/shibbolethcredentials.cpp
creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethrefresher.cpp
creds/shibboleth/shibbolethuserjob.cpp
wizard/abstractcredswizardpage.cpp
wizard/owncloudadvancedsetuppage.cpp
@@ -98,6 +97,7 @@ IF( APPLE )
list(APPEND client_SRCS settingsdialogmac.cpp)
list(APPEND client_SRCS socketapisocket_mac.mm)
list(APPEND client_SRCS systray.mm)
list(APPEND client_SRCS clipboard.mm)
if(SPARKLE_FOUND)
# Define this, we need to check in updater.cpp
@@ -221,7 +221,7 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
endforeach( _file )
endif(NOT WIN32)
install(FILES ${client_I18N} DESTINATION ${DATADIR}/${APPLICATION_EXECUTABLE}/i18n)
install(FILES ${client_I18N} DESTINATION ${SHAREDIR}/${APPLICATION_EXECUTABLE}/i18n)
# we may not add MACOSX_BUNDLE here, if not building one
@@ -292,7 +292,7 @@ install(TARGETS ${APPLICATION_EXECUTABLE}
if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
install(CODE "
message(STATUS \"Deploying (Qt) dependencies and fixing library pathes...\")
message(STATUS \"Deploying (Qt) dependencies and fixing library paths...\")
execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/admin/osx/macdeployqt.py\" ${CMAKE_INSTALL_PREFIX}/${OWNCLOUD_OSX_BUNDLE} ${QT_QMAKE_EXECUTABLE})
" COMPONENT RUNTIME)
endif()
+3 -3
Ver Arquivo
@@ -36,13 +36,13 @@ public:
void save(bool saveCredentials = true);
/**
* Creates account objects from from a given settings file.
* Creates account objects from a given settings file.
* return true if the account was restored
*/
bool restore();
/**
* Add this account in the list of saved account.
* Add this account in the list of saved accounts.
* Typically called from the wizard
*/
AccountState *addAccount(const AccountPtr &newAccount);
@@ -54,7 +54,7 @@ public:
/**
* Return a list of all accounts.
* (this is a list of QSharedPointer for internal reason, one should normaly not keep a copy of them)
* (this is a list of QSharedPointer for internal reasons, one should normally not keep a copy of them)
*/
QList<AccountStatePtr> accounts() { return _accounts; }
+40 -20
Ver Arquivo
@@ -42,6 +42,7 @@
#include <QKeySequence>
#include <QIcon>
#include <QVariant>
#include <QToolTip>
#include <qstringlistmodel.h>
#include <qpropertyanimation.h>
@@ -90,6 +91,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
connect(_model, SIGNAL(suggestExpand(QModelIndex)), ui->_folderList, SLOT(expand(QModelIndex)));
connect(_model, SIGNAL(dirtyChanged()), this, SLOT(refreshSelectiveSyncStatus()));
refreshSelectiveSyncStatus();
connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(refreshSelectiveSyncStatus()));
QAction *resetFolderAction = new QAction(this);
resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5));
@@ -101,7 +104,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow()));
addAction(syncNowAction);
connect(ui->_folderList, SIGNAL(clicked(QModelIndex)), SLOT(slotFolderActivated(QModelIndex)));
connect(ui->_folderList, SIGNAL(clicked(const QModelIndex &)),
this, SLOT(slotFolderListClicked(const QModelIndex&)));
connect(ui->selectiveSyncApply, SIGNAL(clicked()), _model, SLOT(slotApplySelectiveSync()));
connect(ui->selectiveSyncCancel, SIGNAL(clicked()), _model, SLOT(resetFolders()));
@@ -120,12 +124,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
connect( &_quotaInfo, SIGNAL(quotaUpdated(qint64,qint64)),
this, SLOT(slotUpdateQuota(qint64,qint64)));
connect(ui->signInButton, SIGNAL(clicked()) , this, SLOT(slotSignInAccount()));
connect(ui->deleteButton, SIGNAL(clicked()) , this, SLOT(slotDeleteAccount()));
// Expand already on single click
ui->_folderList->setExpandsOnDoubleClick(false);
QObject::connect(ui->_folderList, SIGNAL(clicked(const QModelIndex &)),
this, SLOT(slotFolderListClicked(const QModelIndex&)));
}
void AccountSettings::doExpand()
@@ -133,15 +133,6 @@ void AccountSettings::doExpand()
ui->_folderList->expandToDepth(0);
}
void AccountSettings::slotFolderListClicked( const QModelIndex& indx )
{
if( _model->classify(indx) == FolderStatusModel::RootFolder &&
_accountState && _accountState->state() == AccountState::Connected ) {
bool expanded = ! (ui->_folderList->isExpanded(indx));
ui->_folderList->setExpanded(indx, expanded);
}
}
void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
{
QTreeView *tv = ui->_folderList;
@@ -178,11 +169,17 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
menu->exec(tv->mapToGlobal(pos));
}
void AccountSettings::slotFolderActivated( const QModelIndex& indx )
void AccountSettings::slotFolderListClicked(const QModelIndex& indx)
{
if (indx.data(FolderStatusDelegate::AddButton).toBool()
&& indx.flags() & Qt::ItemIsEnabled) {
slotAddFolder();
if (indx.data(FolderStatusDelegate::AddButton).toBool()) {
if (indx.flags() & Qt::ItemIsEnabled) {
slotAddFolder();
} else {
QToolTip::showText(
QCursor::pos(),
_model->data(indx, Qt::ToolTipRole).toString(),
this);
}
return;
}
if (_model->classify(indx) == FolderStatusModel::RootFolder) {
@@ -191,6 +188,13 @@ void AccountSettings::slotFolderActivated( const QModelIndex& indx )
auto pos = tv->mapFromGlobal(QCursor::pos());
if (FolderStatusDelegate::optionsButtonRect(tv->visualRect(indx)).contains(pos)) {
slotCustomContextMenuRequested(pos);
return;
}
// Expand root items on single click
if(_accountState && _accountState->state() == AccountState::Connected ) {
bool expanded = ! (ui->_folderList->isExpanded(indx));
ui->_folderList->setExpanded(indx, expanded);
}
}
}
@@ -472,6 +476,12 @@ void AccountSettings::slotAccountStateChanged(int state)
serverWithUser = tr("%1 as <i>%2</i>").arg(server, cred->user());
}
if (state != AccountState::SignedOut && ui->signInButton->hasFocus()) {
// The button is about to be hidden, clear the focus so the focus don't go to the
// "remove account" button
ui->signInButton->clearFocus();
}
ui->signInButton->setVisible(state == AccountState::SignedOut);
if (state == AccountState::Connected) {
showConnectionLabel( tr("Connected to %1.").arg(serverWithUser) );
} else if (state == AccountState::ServiceUnavailable) {
@@ -511,8 +521,10 @@ void AccountSettings::refreshSelectiveSyncStatus()
bool shouldBeVisible = _model->isDirty();
QStringList undecidedFolder;
for (int i = 0; !shouldBeVisible && i < _model->rowCount(); ++i) {
if (ui->_folderList->isExpanded(_model->index(i)))
auto index = _model->index(i);
if (ui->_folderList->isExpanded(index) && _model->rowCount(index) > 0) {
shouldBeVisible = true;
}
}
foreach (Folder *folder, FolderMan::instance()->map().values()) {
@@ -554,6 +566,11 @@ void AccountSettings::refreshSelectiveSyncStatus()
}
}
void AccountSettings::slotSignInAccount()
{
_accountState->setSignedOut(false);
}
void AccountSettings::slotDeleteAccount()
{
// Deleting the account potentially deletes 'this', so
@@ -592,6 +609,9 @@ bool AccountSettings::event(QEvent* e)
if (e->type() == QEvent::Hide || e->type() == QEvent::Show) {
_quotaInfo.setActive(isVisible());
}
if (e->type() == QEvent::Show) {
ui->_folderList->setExpanded(_model->index(0, 0), true);
}
return QWidget::event(e);
}
+1 -1
Ver Arquivo
@@ -61,7 +61,6 @@ signals:
void openFolderAlias( const QString& );
public slots:
void slotFolderActivated( const QModelIndex& );
void slotOpenOC();
void slotUpdateQuota( qint64,qint64 );
void slotAccountStateChanged(int state);
@@ -77,6 +76,7 @@ protected slots:
void slotOpenCurrentFolder();
void slotFolderWizardAccepted();
void slotFolderWizardRejected();
void slotSignInAccount();
void slotDeleteAccount();
void refreshSelectiveSyncStatus();
void slotCustomContextMenuRequested(const QPoint&);
+16
Ver Arquivo
@@ -61,6 +61,22 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="signInButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Enter your credentials to connect to the server</string>
</property>
<property name="text">
<string>Sign in</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteButton">
<property name="sizePolicy">
+39 -10
Ver Arquivo
@@ -15,6 +15,7 @@
#include "accountmanager.h"
#include "account.h"
#include "creds/abstractcredentials.h"
#include "logger.h"
#include <QDebug>
#include <QSettings>
@@ -28,6 +29,7 @@ AccountState::AccountState(AccountPtr account)
, _state(AccountState::Disconnected)
, _connectionStatus(ConnectionValidator::Undefined)
, _waitingForNewCredentials(false)
, _credentialsFetchMode(Interactive)
{
qRegisterMetaType<AccountState*>("AccountState*");
@@ -35,6 +37,8 @@ AccountState::AccountState(AccountPtr account)
SLOT(slotInvalidCredentials()));
connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)),
SLOT(slotCredentialsFetched(AbstractCredentials*)));
connect(account.data(), SIGNAL(credentialsAsked(AbstractCredentials*)),
SLOT(slotCredentialsAsked(AbstractCredentials*)));
}
AccountState::~AccountState()
@@ -79,7 +83,7 @@ void AccountState::setState(State state)
_connectionStatus = ConnectionValidator::Undefined;
_connectionErrors.clear();
} else if (oldState == SignedOut && _state == Disconnected) {
checkConnectivity();
checkConnectivity(Interactive);
}
}
@@ -131,7 +135,7 @@ bool AccountState::isConnectedOrTemporarilyUnavailable() const
return isConnected() || _state == ServiceUnavailable;
}
void AccountState::checkConnectivity()
void AccountState::checkConnectivity(CredentialFetchMode credentialsFetchMode)
{
if (isSignedOut() || _waitingForNewCredentials) {
return;
@@ -141,6 +145,7 @@ void AccountState::checkConnectivity()
qDebug() << "ConnectionValidator already running, ignoring";
return;
}
_credentialsFetchMode = credentialsFetchMode;
ConnectionValidator * conValidator = new ConnectionValidator(account());
_connectionValidator = conValidator;
connect(conValidator, SIGNAL(connectionResult(ConnectionValidator::Status,QStringList)),
@@ -202,8 +207,8 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
// much more likely, so keep trying to connect.
setState(NetworkError);
break;
case ConnectionValidator::CredentialsWrong:
account()->handleInvalidCredentials();
case ConnectionValidator::CredentialsMissingOrWrong:
slotInvalidCredentials();
break;
case ConnectionValidator::UserCanceledCredentials:
setState(SignedOut);
@@ -219,15 +224,41 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
void AccountState::slotInvalidCredentials()
{
if (isSignedOut()) {
if (isSignedOut() || _waitingForNewCredentials)
return;
}
if (account()->credentials()->ready())
account()->credentials()->invalidateToken();
account()->credentials()->fetchFromKeychain();
setState(ConfigurationError);
_waitingForNewCredentials = true;
}
void AccountState::slotCredentialsFetched(AbstractCredentials* credentials)
{
if (!credentials->ready()) {
// No exiting credentials found in the keychain
if (_credentialsFetchMode == Interactive)
credentials->askFromUser();
else {
Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("You need to re-login to continue using the account %1.").arg(_account->displayName()));
setState(SignedOut);
_waitingForNewCredentials = false;
}
return;
}
_waitingForNewCredentials = false;
// When new credentials become available we always want to restart the
// connection validation, even if it's currently running.
delete _connectionValidator;
checkConnectivity(_credentialsFetchMode);
}
void AccountState::slotCredentialsAsked(AbstractCredentials* credentials)
{
_waitingForNewCredentials = false;
@@ -239,11 +270,9 @@ void AccountState::slotCredentialsFetched(AbstractCredentials* credentials)
// When new credentials become available we always want to restart the
// connection validation, even if it's currently running.
if (_connectionValidator) {
delete _connectionValidator;
}
delete _connectionValidator;
checkConnectivity();
checkConnectivity(_credentialsFetchMode);
}
std::unique_ptr<QSettings> AccountState::settings()
+5 -2
Ver Arquivo
@@ -19,6 +19,7 @@
#include <QPointer>
#include "utility.h"
#include "connectionvalidator.h"
#include "creds/abstractcredentials.h"
#include <memory>
class QSettings;
@@ -27,7 +28,6 @@ namespace OCC {
class AccountState;
class Account;
class AbstractCredentials;
/**
* @brief Extra info about an ownCloud server account.
@@ -59,6 +59,7 @@ public:
/// An error like invalid credentials where retrying won't help.
ConfigurationError
};
enum CredentialFetchMode { Interactive, NonInteractive };
/// The actual current connectivity status.
typedef ConnectionValidator::Status ConnectionStatus;
@@ -84,7 +85,7 @@ public:
/// Triggers a ping to the server to update state and
/// connection status and errors.
void checkConnectivity();
void checkConnectivity(CredentialFetchMode credentialsFetchMode);
/** Returns a new settings object for this account, already in the right groups. */
std::unique_ptr<QSettings> settings();
@@ -104,6 +105,7 @@ protected Q_SLOTS:
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors);
void slotInvalidCredentials();
void slotCredentialsFetched(AbstractCredentials* creds);
void slotCredentialsAsked(AbstractCredentials* creds);
private:
AccountPtr _account;
@@ -111,6 +113,7 @@ private:
ConnectionStatus _connectionStatus;
QStringList _connectionErrors;
bool _waitingForNewCredentials;
CredentialFetchMode _credentialsFetchMode;
QPointer<ConnectionValidator> _connectionValidator;
};
+13 -6
Ver Arquivo
@@ -35,6 +35,7 @@
#include "accountmanager.h"
#include "creds/abstractcredentials.h"
#include "updater/ocupdater.h"
#include "excludedfiles.h"
#include "config.h"
@@ -103,7 +104,7 @@ Application::Application(int &argc, char **argv) :
{
_startedAt.start();
// TODO: Can't set this without breaking current config pathes
// TODO: Can't set this without breaking current config paths
// setOrganizationName(QLatin1String(APPLICATION_VENDOR));
setOrganizationDomain(QLatin1String(APPLICATION_REV_DOMAIN));
setApplicationName( _theme->appNameGUI() );
@@ -135,6 +136,13 @@ Application::Application(int &argc, char **argv) :
setupLogging();
setupTranslations();
// Setup global excludes
ConfigFile cfg;
ExcludedFiles& excludes = ExcludedFiles::instance();
excludes.addExcludeFilePath( cfg.excludeFile(ConfigFile::SystemScope) );
excludes.addExcludeFilePath( cfg.excludeFile(ConfigFile::UserScope) );
excludes.reloadExcludes();
_folderManager.reset(new FolderMan);
connect(this, SIGNAL(messageReceived(QString, QObject*)), SLOT(slotParseMessage(QString, QObject*)));
@@ -145,7 +153,6 @@ Application::Application(int &argc, char **argv) :
setQuitOnLastWindowClosed(false);
ConfigFile cfg;
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
connect (_theme, SIGNAL(systrayUseMonoIconsChanged(bool)), SLOT(slotUseMonoIconsChanged(bool)));
@@ -172,7 +179,7 @@ Application::Application(int &argc, char **argv) :
connect(&_checkConnectionTimer, SIGNAL(timeout()), this, SLOT(slotCheckConnection()));
_checkConnectionTimer.setInterval(32 * 1000); // check for connection every 32 seconds.
_checkConnectionTimer.start();
// Also check immediatly
// Also check immediately
QTimer::singleShot( 0, this, SLOT( slotCheckConnection() ));
// Update checks
@@ -237,7 +244,7 @@ void Application::slotCheckConnection()
// when the error is permanent.
if (state != AccountState::SignedOut
&& state != AccountState::ConfigurationError) {
accountState->checkConnectivity();
accountState->checkConnectivity(AccountState::NonInteractive);
}
}
@@ -444,7 +451,7 @@ void Application::setHelp()
QString substLang(const QString &lang)
{
// Map the more apropriate script codes
// Map the more appropriate script codes
// to country codes as used by Qt and
// transifex translation conventions.
@@ -486,7 +493,7 @@ void Application::setupTranslations()
// Permissive approach: Qt and keychain translations
// may be missing, but Qt translations must be there in order
// for us to accept the language. Otherwise, we try with the next.
// "en" is an exeption as it is the default language and may not
// "en" is an exception as it is the default language and may not
// have a translation file provided.
qDebug() << Q_FUNC_INFO << "Using" << lang << "translation";
setProperty("ui_lang", lang);
+16
Ver Arquivo
@@ -0,0 +1,16 @@
#include <QString>
#include <QDebug>
#import <Cocoa/Cocoa.h>
namespace OCC {
// https://github.com/owncloud/client/issues/3300
void copyToPasteboard(const QString &string)
{
qDebug() << Q_FUNC_INFO << string;
[[NSPasteboard generalPasteboard] clearContents];
[[NSPasteboard generalPasteboard] setString:[NSString stringWithUTF8String:string.toUtf8().data()]
forType:NSStringPboardType];
}
}
+18 -8
Ver Arquivo
@@ -23,24 +23,34 @@ using namespace QKeychain;
namespace OCC
{
QString HttpCredentialsGui::queryPassword(bool *ok, const QString& hint)
void HttpCredentialsGui::askFromUser()
{
if (!ok) {
return QString();
}
// The rest of the code assumes that this will be done asynchronously
QMetaObject::invokeMethod(this, "askFromUserAsync", Qt::QueuedConnection);
}
void HttpCredentialsGui::askFromUserAsync()
{
QString msg = tr("Please enter %1 password:\n"
"\n"
"User: %2\n"
"Account: %3\n")
.arg(Theme::instance()->appNameGUI(), _user, _account->displayName());
if (!hint.isEmpty()) {
msg += QLatin1String("\n") + hint + QLatin1String("\n");
if (!_fetchErrorString.isEmpty()) {
msg += QLatin1String("\n") + tr("Reading from keychain failed with error: '%1'").arg(
_fetchErrorString) + QLatin1String("\n");
}
return QInputDialog::getText(0, tr("Enter Password"), msg,
bool ok = false;
QString pwd = QInputDialog::getText(0, tr("Enter Password"), msg,
QLineEdit::Password, _previousPassword,
ok);
&ok);
if (ok) {
_password = pwd;
_ready = true;
persist();
}
emit asked();
}
} // namespace OCC
+2 -1
Ver Arquivo
@@ -28,7 +28,8 @@ class HttpCredentialsGui : public HttpCredentials {
public:
explicit HttpCredentialsGui() : HttpCredentials() {}
HttpCredentialsGui(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd) : HttpCredentials(user, password, certificatePath, certificatePasswd) {}
QString queryPassword(bool *ok, const QString& hint) Q_DECL_OVERRIDE;
void askFromUser() Q_DECL_OVERRIDE;
Q_INVOKABLE void askFromUserAsync();
};
} // namespace OCC
@@ -1,55 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <QEventLoop>
#include "account.h"
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibbolethcredentials.h"
namespace OCC
{
ShibbolethRefresher::ShibbolethRefresher(AccountPtr account, ShibbolethCredentials* creds, CSYNC* csync_ctx, QObject* parent)
: QObject(parent),
_account(account),
_creds(creds),
_csync_ctx(csync_ctx)
{}
void ShibbolethRefresher::refresh()
{
QEventLoop loop;
connect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
this, SLOT(onInvalidatedAndFetched(QByteArray)));
connect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
&loop, SLOT(quit()));
QMetaObject::invokeMethod(_creds, "invalidateAndFetch",Qt::QueuedConnection,
Q_ARG(AccountPtr, _account));
loop.exec();
disconnect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
&loop, SLOT(quit()));
}
void ShibbolethRefresher::onInvalidatedAndFetched(const QByteArray& cookies)
{
// "cookies" is const and its data() return const void*. We want just void*.
QByteArray myCookies(cookies);
disconnect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
this, SLOT(onInvalidatedAndFetched(QByteArray)));
csync_set_module_property(_csync_ctx, "session_key", myCookies.data());
}
} // namespace OCC
@@ -1,53 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MIRALL_CREDS_SHIBBOLETH_REFRESHER_H
#define MIRALL_CREDS_SHIBBOLETH_REFRESHER_H
#include <QObject>
#include <csync.h>
class QByteArray;
namespace OCC
{
class Account;
class ShibbolethCredentials;
/**
* @brief The ShibbolethRefresher class
* @ingroup gui
*/
class ShibbolethRefresher : public QObject
{
Q_OBJECT
public:
ShibbolethRefresher(AccountPtr account, ShibbolethCredentials* creds, CSYNC* csync_ctx, QObject* parent = 0);
void refresh();
private Q_SLOTS:
void onInvalidatedAndFetched(const QByteArray& cookieData);
private:
AccountPtr _account;
ShibbolethCredentials* _creds;
CSYNC* _csync_ctx;
};
} // namespace OCC
#endif
+13 -89
Ver Arquivo
@@ -12,7 +12,6 @@
* for more details.
*/
#include <QMutex>
#include <QSettings>
#include <QNetworkReply>
#include <QMessageBox>
@@ -21,7 +20,6 @@
#include "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibbolethcredentials.h"
#include "shibboleth/shibbolethuserjob.h"
#include "creds/credentialscommon.h"
@@ -46,39 +44,6 @@ namespace
const char userC[] = "shib_user";
const char shibCookieNameC[] = "_shibsession_";
int shibboleth_redirect_callback(CSYNC* csync_ctx,
const char* uri)
{
if (!csync_ctx || !uri) {
return 1;
}
const QString qurl(QString::fromLatin1(uri));
QRegExp shibbolethyWords ("SAML|wayf");
shibbolethyWords.setCaseSensitivity (Qt::CaseInsensitive);
if (!qurl.contains(shibbolethyWords)) {
return 1;
}
SyncEngine* engine = reinterpret_cast<SyncEngine*>(csync_get_userdata(csync_ctx));
AccountPtr account = engine->account();
ShibbolethCredentials* creds = qobject_cast<ShibbolethCredentials*>(account->credentials());
if (!creds) {
qDebug() << "Not a Shibboleth creds instance!";
return 1;
}
QMutex mutex;
QMutexLocker locker(&mutex);
ShibbolethRefresher refresher(account, creds, csync_ctx);
// blocks
refresher.refresh();
return creds->ready() ? 0 : 1;
}
} // ns
ShibbolethCredentials::ShibbolethCredentials()
@@ -86,14 +51,12 @@ ShibbolethCredentials::ShibbolethCredentials()
_url(),
_ready(false),
_stillValid(false),
_fetchJobInProgress(false),
_browser(0)
{}
ShibbolethCredentials::ShibbolethCredentials(const QNetworkCookie& cookie)
: _ready(true),
_stillValid(true),
_fetchJobInProgress(false),
_browser(0),
_shibCookie(cookie)
{
@@ -130,12 +93,7 @@ QByteArray ShibbolethCredentials::prepareCookieData() const
void ShibbolethCredentials::syncContextPreStart (CSYNC* ctx)
{
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
csync_owncloud_redirect_callback_t cb = shibboleth_redirect_callback;
csync_set_module_property(ctx, "session_key", prepareCookieData().data());
csync_set_module_property(ctx, "redirect_callback", &cb);
}
bool ShibbolethCredentials::changed(AbstractCredentials* credentials) const
@@ -191,17 +149,12 @@ bool ShibbolethCredentials::ready() const
return _ready;
}
void ShibbolethCredentials::fetch()
void ShibbolethCredentials::fetchFromKeychain()
{
if(_fetchJobInProgress) {
return;
}
if (_user.isEmpty()) {
_user = _account->credentialSetting(QLatin1String(userC)).toString();
}
if (_ready) {
_fetchJobInProgress = false;
Q_EMIT fetched();
} else {
_url = _account->url();
@@ -211,10 +164,14 @@ void ShibbolethCredentials::fetch()
job->setKey(keychainKey(_account->url().toString(), "shibAssertion"));
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start();
_fetchJobInProgress = true;
}
}
void ShibbolethCredentials::askFromUser()
{
showLoginWindow();
}
bool ShibbolethCredentials::stillValid(QNetworkReply *reply)
{
Q_UNUSED(reply)
@@ -229,9 +186,10 @@ void ShibbolethCredentials::persist()
}
}
// only used by Application::slotLogout(). Use invalidateAndFetch for normal usage
void ShibbolethCredentials::invalidateToken()
{
_ready = false;
CookieJar *jar = static_cast<CookieJar*>(_account->networkAccessManager()->cookieJar());
// Remove the _shibCookie
@@ -265,7 +223,7 @@ void ShibbolethCredentials::onShibbolethCookieReceived(const QNetworkCookie& shi
void ShibbolethCredentials::slotFetchUser()
{
// We must first do a request to webdav so the session is enabled.
// (because for some reason we wan't access the API without that.. a bug in the server maybe?)
// (because for some reason we can't access the API without that.. a bug in the server maybe?)
EntityExistsJob* job = new EntityExistsJob(_account->sharedFromThis(), _account->davPath(), this);
connect(job, SIGNAL(exists(QNetworkReply*)), this, SLOT(slotFetchUserHelper()));
job->setIgnoreCredentialFailure(true);
@@ -296,48 +254,14 @@ void ShibbolethCredentials::slotUserFetched(const QString &user)
_stillValid = true;
_ready = true;
_fetchJobInProgress = false;
Q_EMIT fetched();
Q_EMIT asked();
}
void ShibbolethCredentials::slotBrowserRejected()
{
_ready = false;
_fetchJobInProgress = false;
Q_EMIT fetched();
}
void ShibbolethCredentials::invalidateAndFetch()
{
_ready = false;
_fetchJobInProgress = true;
// delete the credentials, then in the slot fetch them again (which will trigger browser)
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
job->setSettings(_account->settingsWithGroup(Theme::instance()->appName(), job).release());
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotInvalidateAndFetchInvalidateDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), "shibAssertion"));
job->start();
}
void ShibbolethCredentials::slotInvalidateAndFetchInvalidateDone(QKeychain::Job*)
{
connect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
_fetchJobInProgress = false;
// small hack to support the ShibbolethRefresher hack
// we already rand fetch() with a valid account object,
// and hence know the url on refresh
fetch();
}
void ShibbolethCredentials::onFetched()
{
disconnect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
Q_EMIT invalidatedAndFetched(prepareCookieData());
Q_EMIT asked();
}
void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
@@ -355,10 +279,10 @@ void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
_ready = true;
_stillValid = true;
_fetchJobInProgress = false;
Q_EMIT fetched();
} else {
showLoginWindow();
_ready = false;
Q_EMIT fetched();
}
}
+3 -9
Ver Arquivo
@@ -44,7 +44,7 @@ Q_OBJECT
public:
ShibbolethCredentials();
/* create a credentials for an already connected account */
/* create credentials for an already connected account */
ShibbolethCredentials(const QNetworkCookie &cookie);
void setAccount(Account* account) Q_DECL_OVERRIDE;
@@ -55,7 +55,8 @@ public:
QString user() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetchFromKeychain() Q_DECL_OVERRIDE;
void askFromUser() Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE;
@@ -66,15 +67,10 @@ public:
static QNetworkCookie findShibCookie(Account *, QList<QNetworkCookie> cookies = QList<QNetworkCookie>());
static QByteArray shibCookieName();
public Q_SLOTS:
void invalidateAndFetch() Q_DECL_OVERRIDE;
private Q_SLOTS:
void onShibbolethCookieReceived(const QNetworkCookie&);
void slotBrowserRejected();
void onFetched();
void slotReadJobDone(QKeychain::Job*);
void slotInvalidateAndFetchInvalidateDone(QKeychain::Job*);
void slotReplyFinished(QNetworkReply*);
void slotUserFetched(const QString& user);
void slotFetchUser();
@@ -82,7 +78,6 @@ private Q_SLOTS:
Q_SIGNALS:
void newCookie(const QNetworkCookie& cookie);
void invalidatedAndFetched(const QByteArray& cookieData);
private:
void storeShibCookie(const QNetworkCookie &cookie);
@@ -93,7 +88,6 @@ private:
bool _ready;
bool _stillValid;
bool _fetchJobInProgress;
QPointer<ShibbolethWebView> _browser;
QNetworkCookie _shibCookie;
QString _user;
+29 -5
Ver Arquivo
@@ -30,7 +30,9 @@
#include "syncrunfilelog.h"
#include "theme.h"
#include "filesystem.h"
#include "excludedfiles.h"
#include <csync_private.h>
#include "creds/abstractcredentials.h"
@@ -88,14 +90,14 @@ Folder::Folder(const FolderDefinition& definition,
bool Folder::init()
{
// We need to reconstruct the url because the path need to be fully decoded, as csync will re-encode the path:
// We need to reconstruct the url because the path needs to be fully decoded, as csync will re-encode the path:
// Remember that csync will just append the filename to the path and pass it to the vio plugin.
// csync_owncloud will then re-encode everything.
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QUrl url = remoteUrl();
QString url_string = url.scheme() + QLatin1String("://") + url.authority(QUrl::EncodeDelimiters) + url.path(QUrl::FullyDecoded);
#else
// Qt4 was broken anyway as it did not encode the '#' as it should have done (it was actually a provlem when parsing the path from QUrl::setPath
// Qt4 was broken anyway as it did not encode the '#' as it should have done (it was actually a problem when parsing the path from QUrl::setPath
QString url_string = remoteUrl().toString();
#endif
url_string = Utility::toCSyncScheme(url_string);
@@ -157,7 +159,7 @@ void Folder::checkLocalPath()
qDebug() << "Checked local path ok";
} else {
// Check directory again
if( !FileSystem::fileExists(_definition.localPath) ) {
if( !FileSystem::fileExists(_definition.localPath, fi) ) {
_syncResult.setErrorString(tr("Local folder %1 does not exist.").arg(_definition.localPath));
_syncResult.setStatus( SyncResult::SetupError );
} else if( !fi.isDir() ) {
@@ -700,6 +702,28 @@ void Folder::removeFromSettings() const
settings->remove(_definition.alias);
}
bool Folder::isFileExcludedAbsolute(const QString& fullPath) const
{
QString myFullPath = fullPath;
if (myFullPath.endsWith(QLatin1Char('/'))) {
myFullPath.chop(1);
}
if (!myFullPath.startsWith(path())) {
// Mark paths we're not responsible for as excluded...
return true;
}
QString relativePath = myFullPath.mid(path().size());
auto excl = ExcludedFiles::instance().isExcluded(myFullPath, relativePath, _definition.ignoreHiddenFiles);
return excl != CSYNC_NOT_EXCLUDED;
}
bool Folder::isFileExcludedRelative(const QString& relativePath) const
{
return isFileExcludedAbsolute(path() + relativePath);
}
void Folder::watcherSlot(QString fn)
{
// FIXME: On OS X we could not do this "if" since on OS X the file watcher ignores events for ourselves
@@ -993,14 +1017,14 @@ void Folder::slotSyncFinished()
}
if (_syncResult.status() == SyncResult::Success) {
// Clear the white list as all the folder that should be on that list are sync-ed
// Clear the white list as all the folders that should be on that list are sync-ed
journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, QStringList());
}
emit syncStateChange();
// The syncFinished result that is to be triggered here makes the folderman
// clearing the current running sync folder marker.
// clear the current running sync folder marker.
// Lets wait a bit to do that because, as long as this marker is not cleared,
// file system change notifications are ignored for that folder. And it takes
// some time under certain conditions to make the file system notifications
+10
Ver Arquivo
@@ -197,6 +197,16 @@ public:
/// Removes the folder from the account's settings.
void removeFromSettings() const;
/**
* Returns whether a file inside this folder should be excluded.
*/
bool isFileExcludedAbsolute(const QString& fullPath) const;
/**
* Returns whether a file inside this folder should be excluded.
*/
bool isFileExcludedRelative(const QString& relativePath) const;
signals:
void syncStateChange();
void syncStarted();
+10 -22
Ver Arquivo
@@ -60,7 +60,6 @@ FolderMan::FolderMan(QObject *parent) :
_instance = this;
_socketApi = new SocketApi(this);
_socketApi->slotReadExcludes();
ConfigFile cfg;
int polltime = cfg.remotePollInterval();
@@ -149,10 +148,6 @@ void FolderMan::registerFolderMonitor( Folder *folder )
if( !_folderWatchers.contains(folder->alias() ) ) {
FolderWatcher *fw = new FolderWatcher(folder->path(), folder);
ConfigFile cfg;
fw->addIgnoreListFile( cfg.excludeFile(ConfigFile::SystemScope) );
fw->addIgnoreListFile( cfg.excludeFile(ConfigFile::UserScope) );
fw->setIgnoreHidden( folder->ignoreHiddenFiles() );
// Connect the pathChanged signal, which comes with the changed path,
// to the signal mapper which maps to the folder alias. The changed path
@@ -249,7 +244,7 @@ int FolderMan::setupFoldersMigration()
dir.setFilter(QDir::Files | QDir::Hidden);
QStringList list = dir.entryList();
// Normaly there should be only one account when migrating.
// Normally there should be only one account when migrating.
AccountState* accountState = AccountManager::instance()->accounts().value(0).data();
foreach ( const QString& alias, list ) {
Folder *f = setupFolderFromOldConfigFile( alias, accountState );
@@ -350,8 +345,8 @@ Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
qDebug() << " ` -> setting up:" << file;
QString escapedAlias(file);
// check the unescaped variant (for the case the filename comes out
// of the directory listing. If the file is not existing, escape the
// check the unescaped variant (for the case when the filename comes out
// of the directory listing). If the file does not exist, escape the
// file and try again.
QFileInfo cfgFile( _folderConfigPath, file);
@@ -361,7 +356,7 @@ Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
cfgFile.setFile( _folderConfigPath, escapedAlias );
}
if( !cfgFile.isReadable() ) {
qDebug() << "Can not read folder definition for alias " << cfgFile.filePath();
qDebug() << "Cannot read folder definition for alias " << cfgFile.filePath();
return folder;
}
@@ -599,12 +594,12 @@ void FolderMan::slotAccountStateChanged()
}
}
// only enable or disable foldermans will to schedule and do syncs.
// only enable or disable foldermans will schedule and do syncs.
// this is not the same as Pause and Resume of folders.
void FolderMan::setSyncEnabled( bool enabled )
{
if (!_syncEnabled && enabled && !_scheduleQueue.isEmpty()) {
// We have things in our queue that were waiting the the connection to go back on.
// We have things in our queue that were waiting for the connection to come back on.
startScheduledSyncSoon();
}
_syncEnabled = enabled;
@@ -696,13 +691,6 @@ void FolderMan::slotStartScheduledFolderSync()
_currentSyncFolder = f;
f->startSync( QStringList() );
// reread the excludes of the socket api
// FIXME: the excludes need rework.
if( _socketApi ) {
_socketApi->slotClearExcludesList();
_socketApi->slotReadExcludes();
}
}
}
@@ -918,7 +906,7 @@ bool FolderMan::startFromScratch( const QString& localFolder )
_socketApi->slotUnregisterPath(f->alias());
}
f->journalDb()->close();
f->slotTerminateSync(); // Normaly it should not be running, but viel hilft viel
f->slotTerminateSync(); // Normally it should not be running, but viel hilft viel
}
}
@@ -948,7 +936,7 @@ void FolderMan::setDirtyProxy(bool value)
if (f->accountState() && f->accountState()->account()
&& f->accountState()->account()->networkAccessManager()) {
// Need to do this have us not use the old determined system proxy
// Need to do this so we do not use the old determined system proxy
f->accountState()->account()->networkAccessManager()->setProxy(
QNetworkProxy(QNetworkProxy::DefaultProxy));
}
@@ -974,7 +962,7 @@ SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
int cnt = folders.count();
// if one folder: show the state of the one folder.
// if more folder:
// if more folders:
// if one of them has an error -> show error
// if one is paused, but others ok, show ok
// do not show "problem" in the tray
@@ -1091,7 +1079,7 @@ QString FolderMan::statusToString( SyncResult syncStatus, bool paused ) const
folderMessage = tr( "Undefined State." );
break;
case SyncResult::NotYetStarted:
folderMessage = tr( "Waits to start syncing." );
folderMessage = tr( "Waiting to start syncing." );
break;
case SyncResult::SyncPrepare:
folderMessage = tr( "Preparing for sync." );
+3 -3
Ver Arquivo
@@ -92,7 +92,7 @@ public:
/**
* Check if @a path is a valid path for a new folder considering the already sync'ed items.
* Make sure that this folder, or any subfolder is not sync'ed alrady.
* Make sure that this folder, or any subfolder is not sync'ed already.
*
* \a forNewDirectory is internal and is used for recursion.
*
@@ -123,7 +123,7 @@ signals:
/**
* signal to indicate a folder has changed its sync state.
*
* Attention: The folder may be zero. Do a general update of the state than.
* Attention: The folder may be zero. Do a general update of the state then.
*/
void folderSyncStateChange(Folder*);
@@ -162,7 +162,7 @@ public slots:
// slot to add a folder to the syncing queue
void slotScheduleSync(Folder*);
// slot to scheule an ETag job
// slot to schedule an ETag job
void slotScheduleETagJob ( const QString &alias, RequestEtagJob *job);
void slotEtagJobDestroyed (QObject*);
void slotRunOneEtagJob();
+1 -1
Ver Arquivo
@@ -33,7 +33,7 @@ QString FolderStatusDelegate::addFolderText()
return tr("Add Folder Sync Connection");
}
//alocate each item size in listview.
// allocate each item size in listview.
QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option ,
const QModelIndex & index) const
{
+115 -48
Ver Arquivo
@@ -90,7 +90,7 @@ Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex &index ) const
}
return Qt::ItemIsEnabled | ret;
}
case ErrorLabel:
case FetchLabel:
return Qt::ItemIsEnabled
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
| Qt::ItemNeverHasChildren
@@ -123,7 +123,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
auto remotePath = _folders.at(0)._folder->remotePath();
if (remotePath.isEmpty() || remotePath == QLatin1String("/")) {
// Syncing the entire owncloud: disable the add folder button (#3438)
return tr("Adding folder is disabled because your are already syncing all your files. "
return tr("Adding folder is disabled because you are already syncing all your files. "
"If you want to sync multiple folders, please remove the currently "
"configured root folder.");
}
@@ -151,11 +151,20 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
}
}
return QVariant();
case ErrorLabel:
case FetchLabel:
{
const auto x = static_cast<SubFolderInfo *>(index.internalPointer());
switch(role) {
case Qt::DisplayRole: return tr("Error while loading the list of folders from the server.");
case Qt::DisplayRole:
if (x->_hasError) {
return tr("Error while loading the list of folders from the server.");
} else {
return tr("Fetching folder list from server...");
}
break;
default: return QVariant();
}
}
case RootFolder:
break;
}
@@ -192,7 +201,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
} else if( status == SyncResult::Undefined ) {
return theme->syncStateIcon( SyncResult::SyncRunning);
} else {
// kepp the previous icon for the prepare phase.
// keep the previous icon for the prepare phase.
if( status == SyncResult::Problem) {
return theme->syncStateIcon( SyncResult::Success);
} else {
@@ -227,7 +236,7 @@ bool FolderStatusModel::setData(const QModelIndex& index, const QVariant& value,
info->_checked = checked;
if (checked == Qt::Checked) {
// If we are checked, check that we may need to check the parent as well if
// all the sibilings are also checked
// all the siblings are also checked
QModelIndex parent = index.parent();
auto parentInfo = infoForIndex(parent);
if (parentInfo && parentInfo->_checked != Qt::Checked) {
@@ -302,7 +311,7 @@ int FolderStatusModel::rowCount(const QModelIndex& parent) const
auto info = infoForIndex(parent);
if (!info)
return 0;
if (info->_hasError)
if (info->hasLabel())
return 1;
return info->_subs.count();
}
@@ -310,7 +319,11 @@ int FolderStatusModel::rowCount(const QModelIndex& parent) const
FolderStatusModel::ItemType FolderStatusModel::classify(const QModelIndex& index) const
{
if (auto sub = static_cast<SubFolderInfo*>(index.internalPointer())) {
return sub->_hasError ? ErrorLabel : SubFolder;
if (sub->hasLabel()) {
return FetchLabel;
} else {
return SubFolder;
}
}
if (index.row() < _folders.count()) {
return RootFolder;
@@ -323,8 +336,7 @@ FolderStatusModel::SubFolderInfo* FolderStatusModel::infoForIndex(const QModelIn
if (!index.isValid())
return 0;
if (auto parentInfo = static_cast<SubFolderInfo*>(index.internalPointer())) {
if (parentInfo->_hasError) {
// Error label
if (parentInfo->hasLabel()) {
return 0;
}
return &parentInfo->_subs[index.row()];
@@ -384,20 +396,21 @@ QModelIndex FolderStatusModel::index(int row, int column, const QModelIndex& par
}
switch(classify(parent)) {
case AddButton:
case ErrorLabel:
case FetchLabel:
return QModelIndex();
case RootFolder:
if (_folders.count() <= parent.row())
return QModelIndex(); // should not happen
return createIndex(row, column, const_cast<SubFolderInfo *>(&_folders[parent.row()]));
case SubFolder: {
auto info = static_cast<SubFolderInfo*>(parent.internalPointer());
if (info->_subs.count() <= parent.row())
auto pinfo = static_cast<SubFolderInfo*>(parent.internalPointer());
if (pinfo->_subs.count() <= parent.row())
return QModelIndex(); // should not happen
if (!info->_subs.at(parent.row())._hasError
&& info->_subs.at(parent.row())._subs.count() <= row)
auto & info = pinfo->_subs[parent.row()];
if (!info.hasLabel()
&& info._subs.count() <= row)
return QModelIndex(); // should not happen
return createIndex(row, column, &info->_subs[parent.row()]);
return createIndex(row, column, &info);
}
}
return QModelIndex();
@@ -413,7 +426,7 @@ QModelIndex FolderStatusModel::parent(const QModelIndex& child) const
case AddButton:
return QModelIndex();
case SubFolder:
case ErrorLabel:
case FetchLabel:
break;
}
auto pathIdx = static_cast<SubFolderInfo*>(child.internalPointer())->_pathIdx;
@@ -453,6 +466,9 @@ bool FolderStatusModel::hasChildren(const QModelIndex& parent) const
bool FolderStatusModel::canFetchMore(const QModelIndex& parent) const
{
if (_accountState->state() != AccountState::Connected) {
return false;
}
auto info = infoForIndex(parent);
if (!info || info->_fetched || info->_fetching)
return false;
@@ -467,7 +483,9 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
if (!info || info->_fetched || info->_fetching)
return;
info->_hasError = false;
info->_fetching = true;
info->_fetchingLabel = false;
QString path = info->_folder->remotePath();
if (info->_path != QLatin1String("/")) {
if (!path.endsWith(QLatin1Char('/'))) {
@@ -483,7 +501,12 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
connect(job, SIGNAL(finishedWithError(QNetworkReply*)),
this, SLOT(slotLscolFinishedWithError(QNetworkReply*)));
job->start();
job->setProperty(propertyParentIndexC , QVariant::fromValue<QPersistentModelIndex>(parent));
QPersistentModelIndex persistentIndex(parent);
job->setProperty(propertyParentIndexC , QVariant::fromValue(persistentIndex));
// Show 'fetching data...' hint after a while.
_fetchingItems[persistentIndex].start();
QTimer::singleShot(1000, this, SLOT(slotShowFetchProgress()));
}
void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
@@ -496,24 +519,35 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
return;
}
auto list = list_;
list.removeFirst(); // remove the parent item
if (parentInfo->_hasError) {
if (parentInfo->hasLabel()) {
beginRemoveRows(idx, 0 ,0);
parentInfo->_hasError = false;
parentInfo->_fetchingLabel = false;
endRemoveRows();
}
beginInsertRows(idx, 0, list.count() - 1);
parentInfo->_fetching = false;
parentInfo->_fetched = true;
auto list = list_;
list.removeFirst(); // remove the parent item
QUrl url = parentInfo->_folder->remoteUrl();
QString pathToRemove = url.path();
if (!pathToRemove.endsWith('/'))
pathToRemove += '/';
parentInfo->_fetched = true;
parentInfo->_fetching = false;
// Drop the folder base path and check for excludes.
QMutableListIterator<QString> it(list);
while (it.hasNext()) {
it.next();
it.value().remove(pathToRemove);
if (parentInfo->_folder->isFileExcludedRelative(it.value())) {
it.remove();
}
}
beginInsertRows(idx, 0, list.count() - 1);
QStringList selectiveSyncBlackList;
if (parentInfo->_checked == Qt::PartiallyChecked) {
@@ -531,7 +565,6 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
newInfo._pathIdx << i++;
auto size = job ? job->_sizes.value(path) : 0;
newInfo._size = size;
path.remove(pathToRemove);
newInfo._path = path;
newInfo._name = path.split('/', QString::SkipEmptyParts).last();
@@ -580,14 +613,17 @@ void FolderStatusModel::slotLscolFinishedWithError(QNetworkReply* r)
}
auto parentInfo = infoForIndex(idx);
if (parentInfo) {
parentInfo->_fetching = false;
if (r->error() == QNetworkReply::ContentNotFoundError) {
parentInfo->_fetched = true;
} else if (!parentInfo->_hasError) {
beginInsertRows(idx, 0, 0);
} else {
if (!parentInfo->hasLabel()) {
beginInsertRows(idx, 0, 0);
endInsertRows();
}
parentInfo->_hasError = true;
endInsertRows();
}
parentInfo->_fetching = false;
parentInfo->_fetchingLabel = false;
}
}
@@ -661,7 +697,7 @@ void FolderStatusModel::slotApplySelectiveSync()
// clear the undecided list
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, QStringList());
// do the sync if there was changes
// do the sync if there were changes
auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
if (!changes.isEmpty()) {
if (folder->isBusy()) {
@@ -724,7 +760,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
<< FolderStatusDelegate::WarningCount;
if (!progress._currentDiscoveredFolder.isEmpty()) {
pi->_progressString = tr("Discovering '%1'").arg(progress._currentDiscoveredFolder);
pi->_progressString = tr("Checking for changes in '%1'").arg(progress._currentDiscoveredFolder);
emit dataChanged(index(folderIndex), index(folderIndex), roles);
return;
}
@@ -829,7 +865,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
.arg(currentFile).arg(totalFileCount)
.arg( Utility::durationToDescriptiveString(progress.totalProgress().estimatedEta) );
} else if (totalFileCount > 0) {
// Don't attemt to estimate the time left if there is no kb to transfer.
// Don't attempt to estimate the time left if there is no kb to transfer.
overallSyncString = tr("file %1 of %2") .arg(currentFile).arg(totalFileCount);
}
@@ -837,7 +873,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
int overallPercent = 0;
if( totalFileCount > 0 ) {
// Add one 'byte' for each files so the percentage is moving when deleting or renaming files
// Add one 'byte' for each file so the percentage is moving when deleting or renaming files
overallPercent = qRound(double(completedSize + completedFile)/double(totalSize + totalFileCount) * 100.0);
}
pi->_overallPercent = qBound(0, overallPercent, 100);
@@ -891,13 +927,8 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f)
if (i->_isDirectory && (i->_instruction == CSYNC_INSTRUCTION_NEW
|| i->_instruction == CSYNC_INSTRUCTION_REMOVE)) {
// There is a new or a removed folder. reset all data
_folders[folderIndex]._fetched = false;
_folders[folderIndex]._fetching = false;
if (!_folders.at(folderIndex)._subs.isEmpty()) {
beginRemoveRows(index(folderIndex), 0, _folders.at(folderIndex)._subs.count() - 1);
_folders[folderIndex]._subs.clear();
endRemoveRows();
}
auto & info = _folders[folderIndex];
info.resetSubs(this, index(folderIndex));
return;
}
}
@@ -933,17 +964,53 @@ void FolderStatusModel::slotNewBigFolder()
}
if (folderIndex < 0) { return; }
_folders[folderIndex]._fetched = false;
_folders[folderIndex]._fetching = false;
if (!_folders.at(folderIndex)._subs.isEmpty()) {
beginRemoveRows(index(folderIndex), 0, _folders.at(folderIndex)._subs.count() - 1);
_folders[folderIndex]._subs.clear();
endRemoveRows();
}
_folders[folderIndex].resetSubs(this, index(folderIndex));
emit suggestExpand(index(folderIndex));
emit dirtyChanged();
}
void FolderStatusModel::slotShowFetchProgress()
{
QMutableMapIterator<QPersistentModelIndex, QElapsedTimer> it(_fetchingItems);
while (it.hasNext()) {
it.next();
if (it.value().elapsed() > 800)
{
auto idx = it.key();
auto* info = infoForIndex(idx);
if (info && info->_fetching) {
if (!info->hasLabel()) {
beginInsertRows(idx, 0, 0);
endInsertRows();
}
info->_fetchingLabel = true;
}
it.remove();
}
}
}
bool FolderStatusModel::SubFolderInfo::hasLabel() const
{
return _hasError || _fetchingLabel;
}
void FolderStatusModel::SubFolderInfo::resetSubs(FolderStatusModel* model, QModelIndex index)
{
_fetched = false;
_fetching = false;
if (hasLabel()) {
model->beginRemoveRows(index, 0 ,0);
_fetchingLabel = false;
_hasError = false;
model->endRemoveRows();
} else if (!_subs.isEmpty()) {
model->beginRemoveRows(index, 0, _subs.count() - 1);
_subs.clear();
model->endRemoveRows();
}
}
} // namespace OCC
+33 -8
Ver Arquivo
@@ -18,7 +18,7 @@
#include <accountfwd.h>
#include <QAbstractItemModel>
#include <QVector>
#include <QElapsedTimer>
class QNetworkReply;
namespace OCC {
@@ -51,20 +51,30 @@ public:
struct SubFolderInfo {
SubFolderInfo()
: _folder(0), _size(0), _fetched(false), _fetching(false), _isUndecided(false),
_hasError(false), _checked(Qt::Checked) {}
: _folder(0), _size(0), _fetched(false), _fetching(false),
_hasError(false), _fetchingLabel(false), _isUndecided(false), _checked(Qt::Checked) {}
Folder *_folder;
QString _name;
QString _path;
QVector<int> _pathIdx;
QVector<SubFolderInfo> _subs;
qint64 _size;
bool _fetched; // If we did the LSCOL for this folder already
bool _fetching;
bool _isUndecided; // undecided folder are the big folder that the user has not accepted yet
bool _fetching; // Whether a LSCOL job is currently running
bool _hasError; // If the last fetching job ended in an error
bool _fetchingLabel; // Whether a 'fetching in progress' label is shown.
bool _isUndecided; // undecided folders are the big folders that the user has not accepted yet
Qt::CheckState _checked;
// Whether this has a FetchLabel subrow
bool hasLabel() const;
// Reset all subfolders and fetch status
void resetSubs(FolderStatusModel* model, QModelIndex index);
struct Progress {
Progress() : _warningCount(0), _overallPercent(0) {}
bool isNull() const
@@ -79,7 +89,7 @@ public:
QVector<SubFolderInfo> _folders;
enum ItemType { RootFolder, SubFolder, AddButton, ErrorLabel };
enum ItemType { RootFolder, SubFolder, AddButton, FetchLabel };
ItemType classify(const QModelIndex &index) const;
SubFolderInfo *infoForIndex(const QModelIndex &index) const;
@@ -88,7 +98,7 @@ public:
/**
* return a QModelIndex for the given path within the given folder.
* Note: this method returns an invalid index if the path was not fetch from the server before
* Note: this method returns an invalid index if the path was not fetched from the server before
*/
QModelIndex indexForPath(Folder *f, const QString &path) const;
@@ -105,12 +115,25 @@ private slots:
void slotFolderScheduleQueueChanged();
void slotNewBigFolder();
/**
* "In progress" labels for fetching data from the server are only
* added after some time to avoid popping.
*/
void slotShowFetchProgress();
private:
QStringList createBlackList(OCC::FolderStatusModel::SubFolderInfo* root,
const QStringList& oldBlackList) const;
const AccountState* _accountState;
bool _dirty; // If the selective sync checkboxes were changed
/**
* Keeps track of items that are fetching data from the server.
*
* See slotShowPendingFetchProgress()
*/
QMap<QPersistentModelIndex, QElapsedTimer> _fetchingItems;
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
//the roles argument was added in Qt5
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>())
@@ -119,7 +142,9 @@ private:
signals:
void dirtyChanged();
void suggestExpand(const QModelIndex &); // Tell the view that this item should be expanded because it has a undecided item
void suggestExpand(const QModelIndex &); // Tell the view that this item should be expanded because it has an undecided item
friend struct SubFolderInfo;
};
} // namespace OCC
+13 -75
Ver Arquivo
@@ -32,12 +32,14 @@
#include "folderwatcher_linux.h"
#endif
#include "excludedfiles.h"
#include "folder.h"
namespace OCC {
FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
: QObject(parent),
_ignoreHidden(true)
FolderWatcher::FolderWatcher(const QString &root, Folder* folder)
: QObject(folder),
_folder(folder)
{
_d.reset(new FolderWatcherPrivate(this, root));
@@ -47,81 +49,17 @@ FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
FolderWatcher::~FolderWatcher()
{ }
void FolderWatcher::setIgnoreHidden(bool ignore)
{
_ignoreHidden = ignore;
}
bool FolderWatcher::ignoreHidden()
{
return _ignoreHidden;
}
void FolderWatcher::addIgnoreListFile( const QString& file )
{
if( file.isEmpty() ) return;
QFile infile( file );
if (!infile.open(QIODevice::ReadOnly | QIODevice::Text))
return;
while (!infile.atEnd()) {
QString line = QString::fromLocal8Bit( infile.readLine() ).trimmed();
if( !(line.startsWith( QLatin1Char('#') ) || line.isEmpty()) ) {
_ignores.append(line);
}
}
}
QStringList FolderWatcher::ignores() const
{
return _ignores;
}
bool FolderWatcher::pathIsIgnored( const QString& path )
{
if( path.isEmpty() ) return true;
if( !_folder ) return false;
// if events caused by changes to hidden files should be ignored, a QFileInfo
// object will tell us if the file is hidden
if( _ignoreHidden ) {
QFileInfo fInfo(path);
if( fInfo.isHidden() ) {
qDebug() << "* Discarded as is hidden!" << fInfo.filePath();
return true;
}
}
// TODO: Best use csync_excluded_no_ctx() here somehow!
foreach (QString pattern, _ignores) {
// The leading ] is a tag and not part of the pattern.
if (pattern.startsWith(']')) {
pattern.remove(0, 1);
}
if(pattern.endsWith('/')) {
// directory only pattern. But since path components are
// checked later, we cut off the trailing dir.
pattern.chop(1);
}
QRegExp regexp(pattern);
regexp.setPatternSyntax(QRegExp::Wildcard);
// if the pattern contains / it needs to match the entire path
if (pattern.contains('/') && regexp.exactMatch(path)) {
qDebug() << "* Discarded by ignore pattern: " << path;
return true;
}
QStringList components = path.split('/');
foreach (const QString& comp, components) {
if(regexp.exactMatch(comp)) {
qDebug() << "* Discarded by component ignore pattern " << comp;
return true;
}
}
#ifndef OWNCLOUD_TEST
if (_folder->isFileExcludedAbsolute(path)) {
qDebug() << "* Ignoring file" << path;
return true;
}
#endif
return false;
}
@@ -137,8 +75,8 @@ void FolderWatcher::changeDetected( const QStringList& paths )
// TODO: this shortcut doesn't look very reliable:
// - why is the timeout only 1 second?
// - what if there are more than one file being updated frequently?
// - why do we skip the file alltogether instead of e.g. reducing the upload frequency?
// - what if there is more than one file being updated frequently?
// - why do we skip the file altogether instead of e.g. reducing the upload frequency?
// Check if the same path was reported within the last second.
QSet<QString> pathsSet = paths.toSet();
+6 -22
Ver Arquivo
@@ -14,8 +14,6 @@
#ifndef MIRALL_FOLDERWATCHER_H
#define MIRALL_FOLDERWATCHER_H
#include "config.h"
#include <QList>
#include <QObject>
#include <QString>
@@ -30,16 +28,17 @@ class QTimer;
namespace OCC {
class FolderWatcherPrivate;
class Folder;
/**
* @brief Montiors a directory recursively for changes
* @brief Monitors a directory recursively for changes
*
* Folder Watcher monitors a directory and its sub directories
* for changes in the local file system. Changes are signalled
* through the pathChanged() signal.
*
* Note that if new folders are created, this folderwatcher class
* does not automatically adds them to the list of monitored
* does not automatically add them to the list of monitored
* dirs. That is the responsibility of the user of this class to
* call addPath() with the new dir.
*
@@ -53,23 +52,13 @@ public:
/**
* @param root Path of the root of the folder
*/
FolderWatcher(const QString &root, QObject *parent = 0L);
FolderWatcher(const QString &root, Folder* folder = 0L);
virtual ~FolderWatcher();
/**
* Set a file name to load a file with ignore patterns.
*
* Valid entries do not start with a hash sign (#)
* and may contain wildcards
*/
void addIgnoreListFile( const QString& );
QStringList ignores() const;
/**
* Not all backends are recursive by default.
* Those need to be notified when a directory is added or removed while the watcher is disabled.
* This is a no-op for backend that are recursive
* This is a no-op for backends that are recursive
*/
void addPath(const QString&);
void removePath(const QString&);
@@ -77,10 +66,6 @@ public:
/* Check if the path is ignored. */
bool pathIsIgnored( const QString& path );
/* set if the folderwatcher ignores events of hidden files */
void setIgnoreHidden(bool ignore);
bool ignoreHidden();
signals:
/** Emitted when one of the watched directories or one
* of the contained files is changed. */
@@ -99,10 +84,9 @@ protected:
private:
QScopedPointer<FolderWatcherPrivate> _d;
QStringList _ignores;
QTime _timer;
QSet<QString> _lastPaths;
bool _ignoreHidden;
Folder* _folder;
friend class FolderWatcherPrivate;
};
+1 -1
Ver Arquivo
@@ -173,7 +173,7 @@ void GeneralSettings::slotAccountAddedOrRemoved()
{
_ui->addAccountButton->setVisible(
AccountManager::instance()->accounts().isEmpty()
|| Theme::instance()->multiAccount());
|| !Theme::instance()->singleAccount());
}
+61 -57
Ver Arquivo
@@ -53,63 +53,6 @@
<string>Advanced</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="newFolderLimitCheckBox">
<property name="text">
<string>Ask confirmation before downloading folders larger than</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="newFolderLimitSpinBox">
<property name="maximum">
<number>999999</number>
</property>
<property name="value">
<number>99</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>MB</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="crashreporterCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show crash reporter</string>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
@@ -158,6 +101,67 @@
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="newFolderLimitCheckBox">
<property name="text">
<string>Ask confirmation before downloading folders larger than</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="newFolderLimitSpinBox">
<property name="maximum">
<number>999999</number>
</property>
<property name="value">
<number>99</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>MB</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QCheckBox" name="crashreporterCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show crash reporter</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
+3
Ver Arquivo
@@ -16,6 +16,7 @@
#include "ignorelisteditor.h"
#include "folderman.h"
#include "ui_ignorelisteditor.h"
#include "excludedfiles.h"
#include <QFile>
#include <QDir>
@@ -126,6 +127,8 @@ void IgnoreListEditor::slotUpdateLocalIgnoreList()
folder->journalDb()->forceRemoteDiscoveryNextSync();
folderMan->slotScheduleSync(folder);
}
ExcludedFiles::instance().reloadExcludes();
}
void IgnoreListEditor::slotAddPattern()
+1 -1
Ver Arquivo
@@ -110,7 +110,7 @@ LogBrowser::LogBrowser(QWidget *parent) :
setModal(false);
// Direct connection for log comming from this thread, and queued for the one in a different thread
// Direct connection for log coming from this thread, and queued for the one in a different thread
connect(Logger::instance(), SIGNAL(newLog(QString)),this,SLOT(slotNewLog(QString)), Qt::AutoConnection);
QAction *showLogWindow = new QAction(this);
+9 -9
Ver Arquivo
@@ -107,7 +107,7 @@ ownCloudGui::ownCloudGui(Application *parent) :
// Use this to do platform specific code to make overlay icons appear
// in the gui
// MacOSX: perform a AppleScript code peace to load the Finder Plugin.
// MacOSX: perform a AppleScript code piece to load the Finder Plugin.
void ownCloudGui::setupOverlayIcons()
@@ -136,7 +136,7 @@ void ownCloudGui::setupOverlayIcons()
p.waitForFinished(5000);
QByteArray result = p.readAll();
QString resultAsString(result); // if appropriate
qDebug() << "Laod Finder Overlay-Plugin: " << resultAsString << ": " << p.exitCode()
qDebug() << "Load Finder Overlay-Plugin: " << resultAsString << ": " << p.exitCode()
<< (p.exitCode() != 0 ? p.errorString() : QString::null);
} else {
qDebug() << finderExtension << "does not exist! Finder Overlay Plugin loading failed";
@@ -269,7 +269,7 @@ void ownCloudGui::slotComputeOverallSyncStatus()
return;
}
// display the info of the least successful sync (eg. not just display the result of the latest sync
// display the info of the least successful sync (eg. do not just display the result of the latest sync)
QString trayMessage;
FolderMan *folderMan = FolderMan::instance();
Folder::Map map = folderMan->map();
@@ -412,7 +412,7 @@ void ownCloudGui::setupContextMenu()
#endif
}
_contextMenu->setTitle(Theme::instance()->appNameGUI() );
// We must call deleteLater because we might be called from the press in one of the action.
// We must call deleteLater because we might be called from the press in one of the actions.
foreach (auto menu, _accountMenus) { menu->deleteLater(); }
_accountMenus.clear();
if (accountList.count() > 1) {
@@ -446,7 +446,7 @@ void ownCloudGui::setupContextMenu()
_contextMenu->addSeparator();
if (atLeastOneSignedIn) {
if (accountList.count() > 1) {
_actionLogout->setText(tr("Log out everywhere"));
_actionLogout->setText(tr("Log out of all accounts"));
} else {
_actionLogout->setText(tr("Log out"));
}
@@ -454,7 +454,7 @@ void ownCloudGui::setupContextMenu()
}
if (atLeastOneSignedOut) {
if (accountList.count() > 1) {
_actionLogin->setText(tr("Log in everywhere..."));
_actionLogin->setText(tr("Log in to all accounts..."));
} else {
_actionLogin->setText(tr("Log in..."));
}
@@ -486,7 +486,7 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin
/*
* open the folder with the given Alais
* open the folder with the given Alias
*/
void ownCloudGui::slotFolderOpenAction( const QString& alias )
{
@@ -558,7 +558,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo&
Q_UNUSED(folder);
if (!progress._currentDiscoveredFolder.isEmpty()) {
_actionStatus->setText( tr("Discovering '%1'")
_actionStatus->setText( tr("Checking for changes in '%1'")
.arg( progress._currentDiscoveredFolder ));
} else if (progress.totalSize() == 0 ) {
quint64 currentFile = progress.currentFile();
@@ -580,7 +580,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo&
if (!progress._lastCompletedItem.isEmpty() && !Progress::isIgnoredKind(progress._lastCompletedItem._status)) {
if (Progress::isWarningKind(progress._lastCompletedItem._status)) {
// display a warn icon if warnings happend.
// display a warn icon if warnings happened.
QIcon warnIcon(":/client/resources/warning");
_actionRecent->setIcon(warnIcon);
}
+2 -2
Ver Arquivo
@@ -129,7 +129,7 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
// Reset the proxy which might had been determined previously in ConnectionValidator::checkServerAndAuth()
// when there was a previous account.
account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::DefaultProxy));
// Set fake credentials beforfe we check what credential it actually is.
// Set fake credentials before we check what credential it actually is.
account->setCredentials(CredentialsFactory::create("dummy"));
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this);
job->setIgnoreCredentialFailure(true);
@@ -439,7 +439,7 @@ bool OwncloudSetupWizard::ensureStartFromScratch(const QString &localFolder) {
return renameOk;
}
// Method executed when the user ends has finished the basic setup.
// Method executed when the user end has finished the basic setup.
void OwncloudSetupWizard::slotAssistantFinished( int result )
{
FolderMan *folderMan = FolderMan::instance();
+1 -1
Ver Arquivo
@@ -74,7 +74,7 @@ private:
QString keychainUsernameKey() const;
QString keychainPasswordKey() const;
/// The hostname:port of the current proxy, used for detetcting switches
/// The hostname:port of the current proxy, used for detecting switches
/// to a different proxy.
QString _proxy;
+1 -1
Ver Arquivo
@@ -100,7 +100,7 @@ void QuotaInfo::slotCheckQuota()
void QuotaInfo::slotUpdateLastQuota(const QVariantMap &result)
{
// The server can return frational bytes (#1374)
// The server can return fractional bytes (#1374)
// <d:quota-available-bytes>1374532061.2</d:quota-available-bytes>
quint64 avail = result["quota-available-bytes"].toDouble();
_lastQuotaUsedBytes = result["quota-used-bytes"].toDouble();
+3 -3
Ver Arquivo
@@ -29,7 +29,7 @@ class PropfindJob;
*
* It is typically owned by the AccountSetting page.
*
* The quota is requested if those 3 conditions are met:
* The quota is requested if these 3 conditions are met:
* - This object is active via setActive() (typically if the settings page is visible.)
* - The account is connected.
* - Every 30 seconds (defaultIntervalT) or 5 seconds in case of failure (failIntervalT)
@@ -52,7 +52,7 @@ public:
/**
* When the quotainfo is active, it requests the quota at regular interval.
* When setting it to active it will request the quota imediatly if the last time
* When setting it to active it will request the quota immediately if the last time
* the quota was requested was more than the interval
*/
void setActive(bool active);
@@ -75,7 +75,7 @@ private:
qint64 _lastQuotaTotalBytes;
qint64 _lastQuotaUsedBytes;
QTimer _jobRestartTimer;
QDateTime _lastQuotaRecieved; // the time at which de quota was recieved last
QDateTime _lastQuotaRecieved; // the time at which the quota was received last
bool _active; // if we should check at regular interval (when the UI is visible)
QPointer<PropfindJob> _job; // the currently running job
};
+25 -4
Ver Arquivo
@@ -156,10 +156,9 @@ void SelectiveSyncTreeView::recursiveInsert(QTreeWidgetItem* parent, QStringList
}
}
void SelectiveSyncTreeView::slotUpdateDirectories(const QStringList&list)
void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list)
{
auto job = qobject_cast<LsColJob *>(sender());
QScopedValueRollback<bool> isInserting(_inserting);
_inserting = true;
@@ -174,12 +173,29 @@ void SelectiveSyncTreeView::slotUpdateDirectories(const QStringList&list)
if (!_folderPath.isEmpty())
pathToRemove.append('/');
// Check for excludes.
//
// We would like to use Folder::isFileExcluded, but the folder doesn't
// exist yet. So we just create one temporarily...
FolderDefinition def;
def.localPath = pathToRemove;
def.ignoreHiddenFiles = FolderMan::instance()->ignoreHiddenFiles();
Folder f(def);
QMutableListIterator<QString> it(list);
while (it.hasNext()) {
it.next();
QString path = it.value();
path.remove(pathToRemove);
if (f.isFileExcludedRelative(path)) {
it.remove();
}
}
// Since / cannot be in the blacklist, expand it to the actual
// list of top-level folders as soon as possible.
if (_oldBlackList == QStringList("/")) {
_oldBlackList.clear();
foreach (QString path, list) {
path.remove(pathToRemove);
if (path.isEmpty()) {
continue;
}
@@ -205,6 +221,11 @@ void SelectiveSyncTreeView::slotUpdateDirectories(const QStringList&list)
} else {
root->setCheckState(0, Qt::PartiallyChecked);
}
qint64 size = job ? job->_sizes.value(pathToRemove, -1) : -1;
if (size >= 0) {
root->setText(1, Utility::octetsToString(size));
root->setData(1, Qt::UserRole, size);
}
}
foreach (QString path, list) {
@@ -255,7 +276,7 @@ void SelectiveSyncTreeView::slotItemChanged(QTreeWidgetItem *item, int col)
if (item->checkState(0) == Qt::Checked) {
// If we are checked, check that we may need to check the parent as well if
// all the sibilings are also checked
// all the siblings are also checked
QTreeWidgetItem *parent = item->parent();
if (parent && parent->checkState(0) != Qt::Checked) {
bool hasUnchecked = false;
+2 -2
Ver Arquivo
@@ -38,7 +38,7 @@ public:
QStringList createBlackList(QTreeWidgetItem* root = 0) const;
QStringList oldBlackList() const;
//Estimate the total size of checked item (recursively)
// Estimates the total size of checked items (recursively)
qint64 estimatedSize(QTreeWidgetItem *root = 0);
void refreshFolders();
@@ -48,7 +48,7 @@ public:
QSize sizeHint() const Q_DECL_OVERRIDE;
private slots:
void slotUpdateDirectories(const QStringList &);
void slotUpdateDirectories(QStringList);
void slotItemExpanded(QTreeWidgetItem *);
void slotItemChanged(QTreeWidgetItem*,int);
void slotLscolFinishedWithError(QNetworkReply*);
+1 -1
Ver Arquivo
@@ -251,7 +251,7 @@ QIcon SettingsDialog::createColorAwareIcon(const QString &name)
{
QColor bg(palette().base().color());
QImage img(name);
// account for different sensitivty of the human eye to certain colors
// account for different sensitivity of the human eye to certain colors
double treshold = 1.0 - ( 0.299 * bg.red() + 0.587 * bg.green() + 0.114 * bg.blue())/255.0;
if (treshold > 0.5) {
img.invertPixels(QImage::InvertRgb);
+1 -1
Ver Arquivo
@@ -41,7 +41,7 @@ namespace OCC {
SettingsDialogMac::SettingsDialogMac(ownCloudGui *gui, QWidget *parent)
: MacPreferencesWindow(parent), _gui(gui)
{
// do not show minimize button. There is no use, and retoring the
// do not show minimize button. There is no use, and restoring the
// dialog from minimize is broken in MacPreferencesWindow
setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint |
Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint);
+91 -9
Ver Arquivo
@@ -29,11 +29,21 @@
#include <QBuffer>
#include <QFileIconProvider>
#include <QClipboard>
#include <QFileInfo>
namespace {
int SHARETYPE_PUBLIC = 3;
// int PERMISSION_READ = 1;
int PERMISSION_UPDATE = 2;
int PERMISSION_CREATE = 4;
// int PERMISSION_DELETE = 8;
// int PERMISSION_SHARE = 16;
// int PERMISSION_ALL = 31;
}
namespace OCC {
ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QString &localPath, bool resharingAllowed, QWidget *parent) :
@@ -50,6 +60,10 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
setObjectName("SharingDialog"); // required as group for saveGeometry call
_ui->setupUi(this);
//Is this a file or folder?
_isFile = QFileInfo(localPath).isFile();
_ui->pushButton_copy->setIcon(QIcon::fromTheme("edit-copy"));
_ui->pushButton_copy->setEnabled(false);
connect(_ui->pushButton_copy, SIGNAL(clicked(bool)), SLOT(slotPushButtonCopyLinkPressed()));
@@ -64,8 +78,10 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_pi_link = new QProgressIndicator();
_pi_password = new QProgressIndicator();
_pi_date = new QProgressIndicator();
_pi_editing = new QProgressIndicator();
_ui->horizontalLayout_shareLink->addWidget(_pi_link);
_ui->horizontalLayout_password->addWidget(_pi_password);
_ui->horizontalLayout_editing->addWidget(_pi_editing);
// _ui->horizontalLayout_expire->addWidget(_pi_date);
connect(_ui->checkBox_shareLink, SIGNAL(clicked()), this, SLOT(slotCheckBoxShareLinkClicked()));
@@ -75,6 +91,7 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
connect(_ui->pushButton_setPassword, SIGNAL(clicked(bool)), SLOT(slotPasswordReturnPressed()));
connect(_ui->checkBox_expire, SIGNAL(clicked()), this, SLOT(slotCheckBoxExpireClicked()));
connect(_ui->calendar, SIGNAL(dateChanged(QDate)), SLOT(slotCalendarClicked(QDate)));
connect(_ui->checkBox_editing, SIGNAL(clicked()), this, SLOT(slotCheckBoxEditingClicked()));
//Disable checkbox
_ui->checkBox_shareLink->setEnabled(false);
@@ -117,7 +134,7 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
// check if the file is already inside of a synced folder
if( sharePath.isEmpty() ) {
// The file is not yet in an ownCloud synced folder. We could automatically
// copy it over, but that is skipped as not all questions can be anwered that
// copy it over, but that is skipped as not all questions can be answered that
// are involved in that, see https://github.com/owncloud/client/issues/2732
//
// _ui->checkBox_shareLink->setEnabled(false);
@@ -142,18 +159,27 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
// Parse capabilities
// If password is enforced make don't allow users to disable it
if (_account->capabilities().publicLinkEnforcePassword()) {
// If password is enforced then don't allow users to disable it
if (_account->capabilities().sharePublicLinkEnforcePassword()) {
_ui->checkBox_password->setEnabled(false);
}
// If expiredate is enforced do not allow disable and set max days
if (_account->capabilities().publicLinkEnforceExpireDate()) {
if (_account->capabilities().sharePublicLinkEnforceExpireDate()) {
_ui->checkBox_expire->setEnabled(false);
_ui->calendar->setMaximumDate(QDate::currentDate().addDays(
_account->capabilities().publicLinkExpireDateDays()
_account->capabilities().sharePublicLinkExpireDateDays()
));
}
// File can't have public upload set.
if (_isFile) {
_ui->checkBox_editing->setEnabled(false);
} else {
if (!_account->capabilities().sharePublicLinkAllowUpload()) {
_ui->checkBox_editing->setEnabled(false);
}
}
}
void ShareDialog::done( int r ) {
@@ -224,7 +250,7 @@ void ShareDialog::slotPasswordReturnPressed()
void ShareDialog::slotPasswordChanged(const QString& newText)
{
// disable the set-passwort button
// disable the set-password button
_ui->pushButton_setPassword->setEnabled( newText.length() > 0 );
}
@@ -355,6 +381,17 @@ void ShareDialog::slotSharesFetched(const QVariantMap &reply)
_ui->checkBox_expire->setChecked(false);
}
if (data.value("permissions").isValid()) {
int permissions = data.value("permissions").toInt();
/*
* Only directories can have public upload set
* For public links the server sets CREATE and UPDATE permissions.
*/
if (!_isFile && (permissions & PERMISSION_UPDATE) && (permissions & PERMISSION_CREATE)) {
_ui->checkBox_editing->setChecked(true);
}
}
QString url;
// From ownCloud server 8.2 the url field is always set for public shares
if (data.contains("url")) {
@@ -466,7 +503,7 @@ void ShareDialog::slotCheckBoxShareLinkClicked()
* Check the capabilities if the server requires a password for a share
* Ask for it directly
*/
if (_account->capabilities().publicLinkEnforcePassword()) {
if (_account->capabilities().sharePublicLinkEnforcePassword()) {
_pi_link->stopAnimation();
_ui->checkBox_password->setChecked(true);
_ui->checkBox_password->setEnabled(false);
@@ -541,7 +578,7 @@ void ShareDialog::slotCheckBoxExpireClicked()
if (_ui->checkBox_expire->checkState() == Qt::Checked)
{
const QDate date = QDate::currentDate().addDays(1);
ShareDialog::setExpireDate(date);
setExpireDate(date);
_ui->calendar->setDate(date);
_ui->calendar->setMinimumDate(date);
_ui->calendar->setEnabled(true);
@@ -553,10 +590,55 @@ void ShareDialog::slotCheckBoxExpireClicked()
}
}
#ifdef Q_OS_MAC
extern void copyToPasteboard(const QString &string);
#endif
void ShareDialog::slotPushButtonCopyLinkPressed()
{
#ifdef Q_OS_MAC
copyToPasteboard(_shareUrl);
#else
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(_shareUrl);
#endif
}
void ShareDialog::slotCheckBoxEditingClicked()
{
ShareDialog::setPublicUpload(_ui->checkBox_editing->checkState() == Qt::Checked);
}
void ShareDialog::setPublicUpload(bool publicUpload)
{
_ui->checkBox_editing->setEnabled(false);
_pi_editing->startAnimation();
const QUrl url = Account::concatUrlPath(_account->url(), QString("ocs/v1.php/apps/files_sharing/api/v1/shares/%1").arg(_public_share_id));
QList<QPair<QString, QString> > requestParams;
const QString value = QString::fromLatin1(publicUpload ? "true" : "false");
requestParams.append(qMakePair(QString::fromLatin1("publicUpload"), value));
OcsShareJob *job = new OcsShareJob("PUT", url, _account, this);
job->setPostParams(requestParams);
connect(job, SIGNAL(jobFinished(QVariantMap)), this, SLOT(slotPublicUploadSet(QVariantMap)));
job->start();
}
void ShareDialog::slotPublicUploadSet(const QVariantMap &reply)
{
QString message;
int code = getJsonReturnCode(reply, message);
if (code == 100) {
_ui->checkBox_editing->setEnabled(true);
} else {
qDebug() << Q_FUNC_INFO << reply;
displayError(code);
}
_pi_editing->stopAnimation();
}
void ShareDialog::setShareCheckBoxTitle(bool haveShares)
@@ -639,7 +721,7 @@ bool ShareDialog::uploadExternalFile()
_ui->label_sharePath->setText(tr("A sync file with the same name exists. "
"The file cannot be registered to sync."));
// TODO: Add a file comparison here. If the existing file is still the same
// then the file-to-copy we can share it.
// as the file-to-copy we can share it.
_sharePath.clear();
} else {
_uploadFails = 0;
+5
Ver Arquivo
@@ -100,6 +100,8 @@ private slots:
void slotPasswordChanged(const QString& newText);
void slotPushButtonCopyLinkPressed();
void slotThumbnailFetched(const int &statusCode, const QByteArray &reply);
void slotCheckBoxEditingClicked();
void slotPublicUploadSet(const QVariantMap &reply);
void done( int r );
private:
@@ -109,6 +111,7 @@ private:
void setShareLink( const QString& url );
void resizeEvent(QResizeEvent *e);
void redrawElidedUrl();
void setPublicUpload(bool publicUpload);
Ui::ShareDialog *_ui;
AccountPtr _account;
@@ -130,8 +133,10 @@ private:
QProgressIndicator *_pi_link;
QProgressIndicator *_pi_password;
QProgressIndicator *_pi_date;
QProgressIndicator *_pi_editing;
bool _resharingAllowed;
bool _isFile;
};
}
+84 -61
Ver Arquivo
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>372</width>
<height>241</height>
<height>277</height>
</rect>
</property>
<property name="windowTitle">
@@ -92,6 +92,84 @@
<property name="rightMargin">
<number>0</number>
</property>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLineEdit" name="lineEdit_password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_setPassword">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set &amp;password </string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox_expire">
<property name="text">
<string>Set &amp;expiration date</string>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="calendar">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_password">
<item>
<widget class="QCheckBox" name="checkBox_password">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set password</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizeConstraint">
@@ -128,23 +206,17 @@
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_password">
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_editing">
<item>
<widget class="QCheckBox" name="checkBox_password">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QCheckBox" name="checkBox_editing">
<property name="text">
<string>Set password</string>
<string>Allow editing</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@@ -158,54 +230,6 @@
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLineEdit" name="lineEdit_password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_setPassword">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set &amp;password </string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox_expire">
<property name="text">
<string>Set &amp;expiration date</string>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="calendar">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
@@ -252,7 +276,6 @@
<zorder>errorLabel</zorder>
<zorder>widget_shareLink</zorder>
<zorder>buttonBox</zorder>
<zorder>checkBox_password</zorder>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
+45 -57
Ver Arquivo
@@ -28,6 +28,8 @@
#include "version.h"
#include "account.h"
#include "accountstate.h"
#include "account.h"
#include "capabilities.h"
#include <QDebug>
#include <QUrl>
@@ -38,6 +40,7 @@
#include <QDir>
#include <QApplication>
#include <QLocalSocket>
#include <QStringBuilder>
#include <sqlite3.h>
@@ -52,30 +55,12 @@
// The second number should be changed when there are new features.
#define MIRALL_SOCKET_API_VERSION "1.0"
extern "C" {
enum csync_exclude_type_e {
CSYNC_NOT_EXCLUDED = 0,
CSYNC_FILE_SILENTLY_EXCLUDED,
CSYNC_FILE_EXCLUDE_AND_REMOVE,
CSYNC_FILE_EXCLUDE_LIST,
CSYNC_FILE_EXCLUDE_INVALID_CHAR,
CSYNC_FILE_EXCLUDE_LONG_FILENAME,
CSYNC_FILE_EXCLUDE_HIDDEN
};
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype);
int csync_exclude_load(const char *fname, c_strlist_t **list);
}
namespace OCC {
#define DEBUG qDebug() << "SocketApi: "
SocketApi::SocketApi(QObject* parent)
: QObject(parent)
, _excludes(0)
{
QString socketPath;
@@ -141,29 +126,6 @@ SocketApi::~SocketApi()
// All remaining sockets will be destroyed with _localServer, their parent
Q_ASSERT(_listeners.isEmpty() || _listeners.first()->parent() == &_localServer);
_listeners.clear();
slotClearExcludesList();
c_strlist_destroy(_excludes);
}
void SocketApi::slotClearExcludesList()
{
c_strlist_clear(_excludes);
}
void SocketApi::slotReadExcludes()
{
ConfigFile cfgFile;
slotClearExcludesList();
QString excludeList = cfgFile.excludeFile( ConfigFile::SystemScope );
if( !excludeList.isEmpty() ) {
qDebug() << "==== added system ignore list to socketapi:" << excludeList.toUtf8();
csync_exclude_load(excludeList.toUtf8(), &_excludes);
}
excludeList = cfgFile.excludeFile( ConfigFile::UserScope );
if( !excludeList.isEmpty() ) {
qDebug() << "==== added user defined ignore list to csync:" << excludeList.toUtf8();
csync_exclude_load(excludeList.toUtf8(), &_excludes);
}
}
void SocketApi::slotNewConnection()
@@ -268,7 +230,7 @@ void SocketApi::slotUpdateFolderView(Folder *f)
f->syncResult().status() == SyncResult::SetupError ) {
broadcastMessage(QLatin1String("STATUS"), f->path() ,
this->fileStatus(f, "", _excludes).toSocketAPIString());
this->fileStatus(f, "").toSocketAPIString());
broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() );
} else {
@@ -311,7 +273,7 @@ void SocketApi::slotSyncItemDiscovered(const QString &folder, const SyncFileItem
QString path = f->path() + item.destination();
// the trailing slash for directories must be appended as the filenames coming in
// from the plugins have that too. Otherwise the according entry item is not found
// from the plugins have that too. Otherwise the matching entry item is not found
// in the plugin.
if( item._type == SyncFileItem::Type::Directory ) {
path += QLatin1Char('/');
@@ -387,13 +349,12 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
statusString = QLatin1String("NOP");
} else {
const QString file = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
SyncFileStatus fileStatus = this->fileStatus(syncFolder, file, _excludes);
SyncFileStatus fileStatus = this->fileStatus(syncFolder, file);
statusString = fileStatus.toSocketAPIString();
}
QString message = QLatin1String("STATUS:")+statusString+QLatin1Char(':')
+QDir::toNativeSeparators(argument);
const QString message = QLatin1String("STATUS:") % statusString % QLatin1Char(':') % QDir::toNativeSeparators(argument);
sendMessage(socket, message);
}
@@ -447,6 +408,39 @@ void SocketApi::command_VERSION(const QString&, QIODevice* socket)
sendMessage(socket, QLatin1String("VERSION:" MIRALL_VERSION_STRING ":" MIRALL_SOCKET_API_VERSION));
}
void SocketApi::command_SHARE_STATUS(const QString &localFile, QIODevice *socket)
{
if (!socket) {
qDebug() << Q_FUNC_INFO << "No valid socket object.";
return;
}
qDebug() << Q_FUNC_INFO << localFile;
Folder *shareFolder = FolderMan::instance()->folderForPath(localFile);
if (!shareFolder) {
const QString message = QLatin1String("SHARE_STATUS:NOP:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
} else {
const Capabilities capabilities = shareFolder->accountState()->account()->capabilities();
if (!capabilities.shareAPI()) {
const QString message = QLatin1String("SHARE_STATUS:DISABLED:")+QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
} else {
QString available = "USER,GROUP";
if (capabilities.sharePublicLink()) {
available += ",LINK";
}
const QString message = QLatin1String("SHARE_STATUS:") + available + ":" + QDir::toNativeSeparators(localFile);
sendMessage(socket, message);
}
}
}
void SocketApi::command_SHARE_MENU_TITLE(const QString &, QIODevice* socket)
{
sendMessage(socket, QLatin1String("SHARE_MENU_TITLE:") + tr("Share with %1", "parameter is ownCloud").arg(Theme::instance()->appNameGUI()));
@@ -541,7 +535,7 @@ SyncJournalFileRecord SocketApi::dbFileRecord_capi( Folder *folder, QString file
/**
* Get status about a single file.
*/
SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes )
SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileName)
{
QString file = folder->path();
QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
@@ -558,7 +552,8 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
fileNameSlash += QLatin1Char('/');
}
if( !FileSystem::fileExists(file) ) {
const QFileInfo fi(file);
if( !FileSystem::fileExists(file, fi) ) {
qDebug() << "OO File " << file << " is not existing";
return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR);
}
@@ -566,7 +561,6 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
// file is ignored?
// Qt considers .lnk files symlinks on Windows so we need to work
// around that here.
const QFileInfo fi(file);
if( fi.isSymLink()
#ifdef Q_OS_WIN
&& fi.suffix() != "lnk"
@@ -581,17 +575,11 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
}
// Is it excluded?
CSYNC_EXCLUDE_TYPE excl = csync_excluded_no_ctx(excludes, fileName.toUtf8(), type);
if( folder->ignoreHiddenFiles()
&& (fi.isHidden()
|| fi.fileName().startsWith(QLatin1Char('.'))) ) {
excl = CSYNC_FILE_EXCLUDE_HIDDEN;
}
if( excl != CSYNC_NOT_EXCLUDED ) {
if( folder->isFileExcludedAbsolute(file) ) {
return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
}
// Error if it is in the selective sync blacklistr
// Error if it is in the selective sync blacklist
foreach(const auto &s, folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList)) {
if (fileNameSlash.startsWith(s)) {
return SyncFileStatus(SyncFileStatus::STATUS_ERROR);
+2 -8
Ver Arquivo
@@ -16,10 +16,6 @@
#ifndef SOCKETAPI_H
#define SOCKETAPI_H
extern "C" {
#include <std/c_string.h>
}
#include "syncfileitem.h"
#include "syncjournalfilerecord.h"
#include "ownsql.h"
@@ -56,8 +52,6 @@ public slots:
void slotUpdateFolderView(Folder *f);
void slotUnregisterPath( const QString& alias );
void slotRegisterPath( const QString& alias );
void slotReadExcludes();
void slotClearExcludesList();
signals:
void shareCommandReceived(const QString &sharePath, const QString &localPath, bool resharingAllowed);
@@ -70,7 +64,7 @@ private slots:
void slotSyncItemDiscovered(const QString &, const SyncFileItem &);
private:
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes );
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName);
SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName );
SqlQuery *getSqlQuery( Folder *folder );
@@ -83,12 +77,12 @@ private:
Q_INVOKABLE void command_VERSION(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_SHARE_STATUS(const QString& localFile, QIODevice *socket);
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QIODevice* socket);
QString buildRegisterPathMessage(const QString& path);
QList<QIODevice*> _listeners;
SocketApiServer _localServer;
c_strlist_t *_excludes;
QHash<Folder*, QSharedPointer<SqlQuery>> _dbQueries;
QHash<Folder*, QSharedPointer<SqlDatabase>> _openDbs;
};
+1 -1
Ver Arquivo
@@ -425,7 +425,7 @@ PassiveUpdateNotifier::PassiveUpdateNotifier(const QUrl &url, QObject *parent)
// remember the version of the currently running binary. On Linux it might happen that the
// package management updates the package while the app is running. This is detected in the
// updater slot: If the installed binary on the hd has a different version than the one
// running, the running app is restart. That happens in folderman.
// running, the running app is restarted. That happens in folderman.
_runningAppVersion = Utility::versionOfInstalledBinary();
}
+4 -4
Ver Arquivo
@@ -35,15 +35,15 @@ namespace OCC {
* This class schedules regular update checks. It also checks the config
* if update checks are wanted at all.
*
* To reflect that all platforms have its own update scheme, a little
* To reflect that all platforms have their own update scheme, a little
* complex class design was set up:
*
* For Windows and Linux, the updaters are inherited from OCUpdater, while
* the MacOSX SparkleUpdater directly uses the class Updater. On windows,
* NSISUpdater starts the update if a new version of the client is available.
* On MacOSX, the sparkle framework handles the installation of the new
* version. On Linux, the update capabilities by the underlying linux distro
* is relied on, and thus the PassiveUpdateNotifier just shows a notification
* version. On Linux, the update capabilities of the underlying linux distro
* are relied on, and thus the PassiveUpdateNotifier just shows a notification
* if there is a new version once at every start of the application.
*
* Simple class diagram of the updater:
@@ -83,7 +83,7 @@ private:
};
/**
* @brief Class that uses an ownCloud propritary XML format to fetch update information
* @brief Class that uses an ownCloud proprietary XML format to fetch update information
* @ingroup gui
*/
class OCUpdater : public QObject, public Updater
+2 -1
Ver Arquivo
@@ -253,7 +253,7 @@ void OwncloudAdvancedSetupPage::slotSelectFolder()
void OwncloudAdvancedSetupPage::slotSelectiveSyncClicked()
{
// Because clicking on it also changes it, restore it to the previous state in case the user cancel the dialog
// Because clicking on it also changes it, restore it to the previous state in case the user cancelled the dialog
_ui.rSyncEverything->setChecked(_selectiveSyncBlacklist.isEmpty());
AccountPtr acc = static_cast<OwncloudWizard *>(wizard())->account();
@@ -308,3 +308,4 @@ void OwncloudAdvancedSetupPage::slotQuotaRetrieved(const QVariantMap &result)
}
} // namespace OCC
+175
Ver Arquivo
@@ -0,0 +1,175 @@
project(libowncloudclient)
set(CMAKE_AUTOMOC TRUE)
include(GenerateExportHeader)
configure_file(version.h.in "${CMAKE_CURRENT_BINARY_DIR}/version.h" )
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
# # csync is required.
include_directories(
${CMAKE_SOURCE_DIR}/csync/src
#${CMAKE_SOURCE_DIR}/csync/src/httpbf/src
${CMAKE_SOURCE_DIR}/src/gui
${CMAKE_BINARY_DIR}/src/gui # for ui_sslerrordialog.h
${CMAKE_SOURCE_DIR}/src/libsync
${CMAKE_BINARY_DIR}/src/libsync # for owncloudlib.h
${CMAKE_BINARY_DIR}/csync
# ${CMAKE_BINARY_DIR}/csync/src
)
include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/qjson)
# include_directories(${OPENSSL_INCLUDE_DIR})
#
if ( APPLE )
list(APPEND OS_SPECIFIC_LINK_LIBRARIES
/System/Library/Frameworks/CoreServices.framework
/System/Library/Frameworks/Foundation.framework
/System/Library/Frameworks/AppKit.framework
)
endif()
set(owncloudclientlib_NAME "owncloudclient")
# IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD|NetBSD|OpenBSD")
# list(APPEND OS_SPECIFIC_LINK_LIBRARIES
# inotify
# )
# ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD|NetBSD|OpenBSD")
#
# if(SPARKLE_FOUND AND NOT BUILD_LIBRARIES_ONLY)
# list (APPEND OS_SPECIFIC_LINK_LIBRARIES ${SPARKLE_LIBRARY})
# endif()
set(libowncloudclient_SRCS
#account.cpp
../gui/folder.cpp
../gui/folderman.cpp
../gui/folderwatcher.cpp
../gui/folderwatcher_linux.cpp
../gui/accountstate.cpp
../gui/accountmanager.cpp
../gui/proxyauthhandler.cpp
../gui/proxyauthdialog.cpp
../gui/sslerrordialog.cpp
../gui/creds/httpcredentialsgui.cpp
../gui/creds/credentialsfactory.cpp
../gui/creds/shibbolethcredentials.cpp
../gui/creds/shibboleth/shibbolethwebview.cpp
# ../gui/creds/shibboleth/shibbolethrefresher.cpp
../gui/creds/shibboleth/shibbolethuserjob.cpp
../gui/socketapi.cpp
../gui/syncrunfilelog.cpp
)
# if(USE_NEON)
# list(APPEND libowncloudclient_SRCS
# propagator_legacy.cpp
# )
# add_definitions(-DUSE_NEON)
# endif(USE_NEON)
# These headers are installed for libowncloudsync to be used by 3rd party apps
set(owncloudclient_HEADERS
../gui/accountmanager.h
../gui/accountstate.h
../gui/folder.h
../gui/folderman.h
../gui/folderwatcher.h
)
IF (NOT APPLE)
INSTALL(
FILES ${owncloudclient_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/${owncloudclientlib_NAME}
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/owncloudclientlib.h
DESTINATION ${INCLUDE_INSTALL_DIR}/${owncloudclientlib_NAME}
)
ENDIF(NOT APPLE)
list(APPEND libowncloudclient_LINK_TARGETS
${QT_LIBRARIES}
ocsync
owncloudsync
${OS_SPECIFIC_LINK_LIBRARIES}
${OPENSSL_LIBRARIES}
)
if(QTKEYCHAIN_FOUND OR QT5KEYCHAIN_FOUND)
list(APPEND libowncloudclient_LINK_TARGETS ${QTKEYCHAIN_LIBRARY})
include_directories(${QTKEYCHAIN_INCLUDE_DIR})
endif()
#
# if(INOTIFY_FOUND)
# include_directories(${INOTIFY_INCLUDE_DIR})
# link_directories(${INOTIFY_LIBRARY_DIR})
# endif()
#
# if(NEON_FOUND)
# list(APPEND libowncloudclient_LINK_TARGETS ${NEON_LIBRARIES} httpbf)
# include_directories(${NEON_INCLUDE_DIRS})
#
# if(NEON_WITH_LFS)
# add_definitions(-DNE_LFS)
# endif()
# endif()
#
# if(ZLIB_FOUND)
# list(APPEND libowncloudclient_LINK_TARGETS ${ZLIB_LIBRARIES})
# include_directories(${ZLIB_INCLUDE_DIRS})
# endif(ZLIB_FOUND)
#
add_library(${owncloudclientlib_NAME} SHARED ${libowncloudclient_SRCS} ${syncMoc})
GENERATE_EXPORT_HEADER( ${owncloudclientlib_NAME}
BASE_NAME ${owncloudclientlib_NAME}
EXPORT_MACRO_NAME OWNCLOUDSYNC_EXPORT
EXPORT_FILE_NAME owncloudclientlib.h
STATIC_DEFINE OWNCLOUD_BUILT_AS_STATIC
)
# if(TOKEN_AUTH_ONLY)
# qt5_use_modules(${owncloudclientlib_NAME} Network Concurrent)
# else()
qt5_use_modules(${owncloudclientlib_NAME} Widgets Network WebKitWidgets Concurrent)
# endif()
set_target_properties( ${owncloudclientlib_NAME} PROPERTIES
VERSION ${MIRALL_VERSION}
SOVERSION ${MIRALL_SOVERSION}
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
)
set_target_properties( ${owncloudclientlib_NAME} PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE}" )
target_link_libraries(${owncloudclientlib_NAME} ${libowncloudclient_LINK_TARGETS} )
if(INOTIFY_FOUND)
target_link_libraries(${owncloudclientlib_NAME} ${INOTIFY_LIBRARY} )
endif()
if(BUILD_LIBRARIES_ONLY)
#add_library(${owncloudclientlib_NAME}_static STATIC ${libowncloudclient_SRCS} ${syncMoc})
#qt5_use_modules(${owncloudclientlib_NAME}_static Widgets Network Xml Sql)
#set_target_properties( ${owncloudclientlib_NAME}_static PROPERTIES
# VERSION ${MIRALL_VERSION}
# SOVERSION ${MIRALL_SOVERSION}
#)
#target_link_libraries(${owncloudclientlib_NAME}_static ${libowncloudclient_LINK_TARGETS} )
endif()
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
install(TARGETS ${owncloudclientlib_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
else()
install(TARGETS ${owncloudclientlib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
if (SPARKLE_FOUND)
install(DIRECTORY "${SPARKLE_LIBRARY}"
DESTINATION "${OWNCLOUD_OSX_BUNDLE}/Contents/Frameworks" USE_SOURCE_PERMISSIONS)
endif (SPARKLE_FOUND)
endif()
+34
Ver Arquivo
@@ -0,0 +1,34 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef VERSION_H
#define VERSION_H
#cmakedefine GIT_SHA1 "@GIT_SHA1@"
#define MIRALL_STRINGIFY(s) MIRALL_TOSTRING(s)
#define MIRALL_TOSTRING(s) #s
/* MIRALL version */
#define MIRALL_VERSION_MAJOR @MIRALL_VERSION_MAJOR@
#define MIRALL_VERSION_MINOR @MIRALL_VERSION_MINOR@
#define MIRALL_VERSION_PATCH @MIRALL_VERSION_PATCH@
#define MIRALL_VERSION_BUILD @MIRALL_VERSION_BUILD@
#define MIRALL_VERSION @MIRALL_VERSION@
#define MIRALL_VERSION_FULL @MIRALL_VERSION_FULL@
#define MIRALL_VERSION_STRING "@MIRALL_VERSION_STRING@"
#endif // VERSION_H
+13
Ver Arquivo
@@ -64,6 +64,7 @@ set(libsync_SRCS
utility.cpp
ownsql.cpp
transmissionchecksumvalidator.cpp
excludedfiles.cpp
creds/dummycredentials.cpp
creds/abstractcredentials.cpp
creds/credentialscommon.cpp
@@ -81,14 +82,22 @@ endif(USE_NEON)
# These headers are installed for libowncloudsync to be used by 3rd party apps
set(owncloudsync_HEADERS
abstractnetworkjob.h
account.h
syncengine.h
configfile.h
networkjobs.h
progressdispatcher.h
syncfileitem.h
syncfilestatus.h
syncjournaldb.h
syncresult.h
utility.h
ownsql.h
clientproxy.h
accountfwd.h
capabilities.h
connectionvalidator.h
)
set(creds_HEADERS
@@ -105,6 +114,10 @@ IF (NOT APPLE)
FILES ${creds_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/${synclib_NAME}/creds
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/owncloudlib.h
DESTINATION ${INCLUDE_INSTALL_DIR}/${synclib_NAME}
)
ENDIF(NOT APPLE)
list(APPEND libsync_LINK_TARGETS
+11 -3
Ver Arquivo
@@ -44,9 +44,9 @@ AbstractNetworkJob::AbstractNetworkJob(AccountPtr account, const QString &path,
: QObject(parent)
, _timedout(false)
, _followRedirects(false)
, _account(account)
, _ignoreCredentialFailure(false)
, _reply(0)
, _account(account)
, _path(path)
, _redirectCount(0)
{
@@ -263,13 +263,21 @@ QString extractErrorMessage(const QByteArray& errorResponse)
return QString::null;
}
QString exception;
while (!reader.atEnd() && reader.error() == QXmlStreamReader::NoError) {
reader.readNextStartElement();
if (reader.name() == QLatin1String("message")) {
return reader.readElementText();
QString message = reader.readElementText();
if (!message.isEmpty()) {
return message;
}
} else if (reader.name() == QLatin1String("exception")) {
exception = reader.readElementText();
}
}
return QString::null;
// Fallback, if message could not be found
return exception;
}
QString errorMessage(const QString& baseError, const QByteArray& body)
+3 -2
Ver Arquivo
@@ -81,7 +81,7 @@ protected:
QByteArray _responseTimestamp;
QElapsedTimer _durationTimer;
quint64 _duration;
bool _timedout; // set to true when the timeout slot is recieved
bool _timedout; // set to true when the timeout slot is received
// Automatically follows redirects. Note that this only works for
// GET requests that don't set up any HTTP body or other flags.
@@ -91,11 +91,12 @@ private slots:
void slotFinished();
virtual void slotTimeout();
protected:
AccountPtr _account;
private:
QNetworkReply* addTimer(QNetworkReply *reply);
bool _ignoreCredentialFailure;
QPointer<QNetworkReply> _reply; // (QPointer because the NetworkManager may be destroyed before the jobs at exit)
AccountPtr _account;
QString _path;
QTimer _timer;
int _redirectCount;
+24 -9
Ver Arquivo
@@ -159,6 +159,8 @@ void Account::setCredentials(AbstractCredentials *cred)
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(_credentials, SIGNAL(fetched()),
SLOT(slotCredentialsFetched()));
connect(_credentials, SIGNAL(asked()),
SLOT(slotCredentialsAsked()));
}
QUrl Account::davUrl() const
@@ -179,7 +181,7 @@ void Account::clearCookieJar()
/*! This shares our official cookie jar (containing all the tasty
authentication cookies) with another QNAM while making sure
of not loosing its ownership. */
of not losing its ownership. */
void Account::lendCookieJarTo(QNetworkAccessManager *guest)
{
auto jar = _am->cookieJar();
@@ -441,16 +443,13 @@ void Account::slotCredentialsFetched()
emit credentialsFetched(_credentials);
}
void Account::slotCredentialsAsked()
{
emit credentialsAsked(_credentials);
}
void Account::handleInvalidCredentials()
{
// invalidate & forget token/password
// but try to re-sign in.
if (_credentials->ready()) {
_credentials->invalidateAndFetch();
} else {
_credentials->fetch();
}
emit invalidCredentials();
}
@@ -479,9 +478,25 @@ QString Account::serverVersion()
return _serverVersion;
}
int Account::serverVersionInt()
{
// FIXME: Use Qt 5.5 QVersionNumber
auto components = serverVersion().split('.');
return (components.value(0).toInt() << 16)
+ (components.value(1).toInt() << 8)
+ components.value(2).toInt();
}
void Account::setServerVersion(const QString& version)
{
_serverVersion = version;
}
bool Account::rootEtagChangesNotOnlySubFolderEtags()
{
return (serverVersionInt() >= 0x080100);
}
} // namespace OCC
+7 -1
Ver Arquivo
@@ -141,7 +141,7 @@ public:
const QList< QPair<QString, QString> > &queryItems = (QList<QPair<QString, QString>>()));
/** Returns a new settings pre-set in a specific group. The Settings will be created
with the given parent. If no parents is specified, the caller must destroy the settings */
with the given parent. If no parent is specified, the caller must destroy the settings */
static std::unique_ptr<QSettings> settingsWithGroup(const QString& group, QObject* parent = 0);
// to be called by credentials only
@@ -154,6 +154,10 @@ public:
const Capabilities &capabilities() const;
void setServerVersion(const QString &version);
QString serverVersion();
int serverVersionInt();
// Fixed from 8.1 https://github.com/owncloud/client/issues/3730
bool rootEtagChangesNotOnlySubFolderEtags();
void clearCookieJar();
void lendCookieJarTo(QNetworkAccessManager *guest);
@@ -168,6 +172,7 @@ signals:
void propagatorNetworkActivity();
void invalidCredentials();
void credentialsFetched(AbstractCredentials* credentials);
void credentialsAsked(AbstractCredentials* credentials);
/// Forwards from QNetworkAccessManager::proxyAuthenticationRequired().
void proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*);
@@ -178,6 +183,7 @@ signals:
protected Q_SLOTS:
void slotHandleSslErrors(QNetworkReply*,QList<QSslError>);
void slotCredentialsFetched();
void slotCredentialsAsked();
private:
Account(QObject *parent = 0);
+2 -2
Ver Arquivo
@@ -294,7 +294,7 @@ void BandwidthManager::relativeDownloadMeasuringTimerExpired()
// We want to wait twice as long since we want to give all
// devices the same quota we used now since we don't want
// any upload to timeout
// any download to timeout
_relativeDownloadDelayTimer.setInterval(realWaitTimeMsec);
_relativeDownloadDelayTimer.start();
@@ -339,7 +339,7 @@ void BandwidthManager::relativeDownloadDelayTimerExpired()
_relativeLimitCurrentMeasuredJob->setBandwidthLimited(false);
_relativeLimitCurrentMeasuredJob->setChoked(false);
// choke all other UploadDevices
// choke all other download jobs
Q_FOREACH(GETFileJob *gfj, _downloadJobList) {
if (gfj != _relativeLimitCurrentMeasuredJob) {
gfj->setBandwidthLimited(true);
+33 -3
Ver Arquivo
@@ -23,19 +23,49 @@ Capabilities::Capabilities(const QVariantMap &capabilities)
{
}
bool Capabilities::publicLinkEnforcePassword() const
bool Capabilities::shareAPI() const
{
if (_capabilities["files_sharing"].toMap().contains("api_enabled")) {
return _capabilities["files_sharing"].toMap()["api_enabled"].toBool();
} else {
// This was later added so if it is not present just assume the API is enabled.
return true;
}
}
bool Capabilities::sharePublicLink() const
{
return _capabilities["files_sharing"].toMap()["public"].toMap()["enabled"].toBool();
}
bool Capabilities::sharePublicLinkAllowUpload() const
{
return _capabilities["files_sharing"].toMap()["public"].toMap()["upload"].toBool();
}
bool Capabilities::sharePublicLinkEnforcePassword() const
{
return _capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced"].toBool();
}
bool Capabilities::publicLinkEnforceExpireDate() const
bool Capabilities::sharePublicLinkEnforceExpireDate() const
{
return _capabilities["files_sharing"].toMap()["public"].toMap()["expire_date"].toMap()["enforced"].toBool();
}
int Capabilities::publicLinkExpireDateDays() const
int Capabilities::sharePublicLinkExpireDateDays() const
{
return _capabilities["files_sharing"].toMap()["public"].toMap()["expire_date"].toMap()["days"].toInt();
}
bool Capabilities::shareResharing() const
{
return _capabilities["files_sharing"].toMap()["resharing"].toBool();
}
QStringList Capabilities::supportedChecksumTypes() const
{
return QStringList();
}
}
+10 -4
Ver Arquivo
@@ -18,11 +18,12 @@
#include "owncloudlib.h"
#include <QVariantMap>
#include <QStringList>
namespace OCC {
/**
* @brief The Capabilities class represent the capabilities of an ownCloud
* @brief The Capabilities class represents the capabilities of an ownCloud
* server
* @ingroup libsync
*/
@@ -31,9 +32,14 @@ class OWNCLOUDSYNC_EXPORT Capabilities {
public:
Capabilities(const QVariantMap &capabilities);
bool publicLinkEnforcePassword() const;
bool publicLinkEnforceExpireDate() const;
int publicLinkExpireDateDays() const;
bool shareAPI() const;
bool sharePublicLink() const;
bool sharePublicLinkAllowUpload() const;
bool sharePublicLinkEnforcePassword() const;
bool sharePublicLinkEnforceExpireDate() const;
int sharePublicLinkExpireDateDays() const;
bool shareResharing() const;
QStringList supportedChecksumTypes() const;
private:
QVariantMap _capabilities;
+1 -1
Ver Arquivo
@@ -60,7 +60,7 @@ public:
/* Server poll interval in milliseconds */
int remotePollInterval( const QString& connection = QString() ) const;
/* Set poll interval. Value in microseconds has to be larger than 5000 */
/* Set poll interval. Value in milliseconds has to be larger than 5000 */
void setRemotePollInterval(int interval, const QString& connection = QString() );
/* Force sync interval, in milliseconds */
+5 -13
Ver Arquivo
@@ -41,7 +41,7 @@ QString ConnectionValidator::statusString( Status stat )
return QLatin1String("NotConfigured");
case ServerVersionMismatch:
return QLatin1String("Server Version Mismatch");
case CredentialsWrong:
case CredentialsMissingOrWrong:
return QLatin1String("Credentials Wrong");
case StatusNotFound:
return QLatin1String("Status not found");
@@ -121,18 +121,10 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf
}
// now check the authentication
AbstractCredentials *creds = _account->credentials();
if (creds->ready()) {
if (_account->credentials()->ready())
QTimer::singleShot( 0, this, SLOT( checkAuthentication() ));
} else {
// We can't proceed with the auth check because we don't have credentials.
// Fetch them now! Once fetched, a new connectivity check will be
// initiated anyway.
creds->fetch();
// no result is reported
deleteLater();
}
else
reportResult( CredentialsMissingOrWrong );
}
// status.php could not be loaded (network or server issue!).
@@ -184,7 +176,7 @@ void ConnectionValidator::slotAuthFailed(QNetworkReply *reply)
qDebug() << reply->error() << reply->errorString();
qDebug() << "******** Password is wrong!";
_errors << tr("The provided credentials are not correct");
stat = CredentialsWrong;
stat = CredentialsMissingOrWrong;
} else if( reply->error() != QNetworkReply::NoError ) {
_errors << errorMessage(reply->errorString(), reply->readAll());
+7 -8
Ver Arquivo
@@ -25,8 +25,8 @@ namespace OCC {
/**
* This is a job-like class to check that the server is up and that we are connected.
* There is two entry point: checkServerAndAuth and checkAuthentication
* checkAutentication is the quick version that only do the propfind
* There are two entry points: checkServerAndAuth and checkAuthentication
* checkAuthentication is the quick version that only does the propfind
* while checkServerAndAuth is doing the 3 calls.
*
* We cannot use the capabilites call to test the login and the password because of
@@ -44,17 +44,16 @@ namespace OCC {
|
+-> slotJobTimeout --> X
|
+-> slotStatusFound
credential->fetch() --+
|
+-----------------------------------+
+-> slotStatusFound --+--> X (if credentials are still missing)
|
+---------------------------+
|
*-+-> checkAuthentication (PROPFIND on root)
PropfindJob
|
+-> slotAuthFailed --> X
|
+-> slotAuthSuccess --+--> X (depending if comming from checkServerAndAuth or not)
+-> slotAuthSuccess --+--> X (depending if coming from checkServerAndAuth or not)
|
+---------------------------+
|
@@ -75,7 +74,7 @@ public:
Connected,
NotConfigured,
ServerVersionMismatch,
CredentialsWrong,
CredentialsMissingOrWrong,
StatusNotFound,
UserCanceledCredentials,
ServiceUnavailable,
+3 -6
Ver Arquivo
@@ -48,21 +48,18 @@ public:
virtual QString user() const = 0;
virtual QNetworkAccessManager* getQNAM() const = 0;
virtual bool ready() const = 0;
virtual void fetch() = 0;
virtual void fetchFromKeychain() = 0;
virtual void askFromUser() = 0;
virtual bool stillValid(QNetworkReply *reply) = 0;
virtual void persist() = 0;
/** Invalidates auth token, or password for basic auth */
virtual void invalidateToken() = 0;
virtual void invalidateAndFetch() {
invalidateToken();
fetch();
}
static QString keychainKey(const QString &url, const QString &user);
Q_SIGNALS:
void fetched();
void asked();
protected:
Account* _account;
+6 -1
Ver Arquivo
@@ -56,11 +56,16 @@ bool DummyCredentials::stillValid(QNetworkReply *reply)
return true;
}
void DummyCredentials::fetch()
void DummyCredentials::fetchFromKeychain()
{
Q_EMIT(fetched());
}
void DummyCredentials::askFromUser()
{
Q_EMIT(asked());
}
void DummyCredentials::persist()
{}
+2 -1
Ver Arquivo
@@ -35,7 +35,8 @@ public:
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetchFromKeychain() Q_DECL_OVERRIDE;
void askFromUser() Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE {}
};
+9 -55
Ver Arquivo
@@ -82,23 +82,16 @@ const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns
HttpCredentials::HttpCredentials()
: _user(),
_password(),
_certificatePath(),
_certificatePasswd(),
_ready(false),
_fetchJobInProgress(false),
_readPwdFromDeprecatedPlace(false)
: _ready(false)
{
}
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd)
: _user(user),
_password(password),
_certificatePath(certificatePath),
_certificatePasswd(certificatePasswd),
_ready(true),
_fetchJobInProgress(false)
_certificatePath(certificatePath),
_certificatePasswd(certificatePasswd)
{
}
@@ -200,12 +193,8 @@ QString HttpCredentials::fetchUser()
return _user;
}
void HttpCredentials::fetch()
void HttpCredentials::fetchFromKeychain()
{
if (_fetchJobInProgress) {
return;
}
// User must be fetched from config file
fetchUser();
_certificatePath = _account->credentialSetting(QLatin1String(certifPathC)).toString();
@@ -235,8 +224,6 @@ void HttpCredentials::fetch()
job->setKey(kck);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start();
_fetchJobInProgress = true;
_readPwdFromDeprecatedPlace = true;
}
}
bool HttpCredentials::stillValid(QNetworkReply *reply)
@@ -256,7 +243,6 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
QKeychain::Error error = job->error();
if( !_password.isEmpty() && error == NoError ) {
_fetchJobInProgress = false;
// All cool, the keychain did not come back with error.
// Still, the password can be empty which indicates a problem and
@@ -266,44 +252,12 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
} else {
// we come here if the password is empty or any other keychain
// error happend.
// In all error conditions it should
// ask the user for the password interactively now.
if( _readPwdFromDeprecatedPlace ) {
// there simply was not a password. Lets restart a read job without
// a settings object as we did it in older client releases.
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
const QString kck = keychainKey(_account->url().toString(), _user);
job->setKey(kck);
_fetchErrorString = job->error() != EntryNotFound ? job->errorString() : QString();
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start();
_readPwdFromDeprecatedPlace = false; // do try that only once.
_fetchJobInProgress = true;
// Note: if this read job succeeds, the value from the old place is still
// NOT persisted into the new account.
} else {
// interactive password dialog starts here
QString hint;
if (job->error() != EntryNotFound) {
hint = tr("Reading from keychain failed with error: '%1'").arg(
job->errorString());
}
bool ok;
QString pwd = queryPassword(&ok, hint);
_fetchJobInProgress = false;
if (ok) {
_password = pwd;
_ready = true;
persist();
} else {
_password = QString::null;
_ready = false;
}
emit fetched();
}
_password = QString();
_ready = false;
emit fetched();
}
}
@@ -343,7 +297,7 @@ void HttpCredentials::invalidateToken()
// clear the session cookie.
_account->clearCookieJar();
// let QNAM fogets about the password
// let QNAM forget about the password
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
_account->networkAccessManager()->clearAccessCache();
#else
+3 -5
Ver Arquivo
@@ -44,12 +44,11 @@ public:
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetchFromKeychain() Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE;
QString password() const;
virtual QString queryPassword(bool *ok, const QString& hint) = 0;
void invalidateToken() Q_DECL_OVERRIDE;
QString fetchUser();
virtual bool sslIsTrusted() { return false; }
@@ -68,13 +67,12 @@ protected:
QString _user;
QString _password;
QString _previousPassword;
QString _fetchErrorString;
bool _ready;
private:
QString _certificatePath;
QString _certificatePasswd;
bool _ready;
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
bool _readPwdFromDeprecatedPlace;
};
} // namespace OCC
+1 -1
Ver Arquivo
@@ -166,7 +166,7 @@ bool TokenCredentials::ready() const
return _ready;
}
void TokenCredentials::fetch()
void TokenCredentials::fetch(FetchMode)
{
Q_EMIT fetched();
}
+1 -1
Ver Arquivo
@@ -46,7 +46,7 @@ public:
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE;
+9 -1
Ver Arquivo
@@ -13,13 +13,14 @@
*/
#include "discoveryphase.h"
#include <csync_private.h>
#include <qdebug.h>
#include <QUrl>
#include "account.h"
#include <QFileInfo>
#include <csync_private.h>
namespace OCC {
@@ -327,6 +328,10 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file,QMap
//This works in concerto with the RequestEtagJob and the Folder object to check if the remote folder changed.
if (map.contains("getetag")) {
_etagConcatenation += map.value("getetag");
if (_firstEtag.isEmpty()) {
_firstEtag = map.value("getetag"); // for directory itself
}
}
}
@@ -339,6 +344,7 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot()
deleteLater();
return;
}
emit etag(_firstEtag);
emit etagConcatenation(_etagConcatenation);
emit finishedWithResult(_results);
deleteLater();
@@ -410,6 +416,8 @@ void DiscoveryMainThread::doOpendirSlot(QString subPath, DiscoveryDirectoryResul
this, SLOT(singleDirectoryJobFirstDirectoryPermissionsSlot(QString)));
QObject::connect(_singleDirJob, SIGNAL(etagConcatenation(QString)),
this, SIGNAL(etagConcatenation(QString)));
QObject::connect(_singleDirJob, SIGNAL(etag(QString)),
this, SIGNAL(etag(QString)));
_singleDirJob->start();
}
+6 -3
Ver Arquivo
@@ -29,8 +29,8 @@ namespace OCC {
class Account;
/**
* The Discovery Phase was once called "update" phase in csync therms.
* Its goal is to look at the files in one of the remote and check comared to the db
* The Discovery Phase was once called "update" phase in csync terms.
* Its goal is to look at the files in one of the remote and check compared to the db
* if the files are new, or changed.
*/
@@ -87,6 +87,7 @@ public:
signals:
void firstDirectoryPermissions(const QString &);
void etagConcatenation(const QString &);
void etag(const QString &);
void finishedWithResult(const QList<FileStatPointer> &);
void finishedWithError(int csyncErrnoCode, QString msg);
private slots:
@@ -97,6 +98,7 @@ private:
QList<FileStatPointer> _results;
QString _subPath;
QString _etagConcatenation;
QString _firstEtag;
AccountPtr _account;
bool _ignoredFirst;
QPointer<LsColJob> _lsColJob;
@@ -134,7 +136,8 @@ public slots:
void slotGetSizeFinishedWithError();
void slotGetSizeResult(const QVariantMap&);
signals:
void etagConcatenation(QString);
void etag(const QString &);
void etagConcatenation(const QString &);
public:
void setupHooks(DiscoveryJob* discoveryJob, const QString &pathPrefix);
};
+80
Ver Arquivo
@@ -0,0 +1,80 @@
/*
* Copyright (C) by Christian Kamm <mail@ckamm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "excludedfiles.h"
#include <QFileInfo>
#include <QReadLocker>
#include <QWriteLocker>
extern "C" {
#include "std/c_string.h"
#include "csync.h"
#include "csync_exclude.h"
}
using namespace OCC;
ExcludedFiles::ExcludedFiles()
: _excludes(NULL)
{
}
ExcludedFiles::~ExcludedFiles()
{
c_strlist_destroy(_excludes);
}
ExcludedFiles& ExcludedFiles::instance()
{
static ExcludedFiles inst;
return inst;
}
void ExcludedFiles::addExcludeFilePath(const QString& path)
{
QWriteLocker locker(&_mutex);
_excludeFiles.append(path);
}
void ExcludedFiles::reloadExcludes()
{
QWriteLocker locker(&_mutex);
c_strlist_destroy(_excludes);
_excludes = NULL;
foreach (const QString& file, _excludeFiles) {
csync_exclude_load(file.toUtf8(), &_excludes);
}
}
CSYNC_EXCLUDE_TYPE ExcludedFiles::isExcluded(
const QString& fullPath,
const QString& relativePath,
bool excludeHidden) const
{
QFileInfo fi(fullPath);
if( excludeHidden ) {
if( fi.isHidden() || fi.fileName().startsWith(QLatin1Char('.')) ) {
return CSYNC_FILE_EXCLUDE_HIDDEN;
}
}
csync_ftw_type_e type = CSYNC_FTW_TYPE_FILE;
if (fi.isDir()) {
type = CSYNC_FTW_TYPE_DIR;
}
QReadLocker lock(&_mutex);
return csync_excluded_no_ctx(_excludes, relativePath.toUtf8(), type);
}
+74
Ver Arquivo
@@ -0,0 +1,74 @@
/*
* Copyright (C) by Christian Kamm <mail@ckamm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#pragma once
#include "owncloudlib.h"
#include <QObject>
#include <QReadWriteLock>
#include <QStringList>
extern "C" {
#include "std/c_string.h"
#include "csync.h"
#include "csync_exclude.h" // for CSYNC_EXCLUDE_TYPE
}
namespace OCC {
/**
* Manages the global system and user exclude lists.
*/
class OWNCLOUDSYNC_EXPORT ExcludedFiles : public QObject
{
Q_OBJECT
public:
static ExcludedFiles & instance();
/**
* Adds a new path to a file containing exclude patterns.
*
* Does not load the file. Use reloadExcludes() afterwards.
*/
void addExcludeFilePath(const QString& path);
/**
* Checks whether a file or directory should be excluded.
*
* @param fullPath the absolute path to the file
* @param relativePath path relative to the folder
*
* For directories, the paths must not contain a trailing /.
*/
CSYNC_EXCLUDE_TYPE isExcluded(
const QString& fullPath,
const QString& relativePath,
bool excludeHidden) const;
public slots:
/**
* Reloads the exclude patterns from the registered paths.
*/
void reloadExcludes();
private:
ExcludedFiles();
~ExcludedFiles();
c_strlist_t* _excludes;
QStringList _excludeFiles;
mutable QReadWriteLock _mutex;
};
} // namespace OCC
+13 -6
Ver Arquivo
@@ -77,7 +77,7 @@ bool FileSystem::fileEquals(const QString& fn1, const QString& fn2)
do {
int r = f1.read(buffer1, BufferSize);
if (f2.read(buffer2, BufferSize) != r) {
// this should normaly not happen: the file are supposed to have the same size.
// this should normally not happen: the files are supposed to have the same size.
return false;
}
if (r <= 0) {
@@ -244,8 +244,8 @@ bool FileSystem::uncheckedRenameReplace(const QString& originFileName,
success = orig.fileEngine()->rename(destinationFileName);
// qDebug() << "Renaming " << tmpFile.fileName() << " to " << fn;
#else
// We want a rename that also overwite. QFile::rename does not overwite.
// Qt 5.1 has QSaveFile::renameOverwrite we cold use.
// We want a rename that also overwites. QFile::rename does not overwite.
// Qt 5.1 has QSaveFile::renameOverwrite we could use.
// ### FIXME
success = true;
bool destExists = fileExists(destinationFileName);
@@ -403,7 +403,7 @@ static bool fileExistsWin(const QString& filename)
}
#endif
bool FileSystem::fileExists(const QString& filename)
bool FileSystem::fileExists(const QString& filename, const QFileInfo& fileInfo)
{
#ifdef Q_OS_WIN
if (isLnkFile(filename)) {
@@ -411,8 +411,15 @@ bool FileSystem::fileExists(const QString& filename)
return fileExistsWin(filename);
}
#endif
QFileInfo file(filename);
return file.exists();
bool re = fileInfo.exists();
// if the filename is different from the filename in fileInfo, the fileInfo is
// not valid. There needs to be one initialised here. Otherwise the incoming
// fileInfo is re-used.
if( fileInfo.filePath() != filename ) {
QFileInfo myFI(filename);
re = myFI.exists();
}
return re;
}
#ifdef Q_OS_WIN
+4 -3
Ver Arquivo
@@ -18,6 +18,7 @@
#include <QString>
#include <ctime>
#include <QCryptographicHash>
#include <QFileInfo>
#include <owncloudlib.h>
@@ -73,7 +74,7 @@ qint64 OWNCLOUDSYNC_EXPORT getSize(const QString& filename);
* Use this over QFileInfo::exists() and QFile::exists() to avoid bugs with lnk
* files, see above.
*/
bool OWNCLOUDSYNC_EXPORT fileExists(const QString& filename);
bool OWNCLOUDSYNC_EXPORT fileExists(const QString& filename, const QFileInfo& = QFileInfo() );
/**
* @brief Rename the file \a originFileName to \a destinationFileName.
@@ -85,7 +86,7 @@ bool OWNCLOUDSYNC_EXPORT rename(const QString& originFileName,
QString* errorString = NULL);
/**
* @brief Check if \a fileName chas changed given previous size and mtime
* @brief Check if \a fileName has changed given previous size and mtime
*
* Nonexisting files are covered through mtime: they have an mtime of -1.
*
@@ -131,7 +132,7 @@ bool uncheckedRenameReplace(const QString &originFileName,
* Replacement for QFile::open(ReadOnly) followed by a seek().
* This version sets a more permissive sharing mode on Windows.
*
* Warning: The resuting file may have an empty fileName and be unsuitable for use
* Warning: The resulting file may have an empty fileName and be unsuitable for use
* with QFileInfo! Calling seek() on the QFile with >32bit signed values will fail!
*/
bool openAndSeekFileSharedRead(QFile* file, QString* error, qint64 seek);
+24 -2
Ver Arquivo
@@ -17,6 +17,7 @@
#include <QDir>
#include <QStringList>
#include <QThread>
#include <qmetaobject.h>
namespace OCC {
@@ -40,7 +41,10 @@ static void mirallLogCatcher(QtMsgType, const QMessageLogContext &ctx, const QSt
}
#else
static void mirallLogCatcher(QtMsgType type, const QMessageLogContext &ctx, const QString &message) {
Logger::instance()->doLog( qFormatLogMessage(type, ctx, message) ) ;
auto logger = Logger::instance();
if (!logger->isNoop()) {
logger->doLog( qFormatLogMessage(type, ctx, message) ) ;
}
}
#endif
@@ -105,6 +109,24 @@ void Logger::log(Log log)
doLog(msg);
}
/**
* Returns true if doLog does nothing and need not to be called
*/
bool Logger::isNoop() const
{
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
return false;
#else
static auto signal = QMetaMethod::fromSignal(&Logger::newLog);
if (isSignalConnected(signal)) {
return false;
}
QMutexLocker lock(const_cast<QMutex *>(&_mutex));
return !_logstream;
#endif
}
void Logger::doLog(const QString& msg)
{
{
@@ -193,7 +215,7 @@ void Logger::enterNextLogFile()
dir.mkpath(".");
}
// Find out what is the file with the highest nymber if any
// Find out what is the file with the highest number if any
QStringList files = dir.entryList(QStringList("owncloud.log.*"),
QDir::Files);
QRegExp rx("owncloud.log.(\\d+)");
+1
Ver Arquivo
@@ -46,6 +46,7 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject
Q_OBJECT
public:
bool isNoop() const;
void log(Log log);
void doLog(const QString &log);
+12 -7
Ver Arquivo
@@ -46,11 +46,16 @@ RequestEtagJob::RequestEtagJob(AccountPtr account, const QString &path, QObject
void RequestEtagJob::start()
{
QNetworkRequest req;
// Let's always request all entries inside a directory. There are/were bugs in the server
// where a root or root-folder ETag is not updated when its contents change. We work around
// this by concatenating the ETags of the root and its contents.
req.setRawHeader("Depth", "1");
// See https://github.com/owncloud/core/issues/5255 and others
if (_account && _account->rootEtagChangesNotOnlySubFolderEtags()) {
// Fixed from 8.1 https://github.com/owncloud/client/issues/3730
req.setRawHeader("Depth", "0");
} else {
// Let's always request all entries inside a directory. There are/were bugs in the server
// where a root or root-folder ETag is not updated when its contents change. We work around
// this by concatenating the ETags of the root and its contents.
req.setRawHeader("Depth", "1");
// See https://github.com/owncloud/core/issues/5255 and others
}
QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"
@@ -311,7 +316,7 @@ void LsColJob::start()
// TODO: Instead of doing all in this slot, we should iteratively parse in readyRead(). This
// would allow us to be more asynchronous in processing while data is coming from the network,
// not in all in one big blobb at the end.
// not all in one big blob at the end.
bool LsColJob::finished()
{
QString contentType = reply()->header(QNetworkRequest::ContentTypeHeader).toString();
@@ -432,7 +437,7 @@ bool CheckServerJob::finished()
mergeSslConfigurationForSslButton(reply()->sslConfiguration(), account());
// The serverInstalls to /owncloud. Let's try that if the file wasn't found
// The server installs to /owncloud. Let's try that if the file wasn't found
// at the original location
if ((reply()->error() == QNetworkReply::ContentNotFoundError) && (!_subdirFallback)) {
_subdirFallback = true;

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais