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