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_MAJOR 2 )
set( MIRALL_VERSION_MINOR 0 ) set( MIRALL_VERSION_MINOR 1 )
set( MIRALL_VERSION_PATCH 2 ) set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_SOVERSION 0 ) set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX ) 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 ) endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
if( NOT DEFINED MIRALL_VERSION_BUILD ) 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) AND NOT CMAKE_CROSSCOMPILING)
if (EXISTS "/etc/debian_version") # is this a debian system ? if (EXISTS "/etc/debian_version") # is this a debian system ?
if(CMAKE_LIBRARY_ARCHITECTURE) if(CMAKE_LIBRARY_ARCHITECTURE)
if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$") set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
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()
endif() endif()
else() # not debian, rely on CMAKE_SIZEOF_VOID_P: else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
if(NOT DEFINED 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 set(csync_HDRS
${CMAKE_CURRENT_BINARY_DIR}/csync_version.h ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h
${CMAKE_CURRENT_BINARY_DIR}/../config_csync.h
csync.h csync.h
vio/csync_vio.h
vio/csync_vio_method.h
vio/csync_vio_module.h
) )
# Statically include sqlite # Statically include sqlite
@@ -142,12 +140,18 @@ else()
RUNTIME DESTINATION RUNTIME DESTINATION
${BIN_INSTALL_DIR}/${APPLICATION_EXECUTABLE} ${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() 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: 1. Edit these Registry keys:
a. (32-bit) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud`` a. (32-bit-Windows) ``HKEY_LOCAL_MACHINE\Software\ownCloud\ownCloud``
b. (64-bit) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud`` b. (64-bit-Windows) ``HKEY_LOCAL_MACHINE\Software\Wow6432Node\ownCloud\ownCloud``
2. Add the key ``skipUpdateCheck`` (of type DWORD). 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) 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) 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}) #---OVERLAY PLUGIN---
install(FILES ownclouddolphinplugin.desktop DESTINATION ${SERVICES_INSTALL_DIR}) kcoreaddons_add_plugin(ownclouddolphinoverlayplugin INSTALL_NAMESPACE "kf5/overlayicon"
install(TARGETS ownclouddolphinplugin DESTINATION ${PLUGIN_INSTALL_DIR}) 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 @@
- Recompile and install recent enough version of dolphin and kio (git from oct 2015)
- 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
- Build and install the plugin - Build and install the plugin
- After installing, run - Make sure to set XDG_DATA_DIRS=$PREFIX/share, QT_PLUGIN_PATH=$PREFIX/lib64/plugins/
kdeinit4 --noincremental
- To test that the plugin is well installed - After installing, run
ktraderclient --servicetype KOverlayIconPlugin kdeinit5 --noincremental
It should show the Owncloud plugin
- restart dolphin (make sure to kill all instances) - 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() endif()
add_subdirectory(libsync) add_subdirectory(libsync)
add_subdirectory(libclient)
if (NOT BUILD_LIBRARIES_ONLY) if (NOT BUILD_LIBRARIES_ONLY)
add_subdirectory(gui) add_subdirectory(gui)
add_subdirectory(cmd) add_subdirectory(cmd)
+7 -5
Ver Arquivo
@@ -42,6 +42,8 @@
#include <termios.h> #include <termios.h>
#endif #endif
#include <csync_private.h>
using namespace OCC; using namespace OCC;
struct CmdOptions { struct CmdOptions {
@@ -114,11 +116,11 @@ public:
_sslTrusted(false) _sslTrusted(false)
{} {}
QString queryPassword(bool *ok, const QString&) Q_DECL_OVERRIDE { void askFromUser() Q_DECL_OVERRIDE {
if (ok) { _password = ::queryPassword(user());
*ok = true; _ready = true;
} persist();
return ::queryPassword(user()); emit asked();
} }
void setSSLTrusted( bool isTrusted ) { void setSSLTrusted( bool isTrusted ) {
+3 -3
Ver Arquivo
@@ -72,7 +72,6 @@ set(client_SRCS
creds/httpcredentialsgui.cpp creds/httpcredentialsgui.cpp
creds/shibbolethcredentials.cpp creds/shibbolethcredentials.cpp
creds/shibboleth/shibbolethwebview.cpp creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethrefresher.cpp
creds/shibboleth/shibbolethuserjob.cpp creds/shibboleth/shibbolethuserjob.cpp
wizard/abstractcredswizardpage.cpp wizard/abstractcredswizardpage.cpp
wizard/owncloudadvancedsetuppage.cpp wizard/owncloudadvancedsetuppage.cpp
@@ -98,6 +97,7 @@ IF( APPLE )
list(APPEND client_SRCS settingsdialogmac.cpp) list(APPEND client_SRCS settingsdialogmac.cpp)
list(APPEND client_SRCS socketapisocket_mac.mm) list(APPEND client_SRCS socketapisocket_mac.mm)
list(APPEND client_SRCS systray.mm) list(APPEND client_SRCS systray.mm)
list(APPEND client_SRCS clipboard.mm)
if(SPARKLE_FOUND) if(SPARKLE_FOUND)
# Define this, we need to check in updater.cpp # Define this, we need to check in updater.cpp
@@ -221,7 +221,7 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
endforeach( _file ) endforeach( _file )
endif(NOT WIN32) 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 # 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) if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
install(CODE " 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}) execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/admin/osx/macdeployqt.py\" ${CMAKE_INSTALL_PREFIX}/${OWNCLOUD_OSX_BUNDLE} ${QT_QMAKE_EXECUTABLE})
" COMPONENT RUNTIME) " COMPONENT RUNTIME)
endif() endif()
+3 -3
Ver Arquivo
@@ -36,13 +36,13 @@ public:
void save(bool saveCredentials = true); 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 * return true if the account was restored
*/ */
bool restore(); 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 * Typically called from the wizard
*/ */
AccountState *addAccount(const AccountPtr &newAccount); AccountState *addAccount(const AccountPtr &newAccount);
@@ -54,7 +54,7 @@ public:
/** /**
* Return a list of all accounts. * 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; } QList<AccountStatePtr> accounts() { return _accounts; }
+40 -20
Ver Arquivo
@@ -42,6 +42,7 @@
#include <QKeySequence> #include <QKeySequence>
#include <QIcon> #include <QIcon>
#include <QVariant> #include <QVariant>
#include <QToolTip>
#include <qstringlistmodel.h> #include <qstringlistmodel.h>
#include <qpropertyanimation.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(suggestExpand(QModelIndex)), ui->_folderList, SLOT(expand(QModelIndex)));
connect(_model, SIGNAL(dirtyChanged()), this, SLOT(refreshSelectiveSyncStatus())); connect(_model, SIGNAL(dirtyChanged()), this, SLOT(refreshSelectiveSyncStatus()));
refreshSelectiveSyncStatus(); refreshSelectiveSyncStatus();
connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(refreshSelectiveSyncStatus()));
QAction *resetFolderAction = new QAction(this); QAction *resetFolderAction = new QAction(this);
resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5)); resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5));
@@ -101,7 +104,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow())); connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow()));
addAction(syncNowAction); 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->selectiveSyncApply, SIGNAL(clicked()), _model, SLOT(slotApplySelectiveSync()));
connect(ui->selectiveSyncCancel, SIGNAL(clicked()), _model, SLOT(resetFolders())); connect(ui->selectiveSyncCancel, SIGNAL(clicked()), _model, SLOT(resetFolders()));
@@ -120,12 +124,8 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent) :
connect( &_quotaInfo, SIGNAL(quotaUpdated(qint64,qint64)), connect( &_quotaInfo, SIGNAL(quotaUpdated(qint64,qint64)),
this, SLOT(slotUpdateQuota(qint64,qint64))); this, SLOT(slotUpdateQuota(qint64,qint64)));
connect(ui->signInButton, SIGNAL(clicked()) , this, SLOT(slotSignInAccount()));
connect(ui->deleteButton, SIGNAL(clicked()) , this, SLOT(slotDeleteAccount())); 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() void AccountSettings::doExpand()
@@ -133,15 +133,6 @@ void AccountSettings::doExpand()
ui->_folderList->expandToDepth(0); 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) void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
{ {
QTreeView *tv = ui->_folderList; QTreeView *tv = ui->_folderList;
@@ -178,11 +169,17 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
menu->exec(tv->mapToGlobal(pos)); menu->exec(tv->mapToGlobal(pos));
} }
void AccountSettings::slotFolderActivated( const QModelIndex& indx ) void AccountSettings::slotFolderListClicked(const QModelIndex& indx)
{ {
if (indx.data(FolderStatusDelegate::AddButton).toBool() if (indx.data(FolderStatusDelegate::AddButton).toBool()) {
&& indx.flags() & Qt::ItemIsEnabled) { if (indx.flags() & Qt::ItemIsEnabled) {
slotAddFolder(); slotAddFolder();
} else {
QToolTip::showText(
QCursor::pos(),
_model->data(indx, Qt::ToolTipRole).toString(),
this);
}
return; return;
} }
if (_model->classify(indx) == FolderStatusModel::RootFolder) { if (_model->classify(indx) == FolderStatusModel::RootFolder) {
@@ -191,6 +188,13 @@ void AccountSettings::slotFolderActivated( const QModelIndex& indx )
auto pos = tv->mapFromGlobal(QCursor::pos()); auto pos = tv->mapFromGlobal(QCursor::pos());
if (FolderStatusDelegate::optionsButtonRect(tv->visualRect(indx)).contains(pos)) { if (FolderStatusDelegate::optionsButtonRect(tv->visualRect(indx)).contains(pos)) {
slotCustomContextMenuRequested(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()); 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) { if (state == AccountState::Connected) {
showConnectionLabel( tr("Connected to %1.").arg(serverWithUser) ); showConnectionLabel( tr("Connected to %1.").arg(serverWithUser) );
} else if (state == AccountState::ServiceUnavailable) { } else if (state == AccountState::ServiceUnavailable) {
@@ -511,8 +521,10 @@ void AccountSettings::refreshSelectiveSyncStatus()
bool shouldBeVisible = _model->isDirty(); bool shouldBeVisible = _model->isDirty();
QStringList undecidedFolder; QStringList undecidedFolder;
for (int i = 0; !shouldBeVisible && i < _model->rowCount(); ++i) { 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; shouldBeVisible = true;
}
} }
foreach (Folder *folder, FolderMan::instance()->map().values()) { foreach (Folder *folder, FolderMan::instance()->map().values()) {
@@ -554,6 +566,11 @@ void AccountSettings::refreshSelectiveSyncStatus()
} }
} }
void AccountSettings::slotSignInAccount()
{
_accountState->setSignedOut(false);
}
void AccountSettings::slotDeleteAccount() void AccountSettings::slotDeleteAccount()
{ {
// Deleting the account potentially deletes 'this', so // 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) { if (e->type() == QEvent::Hide || e->type() == QEvent::Show) {
_quotaInfo.setActive(isVisible()); _quotaInfo.setActive(isVisible());
} }
if (e->type() == QEvent::Show) {
ui->_folderList->setExpanded(_model->index(0, 0), true);
}
return QWidget::event(e); return QWidget::event(e);
} }
+1 -1
Ver Arquivo
@@ -61,7 +61,6 @@ signals:
void openFolderAlias( const QString& ); void openFolderAlias( const QString& );
public slots: public slots:
void slotFolderActivated( const QModelIndex& );
void slotOpenOC(); void slotOpenOC();
void slotUpdateQuota( qint64,qint64 ); void slotUpdateQuota( qint64,qint64 );
void slotAccountStateChanged(int state); void slotAccountStateChanged(int state);
@@ -77,6 +76,7 @@ protected slots:
void slotOpenCurrentFolder(); void slotOpenCurrentFolder();
void slotFolderWizardAccepted(); void slotFolderWizardAccepted();
void slotFolderWizardRejected(); void slotFolderWizardRejected();
void slotSignInAccount();
void slotDeleteAccount(); void slotDeleteAccount();
void refreshSelectiveSyncStatus(); void refreshSelectiveSyncStatus();
void slotCustomContextMenuRequested(const QPoint&); void slotCustomContextMenuRequested(const QPoint&);
+16
Ver Arquivo
@@ -61,6 +61,22 @@
</property> </property>
</widget> </widget>
</item> </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> <item>
<widget class="QPushButton" name="deleteButton"> <widget class="QPushButton" name="deleteButton">
<property name="sizePolicy"> <property name="sizePolicy">
+39 -10
Ver Arquivo
@@ -15,6 +15,7 @@
#include "accountmanager.h" #include "accountmanager.h"
#include "account.h" #include "account.h"
#include "creds/abstractcredentials.h" #include "creds/abstractcredentials.h"
#include "logger.h"
#include <QDebug> #include <QDebug>
#include <QSettings> #include <QSettings>
@@ -28,6 +29,7 @@ AccountState::AccountState(AccountPtr account)
, _state(AccountState::Disconnected) , _state(AccountState::Disconnected)
, _connectionStatus(ConnectionValidator::Undefined) , _connectionStatus(ConnectionValidator::Undefined)
, _waitingForNewCredentials(false) , _waitingForNewCredentials(false)
, _credentialsFetchMode(Interactive)
{ {
qRegisterMetaType<AccountState*>("AccountState*"); qRegisterMetaType<AccountState*>("AccountState*");
@@ -35,6 +37,8 @@ AccountState::AccountState(AccountPtr account)
SLOT(slotInvalidCredentials())); SLOT(slotInvalidCredentials()));
connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)), connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)),
SLOT(slotCredentialsFetched(AbstractCredentials*))); SLOT(slotCredentialsFetched(AbstractCredentials*)));
connect(account.data(), SIGNAL(credentialsAsked(AbstractCredentials*)),
SLOT(slotCredentialsAsked(AbstractCredentials*)));
} }
AccountState::~AccountState() AccountState::~AccountState()
@@ -79,7 +83,7 @@ void AccountState::setState(State state)
_connectionStatus = ConnectionValidator::Undefined; _connectionStatus = ConnectionValidator::Undefined;
_connectionErrors.clear(); _connectionErrors.clear();
} else if (oldState == SignedOut && _state == Disconnected) { } else if (oldState == SignedOut && _state == Disconnected) {
checkConnectivity(); checkConnectivity(Interactive);
} }
} }
@@ -131,7 +135,7 @@ bool AccountState::isConnectedOrTemporarilyUnavailable() const
return isConnected() || _state == ServiceUnavailable; return isConnected() || _state == ServiceUnavailable;
} }
void AccountState::checkConnectivity() void AccountState::checkConnectivity(CredentialFetchMode credentialsFetchMode)
{ {
if (isSignedOut() || _waitingForNewCredentials) { if (isSignedOut() || _waitingForNewCredentials) {
return; return;
@@ -141,6 +145,7 @@ void AccountState::checkConnectivity()
qDebug() << "ConnectionValidator already running, ignoring"; qDebug() << "ConnectionValidator already running, ignoring";
return; return;
} }
_credentialsFetchMode = credentialsFetchMode;
ConnectionValidator * conValidator = new ConnectionValidator(account()); ConnectionValidator * conValidator = new ConnectionValidator(account());
_connectionValidator = conValidator; _connectionValidator = conValidator;
connect(conValidator, SIGNAL(connectionResult(ConnectionValidator::Status,QStringList)), 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. // much more likely, so keep trying to connect.
setState(NetworkError); setState(NetworkError);
break; break;
case ConnectionValidator::CredentialsWrong: case ConnectionValidator::CredentialsMissingOrWrong:
account()->handleInvalidCredentials(); slotInvalidCredentials();
break; break;
case ConnectionValidator::UserCanceledCredentials: case ConnectionValidator::UserCanceledCredentials:
setState(SignedOut); setState(SignedOut);
@@ -219,15 +224,41 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
void AccountState::slotInvalidCredentials() void AccountState::slotInvalidCredentials()
{ {
if (isSignedOut()) { if (isSignedOut() || _waitingForNewCredentials)
return; return;
}
if (account()->credentials()->ready())
account()->credentials()->invalidateToken();
account()->credentials()->fetchFromKeychain();
setState(ConfigurationError); setState(ConfigurationError);
_waitingForNewCredentials = true; _waitingForNewCredentials = true;
} }
void AccountState::slotCredentialsFetched(AbstractCredentials* credentials) 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; _waitingForNewCredentials = false;
@@ -239,11 +270,9 @@ void AccountState::slotCredentialsFetched(AbstractCredentials* credentials)
// When new credentials become available we always want to restart the // When new credentials become available we always want to restart the
// connection validation, even if it's currently running. // connection validation, even if it's currently running.
if (_connectionValidator) { delete _connectionValidator;
delete _connectionValidator;
}
checkConnectivity(); checkConnectivity(_credentialsFetchMode);
} }
std::unique_ptr<QSettings> AccountState::settings() std::unique_ptr<QSettings> AccountState::settings()
+5 -2
Ver Arquivo
@@ -19,6 +19,7 @@
#include <QPointer> #include <QPointer>
#include "utility.h" #include "utility.h"
#include "connectionvalidator.h" #include "connectionvalidator.h"
#include "creds/abstractcredentials.h"
#include <memory> #include <memory>
class QSettings; class QSettings;
@@ -27,7 +28,6 @@ namespace OCC {
class AccountState; class AccountState;
class Account; class Account;
class AbstractCredentials;
/** /**
* @brief Extra info about an ownCloud server account. * @brief Extra info about an ownCloud server account.
@@ -59,6 +59,7 @@ public:
/// An error like invalid credentials where retrying won't help. /// An error like invalid credentials where retrying won't help.
ConfigurationError ConfigurationError
}; };
enum CredentialFetchMode { Interactive, NonInteractive };
/// The actual current connectivity status. /// The actual current connectivity status.
typedef ConnectionValidator::Status ConnectionStatus; typedef ConnectionValidator::Status ConnectionStatus;
@@ -84,7 +85,7 @@ public:
/// Triggers a ping to the server to update state and /// Triggers a ping to the server to update state and
/// connection status and errors. /// connection status and errors.
void checkConnectivity(); void checkConnectivity(CredentialFetchMode credentialsFetchMode);
/** Returns a new settings object for this account, already in the right groups. */ /** Returns a new settings object for this account, already in the right groups. */
std::unique_ptr<QSettings> settings(); std::unique_ptr<QSettings> settings();
@@ -104,6 +105,7 @@ protected Q_SLOTS:
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors); void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList& errors);
void slotInvalidCredentials(); void slotInvalidCredentials();
void slotCredentialsFetched(AbstractCredentials* creds); void slotCredentialsFetched(AbstractCredentials* creds);
void slotCredentialsAsked(AbstractCredentials* creds);
private: private:
AccountPtr _account; AccountPtr _account;
@@ -111,6 +113,7 @@ private:
ConnectionStatus _connectionStatus; ConnectionStatus _connectionStatus;
QStringList _connectionErrors; QStringList _connectionErrors;
bool _waitingForNewCredentials; bool _waitingForNewCredentials;
CredentialFetchMode _credentialsFetchMode;
QPointer<ConnectionValidator> _connectionValidator; QPointer<ConnectionValidator> _connectionValidator;
}; };
+13 -6
Ver Arquivo
@@ -35,6 +35,7 @@
#include "accountmanager.h" #include "accountmanager.h"
#include "creds/abstractcredentials.h" #include "creds/abstractcredentials.h"
#include "updater/ocupdater.h" #include "updater/ocupdater.h"
#include "excludedfiles.h"
#include "config.h" #include "config.h"
@@ -103,7 +104,7 @@ Application::Application(int &argc, char **argv) :
{ {
_startedAt.start(); _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)); // setOrganizationName(QLatin1String(APPLICATION_VENDOR));
setOrganizationDomain(QLatin1String(APPLICATION_REV_DOMAIN)); setOrganizationDomain(QLatin1String(APPLICATION_REV_DOMAIN));
setApplicationName( _theme->appNameGUI() ); setApplicationName( _theme->appNameGUI() );
@@ -135,6 +136,13 @@ Application::Application(int &argc, char **argv) :
setupLogging(); setupLogging();
setupTranslations(); 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); _folderManager.reset(new FolderMan);
connect(this, SIGNAL(messageReceived(QString, QObject*)), SLOT(slotParseMessage(QString, QObject*))); connect(this, SIGNAL(messageReceived(QString, QObject*)), SLOT(slotParseMessage(QString, QObject*)));
@@ -145,7 +153,6 @@ Application::Application(int &argc, char **argv) :
setQuitOnLastWindowClosed(false); setQuitOnLastWindowClosed(false);
ConfigFile cfg;
_theme->setSystrayUseMonoIcons(cfg.monoIcons()); _theme->setSystrayUseMonoIcons(cfg.monoIcons());
connect (_theme, SIGNAL(systrayUseMonoIconsChanged(bool)), SLOT(slotUseMonoIconsChanged(bool))); 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())); connect(&_checkConnectionTimer, SIGNAL(timeout()), this, SLOT(slotCheckConnection()));
_checkConnectionTimer.setInterval(32 * 1000); // check for connection every 32 seconds. _checkConnectionTimer.setInterval(32 * 1000); // check for connection every 32 seconds.
_checkConnectionTimer.start(); _checkConnectionTimer.start();
// Also check immediatly // Also check immediately
QTimer::singleShot( 0, this, SLOT( slotCheckConnection() )); QTimer::singleShot( 0, this, SLOT( slotCheckConnection() ));
// Update checks // Update checks
@@ -237,7 +244,7 @@ void Application::slotCheckConnection()
// when the error is permanent. // when the error is permanent.
if (state != AccountState::SignedOut if (state != AccountState::SignedOut
&& state != AccountState::ConfigurationError) { && state != AccountState::ConfigurationError) {
accountState->checkConnectivity(); accountState->checkConnectivity(AccountState::NonInteractive);
} }
} }
@@ -444,7 +451,7 @@ void Application::setHelp()
QString substLang(const QString &lang) 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 // to country codes as used by Qt and
// transifex translation conventions. // transifex translation conventions.
@@ -486,7 +493,7 @@ void Application::setupTranslations()
// Permissive approach: Qt and keychain translations // Permissive approach: Qt and keychain translations
// may be missing, but Qt translations must be there in order // may be missing, but Qt translations must be there in order
// for us to accept the language. Otherwise, we try with the next. // 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. // have a translation file provided.
qDebug() << Q_FUNC_INFO << "Using" << lang << "translation"; qDebug() << Q_FUNC_INFO << "Using" << lang << "translation";
setProperty("ui_lang", lang); 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 namespace OCC
{ {
QString HttpCredentialsGui::queryPassword(bool *ok, const QString& hint) void HttpCredentialsGui::askFromUser()
{ {
if (!ok) { // The rest of the code assumes that this will be done asynchronously
return QString(); QMetaObject::invokeMethod(this, "askFromUserAsync", Qt::QueuedConnection);
} }
void HttpCredentialsGui::askFromUserAsync()
{
QString msg = tr("Please enter %1 password:\n" QString msg = tr("Please enter %1 password:\n"
"\n" "\n"
"User: %2\n" "User: %2\n"
"Account: %3\n") "Account: %3\n")
.arg(Theme::instance()->appNameGUI(), _user, _account->displayName()); .arg(Theme::instance()->appNameGUI(), _user, _account->displayName());
if (!hint.isEmpty()) { if (!_fetchErrorString.isEmpty()) {
msg += QLatin1String("\n") + hint + QLatin1String("\n"); 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, QLineEdit::Password, _previousPassword,
ok); &ok);
if (ok) {
_password = pwd;
_ready = true;
persist();
}
emit asked();
} }
} // namespace OCC } // namespace OCC
+2 -1
Ver Arquivo
@@ -28,7 +28,8 @@ class HttpCredentialsGui : public HttpCredentials {
public: public:
explicit HttpCredentialsGui() : HttpCredentials() {} explicit HttpCredentialsGui() : HttpCredentials() {}
HttpCredentialsGui(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd) : HttpCredentials(user, password, certificatePath, certificatePasswd) {} 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 } // 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. * for more details.
*/ */
#include <QMutex>
#include <QSettings> #include <QSettings>
#include <QNetworkReply> #include <QNetworkReply>
#include <QMessageBox> #include <QMessageBox>
@@ -21,7 +20,6 @@
#include "creds/shibbolethcredentials.h" #include "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethwebview.h" #include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibbolethcredentials.h" #include "creds/shibbolethcredentials.h"
#include "shibboleth/shibbolethuserjob.h" #include "shibboleth/shibbolethuserjob.h"
#include "creds/credentialscommon.h" #include "creds/credentialscommon.h"
@@ -46,39 +44,6 @@ namespace
const char userC[] = "shib_user"; const char userC[] = "shib_user";
const char shibCookieNameC[] = "_shibsession_"; 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 } // ns
ShibbolethCredentials::ShibbolethCredentials() ShibbolethCredentials::ShibbolethCredentials()
@@ -86,14 +51,12 @@ ShibbolethCredentials::ShibbolethCredentials()
_url(), _url(),
_ready(false), _ready(false),
_stillValid(false), _stillValid(false),
_fetchJobInProgress(false),
_browser(0) _browser(0)
{} {}
ShibbolethCredentials::ShibbolethCredentials(const QNetworkCookie& cookie) ShibbolethCredentials::ShibbolethCredentials(const QNetworkCookie& cookie)
: _ready(true), : _ready(true),
_stillValid(true), _stillValid(true),
_fetchJobInProgress(false),
_browser(0), _browser(0),
_shibCookie(cookie) _shibCookie(cookie)
{ {
@@ -130,12 +93,7 @@ QByteArray ShibbolethCredentials::prepareCookieData() const
void ShibbolethCredentials::syncContextPreStart (CSYNC* ctx) 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, "session_key", prepareCookieData().data());
csync_set_module_property(ctx, "redirect_callback", &cb);
} }
bool ShibbolethCredentials::changed(AbstractCredentials* credentials) const bool ShibbolethCredentials::changed(AbstractCredentials* credentials) const
@@ -191,17 +149,12 @@ bool ShibbolethCredentials::ready() const
return _ready; return _ready;
} }
void ShibbolethCredentials::fetch() void ShibbolethCredentials::fetchFromKeychain()
{ {
if(_fetchJobInProgress) {
return;
}
if (_user.isEmpty()) { if (_user.isEmpty()) {
_user = _account->credentialSetting(QLatin1String(userC)).toString(); _user = _account->credentialSetting(QLatin1String(userC)).toString();
} }
if (_ready) { if (_ready) {
_fetchJobInProgress = false;
Q_EMIT fetched(); Q_EMIT fetched();
} else { } else {
_url = _account->url(); _url = _account->url();
@@ -211,10 +164,14 @@ void ShibbolethCredentials::fetch()
job->setKey(keychainKey(_account->url().toString(), "shibAssertion")); job->setKey(keychainKey(_account->url().toString(), "shibAssertion"));
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*))); connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start(); job->start();
_fetchJobInProgress = true;
} }
} }
void ShibbolethCredentials::askFromUser()
{
showLoginWindow();
}
bool ShibbolethCredentials::stillValid(QNetworkReply *reply) bool ShibbolethCredentials::stillValid(QNetworkReply *reply)
{ {
Q_UNUSED(reply) Q_UNUSED(reply)
@@ -229,9 +186,10 @@ void ShibbolethCredentials::persist()
} }
} }
// only used by Application::slotLogout(). Use invalidateAndFetch for normal usage
void ShibbolethCredentials::invalidateToken() void ShibbolethCredentials::invalidateToken()
{ {
_ready = false;
CookieJar *jar = static_cast<CookieJar*>(_account->networkAccessManager()->cookieJar()); CookieJar *jar = static_cast<CookieJar*>(_account->networkAccessManager()->cookieJar());
// Remove the _shibCookie // Remove the _shibCookie
@@ -265,7 +223,7 @@ void ShibbolethCredentials::onShibbolethCookieReceived(const QNetworkCookie& shi
void ShibbolethCredentials::slotFetchUser() void ShibbolethCredentials::slotFetchUser()
{ {
// We must first do a request to webdav so the session is enabled. // 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); EntityExistsJob* job = new EntityExistsJob(_account->sharedFromThis(), _account->davPath(), this);
connect(job, SIGNAL(exists(QNetworkReply*)), this, SLOT(slotFetchUserHelper())); connect(job, SIGNAL(exists(QNetworkReply*)), this, SLOT(slotFetchUserHelper()));
job->setIgnoreCredentialFailure(true); job->setIgnoreCredentialFailure(true);
@@ -296,48 +254,14 @@ void ShibbolethCredentials::slotUserFetched(const QString &user)
_stillValid = true; _stillValid = true;
_ready = true; _ready = true;
_fetchJobInProgress = false; Q_EMIT asked();
Q_EMIT fetched();
} }
void ShibbolethCredentials::slotBrowserRejected() void ShibbolethCredentials::slotBrowserRejected()
{ {
_ready = false; _ready = false;
_fetchJobInProgress = false; Q_EMIT asked();
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());
} }
void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job) void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
@@ -355,10 +279,10 @@ void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
_ready = true; _ready = true;
_stillValid = true; _stillValid = true;
_fetchJobInProgress = false;
Q_EMIT fetched(); Q_EMIT fetched();
} else { } else {
showLoginWindow(); _ready = false;
Q_EMIT fetched();
} }
} }
+3 -9
Ver Arquivo
@@ -44,7 +44,7 @@ Q_OBJECT
public: public:
ShibbolethCredentials(); ShibbolethCredentials();
/* create a credentials for an already connected account */ /* create credentials for an already connected account */
ShibbolethCredentials(const QNetworkCookie &cookie); ShibbolethCredentials(const QNetworkCookie &cookie);
void setAccount(Account* account) Q_DECL_OVERRIDE; void setAccount(Account* account) Q_DECL_OVERRIDE;
@@ -55,7 +55,8 @@ public:
QString user() const Q_DECL_OVERRIDE; QString user() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE; QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() 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; bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE; void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE; void invalidateToken() Q_DECL_OVERRIDE;
@@ -66,15 +67,10 @@ public:
static QNetworkCookie findShibCookie(Account *, QList<QNetworkCookie> cookies = QList<QNetworkCookie>()); static QNetworkCookie findShibCookie(Account *, QList<QNetworkCookie> cookies = QList<QNetworkCookie>());
static QByteArray shibCookieName(); static QByteArray shibCookieName();
public Q_SLOTS:
void invalidateAndFetch() Q_DECL_OVERRIDE;
private Q_SLOTS: private Q_SLOTS:
void onShibbolethCookieReceived(const QNetworkCookie&); void onShibbolethCookieReceived(const QNetworkCookie&);
void slotBrowserRejected(); void slotBrowserRejected();
void onFetched();
void slotReadJobDone(QKeychain::Job*); void slotReadJobDone(QKeychain::Job*);
void slotInvalidateAndFetchInvalidateDone(QKeychain::Job*);
void slotReplyFinished(QNetworkReply*); void slotReplyFinished(QNetworkReply*);
void slotUserFetched(const QString& user); void slotUserFetched(const QString& user);
void slotFetchUser(); void slotFetchUser();
@@ -82,7 +78,6 @@ private Q_SLOTS:
Q_SIGNALS: Q_SIGNALS:
void newCookie(const QNetworkCookie& cookie); void newCookie(const QNetworkCookie& cookie);
void invalidatedAndFetched(const QByteArray& cookieData);
private: private:
void storeShibCookie(const QNetworkCookie &cookie); void storeShibCookie(const QNetworkCookie &cookie);
@@ -93,7 +88,6 @@ private:
bool _ready; bool _ready;
bool _stillValid; bool _stillValid;
bool _fetchJobInProgress;
QPointer<ShibbolethWebView> _browser; QPointer<ShibbolethWebView> _browser;
QNetworkCookie _shibCookie; QNetworkCookie _shibCookie;
QString _user; QString _user;
+29 -5
Ver Arquivo
@@ -30,7 +30,9 @@
#include "syncrunfilelog.h" #include "syncrunfilelog.h"
#include "theme.h" #include "theme.h"
#include "filesystem.h" #include "filesystem.h"
#include "excludedfiles.h"
#include <csync_private.h>
#include "creds/abstractcredentials.h" #include "creds/abstractcredentials.h"
@@ -88,14 +90,14 @@ Folder::Folder(const FolderDefinition& definition,
bool Folder::init() 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. // 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. // csync_owncloud will then re-encode everything.
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QUrl url = remoteUrl(); QUrl url = remoteUrl();
QString url_string = url.scheme() + QLatin1String("://") + url.authority(QUrl::EncodeDelimiters) + url.path(QUrl::FullyDecoded); QString url_string = url.scheme() + QLatin1String("://") + url.authority(QUrl::EncodeDelimiters) + url.path(QUrl::FullyDecoded);
#else #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(); QString url_string = remoteUrl().toString();
#endif #endif
url_string = Utility::toCSyncScheme(url_string); url_string = Utility::toCSyncScheme(url_string);
@@ -157,7 +159,7 @@ void Folder::checkLocalPath()
qDebug() << "Checked local path ok"; qDebug() << "Checked local path ok";
} else { } else {
// Check directory again // 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.setErrorString(tr("Local folder %1 does not exist.").arg(_definition.localPath));
_syncResult.setStatus( SyncResult::SetupError ); _syncResult.setStatus( SyncResult::SetupError );
} else if( !fi.isDir() ) { } else if( !fi.isDir() ) {
@@ -700,6 +702,28 @@ void Folder::removeFromSettings() const
settings->remove(_definition.alias); 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) 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 // 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) { 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()); journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, QStringList());
} }
emit syncStateChange(); emit syncStateChange();
// The syncFinished result that is to be triggered here makes the folderman // 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, // 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 // file system change notifications are ignored for that folder. And it takes
// some time under certain conditions to make the file system notifications // 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. /// Removes the folder from the account's settings.
void removeFromSettings() const; 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: signals:
void syncStateChange(); void syncStateChange();
void syncStarted(); void syncStarted();
+10 -22
Ver Arquivo
@@ -60,7 +60,6 @@ FolderMan::FolderMan(QObject *parent) :
_instance = this; _instance = this;
_socketApi = new SocketApi(this); _socketApi = new SocketApi(this);
_socketApi->slotReadExcludes();
ConfigFile cfg; ConfigFile cfg;
int polltime = cfg.remotePollInterval(); int polltime = cfg.remotePollInterval();
@@ -149,10 +148,6 @@ void FolderMan::registerFolderMonitor( Folder *folder )
if( !_folderWatchers.contains(folder->alias() ) ) { if( !_folderWatchers.contains(folder->alias() ) ) {
FolderWatcher *fw = new FolderWatcher(folder->path(), folder); 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, // Connect the pathChanged signal, which comes with the changed path,
// to the signal mapper which maps to the folder alias. 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); dir.setFilter(QDir::Files | QDir::Hidden);
QStringList list = dir.entryList(); 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(); AccountState* accountState = AccountManager::instance()->accounts().value(0).data();
foreach ( const QString& alias, list ) { foreach ( const QString& alias, list ) {
Folder *f = setupFolderFromOldConfigFile( alias, accountState ); Folder *f = setupFolderFromOldConfigFile( alias, accountState );
@@ -350,8 +345,8 @@ Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
qDebug() << " ` -> setting up:" << file; qDebug() << " ` -> setting up:" << file;
QString escapedAlias(file); QString escapedAlias(file);
// check the unescaped variant (for the case the filename comes out // check the unescaped variant (for the case when the filename comes out
// of the directory listing. If the file is not existing, escape the // of the directory listing). If the file does not exist, escape the
// file and try again. // file and try again.
QFileInfo cfgFile( _folderConfigPath, file); QFileInfo cfgFile( _folderConfigPath, file);
@@ -361,7 +356,7 @@ Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
cfgFile.setFile( _folderConfigPath, escapedAlias ); cfgFile.setFile( _folderConfigPath, escapedAlias );
} }
if( !cfgFile.isReadable() ) { if( !cfgFile.isReadable() ) {
qDebug() << "Can not read folder definition for alias " << cfgFile.filePath(); qDebug() << "Cannot read folder definition for alias " << cfgFile.filePath();
return folder; 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. // this is not the same as Pause and Resume of folders.
void FolderMan::setSyncEnabled( bool enabled ) void FolderMan::setSyncEnabled( bool enabled )
{ {
if (!_syncEnabled && enabled && !_scheduleQueue.isEmpty()) { 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(); startScheduledSyncSoon();
} }
_syncEnabled = enabled; _syncEnabled = enabled;
@@ -696,13 +691,6 @@ void FolderMan::slotStartScheduledFolderSync()
_currentSyncFolder = f; _currentSyncFolder = f;
f->startSync( QStringList() ); 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()); _socketApi->slotUnregisterPath(f->alias());
} }
f->journalDb()->close(); 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() if (f->accountState() && f->accountState()->account()
&& f->accountState()->account()->networkAccessManager()) { && 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( f->accountState()->account()->networkAccessManager()->setProxy(
QNetworkProxy(QNetworkProxy::DefaultProxy)); QNetworkProxy(QNetworkProxy::DefaultProxy));
} }
@@ -974,7 +962,7 @@ SyncResult FolderMan::accountStatus(const QList<Folder*> &folders)
int cnt = folders.count(); int cnt = folders.count();
// if one folder: show the state of the one folder. // 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 of them has an error -> show error
// if one is paused, but others ok, show ok // if one is paused, but others ok, show ok
// do not show "problem" in the tray // do not show "problem" in the tray
@@ -1091,7 +1079,7 @@ QString FolderMan::statusToString( SyncResult syncStatus, bool paused ) const
folderMessage = tr( "Undefined State." ); folderMessage = tr( "Undefined State." );
break; break;
case SyncResult::NotYetStarted: case SyncResult::NotYetStarted:
folderMessage = tr( "Waits to start syncing." ); folderMessage = tr( "Waiting to start syncing." );
break; break;
case SyncResult::SyncPrepare: case SyncResult::SyncPrepare:
folderMessage = tr( "Preparing for sync." ); 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. * 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. * \a forNewDirectory is internal and is used for recursion.
* *
@@ -123,7 +123,7 @@ signals:
/** /**
* signal to indicate a folder has changed its sync state. * 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*); void folderSyncStateChange(Folder*);
@@ -162,7 +162,7 @@ public slots:
// slot to add a folder to the syncing queue // slot to add a folder to the syncing queue
void slotScheduleSync(Folder*); void slotScheduleSync(Folder*);
// slot to scheule an ETag job // slot to schedule an ETag job
void slotScheduleETagJob ( const QString &alias, RequestEtagJob *job); void slotScheduleETagJob ( const QString &alias, RequestEtagJob *job);
void slotEtagJobDestroyed (QObject*); void slotEtagJobDestroyed (QObject*);
void slotRunOneEtagJob(); void slotRunOneEtagJob();
+1 -1
Ver Arquivo
@@ -33,7 +33,7 @@ QString FolderStatusDelegate::addFolderText()
return tr("Add Folder Sync Connection"); return tr("Add Folder Sync Connection");
} }
//alocate each item size in listview. // allocate each item size in listview.
QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option , QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option ,
const QModelIndex & index) const const QModelIndex & index) const
{ {
+115 -48
Ver Arquivo
@@ -90,7 +90,7 @@ Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex &index ) const
} }
return Qt::ItemIsEnabled | ret; return Qt::ItemIsEnabled | ret;
} }
case ErrorLabel: case FetchLabel:
return Qt::ItemIsEnabled return Qt::ItemIsEnabled
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
| Qt::ItemNeverHasChildren | Qt::ItemNeverHasChildren
@@ -123,7 +123,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
auto remotePath = _folders.at(0)._folder->remotePath(); auto remotePath = _folders.at(0)._folder->remotePath();
if (remotePath.isEmpty() || remotePath == QLatin1String("/")) { if (remotePath.isEmpty() || remotePath == QLatin1String("/")) {
// Syncing the entire owncloud: disable the add folder button (#3438) // 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 " "If you want to sync multiple folders, please remove the currently "
"configured root folder."); "configured root folder.");
} }
@@ -151,11 +151,20 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
} }
} }
return QVariant(); return QVariant();
case ErrorLabel: case FetchLabel:
{
const auto x = static_cast<SubFolderInfo *>(index.internalPointer());
switch(role) { 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(); default: return QVariant();
} }
}
case RootFolder: case RootFolder:
break; break;
} }
@@ -192,7 +201,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
} else if( status == SyncResult::Undefined ) { } else if( status == SyncResult::Undefined ) {
return theme->syncStateIcon( SyncResult::SyncRunning); return theme->syncStateIcon( SyncResult::SyncRunning);
} else { } else {
// kepp the previous icon for the prepare phase. // keep the previous icon for the prepare phase.
if( status == SyncResult::Problem) { if( status == SyncResult::Problem) {
return theme->syncStateIcon( SyncResult::Success); return theme->syncStateIcon( SyncResult::Success);
} else { } else {
@@ -227,7 +236,7 @@ bool FolderStatusModel::setData(const QModelIndex& index, const QVariant& value,
info->_checked = checked; info->_checked = checked;
if (checked == Qt::Checked) { if (checked == Qt::Checked) {
// If we are checked, check that we may need to check the parent as well if // 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(); QModelIndex parent = index.parent();
auto parentInfo = infoForIndex(parent); auto parentInfo = infoForIndex(parent);
if (parentInfo && parentInfo->_checked != Qt::Checked) { if (parentInfo && parentInfo->_checked != Qt::Checked) {
@@ -302,7 +311,7 @@ int FolderStatusModel::rowCount(const QModelIndex& parent) const
auto info = infoForIndex(parent); auto info = infoForIndex(parent);
if (!info) if (!info)
return 0; return 0;
if (info->_hasError) if (info->hasLabel())
return 1; return 1;
return info->_subs.count(); return info->_subs.count();
} }
@@ -310,7 +319,11 @@ int FolderStatusModel::rowCount(const QModelIndex& parent) const
FolderStatusModel::ItemType FolderStatusModel::classify(const QModelIndex& index) const FolderStatusModel::ItemType FolderStatusModel::classify(const QModelIndex& index) const
{ {
if (auto sub = static_cast<SubFolderInfo*>(index.internalPointer())) { 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()) { if (index.row() < _folders.count()) {
return RootFolder; return RootFolder;
@@ -323,8 +336,7 @@ FolderStatusModel::SubFolderInfo* FolderStatusModel::infoForIndex(const QModelIn
if (!index.isValid()) if (!index.isValid())
return 0; return 0;
if (auto parentInfo = static_cast<SubFolderInfo*>(index.internalPointer())) { if (auto parentInfo = static_cast<SubFolderInfo*>(index.internalPointer())) {
if (parentInfo->_hasError) { if (parentInfo->hasLabel()) {
// Error label
return 0; return 0;
} }
return &parentInfo->_subs[index.row()]; return &parentInfo->_subs[index.row()];
@@ -384,20 +396,21 @@ QModelIndex FolderStatusModel::index(int row, int column, const QModelIndex& par
} }
switch(classify(parent)) { switch(classify(parent)) {
case AddButton: case AddButton:
case ErrorLabel: case FetchLabel:
return QModelIndex(); return QModelIndex();
case RootFolder: case RootFolder:
if (_folders.count() <= parent.row()) if (_folders.count() <= parent.row())
return QModelIndex(); // should not happen return QModelIndex(); // should not happen
return createIndex(row, column, const_cast<SubFolderInfo *>(&_folders[parent.row()])); return createIndex(row, column, const_cast<SubFolderInfo *>(&_folders[parent.row()]));
case SubFolder: { case SubFolder: {
auto info = static_cast<SubFolderInfo*>(parent.internalPointer()); auto pinfo = static_cast<SubFolderInfo*>(parent.internalPointer());
if (info->_subs.count() <= parent.row()) if (pinfo->_subs.count() <= parent.row())
return QModelIndex(); // should not happen return QModelIndex(); // should not happen
if (!info->_subs.at(parent.row())._hasError auto & info = pinfo->_subs[parent.row()];
&& info->_subs.at(parent.row())._subs.count() <= row) if (!info.hasLabel()
&& info._subs.count() <= row)
return QModelIndex(); // should not happen return QModelIndex(); // should not happen
return createIndex(row, column, &info->_subs[parent.row()]); return createIndex(row, column, &info);
} }
} }
return QModelIndex(); return QModelIndex();
@@ -413,7 +426,7 @@ QModelIndex FolderStatusModel::parent(const QModelIndex& child) const
case AddButton: case AddButton:
return QModelIndex(); return QModelIndex();
case SubFolder: case SubFolder:
case ErrorLabel: case FetchLabel:
break; break;
} }
auto pathIdx = static_cast<SubFolderInfo*>(child.internalPointer())->_pathIdx; 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 bool FolderStatusModel::canFetchMore(const QModelIndex& parent) const
{ {
if (_accountState->state() != AccountState::Connected) {
return false;
}
auto info = infoForIndex(parent); auto info = infoForIndex(parent);
if (!info || info->_fetched || info->_fetching) if (!info || info->_fetched || info->_fetching)
return false; return false;
@@ -467,7 +483,9 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
if (!info || info->_fetched || info->_fetching) if (!info || info->_fetched || info->_fetching)
return; return;
info->_hasError = false;
info->_fetching = true; info->_fetching = true;
info->_fetchingLabel = false;
QString path = info->_folder->remotePath(); QString path = info->_folder->remotePath();
if (info->_path != QLatin1String("/")) { if (info->_path != QLatin1String("/")) {
if (!path.endsWith(QLatin1Char('/'))) { if (!path.endsWith(QLatin1Char('/'))) {
@@ -483,7 +501,12 @@ void FolderStatusModel::fetchMore(const QModelIndex& parent)
connect(job, SIGNAL(finishedWithError(QNetworkReply*)), connect(job, SIGNAL(finishedWithError(QNetworkReply*)),
this, SLOT(slotLscolFinishedWithError(QNetworkReply*))); this, SLOT(slotLscolFinishedWithError(QNetworkReply*)));
job->start(); 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_) void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
@@ -496,24 +519,35 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
return; return;
} }
auto list = list_; if (parentInfo->hasLabel()) {
list.removeFirst(); // remove the parent item
if (parentInfo->_hasError) {
beginRemoveRows(idx, 0 ,0); beginRemoveRows(idx, 0 ,0);
parentInfo->_hasError = false; parentInfo->_hasError = false;
parentInfo->_fetchingLabel = false;
endRemoveRows(); 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(); QUrl url = parentInfo->_folder->remoteUrl();
QString pathToRemove = url.path(); QString pathToRemove = url.path();
if (!pathToRemove.endsWith('/')) if (!pathToRemove.endsWith('/'))
pathToRemove += '/'; pathToRemove += '/';
parentInfo->_fetched = true; // Drop the folder base path and check for excludes.
parentInfo->_fetching = false; 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; QStringList selectiveSyncBlackList;
if (parentInfo->_checked == Qt::PartiallyChecked) { if (parentInfo->_checked == Qt::PartiallyChecked) {
@@ -531,7 +565,6 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
newInfo._pathIdx << i++; newInfo._pathIdx << i++;
auto size = job ? job->_sizes.value(path) : 0; auto size = job ? job->_sizes.value(path) : 0;
newInfo._size = size; newInfo._size = size;
path.remove(pathToRemove);
newInfo._path = path; newInfo._path = path;
newInfo._name = path.split('/', QString::SkipEmptyParts).last(); newInfo._name = path.split('/', QString::SkipEmptyParts).last();
@@ -580,14 +613,17 @@ void FolderStatusModel::slotLscolFinishedWithError(QNetworkReply* r)
} }
auto parentInfo = infoForIndex(idx); auto parentInfo = infoForIndex(idx);
if (parentInfo) { if (parentInfo) {
parentInfo->_fetching = false;
if (r->error() == QNetworkReply::ContentNotFoundError) { if (r->error() == QNetworkReply::ContentNotFoundError) {
parentInfo->_fetched = true; parentInfo->_fetched = true;
} else if (!parentInfo->_hasError) { } else {
beginInsertRows(idx, 0, 0); if (!parentInfo->hasLabel()) {
beginInsertRows(idx, 0, 0);
endInsertRows();
}
parentInfo->_hasError = true; parentInfo->_hasError = true;
endInsertRows();
} }
parentInfo->_fetching = false;
parentInfo->_fetchingLabel = false;
} }
} }
@@ -661,7 +697,7 @@ void FolderStatusModel::slotApplySelectiveSync()
// clear the undecided list // clear the undecided list
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, QStringList()); 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); auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
if (folder->isBusy()) { if (folder->isBusy()) {
@@ -724,7 +760,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
<< FolderStatusDelegate::WarningCount; << FolderStatusDelegate::WarningCount;
if (!progress._currentDiscoveredFolder.isEmpty()) { 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); emit dataChanged(index(folderIndex), index(folderIndex), roles);
return; return;
} }
@@ -829,7 +865,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
.arg(currentFile).arg(totalFileCount) .arg(currentFile).arg(totalFileCount)
.arg( Utility::durationToDescriptiveString(progress.totalProgress().estimatedEta) ); .arg( Utility::durationToDescriptiveString(progress.totalProgress().estimatedEta) );
} else if (totalFileCount > 0) { } 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); overallSyncString = tr("file %1 of %2") .arg(currentFile).arg(totalFileCount);
} }
@@ -837,7 +873,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
int overallPercent = 0; int overallPercent = 0;
if( totalFileCount > 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); overallPercent = qRound(double(completedSize + completedFile)/double(totalSize + totalFileCount) * 100.0);
} }
pi->_overallPercent = qBound(0, overallPercent, 100); pi->_overallPercent = qBound(0, overallPercent, 100);
@@ -891,13 +927,8 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f)
if (i->_isDirectory && (i->_instruction == CSYNC_INSTRUCTION_NEW if (i->_isDirectory && (i->_instruction == CSYNC_INSTRUCTION_NEW
|| i->_instruction == CSYNC_INSTRUCTION_REMOVE)) { || i->_instruction == CSYNC_INSTRUCTION_REMOVE)) {
// There is a new or a removed folder. reset all data // There is a new or a removed folder. reset all data
_folders[folderIndex]._fetched = false; auto & info = _folders[folderIndex];
_folders[folderIndex]._fetching = false; info.resetSubs(this, index(folderIndex));
if (!_folders.at(folderIndex)._subs.isEmpty()) {
beginRemoveRows(index(folderIndex), 0, _folders.at(folderIndex)._subs.count() - 1);
_folders[folderIndex]._subs.clear();
endRemoveRows();
}
return; return;
} }
} }
@@ -933,17 +964,53 @@ void FolderStatusModel::slotNewBigFolder()
} }
if (folderIndex < 0) { return; } if (folderIndex < 0) { return; }
_folders[folderIndex]._fetched = false; _folders[folderIndex].resetSubs(this, index(folderIndex));
_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();
}
emit suggestExpand(index(folderIndex)); emit suggestExpand(index(folderIndex));
emit dirtyChanged(); 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 } // namespace OCC
+33 -8
Ver Arquivo
@@ -18,7 +18,7 @@
#include <accountfwd.h> #include <accountfwd.h>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QVector> #include <QVector>
#include <QElapsedTimer>
class QNetworkReply; class QNetworkReply;
namespace OCC { namespace OCC {
@@ -51,20 +51,30 @@ public:
struct SubFolderInfo { struct SubFolderInfo {
SubFolderInfo() SubFolderInfo()
: _folder(0), _size(0), _fetched(false), _fetching(false), _isUndecided(false), : _folder(0), _size(0), _fetched(false), _fetching(false),
_hasError(false), _checked(Qt::Checked) {} _hasError(false), _fetchingLabel(false), _isUndecided(false), _checked(Qt::Checked) {}
Folder *_folder; Folder *_folder;
QString _name; QString _name;
QString _path; QString _path;
QVector<int> _pathIdx; QVector<int> _pathIdx;
QVector<SubFolderInfo> _subs; QVector<SubFolderInfo> _subs;
qint64 _size; qint64 _size;
bool _fetched; // If we did the LSCOL for this folder already bool _fetched; // If we did the LSCOL for this folder already
bool _fetching; bool _fetching; // Whether a LSCOL job is currently running
bool _isUndecided; // undecided folder are the big folder that the user has not accepted yet
bool _hasError; // If the last fetching job ended in an error 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; 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 { struct Progress {
Progress() : _warningCount(0), _overallPercent(0) {} Progress() : _warningCount(0), _overallPercent(0) {}
bool isNull() const bool isNull() const
@@ -79,7 +89,7 @@ public:
QVector<SubFolderInfo> _folders; QVector<SubFolderInfo> _folders;
enum ItemType { RootFolder, SubFolder, AddButton, ErrorLabel }; enum ItemType { RootFolder, SubFolder, AddButton, FetchLabel };
ItemType classify(const QModelIndex &index) const; ItemType classify(const QModelIndex &index) const;
SubFolderInfo *infoForIndex(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. * 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; QModelIndex indexForPath(Folder *f, const QString &path) const;
@@ -105,12 +115,25 @@ private slots:
void slotFolderScheduleQueueChanged(); void slotFolderScheduleQueueChanged();
void slotNewBigFolder(); void slotNewBigFolder();
/**
* "In progress" labels for fetching data from the server are only
* added after some time to avoid popping.
*/
void slotShowFetchProgress();
private: private:
QStringList createBlackList(OCC::FolderStatusModel::SubFolderInfo* root, QStringList createBlackList(OCC::FolderStatusModel::SubFolderInfo* root,
const QStringList& oldBlackList) const; const QStringList& oldBlackList) const;
const AccountState* _accountState; const AccountState* _accountState;
bool _dirty; // If the selective sync checkboxes were changed 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) #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
//the roles argument was added in Qt5 //the roles argument was added in Qt5
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()) void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>())
@@ -119,7 +142,9 @@ private:
signals: signals:
void dirtyChanged(); 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 } // namespace OCC
+13 -75
Ver Arquivo
@@ -32,12 +32,14 @@
#include "folderwatcher_linux.h" #include "folderwatcher_linux.h"
#endif #endif
#include "excludedfiles.h"
#include "folder.h"
namespace OCC { namespace OCC {
FolderWatcher::FolderWatcher(const QString &root, QObject *parent) FolderWatcher::FolderWatcher(const QString &root, Folder* folder)
: QObject(parent), : QObject(folder),
_ignoreHidden(true) _folder(folder)
{ {
_d.reset(new FolderWatcherPrivate(this, root)); _d.reset(new FolderWatcherPrivate(this, root));
@@ -47,81 +49,17 @@ FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
FolderWatcher::~FolderWatcher() 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 ) bool FolderWatcher::pathIsIgnored( const QString& path )
{ {
if( path.isEmpty() ) return true; if( path.isEmpty() ) return true;
if( !_folder ) return false;
// if events caused by changes to hidden files should be ignored, a QFileInfo #ifndef OWNCLOUD_TEST
// object will tell us if the file is hidden if (_folder->isFileExcludedAbsolute(path)) {
if( _ignoreHidden ) { qDebug() << "* Ignoring file" << path;
QFileInfo fInfo(path); return true;
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;
}
}
} }
#endif
return false; return false;
} }
@@ -137,8 +75,8 @@ void FolderWatcher::changeDetected( const QStringList& paths )
// TODO: this shortcut doesn't look very reliable: // TODO: this shortcut doesn't look very reliable:
// - why is the timeout only 1 second? // - why is the timeout only 1 second?
// - what if there are more than one file being updated frequently? // - what if there is more than one file being updated frequently?
// - why do we skip the file alltogether instead of e.g. reducing the upload frequency? // - 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. // Check if the same path was reported within the last second.
QSet<QString> pathsSet = paths.toSet(); QSet<QString> pathsSet = paths.toSet();
+6 -22
Ver Arquivo
@@ -14,8 +14,6 @@
#ifndef MIRALL_FOLDERWATCHER_H #ifndef MIRALL_FOLDERWATCHER_H
#define MIRALL_FOLDERWATCHER_H #define MIRALL_FOLDERWATCHER_H
#include "config.h"
#include <QList> #include <QList>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
@@ -30,16 +28,17 @@ class QTimer;
namespace OCC { namespace OCC {
class FolderWatcherPrivate; 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 * Folder Watcher monitors a directory and its sub directories
* for changes in the local file system. Changes are signalled * for changes in the local file system. Changes are signalled
* through the pathChanged() signal. * through the pathChanged() signal.
* *
* Note that if new folders are created, this folderwatcher class * 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 * dirs. That is the responsibility of the user of this class to
* call addPath() with the new dir. * call addPath() with the new dir.
* *
@@ -53,23 +52,13 @@ public:
/** /**
* @param root Path of the root of the folder * @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(); 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. * Not all backends are recursive by default.
* Those need to be notified when a directory is added or removed while the watcher is disabled. * 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 addPath(const QString&);
void removePath(const QString&); void removePath(const QString&);
@@ -77,10 +66,6 @@ public:
/* Check if the path is ignored. */ /* Check if the path is ignored. */
bool pathIsIgnored( const QString& path ); bool pathIsIgnored( const QString& path );
/* set if the folderwatcher ignores events of hidden files */
void setIgnoreHidden(bool ignore);
bool ignoreHidden();
signals: signals:
/** Emitted when one of the watched directories or one /** Emitted when one of the watched directories or one
* of the contained files is changed. */ * of the contained files is changed. */
@@ -99,10 +84,9 @@ protected:
private: private:
QScopedPointer<FolderWatcherPrivate> _d; QScopedPointer<FolderWatcherPrivate> _d;
QStringList _ignores;
QTime _timer; QTime _timer;
QSet<QString> _lastPaths; QSet<QString> _lastPaths;
bool _ignoreHidden; Folder* _folder;
friend class FolderWatcherPrivate; friend class FolderWatcherPrivate;
}; };
+1 -1
Ver Arquivo
@@ -173,7 +173,7 @@ void GeneralSettings::slotAccountAddedOrRemoved()
{ {
_ui->addAccountButton->setVisible( _ui->addAccountButton->setVisible(
AccountManager::instance()->accounts().isEmpty() AccountManager::instance()->accounts().isEmpty()
|| Theme::instance()->multiAccount()); || !Theme::instance()->singleAccount());
} }
+61 -57
Ver Arquivo
@@ -53,63 +53,6 @@
<string>Advanced</string> <string>Advanced</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <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"> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>
@@ -158,6 +101,67 @@
</item> </item>
</layout> </layout>
</item> </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> </layout>
</widget> </widget>
</item> </item>
+3
Ver Arquivo
@@ -16,6 +16,7 @@
#include "ignorelisteditor.h" #include "ignorelisteditor.h"
#include "folderman.h" #include "folderman.h"
#include "ui_ignorelisteditor.h" #include "ui_ignorelisteditor.h"
#include "excludedfiles.h"
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
@@ -126,6 +127,8 @@ void IgnoreListEditor::slotUpdateLocalIgnoreList()
folder->journalDb()->forceRemoteDiscoveryNextSync(); folder->journalDb()->forceRemoteDiscoveryNextSync();
folderMan->slotScheduleSync(folder); folderMan->slotScheduleSync(folder);
} }
ExcludedFiles::instance().reloadExcludes();
} }
void IgnoreListEditor::slotAddPattern() void IgnoreListEditor::slotAddPattern()
+1 -1
Ver Arquivo
@@ -110,7 +110,7 @@ LogBrowser::LogBrowser(QWidget *parent) :
setModal(false); 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); connect(Logger::instance(), SIGNAL(newLog(QString)),this,SLOT(slotNewLog(QString)), Qt::AutoConnection);
QAction *showLogWindow = new QAction(this); 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 // Use this to do platform specific code to make overlay icons appear
// in the gui // 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() void ownCloudGui::setupOverlayIcons()
@@ -136,7 +136,7 @@ void ownCloudGui::setupOverlayIcons()
p.waitForFinished(5000); p.waitForFinished(5000);
QByteArray result = p.readAll(); QByteArray result = p.readAll();
QString resultAsString(result); // if appropriate 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); << (p.exitCode() != 0 ? p.errorString() : QString::null);
} else { } else {
qDebug() << finderExtension << "does not exist! Finder Overlay Plugin loading failed"; qDebug() << finderExtension << "does not exist! Finder Overlay Plugin loading failed";
@@ -269,7 +269,7 @@ void ownCloudGui::slotComputeOverallSyncStatus()
return; 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; QString trayMessage;
FolderMan *folderMan = FolderMan::instance(); FolderMan *folderMan = FolderMan::instance();
Folder::Map map = folderMan->map(); Folder::Map map = folderMan->map();
@@ -412,7 +412,7 @@ void ownCloudGui::setupContextMenu()
#endif #endif
} }
_contextMenu->setTitle(Theme::instance()->appNameGUI() ); _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(); } foreach (auto menu, _accountMenus) { menu->deleteLater(); }
_accountMenus.clear(); _accountMenus.clear();
if (accountList.count() > 1) { if (accountList.count() > 1) {
@@ -446,7 +446,7 @@ void ownCloudGui::setupContextMenu()
_contextMenu->addSeparator(); _contextMenu->addSeparator();
if (atLeastOneSignedIn) { if (atLeastOneSignedIn) {
if (accountList.count() > 1) { if (accountList.count() > 1) {
_actionLogout->setText(tr("Log out everywhere")); _actionLogout->setText(tr("Log out of all accounts"));
} else { } else {
_actionLogout->setText(tr("Log out")); _actionLogout->setText(tr("Log out"));
} }
@@ -454,7 +454,7 @@ void ownCloudGui::setupContextMenu()
} }
if (atLeastOneSignedOut) { if (atLeastOneSignedOut) {
if (accountList.count() > 1) { if (accountList.count() > 1) {
_actionLogin->setText(tr("Log in everywhere...")); _actionLogin->setText(tr("Log in to all accounts..."));
} else { } else {
_actionLogin->setText(tr("Log in...")); _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 ) void ownCloudGui::slotFolderOpenAction( const QString& alias )
{ {
@@ -558,7 +558,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo&
Q_UNUSED(folder); Q_UNUSED(folder);
if (!progress._currentDiscoveredFolder.isEmpty()) { if (!progress._currentDiscoveredFolder.isEmpty()) {
_actionStatus->setText( tr("Discovering '%1'") _actionStatus->setText( tr("Checking for changes in '%1'")
.arg( progress._currentDiscoveredFolder )); .arg( progress._currentDiscoveredFolder ));
} else if (progress.totalSize() == 0 ) { } else if (progress.totalSize() == 0 ) {
quint64 currentFile = progress.currentFile(); 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._lastCompletedItem.isEmpty() && !Progress::isIgnoredKind(progress._lastCompletedItem._status)) {
if (Progress::isWarningKind(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"); QIcon warnIcon(":/client/resources/warning");
_actionRecent->setIcon(warnIcon); _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() // Reset the proxy which might had been determined previously in ConnectionValidator::checkServerAndAuth()
// when there was a previous account. // when there was a previous account.
account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::DefaultProxy)); 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")); account->setCredentials(CredentialsFactory::create("dummy"));
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this); CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this);
job->setIgnoreCredentialFailure(true); job->setIgnoreCredentialFailure(true);
@@ -439,7 +439,7 @@ bool OwncloudSetupWizard::ensureStartFromScratch(const QString &localFolder) {
return renameOk; 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 ) void OwncloudSetupWizard::slotAssistantFinished( int result )
{ {
FolderMan *folderMan = FolderMan::instance(); FolderMan *folderMan = FolderMan::instance();
+1 -1
Ver Arquivo
@@ -74,7 +74,7 @@ private:
QString keychainUsernameKey() const; QString keychainUsernameKey() const;
QString keychainPasswordKey() 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. /// to a different proxy.
QString _proxy; QString _proxy;
+1 -1
Ver Arquivo
@@ -100,7 +100,7 @@ void QuotaInfo::slotCheckQuota()
void QuotaInfo::slotUpdateLastQuota(const QVariantMap &result) 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> // <d:quota-available-bytes>1374532061.2</d:quota-available-bytes>
quint64 avail = result["quota-available-bytes"].toDouble(); quint64 avail = result["quota-available-bytes"].toDouble();
_lastQuotaUsedBytes = result["quota-used-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. * 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.) * - This object is active via setActive() (typically if the settings page is visible.)
* - The account is connected. * - The account is connected.
* - Every 30 seconds (defaultIntervalT) or 5 seconds in case of failure (failIntervalT) * - 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 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 * the quota was requested was more than the interval
*/ */
void setActive(bool active); void setActive(bool active);
@@ -75,7 +75,7 @@ private:
qint64 _lastQuotaTotalBytes; qint64 _lastQuotaTotalBytes;
qint64 _lastQuotaUsedBytes; qint64 _lastQuotaUsedBytes;
QTimer _jobRestartTimer; 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) bool _active; // if we should check at regular interval (when the UI is visible)
QPointer<PropfindJob> _job; // the currently running job 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()); auto job = qobject_cast<LsColJob *>(sender());
QScopedValueRollback<bool> isInserting(_inserting); QScopedValueRollback<bool> isInserting(_inserting);
_inserting = true; _inserting = true;
@@ -174,12 +173,29 @@ void SelectiveSyncTreeView::slotUpdateDirectories(const QStringList&list)
if (!_folderPath.isEmpty()) if (!_folderPath.isEmpty())
pathToRemove.append('/'); 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 // Since / cannot be in the blacklist, expand it to the actual
// list of top-level folders as soon as possible. // list of top-level folders as soon as possible.
if (_oldBlackList == QStringList("/")) { if (_oldBlackList == QStringList("/")) {
_oldBlackList.clear(); _oldBlackList.clear();
foreach (QString path, list) { foreach (QString path, list) {
path.remove(pathToRemove);
if (path.isEmpty()) { if (path.isEmpty()) {
continue; continue;
} }
@@ -205,6 +221,11 @@ void SelectiveSyncTreeView::slotUpdateDirectories(const QStringList&list)
} else { } else {
root->setCheckState(0, Qt::PartiallyChecked); 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) { foreach (QString path, list) {
@@ -255,7 +276,7 @@ void SelectiveSyncTreeView::slotItemChanged(QTreeWidgetItem *item, int col)
if (item->checkState(0) == Qt::Checked) { if (item->checkState(0) == Qt::Checked) {
// If we are checked, check that we may need to check the parent as well if // 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(); QTreeWidgetItem *parent = item->parent();
if (parent && parent->checkState(0) != Qt::Checked) { if (parent && parent->checkState(0) != Qt::Checked) {
bool hasUnchecked = false; bool hasUnchecked = false;
+2 -2
Ver Arquivo
@@ -38,7 +38,7 @@ public:
QStringList createBlackList(QTreeWidgetItem* root = 0) const; QStringList createBlackList(QTreeWidgetItem* root = 0) const;
QStringList oldBlackList() 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); qint64 estimatedSize(QTreeWidgetItem *root = 0);
void refreshFolders(); void refreshFolders();
@@ -48,7 +48,7 @@ public:
QSize sizeHint() const Q_DECL_OVERRIDE; QSize sizeHint() const Q_DECL_OVERRIDE;
private slots: private slots:
void slotUpdateDirectories(const QStringList &); void slotUpdateDirectories(QStringList);
void slotItemExpanded(QTreeWidgetItem *); void slotItemExpanded(QTreeWidgetItem *);
void slotItemChanged(QTreeWidgetItem*,int); void slotItemChanged(QTreeWidgetItem*,int);
void slotLscolFinishedWithError(QNetworkReply*); void slotLscolFinishedWithError(QNetworkReply*);
+1 -1
Ver Arquivo
@@ -251,7 +251,7 @@ QIcon SettingsDialog::createColorAwareIcon(const QString &name)
{ {
QColor bg(palette().base().color()); QColor bg(palette().base().color());
QImage img(name); 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; double treshold = 1.0 - ( 0.299 * bg.red() + 0.587 * bg.green() + 0.114 * bg.blue())/255.0;
if (treshold > 0.5) { if (treshold > 0.5) {
img.invertPixels(QImage::InvertRgb); img.invertPixels(QImage::InvertRgb);
+1 -1
Ver Arquivo
@@ -41,7 +41,7 @@ namespace OCC {
SettingsDialogMac::SettingsDialogMac(ownCloudGui *gui, QWidget *parent) SettingsDialogMac::SettingsDialogMac(ownCloudGui *gui, QWidget *parent)
: MacPreferencesWindow(parent), _gui(gui) : 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 // dialog from minimize is broken in MacPreferencesWindow
setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint | setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint |
Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint); Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint);
+91 -9
Ver Arquivo
@@ -29,11 +29,21 @@
#include <QBuffer> #include <QBuffer>
#include <QFileIconProvider> #include <QFileIconProvider>
#include <QClipboard> #include <QClipboard>
#include <QFileInfo>
namespace { namespace {
int SHARETYPE_PUBLIC = 3; 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 { namespace OCC {
ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QString &localPath, bool resharingAllowed, QWidget *parent) : 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 setObjectName("SharingDialog"); // required as group for saveGeometry call
_ui->setupUi(this); _ui->setupUi(this);
//Is this a file or folder?
_isFile = QFileInfo(localPath).isFile();
_ui->pushButton_copy->setIcon(QIcon::fromTheme("edit-copy")); _ui->pushButton_copy->setIcon(QIcon::fromTheme("edit-copy"));
_ui->pushButton_copy->setEnabled(false); _ui->pushButton_copy->setEnabled(false);
connect(_ui->pushButton_copy, SIGNAL(clicked(bool)), SLOT(slotPushButtonCopyLinkPressed())); 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_link = new QProgressIndicator();
_pi_password = new QProgressIndicator(); _pi_password = new QProgressIndicator();
_pi_date = new QProgressIndicator(); _pi_date = new QProgressIndicator();
_pi_editing = new QProgressIndicator();
_ui->horizontalLayout_shareLink->addWidget(_pi_link); _ui->horizontalLayout_shareLink->addWidget(_pi_link);
_ui->horizontalLayout_password->addWidget(_pi_password); _ui->horizontalLayout_password->addWidget(_pi_password);
_ui->horizontalLayout_editing->addWidget(_pi_editing);
// _ui->horizontalLayout_expire->addWidget(_pi_date); // _ui->horizontalLayout_expire->addWidget(_pi_date);
connect(_ui->checkBox_shareLink, SIGNAL(clicked()), this, SLOT(slotCheckBoxShareLinkClicked())); 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->pushButton_setPassword, SIGNAL(clicked(bool)), SLOT(slotPasswordReturnPressed()));
connect(_ui->checkBox_expire, SIGNAL(clicked()), this, SLOT(slotCheckBoxExpireClicked())); connect(_ui->checkBox_expire, SIGNAL(clicked()), this, SLOT(slotCheckBoxExpireClicked()));
connect(_ui->calendar, SIGNAL(dateChanged(QDate)), SLOT(slotCalendarClicked(QDate))); connect(_ui->calendar, SIGNAL(dateChanged(QDate)), SLOT(slotCalendarClicked(QDate)));
connect(_ui->checkBox_editing, SIGNAL(clicked()), this, SLOT(slotCheckBoxEditingClicked()));
//Disable checkbox //Disable checkbox
_ui->checkBox_shareLink->setEnabled(false); _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 // check if the file is already inside of a synced folder
if( sharePath.isEmpty() ) { if( sharePath.isEmpty() ) {
// The file is not yet in an ownCloud synced folder. We could automatically // 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 // are involved in that, see https://github.com/owncloud/client/issues/2732
// //
// _ui->checkBox_shareLink->setEnabled(false); // _ui->checkBox_shareLink->setEnabled(false);
@@ -142,18 +159,27 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
// Parse capabilities // Parse capabilities
// If password is enforced make don't allow users to disable it // If password is enforced then don't allow users to disable it
if (_account->capabilities().publicLinkEnforcePassword()) { if (_account->capabilities().sharePublicLinkEnforcePassword()) {
_ui->checkBox_password->setEnabled(false); _ui->checkBox_password->setEnabled(false);
} }
// If expiredate is enforced do not allow disable and set max days // 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->checkBox_expire->setEnabled(false);
_ui->calendar->setMaximumDate(QDate::currentDate().addDays( _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 ) { void ShareDialog::done( int r ) {
@@ -224,7 +250,7 @@ void ShareDialog::slotPasswordReturnPressed()
void ShareDialog::slotPasswordChanged(const QString& newText) void ShareDialog::slotPasswordChanged(const QString& newText)
{ {
// disable the set-passwort button // disable the set-password button
_ui->pushButton_setPassword->setEnabled( newText.length() > 0 ); _ui->pushButton_setPassword->setEnabled( newText.length() > 0 );
} }
@@ -355,6 +381,17 @@ void ShareDialog::slotSharesFetched(const QVariantMap &reply)
_ui->checkBox_expire->setChecked(false); _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; QString url;
// From ownCloud server 8.2 the url field is always set for public shares // From ownCloud server 8.2 the url field is always set for public shares
if (data.contains("url")) { if (data.contains("url")) {
@@ -466,7 +503,7 @@ void ShareDialog::slotCheckBoxShareLinkClicked()
* Check the capabilities if the server requires a password for a share * Check the capabilities if the server requires a password for a share
* Ask for it directly * Ask for it directly
*/ */
if (_account->capabilities().publicLinkEnforcePassword()) { if (_account->capabilities().sharePublicLinkEnforcePassword()) {
_pi_link->stopAnimation(); _pi_link->stopAnimation();
_ui->checkBox_password->setChecked(true); _ui->checkBox_password->setChecked(true);
_ui->checkBox_password->setEnabled(false); _ui->checkBox_password->setEnabled(false);
@@ -541,7 +578,7 @@ void ShareDialog::slotCheckBoxExpireClicked()
if (_ui->checkBox_expire->checkState() == Qt::Checked) if (_ui->checkBox_expire->checkState() == Qt::Checked)
{ {
const QDate date = QDate::currentDate().addDays(1); const QDate date = QDate::currentDate().addDays(1);
ShareDialog::setExpireDate(date); setExpireDate(date);
_ui->calendar->setDate(date); _ui->calendar->setDate(date);
_ui->calendar->setMinimumDate(date); _ui->calendar->setMinimumDate(date);
_ui->calendar->setEnabled(true); _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() void ShareDialog::slotPushButtonCopyLinkPressed()
{ {
#ifdef Q_OS_MAC
copyToPasteboard(_shareUrl);
#else
QClipboard *clipboard = QApplication::clipboard(); QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(_shareUrl); 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) 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. " _ui->label_sharePath->setText(tr("A sync file with the same name exists. "
"The file cannot be registered to sync.")); "The file cannot be registered to sync."));
// TODO: Add a file comparison here. If the existing file is still the same // 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(); _sharePath.clear();
} else { } else {
_uploadFails = 0; _uploadFails = 0;
+5
Ver Arquivo
@@ -100,6 +100,8 @@ private slots:
void slotPasswordChanged(const QString& newText); void slotPasswordChanged(const QString& newText);
void slotPushButtonCopyLinkPressed(); void slotPushButtonCopyLinkPressed();
void slotThumbnailFetched(const int &statusCode, const QByteArray &reply); void slotThumbnailFetched(const int &statusCode, const QByteArray &reply);
void slotCheckBoxEditingClicked();
void slotPublicUploadSet(const QVariantMap &reply);
void done( int r ); void done( int r );
private: private:
@@ -109,6 +111,7 @@ private:
void setShareLink( const QString& url ); void setShareLink( const QString& url );
void resizeEvent(QResizeEvent *e); void resizeEvent(QResizeEvent *e);
void redrawElidedUrl(); void redrawElidedUrl();
void setPublicUpload(bool publicUpload);
Ui::ShareDialog *_ui; Ui::ShareDialog *_ui;
AccountPtr _account; AccountPtr _account;
@@ -130,8 +133,10 @@ private:
QProgressIndicator *_pi_link; QProgressIndicator *_pi_link;
QProgressIndicator *_pi_password; QProgressIndicator *_pi_password;
QProgressIndicator *_pi_date; QProgressIndicator *_pi_date;
QProgressIndicator *_pi_editing;
bool _resharingAllowed; bool _resharingAllowed;
bool _isFile;
}; };
} }
+84 -61
Ver Arquivo
@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>372</width> <width>372</width>
<height>241</height> <height>277</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -92,6 +92,84 @@
<property name="rightMargin"> <property name="rightMargin">
<number>0</number> <number>0</number>
</property> </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"> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizeConstraint"> <property name="sizeConstraint">
@@ -128,23 +206,17 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0"> <item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_password"> <layout class="QHBoxLayout" name="horizontalLayout_editing">
<item> <item>
<widget class="QCheckBox" name="checkBox_password"> <widget class="QCheckBox" name="checkBox_editing">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Set password</string> <string>Allow editing</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_3"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@@ -158,54 +230,6 @@
</item> </item>
</layout> </layout>
</item> </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> </layout>
</widget> </widget>
</item> </item>
@@ -252,7 +276,6 @@
<zorder>errorLabel</zorder> <zorder>errorLabel</zorder>
<zorder>widget_shareLink</zorder> <zorder>widget_shareLink</zorder>
<zorder>buttonBox</zorder> <zorder>buttonBox</zorder>
<zorder>checkBox_password</zorder>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>
+45 -57
Ver Arquivo
@@ -28,6 +28,8 @@
#include "version.h" #include "version.h"
#include "account.h" #include "account.h"
#include "accountstate.h" #include "accountstate.h"
#include "account.h"
#include "capabilities.h"
#include <QDebug> #include <QDebug>
#include <QUrl> #include <QUrl>
@@ -38,6 +40,7 @@
#include <QDir> #include <QDir>
#include <QApplication> #include <QApplication>
#include <QLocalSocket> #include <QLocalSocket>
#include <QStringBuilder>
#include <sqlite3.h> #include <sqlite3.h>
@@ -52,30 +55,12 @@
// The second number should be changed when there are new features. // The second number should be changed when there are new features.
#define MIRALL_SOCKET_API_VERSION "1.0" #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 { namespace OCC {
#define DEBUG qDebug() << "SocketApi: " #define DEBUG qDebug() << "SocketApi: "
SocketApi::SocketApi(QObject* parent) SocketApi::SocketApi(QObject* parent)
: QObject(parent) : QObject(parent)
, _excludes(0)
{ {
QString socketPath; QString socketPath;
@@ -141,29 +126,6 @@ SocketApi::~SocketApi()
// All remaining sockets will be destroyed with _localServer, their parent // All remaining sockets will be destroyed with _localServer, their parent
Q_ASSERT(_listeners.isEmpty() || _listeners.first()->parent() == &_localServer); Q_ASSERT(_listeners.isEmpty() || _listeners.first()->parent() == &_localServer);
_listeners.clear(); _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() void SocketApi::slotNewConnection()
@@ -268,7 +230,7 @@ void SocketApi::slotUpdateFolderView(Folder *f)
f->syncResult().status() == SyncResult::SetupError ) { f->syncResult().status() == SyncResult::SetupError ) {
broadcastMessage(QLatin1String("STATUS"), f->path() , broadcastMessage(QLatin1String("STATUS"), f->path() ,
this->fileStatus(f, "", _excludes).toSocketAPIString()); this->fileStatus(f, "").toSocketAPIString());
broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() ); broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() );
} else { } else {
@@ -311,7 +273,7 @@ void SocketApi::slotSyncItemDiscovered(const QString &folder, const SyncFileItem
QString path = f->path() + item.destination(); QString path = f->path() + item.destination();
// the trailing slash for directories must be appended as the filenames coming in // 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. // in the plugin.
if( item._type == SyncFileItem::Type::Directory ) { if( item._type == SyncFileItem::Type::Directory ) {
path += QLatin1Char('/'); path += QLatin1Char('/');
@@ -387,13 +349,12 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
statusString = QLatin1String("NOP"); statusString = QLatin1String("NOP");
} else { } else {
const QString file = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1); 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(); statusString = fileStatus.toSocketAPIString();
} }
QString message = QLatin1String("STATUS:")+statusString+QLatin1Char(':') const QString message = QLatin1String("STATUS:") % statusString % QLatin1Char(':') % QDir::toNativeSeparators(argument);
+QDir::toNativeSeparators(argument);
sendMessage(socket, message); 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)); 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) 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())); 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. * 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 file = folder->path();
QString fileName = systemFileName.normalized(QString::NormalizationForm_C); QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
@@ -558,7 +552,8 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
fileNameSlash += QLatin1Char('/'); fileNameSlash += QLatin1Char('/');
} }
if( !FileSystem::fileExists(file) ) { const QFileInfo fi(file);
if( !FileSystem::fileExists(file, fi) ) {
qDebug() << "OO File " << file << " is not existing"; qDebug() << "OO File " << file << " is not existing";
return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR); return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR);
} }
@@ -566,7 +561,6 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
// file is ignored? // file is ignored?
// Qt considers .lnk files symlinks on Windows so we need to work // Qt considers .lnk files symlinks on Windows so we need to work
// around that here. // around that here.
const QFileInfo fi(file);
if( fi.isSymLink() if( fi.isSymLink()
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
&& fi.suffix() != "lnk" && fi.suffix() != "lnk"
@@ -581,17 +575,11 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
} }
// Is it excluded? // Is it excluded?
CSYNC_EXCLUDE_TYPE excl = csync_excluded_no_ctx(excludes, fileName.toUtf8(), type); if( folder->isFileExcludedAbsolute(file) ) {
if( folder->ignoreHiddenFiles()
&& (fi.isHidden()
|| fi.fileName().startsWith(QLatin1Char('.'))) ) {
excl = CSYNC_FILE_EXCLUDE_HIDDEN;
}
if( excl != CSYNC_NOT_EXCLUDED ) {
return SyncFileStatus(SyncFileStatus::STATUS_IGNORE); 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)) { foreach(const auto &s, folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList)) {
if (fileNameSlash.startsWith(s)) { if (fileNameSlash.startsWith(s)) {
return SyncFileStatus(SyncFileStatus::STATUS_ERROR); return SyncFileStatus(SyncFileStatus::STATUS_ERROR);
+2 -8
Ver Arquivo
@@ -16,10 +16,6 @@
#ifndef SOCKETAPI_H #ifndef SOCKETAPI_H
#define SOCKETAPI_H #define SOCKETAPI_H
extern "C" {
#include <std/c_string.h>
}
#include "syncfileitem.h" #include "syncfileitem.h"
#include "syncjournalfilerecord.h" #include "syncjournalfilerecord.h"
#include "ownsql.h" #include "ownsql.h"
@@ -56,8 +52,6 @@ public slots:
void slotUpdateFolderView(Folder *f); void slotUpdateFolderView(Folder *f);
void slotUnregisterPath( const QString& alias ); void slotUnregisterPath( const QString& alias );
void slotRegisterPath( const QString& alias ); void slotRegisterPath( const QString& alias );
void slotReadExcludes();
void slotClearExcludesList();
signals: signals:
void shareCommandReceived(const QString &sharePath, const QString &localPath, bool resharingAllowed); void shareCommandReceived(const QString &sharePath, const QString &localPath, bool resharingAllowed);
@@ -70,7 +64,7 @@ private slots:
void slotSyncItemDiscovered(const QString &, const SyncFileItem &); void slotSyncItemDiscovered(const QString &, const SyncFileItem &);
private: 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 ); SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName );
SqlQuery *getSqlQuery( Folder *folder ); SqlQuery *getSqlQuery( Folder *folder );
@@ -83,12 +77,12 @@ private:
Q_INVOKABLE void command_VERSION(const QString& argument, QIODevice* socket); 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); Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QIODevice* socket);
QString buildRegisterPathMessage(const QString& path); QString buildRegisterPathMessage(const QString& path);
QList<QIODevice*> _listeners; QList<QIODevice*> _listeners;
SocketApiServer _localServer; SocketApiServer _localServer;
c_strlist_t *_excludes;
QHash<Folder*, QSharedPointer<SqlQuery>> _dbQueries; QHash<Folder*, QSharedPointer<SqlQuery>> _dbQueries;
QHash<Folder*, QSharedPointer<SqlDatabase>> _openDbs; 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 // 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 // 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 // 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(); _runningAppVersion = Utility::versionOfInstalledBinary();
} }
+4 -4
Ver Arquivo
@@ -35,15 +35,15 @@ namespace OCC {
* This class schedules regular update checks. It also checks the config * This class schedules regular update checks. It also checks the config
* if update checks are wanted at all. * 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: * complex class design was set up:
* *
* For Windows and Linux, the updaters are inherited from OCUpdater, while * For Windows and Linux, the updaters are inherited from OCUpdater, while
* the MacOSX SparkleUpdater directly uses the class Updater. On windows, * the MacOSX SparkleUpdater directly uses the class Updater. On windows,
* NSISUpdater starts the update if a new version of the client is available. * NSISUpdater starts the update if a new version of the client is available.
* On MacOSX, the sparkle framework handles the installation of the new * On MacOSX, the sparkle framework handles the installation of the new
* version. On Linux, the update capabilities by the underlying linux distro * version. On Linux, the update capabilities of the underlying linux distro
* is relied on, and thus the PassiveUpdateNotifier just shows a notification * are relied on, and thus the PassiveUpdateNotifier just shows a notification
* if there is a new version once at every start of the application. * if there is a new version once at every start of the application.
* *
* Simple class diagram of the updater: * 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 * @ingroup gui
*/ */
class OCUpdater : public QObject, public Updater class OCUpdater : public QObject, public Updater
+2 -1
Ver Arquivo
@@ -253,7 +253,7 @@ void OwncloudAdvancedSetupPage::slotSelectFolder()
void OwncloudAdvancedSetupPage::slotSelectiveSyncClicked() 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()); _ui.rSyncEverything->setChecked(_selectiveSyncBlacklist.isEmpty());
AccountPtr acc = static_cast<OwncloudWizard *>(wizard())->account(); AccountPtr acc = static_cast<OwncloudWizard *>(wizard())->account();
@@ -308,3 +308,4 @@ void OwncloudAdvancedSetupPage::slotQuotaRetrieved(const QVariantMap &result)
} }
} // namespace OCC } // 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 utility.cpp
ownsql.cpp ownsql.cpp
transmissionchecksumvalidator.cpp transmissionchecksumvalidator.cpp
excludedfiles.cpp
creds/dummycredentials.cpp creds/dummycredentials.cpp
creds/abstractcredentials.cpp creds/abstractcredentials.cpp
creds/credentialscommon.cpp creds/credentialscommon.cpp
@@ -81,14 +82,22 @@ endif(USE_NEON)
# These headers are installed for libowncloudsync to be used by 3rd party apps # These headers are installed for libowncloudsync to be used by 3rd party apps
set(owncloudsync_HEADERS set(owncloudsync_HEADERS
abstractnetworkjob.h
account.h account.h
syncengine.h syncengine.h
configfile.h configfile.h
networkjobs.h networkjobs.h
progressdispatcher.h progressdispatcher.h
syncfileitem.h syncfileitem.h
syncfilestatus.h
syncjournaldb.h syncjournaldb.h
syncresult.h syncresult.h
utility.h
ownsql.h
clientproxy.h
accountfwd.h
capabilities.h
connectionvalidator.h
) )
set(creds_HEADERS set(creds_HEADERS
@@ -105,6 +114,10 @@ IF (NOT APPLE)
FILES ${creds_HEADERS} FILES ${creds_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/${synclib_NAME}/creds DESTINATION ${INCLUDE_INSTALL_DIR}/${synclib_NAME}/creds
) )
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/owncloudlib.h
DESTINATION ${INCLUDE_INSTALL_DIR}/${synclib_NAME}
)
ENDIF(NOT APPLE) ENDIF(NOT APPLE)
list(APPEND libsync_LINK_TARGETS list(APPEND libsync_LINK_TARGETS
+11 -3
Ver Arquivo
@@ -44,9 +44,9 @@ AbstractNetworkJob::AbstractNetworkJob(AccountPtr account, const QString &path,
: QObject(parent) : QObject(parent)
, _timedout(false) , _timedout(false)
, _followRedirects(false) , _followRedirects(false)
, _account(account)
, _ignoreCredentialFailure(false) , _ignoreCredentialFailure(false)
, _reply(0) , _reply(0)
, _account(account)
, _path(path) , _path(path)
, _redirectCount(0) , _redirectCount(0)
{ {
@@ -263,13 +263,21 @@ QString extractErrorMessage(const QByteArray& errorResponse)
return QString::null; return QString::null;
} }
QString exception;
while (!reader.atEnd() && reader.error() == QXmlStreamReader::NoError) { while (!reader.atEnd() && reader.error() == QXmlStreamReader::NoError) {
reader.readNextStartElement(); reader.readNextStartElement();
if (reader.name() == QLatin1String("message")) { 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) QString errorMessage(const QString& baseError, const QByteArray& body)
+3 -2
Ver Arquivo
@@ -81,7 +81,7 @@ protected:
QByteArray _responseTimestamp; QByteArray _responseTimestamp;
QElapsedTimer _durationTimer; QElapsedTimer _durationTimer;
quint64 _duration; 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 // Automatically follows redirects. Note that this only works for
// GET requests that don't set up any HTTP body or other flags. // GET requests that don't set up any HTTP body or other flags.
@@ -91,11 +91,12 @@ private slots:
void slotFinished(); void slotFinished();
virtual void slotTimeout(); virtual void slotTimeout();
protected:
AccountPtr _account;
private: private:
QNetworkReply* addTimer(QNetworkReply *reply); QNetworkReply* addTimer(QNetworkReply *reply);
bool _ignoreCredentialFailure; bool _ignoreCredentialFailure;
QPointer<QNetworkReply> _reply; // (QPointer because the NetworkManager may be destroyed before the jobs at exit) QPointer<QNetworkReply> _reply; // (QPointer because the NetworkManager may be destroyed before the jobs at exit)
AccountPtr _account;
QString _path; QString _path;
QTimer _timer; QTimer _timer;
int _redirectCount; int _redirectCount;
+24 -9
Ver Arquivo
@@ -159,6 +159,8 @@ void Account::setCredentials(AbstractCredentials *cred)
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(_credentials, SIGNAL(fetched()), connect(_credentials, SIGNAL(fetched()),
SLOT(slotCredentialsFetched())); SLOT(slotCredentialsFetched()));
connect(_credentials, SIGNAL(asked()),
SLOT(slotCredentialsAsked()));
} }
QUrl Account::davUrl() const QUrl Account::davUrl() const
@@ -179,7 +181,7 @@ void Account::clearCookieJar()
/*! This shares our official cookie jar (containing all the tasty /*! This shares our official cookie jar (containing all the tasty
authentication cookies) with another QNAM while making sure authentication cookies) with another QNAM while making sure
of not loosing its ownership. */ of not losing its ownership. */
void Account::lendCookieJarTo(QNetworkAccessManager *guest) void Account::lendCookieJarTo(QNetworkAccessManager *guest)
{ {
auto jar = _am->cookieJar(); auto jar = _am->cookieJar();
@@ -441,16 +443,13 @@ void Account::slotCredentialsFetched()
emit credentialsFetched(_credentials); emit credentialsFetched(_credentials);
} }
void Account::slotCredentialsAsked()
{
emit credentialsAsked(_credentials);
}
void Account::handleInvalidCredentials() void Account::handleInvalidCredentials()
{ {
// invalidate & forget token/password
// but try to re-sign in.
if (_credentials->ready()) {
_credentials->invalidateAndFetch();
} else {
_credentials->fetch();
}
emit invalidCredentials(); emit invalidCredentials();
} }
@@ -479,9 +478,25 @@ QString Account::serverVersion()
return _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) void Account::setServerVersion(const QString& version)
{ {
_serverVersion = version; _serverVersion = version;
} }
bool Account::rootEtagChangesNotOnlySubFolderEtags()
{
return (serverVersionInt() >= 0x080100);
}
} // namespace OCC } // namespace OCC
+7 -1
Ver Arquivo
@@ -141,7 +141,7 @@ public:
const QList< QPair<QString, QString> > &queryItems = (QList<QPair<QString, QString>>())); 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 /** 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); static std::unique_ptr<QSettings> settingsWithGroup(const QString& group, QObject* parent = 0);
// to be called by credentials only // to be called by credentials only
@@ -154,6 +154,10 @@ public:
const Capabilities &capabilities() const; const Capabilities &capabilities() const;
void setServerVersion(const QString &version); void setServerVersion(const QString &version);
QString serverVersion(); QString serverVersion();
int serverVersionInt();
// Fixed from 8.1 https://github.com/owncloud/client/issues/3730
bool rootEtagChangesNotOnlySubFolderEtags();
void clearCookieJar(); void clearCookieJar();
void lendCookieJarTo(QNetworkAccessManager *guest); void lendCookieJarTo(QNetworkAccessManager *guest);
@@ -168,6 +172,7 @@ signals:
void propagatorNetworkActivity(); void propagatorNetworkActivity();
void invalidCredentials(); void invalidCredentials();
void credentialsFetched(AbstractCredentials* credentials); void credentialsFetched(AbstractCredentials* credentials);
void credentialsAsked(AbstractCredentials* credentials);
/// Forwards from QNetworkAccessManager::proxyAuthenticationRequired(). /// Forwards from QNetworkAccessManager::proxyAuthenticationRequired().
void proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*); void proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*);
@@ -178,6 +183,7 @@ signals:
protected Q_SLOTS: protected Q_SLOTS:
void slotHandleSslErrors(QNetworkReply*,QList<QSslError>); void slotHandleSslErrors(QNetworkReply*,QList<QSslError>);
void slotCredentialsFetched(); void slotCredentialsFetched();
void slotCredentialsAsked();
private: private:
Account(QObject *parent = 0); 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 // 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 // devices the same quota we used now since we don't want
// any upload to timeout // any download to timeout
_relativeDownloadDelayTimer.setInterval(realWaitTimeMsec); _relativeDownloadDelayTimer.setInterval(realWaitTimeMsec);
_relativeDownloadDelayTimer.start(); _relativeDownloadDelayTimer.start();
@@ -339,7 +339,7 @@ void BandwidthManager::relativeDownloadDelayTimerExpired()
_relativeLimitCurrentMeasuredJob->setBandwidthLimited(false); _relativeLimitCurrentMeasuredJob->setBandwidthLimited(false);
_relativeLimitCurrentMeasuredJob->setChoked(false); _relativeLimitCurrentMeasuredJob->setChoked(false);
// choke all other UploadDevices // choke all other download jobs
Q_FOREACH(GETFileJob *gfj, _downloadJobList) { Q_FOREACH(GETFileJob *gfj, _downloadJobList) {
if (gfj != _relativeLimitCurrentMeasuredJob) { if (gfj != _relativeLimitCurrentMeasuredJob) {
gfj->setBandwidthLimited(true); 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(); 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(); 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(); 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 "owncloudlib.h"
#include <QVariantMap> #include <QVariantMap>
#include <QStringList>
namespace OCC { namespace OCC {
/** /**
* @brief The Capabilities class represent the capabilities of an ownCloud * @brief The Capabilities class represents the capabilities of an ownCloud
* server * server
* @ingroup libsync * @ingroup libsync
*/ */
@@ -31,9 +32,14 @@ class OWNCLOUDSYNC_EXPORT Capabilities {
public: public:
Capabilities(const QVariantMap &capabilities); Capabilities(const QVariantMap &capabilities);
bool publicLinkEnforcePassword() const; bool shareAPI() const;
bool publicLinkEnforceExpireDate() const; bool sharePublicLink() const;
int publicLinkExpireDateDays() const; bool sharePublicLinkAllowUpload() const;
bool sharePublicLinkEnforcePassword() const;
bool sharePublicLinkEnforceExpireDate() const;
int sharePublicLinkExpireDateDays() const;
bool shareResharing() const;
QStringList supportedChecksumTypes() const;
private: private:
QVariantMap _capabilities; QVariantMap _capabilities;
+1 -1
Ver Arquivo
@@ -60,7 +60,7 @@ public:
/* Server poll interval in milliseconds */ /* Server poll interval in milliseconds */
int remotePollInterval( const QString& connection = QString() ) const; 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() ); void setRemotePollInterval(int interval, const QString& connection = QString() );
/* Force sync interval, in milliseconds */ /* Force sync interval, in milliseconds */
+5 -13
Ver Arquivo
@@ -41,7 +41,7 @@ QString ConnectionValidator::statusString( Status stat )
return QLatin1String("NotConfigured"); return QLatin1String("NotConfigured");
case ServerVersionMismatch: case ServerVersionMismatch:
return QLatin1String("Server Version Mismatch"); return QLatin1String("Server Version Mismatch");
case CredentialsWrong: case CredentialsMissingOrWrong:
return QLatin1String("Credentials Wrong"); return QLatin1String("Credentials Wrong");
case StatusNotFound: case StatusNotFound:
return QLatin1String("Status not found"); return QLatin1String("Status not found");
@@ -121,18 +121,10 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf
} }
// now check the authentication // now check the authentication
AbstractCredentials *creds = _account->credentials(); if (_account->credentials()->ready())
if (creds->ready()) {
QTimer::singleShot( 0, this, SLOT( checkAuthentication() )); QTimer::singleShot( 0, this, SLOT( checkAuthentication() ));
} else { else
// We can't proceed with the auth check because we don't have credentials. reportResult( CredentialsMissingOrWrong );
// Fetch them now! Once fetched, a new connectivity check will be
// initiated anyway.
creds->fetch();
// no result is reported
deleteLater();
}
} }
// status.php could not be loaded (network or server issue!). // 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() << reply->error() << reply->errorString();
qDebug() << "******** Password is wrong!"; qDebug() << "******** Password is wrong!";
_errors << tr("The provided credentials are not correct"); _errors << tr("The provided credentials are not correct");
stat = CredentialsWrong; stat = CredentialsMissingOrWrong;
} else if( reply->error() != QNetworkReply::NoError ) { } else if( reply->error() != QNetworkReply::NoError ) {
_errors << errorMessage(reply->errorString(), reply->readAll()); _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. * 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 * There are two entry points: checkServerAndAuth and checkAuthentication
* checkAutentication is the quick version that only do the propfind * checkAuthentication is the quick version that only does the propfind
* while checkServerAndAuth is doing the 3 calls. * while checkServerAndAuth is doing the 3 calls.
* *
* We cannot use the capabilites call to test the login and the password because of * We cannot use the capabilites call to test the login and the password because of
@@ -44,17 +44,16 @@ namespace OCC {
| |
+-> slotJobTimeout --> X +-> slotJobTimeout --> X
| |
+-> slotStatusFound +-> slotStatusFound --+--> X (if credentials are still missing)
credential->fetch() --+ |
| +---------------------------+
+-----------------------------------+
| |
*-+-> checkAuthentication (PROPFIND on root) *-+-> checkAuthentication (PROPFIND on root)
PropfindJob PropfindJob
| |
+-> slotAuthFailed --> X +-> 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, Connected,
NotConfigured, NotConfigured,
ServerVersionMismatch, ServerVersionMismatch,
CredentialsWrong, CredentialsMissingOrWrong,
StatusNotFound, StatusNotFound,
UserCanceledCredentials, UserCanceledCredentials,
ServiceUnavailable, ServiceUnavailable,
+3 -6
Ver Arquivo
@@ -48,21 +48,18 @@ public:
virtual QString user() const = 0; virtual QString user() const = 0;
virtual QNetworkAccessManager* getQNAM() const = 0; virtual QNetworkAccessManager* getQNAM() const = 0;
virtual bool ready() 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 bool stillValid(QNetworkReply *reply) = 0;
virtual void persist() = 0; virtual void persist() = 0;
/** Invalidates auth token, or password for basic auth */ /** Invalidates auth token, or password for basic auth */
virtual void invalidateToken() = 0; virtual void invalidateToken() = 0;
virtual void invalidateAndFetch() {
invalidateToken();
fetch();
}
static QString keychainKey(const QString &url, const QString &user); static QString keychainKey(const QString &url, const QString &user);
Q_SIGNALS: Q_SIGNALS:
void fetched(); void fetched();
void asked();
protected: protected:
Account* _account; Account* _account;
+6 -1
Ver Arquivo
@@ -56,11 +56,16 @@ bool DummyCredentials::stillValid(QNetworkReply *reply)
return true; return true;
} }
void DummyCredentials::fetch() void DummyCredentials::fetchFromKeychain()
{ {
Q_EMIT(fetched()); Q_EMIT(fetched());
} }
void DummyCredentials::askFromUser()
{
Q_EMIT(asked());
}
void DummyCredentials::persist() void DummyCredentials::persist()
{} {}
+2 -1
Ver Arquivo
@@ -35,7 +35,8 @@ public:
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE; QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE; bool ready() const Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) 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 persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE {} void invalidateToken() Q_DECL_OVERRIDE {}
}; };
+9 -55
Ver Arquivo
@@ -82,23 +82,16 @@ const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns } // ns
HttpCredentials::HttpCredentials() HttpCredentials::HttpCredentials()
: _user(), : _ready(false)
_password(),
_certificatePath(),
_certificatePasswd(),
_ready(false),
_fetchJobInProgress(false),
_readPwdFromDeprecatedPlace(false)
{ {
} }
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd) HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd)
: _user(user), : _user(user),
_password(password), _password(password),
_certificatePath(certificatePath),
_certificatePasswd(certificatePasswd),
_ready(true), _ready(true),
_fetchJobInProgress(false) _certificatePath(certificatePath),
_certificatePasswd(certificatePasswd)
{ {
} }
@@ -200,12 +193,8 @@ QString HttpCredentials::fetchUser()
return _user; return _user;
} }
void HttpCredentials::fetch() void HttpCredentials::fetchFromKeychain()
{ {
if (_fetchJobInProgress) {
return;
}
// User must be fetched from config file // User must be fetched from config file
fetchUser(); fetchUser();
_certificatePath = _account->credentialSetting(QLatin1String(certifPathC)).toString(); _certificatePath = _account->credentialSetting(QLatin1String(certifPathC)).toString();
@@ -235,8 +224,6 @@ void HttpCredentials::fetch()
job->setKey(kck); job->setKey(kck);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*))); connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start(); job->start();
_fetchJobInProgress = true;
_readPwdFromDeprecatedPlace = true;
} }
} }
bool HttpCredentials::stillValid(QNetworkReply *reply) bool HttpCredentials::stillValid(QNetworkReply *reply)
@@ -256,7 +243,6 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
QKeychain::Error error = job->error(); QKeychain::Error error = job->error();
if( !_password.isEmpty() && error == NoError ) { if( !_password.isEmpty() && error == NoError ) {
_fetchJobInProgress = false;
// All cool, the keychain did not come back with error. // All cool, the keychain did not come back with error.
// Still, the password can be empty which indicates a problem and // Still, the password can be empty which indicates a problem and
@@ -266,44 +252,12 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
} else { } else {
// we come here if the password is empty or any other keychain // we come here if the password is empty or any other keychain
// error happend. // 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); _fetchErrorString = job->error() != EntryNotFound ? job->errorString() : QString();
job->setKey(kck);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*))); _password = QString();
job->start(); _ready = false;
_readPwdFromDeprecatedPlace = false; // do try that only once. emit fetched();
_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();
}
} }
} }
@@ -343,7 +297,7 @@ void HttpCredentials::invalidateToken()
// clear the session cookie. // clear the session cookie.
_account->clearCookieJar(); _account->clearCookieJar();
// let QNAM fogets about the password // let QNAM forget about the password
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
_account->networkAccessManager()->clearAccessCache(); _account->networkAccessManager()->clearAccessCache();
#else #else
+3 -5
Ver Arquivo
@@ -44,12 +44,11 @@ public:
QString authType() const Q_DECL_OVERRIDE; QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE; QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() 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; bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE; void persist() Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE; QString user() const Q_DECL_OVERRIDE;
QString password() const; QString password() const;
virtual QString queryPassword(bool *ok, const QString& hint) = 0;
void invalidateToken() Q_DECL_OVERRIDE; void invalidateToken() Q_DECL_OVERRIDE;
QString fetchUser(); QString fetchUser();
virtual bool sslIsTrusted() { return false; } virtual bool sslIsTrusted() { return false; }
@@ -68,13 +67,12 @@ protected:
QString _user; QString _user;
QString _password; QString _password;
QString _previousPassword; QString _previousPassword;
QString _fetchErrorString;
bool _ready;
private: private:
QString _certificatePath; QString _certificatePath;
QString _certificatePasswd; QString _certificatePasswd;
bool _ready;
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
bool _readPwdFromDeprecatedPlace;
}; };
} // namespace OCC } // namespace OCC
+1 -1
Ver Arquivo
@@ -166,7 +166,7 @@ bool TokenCredentials::ready() const
return _ready; return _ready;
} }
void TokenCredentials::fetch() void TokenCredentials::fetch(FetchMode)
{ {
Q_EMIT fetched(); Q_EMIT fetched();
} }
+1 -1
Ver Arquivo
@@ -46,7 +46,7 @@ public:
QString authType() const Q_DECL_OVERRIDE; QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE; QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() 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; bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE; void persist() Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE; QString user() const Q_DECL_OVERRIDE;
+9 -1
Ver Arquivo
@@ -13,13 +13,14 @@
*/ */
#include "discoveryphase.h" #include "discoveryphase.h"
#include <csync_private.h>
#include <qdebug.h> #include <qdebug.h>
#include <QUrl> #include <QUrl>
#include "account.h" #include "account.h"
#include <QFileInfo> #include <QFileInfo>
#include <csync_private.h>
namespace OCC { 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. //This works in concerto with the RequestEtagJob and the Folder object to check if the remote folder changed.
if (map.contains("getetag")) { if (map.contains("getetag")) {
_etagConcatenation += map.value("getetag"); _etagConcatenation += map.value("getetag");
if (_firstEtag.isEmpty()) {
_firstEtag = map.value("getetag"); // for directory itself
}
} }
} }
@@ -339,6 +344,7 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot()
deleteLater(); deleteLater();
return; return;
} }
emit etag(_firstEtag);
emit etagConcatenation(_etagConcatenation); emit etagConcatenation(_etagConcatenation);
emit finishedWithResult(_results); emit finishedWithResult(_results);
deleteLater(); deleteLater();
@@ -410,6 +416,8 @@ void DiscoveryMainThread::doOpendirSlot(QString subPath, DiscoveryDirectoryResul
this, SLOT(singleDirectoryJobFirstDirectoryPermissionsSlot(QString))); this, SLOT(singleDirectoryJobFirstDirectoryPermissionsSlot(QString)));
QObject::connect(_singleDirJob, SIGNAL(etagConcatenation(QString)), QObject::connect(_singleDirJob, SIGNAL(etagConcatenation(QString)),
this, SIGNAL(etagConcatenation(QString))); this, SIGNAL(etagConcatenation(QString)));
QObject::connect(_singleDirJob, SIGNAL(etag(QString)),
this, SIGNAL(etag(QString)));
_singleDirJob->start(); _singleDirJob->start();
} }
+6 -3
Ver Arquivo
@@ -29,8 +29,8 @@ namespace OCC {
class Account; class Account;
/** /**
* The Discovery Phase was once called "update" phase in csync therms. * 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 comared to the db * 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. * if the files are new, or changed.
*/ */
@@ -87,6 +87,7 @@ public:
signals: signals:
void firstDirectoryPermissions(const QString &); void firstDirectoryPermissions(const QString &);
void etagConcatenation(const QString &); void etagConcatenation(const QString &);
void etag(const QString &);
void finishedWithResult(const QList<FileStatPointer> &); void finishedWithResult(const QList<FileStatPointer> &);
void finishedWithError(int csyncErrnoCode, QString msg); void finishedWithError(int csyncErrnoCode, QString msg);
private slots: private slots:
@@ -97,6 +98,7 @@ private:
QList<FileStatPointer> _results; QList<FileStatPointer> _results;
QString _subPath; QString _subPath;
QString _etagConcatenation; QString _etagConcatenation;
QString _firstEtag;
AccountPtr _account; AccountPtr _account;
bool _ignoredFirst; bool _ignoredFirst;
QPointer<LsColJob> _lsColJob; QPointer<LsColJob> _lsColJob;
@@ -134,7 +136,8 @@ public slots:
void slotGetSizeFinishedWithError(); void slotGetSizeFinishedWithError();
void slotGetSizeResult(const QVariantMap&); void slotGetSizeResult(const QVariantMap&);
signals: signals:
void etagConcatenation(QString); void etag(const QString &);
void etagConcatenation(const QString &);
public: public:
void setupHooks(DiscoveryJob* discoveryJob, const QString &pathPrefix); 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 { do {
int r = f1.read(buffer1, BufferSize); int r = f1.read(buffer1, BufferSize);
if (f2.read(buffer2, BufferSize) != r) { 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; return false;
} }
if (r <= 0) { if (r <= 0) {
@@ -244,8 +244,8 @@ bool FileSystem::uncheckedRenameReplace(const QString& originFileName,
success = orig.fileEngine()->rename(destinationFileName); success = orig.fileEngine()->rename(destinationFileName);
// qDebug() << "Renaming " << tmpFile.fileName() << " to " << fn; // qDebug() << "Renaming " << tmpFile.fileName() << " to " << fn;
#else #else
// We want a rename that also overwite. QFile::rename does not overwite. // We want a rename that also overwites. QFile::rename does not overwite.
// Qt 5.1 has QSaveFile::renameOverwrite we cold use. // Qt 5.1 has QSaveFile::renameOverwrite we could use.
// ### FIXME // ### FIXME
success = true; success = true;
bool destExists = fileExists(destinationFileName); bool destExists = fileExists(destinationFileName);
@@ -403,7 +403,7 @@ static bool fileExistsWin(const QString& filename)
} }
#endif #endif
bool FileSystem::fileExists(const QString& filename) bool FileSystem::fileExists(const QString& filename, const QFileInfo& fileInfo)
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
if (isLnkFile(filename)) { if (isLnkFile(filename)) {
@@ -411,8 +411,15 @@ bool FileSystem::fileExists(const QString& filename)
return fileExistsWin(filename); return fileExistsWin(filename);
} }
#endif #endif
QFileInfo file(filename); bool re = fileInfo.exists();
return file.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 #ifdef Q_OS_WIN
+4 -3
Ver Arquivo
@@ -18,6 +18,7 @@
#include <QString> #include <QString>
#include <ctime> #include <ctime>
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QFileInfo>
#include <owncloudlib.h> #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 * Use this over QFileInfo::exists() and QFile::exists() to avoid bugs with lnk
* files, see above. * 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. * @brief Rename the file \a originFileName to \a destinationFileName.
@@ -85,7 +86,7 @@ bool OWNCLOUDSYNC_EXPORT rename(const QString& originFileName,
QString* errorString = NULL); 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. * 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(). * Replacement for QFile::open(ReadOnly) followed by a seek().
* This version sets a more permissive sharing mode on Windows. * 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! * with QFileInfo! Calling seek() on the QFile with >32bit signed values will fail!
*/ */
bool openAndSeekFileSharedRead(QFile* file, QString* error, qint64 seek); bool openAndSeekFileSharedRead(QFile* file, QString* error, qint64 seek);
+24 -2
Ver Arquivo
@@ -17,6 +17,7 @@
#include <QDir> #include <QDir>
#include <QStringList> #include <QStringList>
#include <QThread> #include <QThread>
#include <qmetaobject.h>
namespace OCC { namespace OCC {
@@ -40,7 +41,10 @@ static void mirallLogCatcher(QtMsgType, const QMessageLogContext &ctx, const QSt
} }
#else #else
static void mirallLogCatcher(QtMsgType type, const QMessageLogContext &ctx, const QString &message) { 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 #endif
@@ -105,6 +109,24 @@ void Logger::log(Log log)
doLog(msg); 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) void Logger::doLog(const QString& msg)
{ {
{ {
@@ -193,7 +215,7 @@ void Logger::enterNextLogFile()
dir.mkpath("."); 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.*"), QStringList files = dir.entryList(QStringList("owncloud.log.*"),
QDir::Files); QDir::Files);
QRegExp rx("owncloud.log.(\\d+)"); QRegExp rx("owncloud.log.(\\d+)");
+1
Ver Arquivo
@@ -46,6 +46,7 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject
Q_OBJECT Q_OBJECT
public: public:
bool isNoop() const;
void log(Log log); void log(Log log);
void doLog(const QString &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() void RequestEtagJob::start()
{ {
QNetworkRequest req; QNetworkRequest req;
// Let's always request all entries inside a directory. There are/were bugs in the server if (_account && _account->rootEtagChangesNotOnlySubFolderEtags()) {
// where a root or root-folder ETag is not updated when its contents change. We work around // Fixed from 8.1 https://github.com/owncloud/client/issues/3730
// this by concatenating the ETags of the root and its contents. req.setRawHeader("Depth", "0");
req.setRawHeader("Depth", "1"); } else {
// See https://github.com/owncloud/core/issues/5255 and others // 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" QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\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 // 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, // 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() bool LsColJob::finished()
{ {
QString contentType = reply()->header(QNetworkRequest::ContentTypeHeader).toString(); QString contentType = reply()->header(QNetworkRequest::ContentTypeHeader).toString();
@@ -432,7 +437,7 @@ bool CheckServerJob::finished()
mergeSslConfigurationForSslButton(reply()->sslConfiguration(), account()); 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 // at the original location
if ((reply()->error() == QNetworkReply::ContentNotFoundError) && (!_subdirFallback)) { if ((reply()->error() == QNetworkReply::ContentNotFoundError) && (!_subdirFallback)) {
_subdirFallback = true; _subdirFallback = true;

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