Comparar commits

..

33 Commits

Autor SHA1 Mensagem Data
Daniel Molkentin 914df32587 Documentation: Fix PDF logo, version number 2015-11-17 12:55:41 +01:00
Markus Goetz 99b0d659bd Merge pull request #4073 from RealRancor/backport_4052_2.0
Backport #4052 to 2.0
2015-11-04 16:32:34 +01:00
RealRancor 854264c3d2 Backport #4052 to 2.0 2015-11-04 15:55:07 +01:00
Markus Goetz be9ed2f6a9 Merge pull request #4058 from owncloud/client-updates
some doc fixes & updates
2015-11-04 15:11:28 +01:00
Jenkins for ownCloud 03cc67a2b1 [tx-robot] updated from transifex 2015-11-04 02:19:04 -05:00
Jenkins for ownCloud 89734b95c4 [tx-robot] updated from transifex 2015-11-03 02:19:04 -05:00
Carla Schroder a59c3ef278 some doc fixes & updates 2015-11-02 11:18:31 -08:00
Jenkins for ownCloud 3f85694394 [tx-robot] updated from transifex 2015-11-01 02:18:55 -05:00
Jenkins for ownCloud d2cd237e25 [tx-robot] updated from transifex 2015-10-30 02:19:00 -04:00
Klaas Freitag bc5890d8b5 Add version suffix git. 2015-10-29 15:46:02 +01:00
Klaas Freitag ee65315520 Merge branch '2.0.2' into 2.0
Conflicts:
	ChangeLog
2015-10-29 15:44:56 +01:00
Klaas Freitag 726be08917 Revert "Config: Use monochrome icons per default on MacOSX."
This reverts commit 546cab3f62.
For OEMs this patch causes an empty tray icon set.
2015-10-29 15:37:31 +01:00
Jenkins for ownCloud 4d7fde59c2 [tx-robot] updated from transifex 2015-10-29 02:18:59 -04:00
Olivier Goffart 3ff7fa0092 Merge pull request #3997 from owncloud/phil-davis-patch-1
ChangeLog 2.0.2 minor typos for 2.0 branch
2015-10-27 12:58:59 +01:00
Jenkins for ownCloud 6611d878ea [tx-robot] updated from transifex 2015-10-25 02:19:01 -04:00
Jenkins for ownCloud c3fc711095 [tx-robot] updated from transifex 2015-10-24 02:18:59 -04:00
Phil Davis 2eb5715599 ChangeLog 2.0.2 minor typos for 2.0 branch
These changes were committed to 2.0.2-rc1 branch https://github.com/owncloud/client/pull/3957/files https://github.com/owncloud/client/commit/6da2139a1bc4069f1cd1dfb017502f089c3af26f but that branch was never merged up into 2.0 (or 2.0.2-rc2) so the changes never went anywhere.

These changes could also be applied on 2.0.2-rc2 and 2.0.2 branch for completeness - then they would be in every branch in which they have appeared.
2015-10-23 21:21:31 +05:45
Markus Goetz e5570c24f2 Merge pull request #3995 from owncloud/return-code-of-version-and-help
owncloudcmd: Make returncode 0 for --version and --help
2015-10-23 15:36:01 +02:00
Joas Schilling 6d87bd15cd Make returncode 0 for --version and --help 2015-10-23 15:17:29 +02:00
Jenkins for ownCloud 6fae06f1d0 [tx-robot] updated from transifex 2015-10-23 02:19:00 -04:00
Jenkins for ownCloud b5390b5aa2 [tx-robot] updated from transifex 2015-10-22 02:19:02 -04:00
Daniel Molkentin c8ae54d9e8 Merge pull request #3982 from owncloud/20-update
update 3-dot menu
2015-10-21 18:49:38 +02:00
Carla Schroder daf6d8772f update 3-dot menu 2015-10-21 09:44:38 -07:00
Daniel Molkentin 78d782601e 2.0.2 final 2015-10-21 09:54:02 +02:00
Daniel Molkentin 86a83dc32c Finalize ChangeLog, adjust formatting 2015-10-21 09:53:34 +02:00
Daniel Molkentin c67e53c7b2 set version suffix back to git 2015-10-21 09:48:18 +02:00
Jenkins for ownCloud 5659e04e89 [tx-robot] updated from transifex 2015-10-21 02:19:02 -04:00
Markus Goetz 5f43c9cfad Merge tag 'v2.0.2-rc2' into 2.0
Second RC of ownCloud Client 2.0.2
2015-10-20 15:46:09 +02:00
Markus Goetz 4c9bc42b69 Revert libqsqlite changes for now
QtWebKit depends on it unfortunately
2015-10-20 13:04:33 +02:00
Klaas Freitag d09de79491 Bump version to RC2 2015-10-20 11:30:00 +02:00
Markus Goetz 24a801dfd3 CMake/NSIS: We don't need QtSql (more) 2015-10-19 13:56:36 +02:00
Markus Goetz af79bc9211 CMake/NSIS: We don't need QtSql
The NSIS change also had a redundant libsqlite3 DLL entry
2015-10-19 13:46:46 +02:00
Klaas Freitag a3904f4d32 Theme: Revert logic of singleAccount switch.
To use the same logic as the other clients and unify ownBrander
implementations, the switch is now called multiAccount() rather
than singleAccount() with a reverse logic.
Desktop Client stays with the default of having multiaacount
enabled.

Note that existing brandings need to rename the switch.

