-
Notifications
You must be signed in to change notification settings - Fork 667
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Minimal libcloudproviders support #7209
- Add it as an optional dependency for linux builds, controlled by WITH_LIBCLOUDPROVIDERS, which is enabled automatically if the dependencies are available. Note that >=0.3.0 is required. - Add code to export sync folders through the library and to add a minimal "Settings..." menu action. - Set up cloud provider registration by installing a file into a path like /usr/share/cloud-providers/. - DBus name and path are derived from APPLICATION_REV_DOMAIN by default and may be overridden with APPLICATION_CLOUDPROVIDERS_DBUS_NAME and APPLICATION_CLOUDPROVIDERS_DBUS_PATH if necessary.
- Loading branch information
Showing
12 changed files
with
462 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# (c) 2019 Copyright ownCloud GmbH | ||
# Redistribution and use is allowed according to the terms of the BSD license. | ||
# For details see the accompanying COPYING* file. | ||
|
||
find_path(LIBCLOUDPROVIDERS_INCLUDE_DIR | ||
NAMES | ||
cloudprovidersaccountexporter.h | ||
cloudprovidersproviderexporter.h | ||
PATH_SUFFIXES | ||
cloudproviders | ||
) | ||
|
||
find_library(LIBCLOUDPROVIDERS_LIBRARY | ||
NAMES | ||
cloudproviders | ||
PATHS | ||
/usr/lib | ||
/usr/lib/${CMAKE_ARCH_TRIPLET} | ||
/usr/local/lib | ||
${CMAKE_LIBRARY_PATH} | ||
${CMAKE_INSTALL_PREFIX}/lib | ||
) | ||
|
||
# Using version <0.3.0 would lead to crashes during runtime when accounts are unexported. | ||
get_filename_component(LIBCLOUDPROVIDERS_LIBRARY_REALPATH ${LIBCLOUDPROVIDERS_LIBRARY} REALPATH) | ||
if(${LIBCLOUDPROVIDERS_LIBRARY_REALPATH} MATCHES "\.([0-9]*)\.([0-9]*)\.([0-9]*)$") | ||
if ((${CMAKE_MATCH_1} EQUAL 0) AND (${CMAKE_MATCH_2} LESS 3)) | ||
message("libcloudproviders version is older than 0.3.0, not enabling it") | ||
set(LIBCLOUDPROVIDERS_LIBRARY "") | ||
endif() | ||
else() | ||
message("Can't determine libcloudproviders version, not enabling it") | ||
set(LIBCLOUDPROVIDERS_LIBRARY "") | ||
endif() | ||
|
||
include(FindPackageHandleStandardArgs) | ||
find_package_handle_standard_args( | ||
LIBCLOUDPROVIDERS | ||
DEFAULT_MSG | ||
LIBCLOUDPROVIDERS_LIBRARY LIBCLOUDPROVIDERS_INCLUDE_DIR) | ||
|
||
mark_as_advanced(LIBCLOUDPROVIDERS_INCLUDE_DIR LIBCLOUDPROVIDERS_LIBRARY) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[Cloud Providers] | ||
BusName=@APPLICATION_CLOUDPROVIDERS_DBUS_NAME@ | ||
ObjectPath=@APPLICATION_CLOUDPROVIDERS_DBUS_PATH@ | ||
Version=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
find_package(Libcloudproviders) | ||
find_package(PkgConfig REQUIRED) | ||
pkg_search_module(GIO gio-2.0) | ||
|
||
# The cloudproviders feature can only be enabled if the libcloudproviders | ||
# and gio-2.0 libraries are available | ||
set(LIBCLOUDPROVIDERS_POSSIBLE "") | ||
if(LIBCLOUDPROVIDERS_FOUND AND GIO_FOUND) | ||
set(LIBCLOUDPROVIDERS_POSSIBLE "1") | ||
endif() | ||
|
||
# User visible config switch | ||
set(WITH_LIBCLOUDPROVIDERS ${LIBCLOUDPROVIDERS_POSSIBLE} CACHE BOOL "Whether to bulid with libcloudproviders") | ||
|
||
if(WITH_LIBCLOUDPROVIDERS AND NOT LIBCLOUDPROVIDERS_POSSIBLE) | ||
message(FATAL_ERROR "Trying to enable libcloudproviders but dependencies are missing") | ||
endif() | ||
|
||
if(WITH_LIBCLOUDPROVIDERS) | ||
target_sources(${APPLICATION_EXECUTABLE} PRIVATE | ||
libcloudproviders/libcloudproviders.cpp | ||
) | ||
target_include_directories(${APPLICATION_EXECUTABLE} SYSTEM PRIVATE ${GIO_INCLUDE_DIRS}) | ||
target_compile_definitions(${APPLICATION_EXECUTABLE} PRIVATE WITH_LIBCLOUDPROVIDERS) | ||
target_link_libraries(${APPLICATION_EXECUTABLE} | ||
cloudproviders | ||
${GIO_LDFLAGS} | ||
) | ||
|
||
configure_file(libcloudproviders/cloud-provider.ini.in ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_CLOUDPROVIDERS_DBUS_NAME}.ini) | ||
install( | ||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_CLOUDPROVIDERS_DBUS_NAME}.ini | ||
DESTINATION "${DATADIR}/cloud-providers") | ||
|
||
message("Building with libcloudproviders") | ||
elseif(UNIX AND NOT APPLE) | ||
message("Building without libcloudproviders") | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
/* | ||
* Copyright (C) by Christian Kamm <mail@ckamm.de> | ||
* | ||
* 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. | ||
*/ | ||
|
||
extern "C" { | ||
#include <cloudproviders/cloudprovidersaccountexporter.h> | ||
#include <cloudproviders/cloudprovidersproviderexporter.h> | ||
#include <gio/gio.h> | ||
#include <glib.h> | ||
} | ||
|
||
#include "libcloudproviders.h" | ||
#include "libcloudproviders_p.h" | ||
|
||
#include <QMap> | ||
#include "folder.h" | ||
#include "folderman.h" | ||
#include "theme.h" | ||
#include "accountstate.h" | ||
#include "config.h" | ||
#include "account.h" | ||
#include "accountmanager.h" | ||
|
||
// These must match the name and path defined in a file in $DATADIR/cloud-providers/ | ||
const gchar dbusName[] = APPLICATION_CLOUDPROVIDERS_DBUS_NAME; | ||
const gchar dbusPath[] = APPLICATION_CLOUDPROVIDERS_DBUS_PATH; | ||
|
||
namespace OCC { | ||
|
||
LibCloudProvidersPrivate::~LibCloudProvidersPrivate() | ||
{ | ||
for (const auto folder : _folderExports.keys()) | ||
unexportFolder(folder); | ||
g_clear_object(&_exporter); | ||
if (_busOwnerId) | ||
g_bus_unown_name(_busOwnerId); | ||
} | ||
|
||
static void onBusAcquired(GDBusConnection *connection, const gchar *, gpointer userData) | ||
{ | ||
auto d = static_cast<LibCloudProvidersPrivate *>(userData); | ||
|
||
d->_exporter = cloud_providers_provider_exporter_new(connection, dbusName, dbusPath); | ||
cloud_providers_provider_exporter_set_name(d->_exporter, Theme::instance()->appNameGUI().toUtf8().constData()); | ||
|
||
d->updateExportedFolderList(); | ||
} | ||
|
||
static void onNameLost(GDBusConnection *, const gchar *, gpointer userData) | ||
{ | ||
auto d = static_cast<LibCloudProvidersPrivate *>(userData); | ||
|
||
d->_folderExports.clear(); | ||
g_clear_object(&d->_exporter); | ||
} | ||
|
||
void LibCloudProvidersPrivate::start() | ||
{ | ||
_busOwnerId = g_bus_own_name( | ||
G_BUS_TYPE_SESSION, dbusName, G_BUS_NAME_OWNER_FLAGS_NONE, | ||
&onBusAcquired, | ||
nullptr, // onNameAcquired | ||
&onNameLost, | ||
this, // user data | ||
nullptr // user data free func | ||
); | ||
|
||
auto folderMan = FolderMan::instance(); | ||
connect(folderMan, &FolderMan::folderListChanged, | ||
this, &LibCloudProvidersPrivate::updateExportedFolderList); | ||
connect(folderMan, &FolderMan::folderSyncStateChange, | ||
this, &LibCloudProvidersPrivate::updateFolderExport); | ||
} | ||
|
||
void LibCloudProvidersPrivate::updateExportedFolderList() | ||
{ | ||
const auto newFolders = FolderMan::instance()->list(); | ||
const auto oldFolders = _folderExports.keys(); | ||
|
||
// Remove folders that are no longer exported | ||
for (const auto old : oldFolders) { | ||
if (!newFolders.contains(old)) | ||
unexportFolder(old); | ||
} | ||
|
||
// Add new folders | ||
for (const auto n : newFolders) { | ||
if (!oldFolders.contains(n)) | ||
exportFolder(n); | ||
} | ||
} | ||
|
||
static void actionDispatcher(GSimpleAction *action, GVariant *, gpointer userData) | ||
{ | ||
gchar *strval; | ||
g_object_get(action, "name", &strval, NULL); | ||
QByteArray name(strval); | ||
g_free(strval); | ||
|
||
auto d = static_cast<LibCloudProvidersPrivate *>(userData); | ||
auto q = d->_q; | ||
if (name == "settings") | ||
q->showSettings(); | ||
else | ||
ASSERT(false, "unknown action string"); | ||
} | ||
|
||
|
||
void LibCloudProvidersPrivate::exportFolder(Folder *folder) | ||
{ | ||
if (!_exporter) | ||
return; | ||
|
||
GError *error = nullptr; | ||
auto icon = g_icon_new_for_string(APPLICATION_ICON_NAME, &error); | ||
if (error) { | ||
qWarning() << "Could not create icon for" << APPLICATION_ICON_NAME << "error" << error->message; | ||
g_error_free(error); | ||
} | ||
|
||
auto exporter = cloud_providers_account_exporter_new(_exporter, folder->alias().toUtf8().constData()); | ||
cloud_providers_account_exporter_set_path(exporter, folder->path().toUtf8().constData()); | ||
cloud_providers_account_exporter_set_icon(exporter, icon); | ||
cloud_providers_account_exporter_set_status(exporter, CLOUD_PROVIDERS_ACCOUNT_STATUS_IDLE); | ||
|
||
auto menu = g_menu_new(); | ||
// The "cloudprovider" scope is hardcoded into the gtk code that uses this data. | ||
// Different scopes will not work. | ||
g_menu_append(menu, tr("Settings").toUtf8().constData(), "cloudprovider.settings"); | ||
|
||
auto actionGroup = g_simple_action_group_new(); | ||
const GActionEntry entries[] = { | ||
{ "settings", actionDispatcher, nullptr, nullptr, nullptr, {}}, | ||
}; | ||
g_action_map_add_action_entries(G_ACTION_MAP(actionGroup), entries, G_N_ELEMENTS(entries), this); | ||
|
||
cloud_providers_account_exporter_set_menu_model(exporter, G_MENU_MODEL(menu)); | ||
cloud_providers_account_exporter_set_action_group(exporter, G_ACTION_GROUP(actionGroup)); | ||
|
||
// Currently there's no reason for us to keep these around: no further modifications are done | ||
g_clear_object(&menu); | ||
g_clear_object(&actionGroup); | ||
|
||
_folderExports[folder] = FolderExport{folder, exporter}; | ||
updateFolderExport(); | ||
} | ||
|
||
void LibCloudProvidersPrivate::unexportFolder(Folder *folder) | ||
{ | ||
if (!_folderExports.contains(folder)) | ||
return; | ||
auto folderExporter = _folderExports[folder]._exporter; | ||
cloud_providers_provider_exporter_remove_account(_exporter, folderExporter); | ||
// the remove_account already calls _unref | ||
_folderExports.remove(folder); | ||
} | ||
|
||
void LibCloudProvidersPrivate::updateFolderExport() | ||
{ | ||
for (auto folderExport : _folderExports) { | ||
if (!folderExport._folder) | ||
continue; | ||
Folder *folder = folderExport._folder; | ||
|
||
// Update the name, may change if accounts are added/removed | ||
QString displayName = folder->shortGuiRemotePathOrAppName(); | ||
if (AccountManager::instance()->accounts().size() > 1) { | ||
displayName = QStringLiteral("%1 (%2)").arg( | ||
displayName, folder->accountState()->account()->displayName()); | ||
} | ||
cloud_providers_account_exporter_set_name(folderExport._exporter, displayName.toUtf8().constData()); | ||
|
||
CloudProvidersAccountStatus status = CLOUD_PROVIDERS_ACCOUNT_STATUS_INVALID; | ||
auto syncResult = folder->syncResult(); | ||
switch (syncResult.status()) { | ||
case SyncResult::Undefined: | ||
status = CLOUD_PROVIDERS_ACCOUNT_STATUS_INVALID; | ||
break; | ||
case SyncResult::NotYetStarted: | ||
case SyncResult::Success: | ||
case SyncResult::Problem: | ||
status = CLOUD_PROVIDERS_ACCOUNT_STATUS_IDLE; | ||
break; | ||
case SyncResult::SyncPrepare: | ||
case SyncResult::SyncRunning: | ||
case SyncResult::SyncAbortRequested: | ||
status = CLOUD_PROVIDERS_ACCOUNT_STATUS_SYNCING; | ||
break; | ||
case SyncResult::Error: | ||
case SyncResult::SetupError: | ||
status = CLOUD_PROVIDERS_ACCOUNT_STATUS_ERROR; | ||
break; | ||
case SyncResult::Paused: | ||
// There's no status that fits exactly. If our choice is only | ||
// between IDLE And ERROR, let's go for ERROR to show that no | ||
// syncing is happening. | ||
status = CLOUD_PROVIDERS_ACCOUNT_STATUS_ERROR; | ||
break; | ||
} | ||
|
||
// Similarly to Paused: If disconnected, show something's wrong! | ||
if (!folder->accountState()->isConnected()) | ||
status = CLOUD_PROVIDERS_ACCOUNT_STATUS_ERROR; | ||
|
||
auto message = FolderMan::trayTooltipStatusString( | ||
syncResult.status(), | ||
syncResult.hasUnresolvedConflicts(), | ||
folder->syncPaused()); | ||
|
||
cloud_providers_account_exporter_set_status(folderExport._exporter, status); | ||
cloud_providers_account_exporter_set_status_details(folderExport._exporter, message.toUtf8().constData()); | ||
} | ||
} | ||
|
||
LibCloudProviders::LibCloudProviders(QObject *parent) | ||
: QObject(parent) | ||
, d_ptr(new LibCloudProvidersPrivate) | ||
{ | ||
d_ptr->_q = this; | ||
} | ||
|
||
void LibCloudProviders::start() | ||
{ | ||
d_ptr->start(); | ||
} | ||
|
||
} // namespace OCC |
Oops, something went wrong.