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