https://github.com/owncloud/ownbrander/issues/443
2015-10-19 12:26:42 +02:00
144 arquivos alterados com 2215 adições e 2429 exclusões
+30 -30
Ver Arquivo
@@ -1,49 +1,49 @@
ChangeLog ChangeLog
========= =========
version 2.0.2 (release 2015-10-xx) version 2.0.2 (release 2015-10-21)
* csync_file_stat_s: Save a bit of memory * csync_file_stat_s: Save a bit of memory
* Shibboleth: Add our base user agent to WebKit * Shibboleth: Add our base user agent to WebKit
* SelectiveSync: Increase folder list timeout to 60 * SelectiveSync: Increase folder list timeout to 60
* Propagation: Try another sync on 423 Locked #3387 * Propagation: Try another sync on 423 Locked (#3387)
* Propagation: Make 423 Locked a soft error #3387 * Propagation: Make 423 Locked a soft error (#3387)
* Propagation: Reset upload blacklist if a chunk suceeds * Propagation: Reset upload blacklist if a chunk suceeds
* Application: Fix crash on early shutdown #3898 * Application: Fix crash on early shutdown (#3898)
* Linux: Don't show settings dialog always when launched twice #3273 #3771 #3485 * Linux: Don't show settings dialog always when launched twice (#3273, #3771, #3485)
* win32 vio: Add the OPEN_REPARSE_POINTS flag to the CreateFileW call. #3813 * win32 vio: Add the OPEN_REPARSE_POINTS flag to the CreateFileW call. (#3813)
* AccountSettings: only expand root elements on single click. * AccountSettings: only expand root elements on single click.
* AccountSettings: Do not allow to expand the folder list when disconnected. * AccountSettings: Do not allow to expand the folder list when disconnected.
* Use application SHORT name for the name of the MacOSX pkg file (ownBrander). * Use application SHORT name for the name of the MacOSX pkg file (ownBrander).
* FolderMan: Fix for removing a syncing folder #3843 * FolderMan: Fix for removing a syncing folder (#3843)
* ConnectionMethodDialog: Don't be insecure on close #3863 * ConnectionMethodDialog: Don't be insecure on close (#3863)
* Updater: Ensure folders are not removed #3747 * Updater: Ensure folders are not removed (#3747)
* Folder settings: Ensure path is cleaned #3811 * Folder settings: Ensure path is cleaned (#3811)
* Propagator: Simplify sub job finished counting #3844 * Propagator: Simplify sub job finished counting (#3844)
* Share dialog: Hide settings dialog before showing #3783 * Share dialog: Hide settings dialog before showing (#3783)
* UI: Only expand 1 level in folder list #3585 * UI: Only expand 1 level in folder list (#3585)
* UI: Allow folder expanding from button click #3585 * UI: Allow folder expanding from button click (#3585)
* UI: Expand folder treeview on single click #3585 * UI: Expand folder treeview on single click (#3585)
* GUI: Change tray menu order #3657 * GUI: Change tray menu order (#3657)
* GUI: Replace term "sign in" with "Log in" and friends. * GUI: Replace term "sign in" with "Log in" and friends.
* SetupPage: Fix crash caused by uninitialized Account object. * SetupPage: Fix crash caused by uninitialized Account object.
* Use a themable WebDAV path all over. * Use a themable WebDAV path all over.
* Units: Back to the "usual" mix units (JEDEC standard). * Units: Back to the "usual" mix units (JEDEC standard).
* csync io: Full UNC path support on Win #3748 * csync io: Full UNC path support on Win (#3748)
* Tray: Don't use the tray workaround with the KDE theme #3706, #3765 * Tray: Don't use the tray workaround with the KDE theme (#3706, #3765)
* ShareDialog: Fix folder display #3659 * ShareDialog: Fix folder display (#3659)
* AccountSettings: Restore from legacy only once #3565 * AccountSettings: Restore from legacy only once (#3565)
* SSL Certificate Error Dialog: show account name #3729 * SSL Certificate Error Dialog: show account name (#3729)
* Tray notification: Don't show a message about modified folder #3613 * Tray notification: Don't show a message about modified folder (#3613)
* PropagateLocalRemove: remove entries from the DB even if there was an error. * PropagateLocalRemove: remove entries from the DB even if there was an error.
* Settings UI improvements (eg. #3713, #3721, #3619 and others) * Settings UI improvements (eg. #3713, #3721, #3619 and others)
* Folder: Do not create the sync folder if it does not exist #3692 * Folder: Do not create the sync folder if it does not exist (#3692)
* Shell integratioon: don't show share menu item for top level folders * Shell integratioon: don't show share menu item for top level folders
* Tray: Hide while modifying menus #3656 #3672 * Tray: Hide while modifying menus (#3656, #3672)
* AddFolder: Improve remote path selection error handling #3573 * AddFolder: Improve remote path selection error handling (#3573)
* csync_update: Use excluded_traversal() to improve performance #3638 * csync_update: Use excluded_traversal() to improve performance (#3638)
* csync_excluded: Add fast _traversal() function #3638 * csync_excluded: Add fast _traversal() function (#3638)
* csync_exclude: Speed up siginificantly #3638 * csync_exclude: Speed up siginificantly (#3638)
* AccountSettings: Adjust quota info design #3644 #3651 * AccountSettings: Adjust quota info design (#3644, #3651)
* Adjust buttons on remove folder/account questions #3654 * Adjust buttons on remove folder/account questions (#3654)
version 2.0.1 (release 2015-09-01) version 2.0.1 (release 2015-09-01)
* AccountWizard: fix when the theme specify a override URL (#3699) * AccountWizard: fix when the theme specify a override URL (#3699)
+2 -2
Ver Arquivo
@@ -1,6 +1,6 @@
set( MIRALL_VERSION_MAJOR 2 ) set( MIRALL_VERSION_MAJOR 2 )
set( MIRALL_VERSION_MINOR 1 ) set( MIRALL_VERSION_MINOR 0 )
set( MIRALL_VERSION_PATCH 0 ) set( MIRALL_VERSION_PATCH 2 )
set( MIRALL_SOVERSION 0 ) set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX ) if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
+7 -1
Ver Arquivo
@@ -134,7 +134,13 @@ 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)
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}") if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX
AND "${_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
set(__LAST_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
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)
+9 -13
Ver Arquivo
@@ -88,8 +88,10 @@ 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
@@ -140,18 +142,12 @@ 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}
# )
+3 -3
Ver Arquivo
@@ -11,8 +11,8 @@ the Updater will check for updates and notify you when a new version is
available. available.
.. note:: Because of various technical issues, desktop sync clients older than .. note:: Because of various technical issues, desktop sync clients older than
1.7 will not be allowed to connect and sync with the ownCloud 8.1 server. It is 1.7 will not be allowed to connect and sync with the ownCloud 8.1+ server. It
highly recommended to keep your client updated. is highly recommended to keep your client updated.
Basic Workflow Basic Workflow
-------------- --------------
@@ -89,7 +89,7 @@ To prevent automatic updates and disallow manual overrides:
1. Edit this Registry key: 1. Edit this Registry key:
HKEY_LOCAL_MACHINE\Software\Policies\ownCloud\ownCloud ``HKEY_LOCAL_MACHINE\Software\Policies\ownCloud\ownCloud``
2. Add the key ``skipUpdateCheck`` (of type DWORD). 2. Add the key ``skipUpdateCheck`` (of type DWORD).
+3 -3
Ver Arquivo
@@ -48,9 +48,9 @@ copyright = u'2013, The ownCloud developers'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '@VERSION_MAJOR@.@VERSION_MINOR@' version = '@MIRALL_VERSION_MAJOR@.@MIRALL_VERSION_MINOR@'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '@VERSION@' release = '@MIRALL_VERSION@'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@@ -189,7 +189,7 @@ latex_documents = [
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
# the title page. # the title page.
#latex_logo = None latex_logo = '@LATEX_LOGO@'
# For "manual" documents, if this is true, then toplevel headings are parts, # For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters. # not chapters.
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 5.7 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 5.5 KiB

Arquivo executável
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 39 KiB

Arquivo executável
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 41 KiB

Arquivo executável
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 44 KiB

Arquivo executável
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 59 KiB

+5 -1
Ver Arquivo
@@ -3,7 +3,8 @@ Installing the Desktop Synchronization Client
============================================= =============================================
You can download the latest version of the ownCloud Desktop Synchronization You can download the latest version of the ownCloud Desktop Synchronization
Client from the `ownCloud Website <https://owncloud.org/install/#desktop>`_. Client from the `ownCloud download page
<https://owncloud.org/install/#desktop>`_.
There are clients for Linux, Mac OS X, and Microsoft Windows. There are clients for Linux, Mac OS X, and Microsoft Windows.
Installation on Mac OS X and Windows is the same as for any software Installation on Mac OS X and Windows is the same as for any software
@@ -21,6 +22,9 @@ will display a notification when an update is available.
Linux users must also have a password manager enabled, such as GNOME Keyring or Linux users must also have a password manager enabled, such as GNOME Keyring or
KWallet, so that the sync client can login automatically. KWallet, so that the sync client can login automatically.
You will also find links to source code archives and older versions on the
download page.
Installation Wizard Installation Wizard
------------------- -------------------
+4 -3
Ver Arquivo
@@ -13,14 +13,15 @@ Your files are always automatically synchronized between your ownCloud server
and local PC. and local PC.
.. note:: Because of various technical issues, desktop sync clients older than .. note:: Because of various technical issues, desktop sync clients older than
1.7 will not allowed to connect and sync with the ownCloud 8.1 server. It is 1.7 will not allowed to connect and sync with the ownCloud 8.1+ server. It
highly recommended to keep your client updated. is highly recommended to keep your client updated.
Improvements and New Features Improvements and New Features
----------------------------- -----------------------------
The 2.0 release of the ownCloud desktop sync client has many new features and The 2.0 release of the ownCloud desktop sync client has many new features and
improvements. improvements. (See the `complete changelog
<https://owncloud.org/changelog/desktop/>`_.)
* Multi-account support * Multi-account support
* Many UI improvements * Many UI improvements
Arquivo binário não exibido.
+26 -13
Ver Arquivo
@@ -92,18 +92,27 @@ have the following features:
removed synchronization on an account (see **Remove Sync** below). removed synchronization on an account (see **Remove Sync** below).
The little button with three dots that sits to the right of the sync status bar The little button with three dots that sits to the right of the sync status bar
offers three additional options: offers four additional options:
* Open Folder * Open Folder
* Pause Sync * Choose What to Sync
* Pause Sync / Resume Sync
* Remove Sync * Remove Sync
**Pause Sync** pauses sync operations without making any changes to your account. **Open Folder** opens a file explorer window displaying the client-side folder
that is being synced.
**Remove Sync** suspends synchronization without removing the account, and it **Choose What to Sync** opens the folder sync tree view. From there you can
removes your folder sync selection. When you're ready to resume synchronization choose to sync all or only some of the folders in the folder tree.
click the **Add Folder Sync Connection** button, and re-select the folders you
want to sync. **Pause Sync** pauses sync operations for just this folder sync connection
without making any changes to your account.
**Resume Sync** resumes sync operations for this folder sync connection.
**Remove Sync** removes this folder sync connection without removing the
account. If you want to synchronize the folder tree again then click the
**Add Folder Sync Connection** button, and re-select the folder tree that
you want to sync.
.. image:: images/client-7.png .. image:: images/client-7.png
:alt: Extra options for sync operations :alt: Extra options for sync operations
@@ -122,12 +131,15 @@ Multi-Account Support
You may now configure multiple ownCloud accounts in your desktop sync client. You may now configure multiple ownCloud accounts in your desktop sync client.
Simply click the **Add an Account** button on the General tab, and follow the Simply click the **Add an Account** button on the General tab, and follow the
account creation wizard. The new account will appear as a new tab in the settings dialog, where you can adjust its settings at any time. account creation wizard. The new account will appear as a new tab in the
settings dialog, where you can adjust its settings at any time.
Editing Ignored Files Editing Ignored Files
--------------------- ---------------------
The Ignored Files Editor can be opened by clicking on the button in the General tab of the settings dialog. The settings apply to all configured accounts. The :guilabel:`Ignored Files Editor` provides a list of files that are ignored The Ignored Files Editor can be opened by clicking on the button in the General
tab of the settings dialog. The settings apply to all configured accounts. The
:guilabel:`Ignored Files Editor` provides a list of files that are ignored
(that is, not synchronized) by the client and server during synchronizations. (that is, not synchronized) by the client and server during synchronizations.
You may add additional files or directories that you want to exclude from the You may add additional files or directories that you want to exclude from the
synchronization process. In addition to using standard characters, the Ignored synchronization process. In addition to using standard characters, the Ignored
@@ -184,7 +196,8 @@ components of the path being checked.
.. note:: Custom entries are currently not validated for syntactical .. note:: Custom entries are currently not validated for syntactical
correctness by the editor, so you will not see any warnings for bad correctness by the editor, so you will not see any warnings for bad
syntax. If your synchronization does not work as you expected, check your syntax. syntax. If your synchronization does not work as you expected, check your
syntax.
Each pattern string in the list is preceded by a checkbox. When the check box Each pattern string in the list is preceded by a checkbox. When the check box
contains a check mark, in addition to ignoring the file or directory component contains a check mark, in addition to ignoring the file or directory component
@@ -197,8 +210,8 @@ this list:
- The ownCloud Client always excludes files containing characters that cannot - The ownCloud Client always excludes files containing characters that cannot
be synchronized to other file systems. be synchronized to other file systems.
- Files are removed that cause individual errors three times during a synchronization. - Files are removed that cause individual errors three times during a
However, the client provides the option of retrying a synchronization three additional synchronization. However, the client provides the option of retrying a
times on files that produce errors. synchronization three additional times on files that produce errors.
For more detailed information see :ref:`ignored-files-label`. For more detailed information see :ref:`ignored-files-label`.
@@ -0,0 +1,256 @@
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
+12 -41
Ver Arquivo
@@ -1,46 +1,17 @@
cmake_minimum_required(VERSION 2.6)
project(dolphin-owncloud) project(dolphin-owncloud)
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
include(MacroLibrary)
find_package(LibKonq REQUIRED)
cmake_minimum_required(VERSION 2.8.12) add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
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} )
#---HELPER--- kde4_add_plugin(ownclouddolphinplugin ownclouddolphinplugin.cpp)
add_library(ownclouddolphinpluginhelper SHARED ownclouddolphinpluginhelper.cpp)
target_link_libraries(ownclouddolphinpluginhelper Qt5::Network)
generate_export_header(ownclouddolphinpluginhelper)
install(TARGETS ownclouddolphinpluginhelper LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
#---OVERLAY PLUGIN--- target_link_libraries(ownclouddolphinplugin ${KDE4_KIO_LIBS} ${LIBKONQ_LIBRARY})
kcoreaddons_add_plugin(ownclouddolphinoverlayplugin INSTALL_NAMESPACE "kf5/overlayicon" install(FILES ownclouddolphinplugin.desktop DESTINATION ${SERVICES_INSTALL_DIR})
JSON ownclouddolphinoverlayplugin.json SOURCES ownclouddolphinoverlayplugin.cpp) install(TARGETS ownclouddolphinplugin DESTINATION ${PLUGIN_INSTALL_DIR})
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})
+11 -4
Ver Arquivo
@@ -1,11 +1,18 @@
- 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
- Make sure to set XDG_DATA_DIRS=$PREFIX/share, QT_PLUGIN_PATH=$PREFIX/lib64/plugins/
- After installing, run - After installing, run
kdeinit5 --noincremental kdeinit4 --noincremental
- To test that the plugin is well installed
ktraderclient --servicetype KOverlayIconPlugin
It should show the Owncloud plugin
- restart dolphin (make sure to kill all instances) - restart dolphin (make sure to kill all instances)
@@ -1,67 +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 <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"
@@ -1,6 +0,0 @@
[Desktop Entry]
Type=Service
Name=OwncloudAction
ServiceTypes=KFileItemAction/Plugin
MimeType=application/octet-stream;inode/directory;
X-KDE-Library=ownclouddolphinactionplugin
@@ -1,101 +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>
#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"
@@ -1,8 +0,0 @@
{
"KPlugin": {
"Description": "Overlay icon for owncloud",
"ServiceTypes": [
"KOverlayIconPlugin"
]
}
}
@@ -0,0 +1,131 @@
/******************************************************************************
* 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"
@@ -0,0 +1,6 @@
[Desktop Entry]
Type=Service
Name=Owncloud
X-KDE-ServiceTypes=KOverlayIconPlugin
MimeType=text/plain;
X-KDE-Library=ownclouddolphinplugin
@@ -1,98 +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 <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);
}
}
@@ -1,52 +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 *
******************************************************************************/
#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;
};
@@ -0,0 +1,267 @@
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
@@ -0,0 +1,30 @@
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
@@ -0,0 +1,16 @@
- 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)
@@ -0,0 +1,131 @@
/******************************************************************************
* 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"
@@ -0,0 +1,6 @@
[Desktop Entry]
Type=Service
Name=Owncloud
X-KDE-ServiceTypes=KOverlayIconPlugin
MimeType=text/plain;
X-KDE-Library=ownclouddolphinplugin
-1
Ver Arquivo
@@ -10,7 +10,6 @@ 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 -9
Ver Arquivo
@@ -42,8 +42,6 @@
#include <termios.h> #include <termios.h>
#endif #endif
#include <csync_private.h>
using namespace OCC; using namespace OCC;
struct CmdOptions { struct CmdOptions {
@@ -116,11 +114,11 @@ public:
_sslTrusted(false) _sslTrusted(false)
{} {}
void askFromUser() Q_DECL_OVERRIDE { QString queryPassword(bool *ok, const QString&) Q_DECL_OVERRIDE {
_password = ::queryPassword(user()); if (ok) {
_ready = true; *ok = true;
persist(); }
emit asked(); return ::queryPassword(user());
} }
void setSSLTrusted( bool isTrusted ) { void setSSLTrusted( bool isTrusted ) {
@@ -160,14 +158,14 @@ void help()
std::cout << " -h Sync hidden files,do not ignore them" << std::endl; std::cout << " -h Sync hidden files,do not ignore them" << std::endl;
std::cout << " --version, -v Display version and exit" << std::endl; std::cout << " --version, -v Display version and exit" << std::endl;
std::cout << "" << std::endl; std::cout << "" << std::endl;
exit(1); exit(0);
} }
void showVersion() { void showVersion() {
const char *binaryName = APPLICATION_EXECUTABLE "cmd"; const char *binaryName = APPLICATION_EXECUTABLE "cmd";
std::cout << binaryName << " version " << qPrintable(Theme::instance()->version()) << std::endl; std::cout << binaryName << " version " << qPrintable(Theme::instance()->version()) << std::endl;
exit(1); exit(0);
} }
void parseOptions( const QStringList& app_args, CmdOptions *options ) void parseOptions( const QStringList& app_args, CmdOptions *options )
+3 -3
Ver Arquivo
@@ -72,6 +72,7 @@ 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
@@ -97,7 +98,6 @@ 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 ${SHAREDIR}/${APPLICATION_EXECUTABLE}/i18n) install(FILES ${client_I18N} DESTINATION ${DATADIR}/${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 paths...\") message(STATUS \"Deploying (Qt) dependencies and fixing library pathes...\")
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 a given settings file. * Creates account objects from 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 accounts. * Add this account in the list of saved account.
* 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 reasons, one should normally not keep a copy of them) * (this is a list of QSharedPointer for internal reason, one should normaly not keep a copy of them)
*/ */
QList<AccountStatePtr> accounts() { return _accounts; } QList<AccountStatePtr> accounts() { return _accounts; }
+20 -40
Ver Arquivo
@@ -42,7 +42,6 @@
#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>
@@ -91,8 +90,6 @@ 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));
@@ -104,8 +101,7 @@ 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(const QModelIndex &)), connect(ui->_folderList, SIGNAL(clicked(QModelIndex)), SLOT(slotFolderActivated(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()));
@@ -124,8 +120,12 @@ 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,6 +133,15 @@ 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;
@@ -169,17 +178,11 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
menu->exec(tv->mapToGlobal(pos)); menu->exec(tv->mapToGlobal(pos));
} }
void AccountSettings::slotFolderListClicked(const QModelIndex& indx) void AccountSettings::slotFolderActivated( const QModelIndex& indx )
{ {
if (indx.data(FolderStatusDelegate::AddButton).toBool()) { if (indx.data(FolderStatusDelegate::AddButton).toBool()
if (indx.flags() & Qt::ItemIsEnabled) { && 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) {
@@ -188,13 +191,6 @@ void AccountSettings::slotFolderListClicked(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);
} }
} }
} }
@@ -476,12 +472,6 @@ 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) {
@@ -521,10 +511,8 @@ 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) {
auto index = _model->index(i); if (ui->_folderList->isExpanded(_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()) {
@@ -566,11 +554,6 @@ 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
@@ -609,9 +592,6 @@ 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,6 +61,7 @@ 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);
@@ -76,7 +77,6 @@ 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,22 +61,6 @@
</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">
+10 -39
Ver Arquivo
@@ -15,7 +15,6 @@
#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>
@@ -29,7 +28,6 @@ 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*");
@@ -37,8 +35,6 @@ 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()
@@ -83,7 +79,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(Interactive); checkConnectivity();
} }
} }
@@ -135,7 +131,7 @@ bool AccountState::isConnectedOrTemporarilyUnavailable() const
return isConnected() || _state == ServiceUnavailable; return isConnected() || _state == ServiceUnavailable;
} }
void AccountState::checkConnectivity(CredentialFetchMode credentialsFetchMode) void AccountState::checkConnectivity()
{ {
if (isSignedOut() || _waitingForNewCredentials) { if (isSignedOut() || _waitingForNewCredentials) {
return; return;
@@ -145,7 +141,6 @@ void AccountState::checkConnectivity(CredentialFetchMode credentialsFetchMode)
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)),
@@ -207,8 +202,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::CredentialsMissingOrWrong: case ConnectionValidator::CredentialsWrong:
slotInvalidCredentials(); account()->handleInvalidCredentials();
break; break;
case ConnectionValidator::UserCanceledCredentials: case ConnectionValidator::UserCanceledCredentials:
setState(SignedOut); setState(SignedOut);
@@ -224,41 +219,15 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
void AccountState::slotInvalidCredentials() void AccountState::slotInvalidCredentials()
{ {
if (isSignedOut() || _waitingForNewCredentials) if (isSignedOut()) {
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;
@@ -270,9 +239,11 @@ void AccountState::slotCredentialsAsked(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.
delete _connectionValidator; if (_connectionValidator) {
delete _connectionValidator;
}
checkConnectivity(_credentialsFetchMode); checkConnectivity();
} }
std::unique_ptr<QSettings> AccountState::settings() std::unique_ptr<QSettings> AccountState::settings()
+2 -5
Ver Arquivo
@@ -19,7 +19,6 @@
#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;
@@ -28,6 +27,7 @@ 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,7 +59,6 @@ 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;
@@ -85,7 +84,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(CredentialFetchMode credentialsFetchMode); void checkConnectivity();
/** 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();
@@ -105,7 +104,6 @@ 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;
@@ -113,7 +111,6 @@ private:
ConnectionStatus _connectionStatus; ConnectionStatus _connectionStatus;
QStringList _connectionErrors; QStringList _connectionErrors;
bool _waitingForNewCredentials; bool _waitingForNewCredentials;
CredentialFetchMode _credentialsFetchMode;
QPointer<ConnectionValidator> _connectionValidator; QPointer<ConnectionValidator> _connectionValidator;
}; };
+6 -13
Ver Arquivo
@@ -35,7 +35,6 @@
#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"
@@ -104,7 +103,7 @@ Application::Application(int &argc, char **argv) :
{ {
_startedAt.start(); _startedAt.start();
// TODO: Can't set this without breaking current config paths // TODO: Can't set this without breaking current config pathes
// setOrganizationName(QLatin1String(APPLICATION_VENDOR)); // setOrganizationName(QLatin1String(APPLICATION_VENDOR));
setOrganizationDomain(QLatin1String(APPLICATION_REV_DOMAIN)); setOrganizationDomain(QLatin1String(APPLICATION_REV_DOMAIN));
setApplicationName( _theme->appNameGUI() ); setApplicationName( _theme->appNameGUI() );
@@ -136,13 +135,6 @@ 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*)));
@@ -153,6 +145,7 @@ 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)));
@@ -179,7 +172,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 immediately // Also check immediatly
QTimer::singleShot( 0, this, SLOT( slotCheckConnection() )); QTimer::singleShot( 0, this, SLOT( slotCheckConnection() ));
// Update checks // Update checks
@@ -244,7 +237,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::NonInteractive); accountState->checkConnectivity();
} }
} }
@@ -451,7 +444,7 @@ void Application::setHelp()
QString substLang(const QString &lang) QString substLang(const QString &lang)
{ {
// Map the more appropriate script codes // Map the more apropriate script codes
// to country codes as used by Qt and // to country codes as used by Qt and
// transifex translation conventions. // transifex translation conventions.
@@ -493,7 +486,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 exception as it is the default language and may not // "en" is an exeption 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
@@ -1,16 +0,0 @@
#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];
}
}
+8 -18
Ver Arquivo
@@ -23,34 +23,24 @@ using namespace QKeychain;
namespace OCC namespace OCC
{ {
void HttpCredentialsGui::askFromUser() QString HttpCredentialsGui::queryPassword(bool *ok, const QString& hint)
{ {
// The rest of the code assumes that this will be done asynchronously if (!ok) {
QMetaObject::invokeMethod(this, "askFromUserAsync", Qt::QueuedConnection); return QString();
} }
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 (!_fetchErrorString.isEmpty()) { if (!hint.isEmpty()) {
msg += QLatin1String("\n") + tr("Reading from keychain failed with error: '%1'").arg( msg += QLatin1String("\n") + hint + QLatin1String("\n");
_fetchErrorString) + QLatin1String("\n");
} }
bool ok = false; return QInputDialog::getText(0, tr("Enter Password"), msg,
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
+1 -2
Ver Arquivo
@@ -28,8 +28,7 @@ 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) {}
void askFromUser() Q_DECL_OVERRIDE; QString queryPassword(bool *ok, const QString& hint) Q_DECL_OVERRIDE;
Q_INVOKABLE void askFromUserAsync();
}; };
} // namespace OCC } // namespace OCC
@@ -0,0 +1,55 @@
/*
* 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
@@ -0,0 +1,53 @@
/*
* 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
+89 -13
Ver Arquivo
@@ -12,6 +12,7 @@
* for more details. * for more details.
*/ */
#include <QMutex>
#include <QSettings> #include <QSettings>
#include <QNetworkReply> #include <QNetworkReply>
#include <QMessageBox> #include <QMessageBox>
@@ -20,6 +21,7 @@
#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"
@@ -44,6 +46,39 @@ 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()
@@ -51,12 +86,14 @@ 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)
{ {
@@ -93,7 +130,12 @@ 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
@@ -149,12 +191,17 @@ bool ShibbolethCredentials::ready() const
return _ready; return _ready;
} }
void ShibbolethCredentials::fetchFromKeychain() void ShibbolethCredentials::fetch()
{ {
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();
@@ -164,14 +211,10 @@ void ShibbolethCredentials::fetchFromKeychain()
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)
@@ -186,10 +229,9 @@ 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
@@ -223,7 +265,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 can't access the API without that.. a bug in the server maybe?) // (because for some reason we wan'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);
@@ -254,14 +296,48 @@ void ShibbolethCredentials::slotUserFetched(const QString &user)
_stillValid = true; _stillValid = true;
_ready = true; _ready = true;
Q_EMIT asked(); _fetchJobInProgress = false;
Q_EMIT fetched();
} }
void ShibbolethCredentials::slotBrowserRejected() void ShibbolethCredentials::slotBrowserRejected()
{ {
_ready = false; _ready = false;
Q_EMIT asked(); _fetchJobInProgress = false;
Q_EMIT fetched();
}
void ShibbolethCredentials::invalidateAndFetch()
{
_ready = false;
_fetchJobInProgress = true;
// delete the credentials, then in the slot fetch them again (which will trigger browser)
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
job->setSettings(_account->settingsWithGroup(Theme::instance()->appName(), job).release());
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotInvalidateAndFetchInvalidateDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), "shibAssertion"));
job->start();
}
void ShibbolethCredentials::slotInvalidateAndFetchInvalidateDone(QKeychain::Job*)
{
connect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
_fetchJobInProgress = false;
// small hack to support the ShibbolethRefresher hack
// we already rand fetch() with a valid account object,
// and hence know the url on refresh
fetch();
}
void ShibbolethCredentials::onFetched()
{
disconnect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
Q_EMIT invalidatedAndFetched(prepareCookieData());
} }
void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job) void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
@@ -279,10 +355,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 {
_ready = false; showLoginWindow();
Q_EMIT fetched();
} }
} }
+9 -3
Ver Arquivo
@@ -44,7 +44,7 @@ Q_OBJECT
public: public:
ShibbolethCredentials(); ShibbolethCredentials();
/* create credentials for an already connected account */ /* create a 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,8 +55,7 @@ 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 fetchFromKeychain() Q_DECL_OVERRIDE; void fetch() 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;
@@ -67,10 +66,15 @@ 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();
@@ -78,6 +82,7 @@ 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);
@@ -88,6 +93,7 @@ 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;
+5 -29
Ver Arquivo
@@ -30,9 +30,7 @@
#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"
@@ -90,14 +88,14 @@ Folder::Folder(const FolderDefinition& definition,
bool Folder::init() bool Folder::init()
{ {
// We need to reconstruct the url because the path needs to be fully decoded, as csync will re-encode the path: // We need to reconstruct the url because the path need 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 problem 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 provlem 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);
@@ -159,7 +157,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, fi) ) { if( !FileSystem::fileExists(_definition.localPath) ) {
_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() ) {
@@ -702,28 +700,6 @@ 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
@@ -1017,14 +993,14 @@ void Folder::slotSyncFinished()
} }
if (_syncResult.status() == SyncResult::Success) { if (_syncResult.status() == SyncResult::Success) {
// Clear the white list as all the folders that should be on that list are sync-ed // Clear the white list as all the folder 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
// clear the current running sync folder marker. // clearing 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,16 +197,6 @@ 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();
+22 -10
Ver Arquivo
@@ -60,6 +60,7 @@ 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();
@@ -148,6 +149,10 @@ 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
@@ -244,7 +249,7 @@ int FolderMan::setupFoldersMigration()
dir.setFilter(QDir::Files | QDir::Hidden); dir.setFilter(QDir::Files | QDir::Hidden);
QStringList list = dir.entryList(); QStringList list = dir.entryList();
// Normally there should be only one account when migrating. // Normaly 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 );
@@ -345,8 +350,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 when the filename comes out // check the unescaped variant (for the case the filename comes out
// of the directory listing). If the file does not exist, escape the // of the directory listing. If the file is not existing, escape the
// file and try again. // file and try again.
QFileInfo cfgFile( _folderConfigPath, file); QFileInfo cfgFile( _folderConfigPath, file);
@@ -356,7 +361,7 @@ Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
cfgFile.setFile( _folderConfigPath, escapedAlias ); cfgFile.setFile( _folderConfigPath, escapedAlias );
} }
if( !cfgFile.isReadable() ) { if( !cfgFile.isReadable() ) {
qDebug() << "Cannot read folder definition for alias " << cfgFile.filePath(); qDebug() << "Can not read folder definition for alias " << cfgFile.filePath();
return folder; return folder;
} }
@@ -594,12 +599,12 @@ void FolderMan::slotAccountStateChanged()
} }
} }
// only enable or disable foldermans will schedule and do syncs. // only enable or disable foldermans will to 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 for the connection to come back on. // We have things in our queue that were waiting the the connection to go back on.
startScheduledSyncSoon(); startScheduledSyncSoon();
} }
_syncEnabled = enabled; _syncEnabled = enabled;
@@ -691,6 +696,13 @@ 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();
}
} }
} }
@@ -906,7 +918,7 @@ bool FolderMan::startFromScratch( const QString& localFolder )
_socketApi->slotUnregisterPath(f->alias()); _socketApi->slotUnregisterPath(f->alias());
} }
f->journalDb()->close(); f->journalDb()->close();
f->slotTerminateSync(); // Normally it should not be running, but viel hilft viel f->slotTerminateSync(); // Normaly it should not be running, but viel hilft viel
} }
} }
@@ -936,7 +948,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 so we do not use the old determined system proxy // Need to do this have us not use the old determined system proxy
f->accountState()->account()->networkAccessManager()->setProxy( f->accountState()->account()->networkAccessManager()->setProxy(
QNetworkProxy(QNetworkProxy::DefaultProxy)); QNetworkProxy(QNetworkProxy::DefaultProxy));
} }
@@ -962,7 +974,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 folders: // if more folder:
// 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
@@ -1079,7 +1091,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( "Waiting to start syncing." ); folderMessage = tr( "Waits 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 already. * Make sure that this folder, or any subfolder is not sync'ed alrady.
* *
* \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 then. * Attention: The folder may be zero. Do a general update of the state than.
*/ */
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 schedule an ETag job // slot to scheule 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");
} }
// allocate each item size in listview. //alocate 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
{ {
+48 -115
Ver Arquivo
@@ -90,7 +90,7 @@ Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex &index ) const
} }
return Qt::ItemIsEnabled | ret; return Qt::ItemIsEnabled | ret;
} }
case FetchLabel: case ErrorLabel:
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 you are already syncing all your files. " return tr("Adding folder is disabled because your 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,20 +151,11 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
} }
} }
return QVariant(); return QVariant();
case FetchLabel: case ErrorLabel:
{
const auto x = static_cast<SubFolderInfo *>(index.internalPointer());
switch(role) { switch(role) {
case Qt::DisplayRole: case Qt::DisplayRole: return tr("Error while loading the list of folders from the server.");
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;
} }
@@ -201,7 +192,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 {
// keep the previous icon for the prepare phase. // kepp 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 {
@@ -236,7 +227,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 siblings are also checked // all the sibilings 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) {
@@ -311,7 +302,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->hasLabel()) if (info->_hasError)
return 1; return 1;
return info->_subs.count(); return info->_subs.count();
} }
@@ -319,11 +310,7 @@ 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())) {
if (sub->hasLabel()) { return sub->_hasError ? ErrorLabel : SubFolder;
return FetchLabel;
} else {
return SubFolder;
}
} }
if (index.row() < _folders.count()) { if (index.row() < _folders.count()) {
return RootFolder; return RootFolder;
@@ -336,7 +323,8 @@ 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->hasLabel()) { if (parentInfo->_hasError) {
// Error label
return 0; return 0;
} }
return &parentInfo->_subs[index.row()]; return &parentInfo->_subs[index.row()];
@@ -396,21 +384,20 @@ QModelIndex FolderStatusModel::index(int row, int column, const QModelIndex& par
} }
switch(classify(parent)) { switch(classify(parent)) {
case AddButton: case AddButton:
case FetchLabel: case ErrorLabel:
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 pinfo = static_cast<SubFolderInfo*>(parent.internalPointer()); auto info = static_cast<SubFolderInfo*>(parent.internalPointer());
if (pinfo->_subs.count() <= parent.row()) if (info->_subs.count() <= parent.row())
return QModelIndex(); // should not happen return QModelIndex(); // should not happen
auto & info = pinfo->_subs[parent.row()]; if (!info->_subs.at(parent.row())._hasError
if (!info.hasLabel() && info->_subs.at(parent.row())._subs.count() <= row)
&& info._subs.count() <= row)
return QModelIndex(); // should not happen return QModelIndex(); // should not happen
return createIndex(row, column, &info); return createIndex(row, column, &info->_subs[parent.row()]);
} }
} }
return QModelIndex(); return QModelIndex();
@@ -426,7 +413,7 @@ QModelIndex FolderStatusModel::parent(const QModelIndex& child) const
case AddButton: case AddButton:
return QModelIndex(); return QModelIndex();
case SubFolder: case SubFolder:
case FetchLabel: case ErrorLabel:
break; break;
} }
auto pathIdx = static_cast<SubFolderInfo*>(child.internalPointer())->_pathIdx; auto pathIdx = static_cast<SubFolderInfo*>(child.internalPointer())->_pathIdx;
@@ -466,9 +453,6 @@ 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;
@@ -483,9 +467,7 @@ 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('/'))) {
@@ -501,12 +483,7 @@ 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();
QPersistentModelIndex persistentIndex(parent); job->setProperty(propertyParentIndexC , QVariant::fromValue<QPersistentModelIndex>(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_)
@@ -519,35 +496,24 @@ void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
return; return;
} }
if (parentInfo->hasLabel()) { auto list = list_;
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();
} }
parentInfo->_fetching = false; beginInsertRows(idx, 0, list.count() - 1);
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 += '/';
// Drop the folder base path and check for excludes. parentInfo->_fetched = true;
QMutableListIterator<QString> it(list); parentInfo->_fetching = false;
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) {
@@ -565,6 +531,7 @@ 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();
@@ -613,17 +580,14 @@ 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 { } else if (!parentInfo->_hasError) {
if (!parentInfo->hasLabel()) { beginInsertRows(idx, 0, 0);
beginInsertRows(idx, 0, 0);
endInsertRows();
}
parentInfo->_hasError = true; parentInfo->_hasError = true;
endInsertRows();
} }
parentInfo->_fetching = false;
parentInfo->_fetchingLabel = false;
} }
} }
@@ -697,7 +661,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 were changes // do the sync if there was 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()) {
@@ -760,7 +724,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
<< FolderStatusDelegate::WarningCount; << FolderStatusDelegate::WarningCount;
if (!progress._currentDiscoveredFolder.isEmpty()) { if (!progress._currentDiscoveredFolder.isEmpty()) {
pi->_progressString = tr("Checking for changes in '%1'").arg(progress._currentDiscoveredFolder); pi->_progressString = tr("Discovering '%1'").arg(progress._currentDiscoveredFolder);
emit dataChanged(index(folderIndex), index(folderIndex), roles); emit dataChanged(index(folderIndex), index(folderIndex), roles);
return; return;
} }
@@ -865,7 +829,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 attempt to estimate the time left if there is no kb to transfer. // Don't attemt 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);
} }
@@ -873,7 +837,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
int overallPercent = 0; int overallPercent = 0;
if( totalFileCount > 0 ) { if( totalFileCount > 0 ) {
// Add one 'byte' for each file so the percentage is moving when deleting or renaming files // Add one 'byte' for each files 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);
@@ -927,8 +891,13 @@ 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
auto & info = _folders[folderIndex]; _folders[folderIndex]._fetched = false;
info.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();
}
return; return;
} }
} }
@@ -964,53 +933,17 @@ void FolderStatusModel::slotNewBigFolder()
} }
if (folderIndex < 0) { return; } if (folderIndex < 0) { return; }
_folders[folderIndex].resetSubs(this, index(folderIndex)); _folders[folderIndex]._fetched = false;
_folders[folderIndex]._fetching = false;
if (!_folders.at(folderIndex)._subs.isEmpty()) {
beginRemoveRows(index(folderIndex), 0, _folders.at(folderIndex)._subs.count() - 1);
_folders[folderIndex]._subs.clear();
endRemoveRows();
}
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
+8 -33
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,30 +51,20 @@ public:
struct SubFolderInfo { struct SubFolderInfo {
SubFolderInfo() SubFolderInfo()
: _folder(0), _size(0), _fetched(false), _fetching(false), : _folder(0), _size(0), _fetched(false), _fetching(false), _isUndecided(false),
_hasError(false), _fetchingLabel(false), _isUndecided(false), _checked(Qt::Checked) {} _hasError(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; // Whether a LSCOL job is currently running bool _fetching;
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
@@ -89,7 +79,7 @@ public:
QVector<SubFolderInfo> _folders; QVector<SubFolderInfo> _folders;
enum ItemType { RootFolder, SubFolder, AddButton, FetchLabel }; enum ItemType { RootFolder, SubFolder, AddButton, ErrorLabel };
ItemType classify(const QModelIndex &index) const; ItemType classify(const QModelIndex &index) const;
SubFolderInfo *infoForIndex(const QModelIndex &index) const; SubFolderInfo *infoForIndex(const QModelIndex &index) const;
@@ -98,7 +88,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 fetched from the server before * Note: this method returns an invalid index if the path was not fetch from the server before
*/ */
QModelIndex indexForPath(Folder *f, const QString &path) const; QModelIndex indexForPath(Folder *f, const QString &path) const;
@@ -115,25 +105,12 @@ 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>())
@@ -142,9 +119,7 @@ private:
signals: signals:
void dirtyChanged(); void dirtyChanged();
void suggestExpand(const QModelIndex &); // Tell the view that this item should be expanded because it has an undecided item void suggestExpand(const QModelIndex &); // Tell the view that this item should be expanded because it has a undecided item
friend struct SubFolderInfo;
}; };
} // namespace OCC } // namespace OCC
+75 -13
Ver Arquivo
@@ -32,14 +32,12 @@
#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, Folder* folder) FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
: QObject(folder), : QObject(parent),
_folder(folder) _ignoreHidden(true)
{ {
_d.reset(new FolderWatcherPrivate(this, root)); _d.reset(new FolderWatcherPrivate(this, root));
@@ -49,17 +47,81 @@ FolderWatcher::FolderWatcher(const QString &root, Folder* folder)
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;
#ifndef OWNCLOUD_TEST // if events caused by changes to hidden files should be ignored, a QFileInfo
if (_folder->isFileExcludedAbsolute(path)) { // object will tell us if the file is hidden
qDebug() << "* Ignoring file" << path; if( _ignoreHidden ) {
return true; QFileInfo fInfo(path);
if( fInfo.isHidden() ) {
qDebug() << "* Discarded as is hidden!" << fInfo.filePath();
return true;
}
}
// TODO: Best use csync_excluded_no_ctx() here somehow!
foreach (QString pattern, _ignores) {
// The leading ] is a tag and not part of the pattern.
if (pattern.startsWith(']')) {
pattern.remove(0, 1);
}
if(pattern.endsWith('/')) {
// directory only pattern. But since path components are
// checked later, we cut off the trailing dir.
pattern.chop(1);
}
QRegExp regexp(pattern);
regexp.setPatternSyntax(QRegExp::Wildcard);
// if the pattern contains / it needs to match the entire path
if (pattern.contains('/') && regexp.exactMatch(path)) {
qDebug() << "* Discarded by ignore pattern: " << path;
return true;
}
QStringList components = path.split('/');
foreach (const QString& comp, components) {
if(regexp.exactMatch(comp)) {
qDebug() << "* Discarded by component ignore pattern " << comp;
return true;
}
}
} }
#endif
return false; return false;
} }
@@ -75,8 +137,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 is more than one file being updated frequently? // - what if there are more than one file being updated frequently?
// - why do we skip the file altogether instead of e.g. reducing the upload frequency? // - why do we skip the file alltogether 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();
+22 -6
Ver Arquivo
@@ -14,6 +14,8 @@
#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>
@@ -28,17 +30,16 @@ class QTimer;
namespace OCC { namespace OCC {
class FolderWatcherPrivate; class FolderWatcherPrivate;
class Folder;
/** /**
* @brief Monitors a directory recursively for changes * @brief Montiors 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 add them to the list of monitored * does not automatically adds 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.
* *
@@ -52,13 +53,23 @@ public:
/** /**
* @param root Path of the root of the folder * @param root Path of the root of the folder
*/ */
FolderWatcher(const QString &root, Folder* folder = 0L); FolderWatcher(const QString &root, QObject *parent = 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 backends that are recursive * This is a no-op for backend that are recursive
*/ */
void addPath(const QString&); void addPath(const QString&);
void removePath(const QString&); void removePath(const QString&);
@@ -66,6 +77,10 @@ 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. */
@@ -84,9 +99,10 @@ protected:
private: private:
QScopedPointer<FolderWatcherPrivate> _d; QScopedPointer<FolderWatcherPrivate> _d;
QStringList _ignores;
QTime _timer; QTime _timer;
QSet<QString> _lastPaths; QSet<QString> _lastPaths;
Folder* _folder; bool _ignoreHidden;
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()->singleAccount()); || Theme::instance()->multiAccount());
} }
+53 -57
Ver Arquivo
@@ -53,54 +53,6 @@
<string>Advanced</string> <string>Advanced</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="ignoredFilesButton">
<property name="text">
<string>Edit Ignored Files</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<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="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="addAccountButton">
<property name="text">
<string>Add an Account</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<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="1" column="0" colspan="2"> <item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
@@ -146,20 +98,64 @@
</layout> </layout>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_5"> <widget class="QCheckBox" name="crashreporterCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show crash reporter</string>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>
<widget class="QCheckBox" name="crashreporterCheckBox"> <widget class="QPushButton" name="ignoredFilesButton">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Show crash reporter</string> <string>Edit Ignored Files</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_4">
<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="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="addAccountButton">
<property name="text">
<string>Add an Account</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<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> </layout>
</item> </item>
</layout> </layout>
-3
Ver Arquivo
@@ -16,7 +16,6 @@
#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>
@@ -127,8 +126,6 @@ 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 coming from this thread, and queued for the one in a different thread // Direct connection for log comming 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 piece to load the Finder Plugin. // MacOSX: perform a AppleScript code peace 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() << "Load Finder Overlay-Plugin: " << resultAsString << ": " << p.exitCode() qDebug() << "Laod 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. do not just display the result of the latest sync) // display the info of the least successful sync (eg. 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 actions. // We must call deleteLater because we might be called from the press in one of the action.
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 of all accounts")); _actionLogout->setText(tr("Log out everywhere"));
} 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 to all accounts...")); _actionLogin->setText(tr("Log in everywhere..."));
} 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 Alias * open the folder with the given Alais
*/ */
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("Checking for changes in '%1'") _actionStatus->setText( tr("Discovering '%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 happened. // display a warn icon if warnings happend.
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 before we check what credential it actually is. // Set fake credentials beforfe 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 end has finished the basic setup. // Method executed when the user ends 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 detecting switches /// The hostname:port of the current proxy, used for detetcting 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 fractional bytes (#1374) // The server can return frational 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 these 3 conditions are met: * The quota is requested if those 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 immediately if the last time * When setting it to active it will request the quota imediatly 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 the quota was received last QDateTime _lastQuotaRecieved; // the time at which de quota was recieved 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
}; };
+4 -25
Ver Arquivo
@@ -156,9 +156,10 @@ void SelectiveSyncTreeView::recursiveInsert(QTreeWidgetItem* parent, QStringList
} }
} }
void SelectiveSyncTreeView::slotUpdateDirectories(QStringList list) void SelectiveSyncTreeView::slotUpdateDirectories(const 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;
@@ -173,29 +174,12 @@ void SelectiveSyncTreeView::slotUpdateDirectories(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;
} }
@@ -221,11 +205,6 @@ void SelectiveSyncTreeView::slotUpdateDirectories(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) {
@@ -276,7 +255,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 siblings are also checked // all the sibilings 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;
// Estimates the total size of checked items (recursively) //Estimate the total size of checked item (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(QStringList); void slotUpdateDirectories(const 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 sensitivity of the human eye to certain colors // account for different sensitivty 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 restoring the // do not show minimize button. There is no use, and retoring 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);
+9 -91
Ver Arquivo
@@ -29,21 +29,11 @@
#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) :
@@ -60,10 +50,6 @@ 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()));
@@ -78,10 +64,8 @@ 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()));
@@ -91,7 +75,6 @@ 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);
@@ -134,7 +117,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 answered that // copy it over, but that is skipped as not all questions can be anwered 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);
@@ -159,27 +142,18 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
// Parse capabilities // Parse capabilities
// If password is enforced then don't allow users to disable it // If password is enforced make don't allow users to disable it
if (_account->capabilities().sharePublicLinkEnforcePassword()) { if (_account->capabilities().publicLinkEnforcePassword()) {
_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().sharePublicLinkEnforceExpireDate()) { if (_account->capabilities().publicLinkEnforceExpireDate()) {
_ui->checkBox_expire->setEnabled(false); _ui->checkBox_expire->setEnabled(false);
_ui->calendar->setMaximumDate(QDate::currentDate().addDays( _ui->calendar->setMaximumDate(QDate::currentDate().addDays(
_account->capabilities().sharePublicLinkExpireDateDays() _account->capabilities().publicLinkExpireDateDays()
)); ));
} }
// 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 ) {
@@ -250,7 +224,7 @@ void ShareDialog::slotPasswordReturnPressed()
void ShareDialog::slotPasswordChanged(const QString& newText) void ShareDialog::slotPasswordChanged(const QString& newText)
{ {
// disable the set-password button // disable the set-passwort button
_ui->pushButton_setPassword->setEnabled( newText.length() > 0 ); _ui->pushButton_setPassword->setEnabled( newText.length() > 0 );
} }
@@ -381,17 +355,6 @@ 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")) {
@@ -503,7 +466,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().sharePublicLinkEnforcePassword()) { if (_account->capabilities().publicLinkEnforcePassword()) {
_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);
@@ -578,7 +541,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);
setExpireDate(date); ShareDialog::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);
@@ -590,55 +553,10 @@ 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)
@@ -721,7 +639,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
// as the file-to-copy we can share it. // then the file-to-copy we can share it.
_sharePath.clear(); _sharePath.clear();
} else { } else {
_uploadFails = 0; _uploadFails = 0;
-5
Ver Arquivo
@@ -100,8 +100,6 @@ 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:
@@ -111,7 +109,6 @@ 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;
@@ -133,10 +130,8 @@ 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;
}; };
} }
+61 -84
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>277</height> <height>241</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -92,84 +92,6 @@
<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">
@@ -206,17 +128,23 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0"> <item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_editing"> <layout class="QHBoxLayout" name="horizontalLayout_password">
<item> <item>
<widget class="QCheckBox" name="checkBox_editing"> <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"> <property name="text">
<string>Allow editing</string> <string>Set password</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@@ -230,6 +158,54 @@
</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>
@@ -276,6 +252,7 @@
<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>
+57 -45
Ver Arquivo
@@ -28,8 +28,6 @@
#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>
@@ -40,7 +38,6 @@
#include <QDir> #include <QDir>
#include <QApplication> #include <QApplication>
#include <QLocalSocket> #include <QLocalSocket>
#include <QStringBuilder>
#include <sqlite3.h> #include <sqlite3.h>
@@ -55,12 +52,30 @@
// 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;
@@ -126,6 +141,29 @@ 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()
@@ -230,7 +268,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, "").toSocketAPIString()); this->fileStatus(f, "", _excludes).toSocketAPIString());
broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() ); broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() );
} else { } else {
@@ -273,7 +311,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 matching entry item is not found // from the plugins have that too. Otherwise the according 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('/');
@@ -349,12 +387,13 @@ 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); SyncFileStatus fileStatus = this->fileStatus(syncFolder, file, _excludes);
statusString = fileStatus.toSocketAPIString(); statusString = fileStatus.toSocketAPIString();
} }
const QString message = QLatin1String("STATUS:") % statusString % QLatin1Char(':') % QDir::toNativeSeparators(argument); QString message = QLatin1String("STATUS:")+statusString+QLatin1Char(':')
+QDir::toNativeSeparators(argument);
sendMessage(socket, message); sendMessage(socket, message);
} }
@@ -408,39 +447,6 @@ 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()));
@@ -535,7 +541,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) SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes )
{ {
QString file = folder->path(); QString file = folder->path();
QString fileName = systemFileName.normalized(QString::NormalizationForm_C); QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
@@ -552,8 +558,7 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
fileNameSlash += QLatin1Char('/'); fileNameSlash += QLatin1Char('/');
} }
const QFileInfo fi(file); if( !FileSystem::fileExists(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);
} }
@@ -561,6 +566,7 @@ 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"
@@ -575,11 +581,17 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
} }
// Is it excluded? // Is it excluded?
if( folder->isFileExcludedAbsolute(file) ) { CSYNC_EXCLUDE_TYPE excl = csync_excluded_no_ctx(excludes, fileName.toUtf8(), type);
if( folder->ignoreHiddenFiles()
&& (fi.isHidden()
|| fi.fileName().startsWith(QLatin1Char('.'))) ) {
excl = CSYNC_FILE_EXCLUDE_HIDDEN;
}
if( excl != CSYNC_NOT_EXCLUDED ) {
return SyncFileStatus(SyncFileStatus::STATUS_IGNORE); return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
} }
// Error if it is in the selective sync blacklist // Error if it is in the selective sync blacklistr
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);
+8 -2
Ver Arquivo
@@ -16,6 +16,10 @@
#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"
@@ -52,6 +56,8 @@ 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);
@@ -64,7 +70,7 @@ private slots:
void slotSyncItemDiscovered(const QString &, const SyncFileItem &); void slotSyncItemDiscovered(const QString &, const SyncFileItem &);
private: private:
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName); SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes );
SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName ); SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName );
SqlQuery *getSqlQuery( Folder *folder ); SqlQuery *getSqlQuery( Folder *folder );
@@ -77,12 +83,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 restarted. That happens in folderman. // running, the running app is restart. 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 their own update scheme, a little * To reflect that all platforms have its 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 of the underlying linux distro * version. On Linux, the update capabilities by the underlying linux distro
* are relied on, and thus the PassiveUpdateNotifier just shows a notification * is 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 proprietary XML format to fetch update information * @brief Class that uses an ownCloud propritary XML format to fetch update information
* @ingroup gui * @ingroup gui
*/ */
class OCUpdater : public QObject, public Updater class OCUpdater : public QObject, public Updater
+1 -2
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 cancelled the dialog // Because clicking on it also changes it, restore it to the previous state in case the user cancel 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,4 +308,3 @@ void OwncloudAdvancedSetupPage::slotQuotaRetrieved(const QVariantMap &result)
} }
} // namespace OCC } // namespace OCC
-175
Ver Arquivo
@@ -1,175 +0,0 @@
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
@@ -1,34 +0,0 @@
/*
* 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,7 +64,6 @@ 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
@@ -82,22 +81,14 @@ 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
@@ -114,10 +105,6 @@ 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
+3 -11
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,21 +263,13 @@ 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")) {
QString message = reader.readElementText(); return reader.readElementText();
if (!message.isEmpty()) {
return message;
}
} else if (reader.name() == QLatin1String("exception")) {
exception = reader.readElementText();
} }
} }
// Fallback, if message could not be found return QString::null;
return exception;
} }
QString errorMessage(const QString& baseError, const QByteArray& body) QString errorMessage(const QString& baseError, const QByteArray& body)
+2 -3
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 received bool _timedout; // set to true when the timeout slot is recieved
// 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,12 +91,11 @@ 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;
+9 -24
Ver Arquivo
@@ -159,8 +159,6 @@ 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
@@ -181,7 +179,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 losing its ownership. */ of not loosing its ownership. */
void Account::lendCookieJarTo(QNetworkAccessManager *guest) void Account::lendCookieJarTo(QNetworkAccessManager *guest)
{ {
auto jar = _am->cookieJar(); auto jar = _am->cookieJar();
@@ -443,13 +441,16 @@ 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();
} }
@@ -478,25 +479,9 @@ 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
+1 -7
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 parent is specified, the caller must destroy the settings */ with the given parent. If no parents 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,10 +154,6 @@ 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);
@@ -172,7 +168,6 @@ 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*);
@@ -183,7 +178,6 @@ 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 download to timeout // any upload 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 download jobs // choke all other UploadDevices
Q_FOREACH(GETFileJob *gfj, _downloadJobList) { Q_FOREACH(GETFileJob *gfj, _downloadJobList) {
if (gfj != _relativeLimitCurrentMeasuredJob) { if (gfj != _relativeLimitCurrentMeasuredJob) {
gfj->setBandwidthLimited(true); gfj->setBandwidthLimited(true);
+3 -33
Ver Arquivo
@@ -23,49 +23,19 @@ Capabilities::Capabilities(const QVariantMap &capabilities)
{ {
} }
bool Capabilities::shareAPI() const bool Capabilities::publicLinkEnforcePassword() 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::sharePublicLinkEnforceExpireDate() const bool Capabilities::publicLinkEnforceExpireDate() 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::sharePublicLinkExpireDateDays() const int Capabilities::publicLinkExpireDateDays() 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();
}
} }
+4 -10
Ver Arquivo
@@ -18,12 +18,11 @@
#include "owncloudlib.h" #include "owncloudlib.h"
#include <QVariantMap> #include <QVariantMap>
#include <QStringList>
namespace OCC { namespace OCC {
/** /**
* @brief The Capabilities class represents the capabilities of an ownCloud * @brief The Capabilities class represent the capabilities of an ownCloud
* server * server
* @ingroup libsync * @ingroup libsync
*/ */
@@ -32,14 +31,9 @@ class OWNCLOUDSYNC_EXPORT Capabilities {
public: public:
Capabilities(const QVariantMap &capabilities); Capabilities(const QVariantMap &capabilities);
bool shareAPI() const; bool publicLinkEnforcePassword() const;
bool sharePublicLink() const; bool publicLinkEnforceExpireDate() const;
bool sharePublicLinkAllowUpload() const; int publicLinkExpireDateDays() const;
bool sharePublicLinkEnforcePassword() const;
bool sharePublicLinkEnforceExpireDate() const;
int sharePublicLinkExpireDateDays() const;
bool shareResharing() const;
QStringList supportedChecksumTypes() const;
private: private:
QVariantMap _capabilities; QVariantMap _capabilities;
+1 -5
Ver Arquivo
@@ -588,11 +588,7 @@ void ConfigFile::setNewBigFolderSizeLimit(bool isChecked, quint64 mbytes)
bool ConfigFile::monoIcons() const bool ConfigFile::monoIcons() const
{ {
QSettings settings(configFile(), QSettings::IniFormat); QSettings settings(configFile(), QSettings::IniFormat);
bool deflt = false; return settings.value(QLatin1String(monoIconsC), false).toBool();
if( Utility::isMac() ) {
deflt = true;
}
return settings.value(QLatin1String(monoIconsC), deflt).toBool();
} }
void ConfigFile::setMonoIcons(bool useMonoIcons) void ConfigFile::setMonoIcons(bool useMonoIcons)
+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 milliseconds has to be larger than 5000 */ /* Set poll interval. Value in microseconds 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 */
+13 -5
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 CredentialsMissingOrWrong: case CredentialsWrong:
return QLatin1String("Credentials Wrong"); return QLatin1String("Credentials Wrong");
case StatusNotFound: case StatusNotFound:
return QLatin1String("Status not found"); return QLatin1String("Status not found");
@@ -121,10 +121,18 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf
} }
// now check the authentication // now check the authentication
if (_account->credentials()->ready()) AbstractCredentials *creds = _account->credentials();
if (creds->ready()) {
QTimer::singleShot( 0, this, SLOT( checkAuthentication() )); QTimer::singleShot( 0, this, SLOT( checkAuthentication() ));
else } else {
reportResult( CredentialsMissingOrWrong ); // We can't proceed with the auth check because we don't have credentials.
// Fetch them now! Once fetched, a new connectivity check will be
// initiated anyway.
creds->fetch();
// no result is reported
deleteLater();
}
} }
// status.php could not be loaded (network or server issue!). // status.php could not be loaded (network or server issue!).
@@ -176,7 +184,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 = CredentialsMissingOrWrong; stat = CredentialsWrong;
} else if( reply->error() != QNetworkReply::NoError ) { } else if( reply->error() != QNetworkReply::NoError ) {
_errors << errorMessage(reply->errorString(), reply->readAll()); _errors << errorMessage(reply->errorString(), reply->readAll());
+8 -7
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 are two entry points: checkServerAndAuth and checkAuthentication * There is two entry point: checkServerAndAuth and checkAuthentication
* checkAuthentication is the quick version that only does the propfind * checkAutentication is the quick version that only do 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,16 +44,17 @@ namespace OCC {
| |
+-> slotJobTimeout --> X +-> slotJobTimeout --> X
| |
+-> slotStatusFound --+--> X (if credentials are still missing) +-> slotStatusFound
| credential->fetch() --+
+---------------------------+ |
+-----------------------------------+
| |
*-+-> checkAuthentication (PROPFIND on root) *-+-> checkAuthentication (PROPFIND on root)
PropfindJob PropfindJob
| |
+-> slotAuthFailed --> X +-> slotAuthFailed --> X
| |
+-> slotAuthSuccess --+--> X (depending if coming from checkServerAndAuth or not) +-> slotAuthSuccess --+--> X (depending if comming from checkServerAndAuth or not)
| |
+---------------------------+ +---------------------------+
| |
@@ -74,7 +75,7 @@ public:
Connected, Connected,
NotConfigured, NotConfigured,
ServerVersionMismatch, ServerVersionMismatch,
CredentialsMissingOrWrong, CredentialsWrong,
StatusNotFound, StatusNotFound,
UserCanceledCredentials, UserCanceledCredentials,
ServiceUnavailable, ServiceUnavailable,
+6 -3
Ver Arquivo
@@ -48,18 +48,21 @@ 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 fetchFromKeychain() = 0; virtual void fetch() = 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;
+1 -6
Ver Arquivo
@@ -56,16 +56,11 @@ bool DummyCredentials::stillValid(QNetworkReply *reply)
return true; return true;
} }
void DummyCredentials::fetchFromKeychain() void DummyCredentials::fetch()
{ {
Q_EMIT(fetched()); Q_EMIT(fetched());
} }
void DummyCredentials::askFromUser()
{
Q_EMIT(asked());
}
void DummyCredentials::persist() void DummyCredentials::persist()
{} {}
+1 -2
Ver Arquivo
@@ -35,8 +35,7 @@ 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 fetchFromKeychain() Q_DECL_OVERRIDE; void fetch() 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 {}
}; };
+55 -9
Ver Arquivo
@@ -82,16 +82,23 @@ const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns } // ns
HttpCredentials::HttpCredentials() HttpCredentials::HttpCredentials()
: _ready(false) : _user(),
_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),
_ready(true),
_certificatePath(certificatePath), _certificatePath(certificatePath),
_certificatePasswd(certificatePasswd) _certificatePasswd(certificatePasswd),
_ready(true),
_fetchJobInProgress(false)
{ {
} }
@@ -193,8 +200,12 @@ QString HttpCredentials::fetchUser()
return _user; return _user;
} }
void HttpCredentials::fetchFromKeychain() void HttpCredentials::fetch()
{ {
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();
@@ -224,6 +235,8 @@ void HttpCredentials::fetchFromKeychain()
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)
@@ -243,6 +256,7 @@ 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
@@ -252,12 +266,44 @@ 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());
_fetchErrorString = job->error() != EntryNotFound ? job->errorString() : QString(); const QString kck = keychainKey(_account->url().toString(), _user);
job->setKey(kck);
_password = QString(); connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
_ready = false; job->start();
emit fetched(); _readPwdFromDeprecatedPlace = false; // do try that only once.
_fetchJobInProgress = true;
// Note: if this read job succeeds, the value from the old place is still
// NOT persisted into the new account.
} else {
// interactive password dialog starts here
QString hint;
if (job->error() != EntryNotFound) {
hint = tr("Reading from keychain failed with error: '%1'").arg(
job->errorString());
}
bool ok;
QString pwd = queryPassword(&ok, hint);
_fetchJobInProgress = false;
if (ok) {
_password = pwd;
_ready = true;
persist();
} else {
_password = QString::null;
_ready = false;
}
emit fetched();
}
} }
} }
@@ -297,7 +343,7 @@ void HttpCredentials::invalidateToken()
// clear the session cookie. // clear the session cookie.
_account->clearCookieJar(); _account->clearCookieJar();
// let QNAM forget about the password // let QNAM fogets 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
+5 -3
Ver Arquivo
@@ -44,11 +44,12 @@ 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 fetchFromKeychain() Q_DECL_OVERRIDE; void fetch() 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; }
@@ -67,12 +68,13 @@ 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(FetchMode) void TokenCredentials::fetch()
{ {
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(FetchMode mode = Interactive) Q_DECL_OVERRIDE; void fetch() 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;
+1 -9
Ver Arquivo
@@ -13,14 +13,13 @@
*/ */
#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 {
@@ -328,10 +327,6 @@ 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
}
} }
} }
@@ -344,7 +339,6 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot()
deleteLater(); deleteLater();
return; return;
} }
emit etag(_firstEtag);
emit etagConcatenation(_etagConcatenation); emit etagConcatenation(_etagConcatenation);
emit finishedWithResult(_results); emit finishedWithResult(_results);
deleteLater(); deleteLater();
@@ -416,8 +410,6 @@ 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();
} }

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