diff --git a/CMakeLists.txt b/CMakeLists.txt index 3011d43..f2c2a68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,92 +1,95 @@ # vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab: cmake_minimum_required (VERSION 2.8.12) project (PlasmaVault) set(PROJECT_VERSION "5.13.80") set(PROJECT_VERSION_MAJOR 5) set (PLASMAVAULT_VERSION "0.1") set (REQUIRED_QT_VERSION 5.7.0) # We don't build in-source if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message ( FATAL_ERROR "plasmavault requires an out of source build. Please create a separate build directory and run 'cmake path_to_plasma [options]' there." ) endif () # Extra CMake stuff include (FeatureSummary) find_package (ECM 5.17.0 NO_MODULE) set_package_properties (ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary (WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include (KDEInstallDirs) include (KDECMakeSettings) include (KDECompilerSettings) include (GenerateExportHeader) include (ECMGenerateHeaders) # Qt set (CMAKE_AUTOMOC ON) find_package ( Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED COMPONENTS Core DBus Quick Widgets ) # KDE Frameworks set (KF5_DEP_VERSION "5.17.0") # handled by release scripts find_package ( KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS Activities Config ConfigWidgets CoreAddons DBusAddons I18n KIO Plasma WidgetsAddons - NetworkManagerQt ) +find_package (KF5NetworkManagerQt ${KF5_DEP_VERSION}) +if (KF5NetworkManagerQt_FOUND) + set (HAVE_NETWORKMANAGER TRUE) +endif() find_package (KF5SysGuard REQUIRED) include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/common ) # Basic includes include (CPack) include (ECMPackageConfigHelpers) include (ECMSetupVersion) add_definitions (-DQT_NO_URL_CAST_FROM_STRING) add_definitions (-DQT_NO_CAST_TO_ASCII) add_definitions (-DTRANSLATION_DOMAIN=\"plasmavault-kde\") add_definitions (-fexceptions) if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ki18n_install (po) endif () # libPlasmaVault add_subdirectory (kded) add_subdirectory (plasma) add_subdirectory (icons) # Write out the features feature_summary (WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/kded/CMakeLists.txt b/kded/CMakeLists.txt index 666100e..0d138d8 100644 --- a/kded/CMakeLists.txt +++ b/kded/CMakeLists.txt @@ -1,94 +1,101 @@ +configure_file (config-plasma-vault.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-plasma-vault.h) + include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/engine ) set ( kded_plasmavault_SRCS service.cpp engine/vault.cpp engine/backend_p.cpp engine/fusebackend_p.cpp engine/types.cpp engine/commandresult.cpp engine/backends/encfs/encfsbackend.cpp engine/backends/cryfs/cryfsbackend.cpp ui/dialogdsl.cpp ui/activitieslinkingwidget.cpp ui/backendchooserwidget.cpp ui/cryfscypherchooserwidget.cpp ui/directorypairchooserwidget.cpp ui/directorychooserwidget.cpp ui/namechooserwidget.cpp ui/noticewidget.cpp ui/passwordchooserwidget.cpp ui/offlineonlywidget.cpp ui/vaultdeletionwidget.cpp ui/vaultcreationwizard.cpp ui/vaultconfigurationwizard.cpp ui/mountdialog.cpp ../common/vaultinfo.cpp ) ki18n_wrap_ui ( kded_plasmavault_SRCS ui/activitieslinkingwidget.ui ui/backendchooserwidget.ui ui/cryfscypherchooserwidget.ui ui/directorypairchooserwidget.ui ui/directorychooserwidget.ui ui/namechooserwidget.ui ui/noticewidget.ui ui/passwordchooserwidget.ui ui/offlineonlywidget.ui ui/vaultdeletionwidget.ui ui/vaultcreationwizard.ui ui/vaultconfigurationwizard.ui ui/mountdialog.ui ) add_library ( kded_plasmavault MODULE ${kded_plasmavault_SRCS} ) set_target_properties ( kded_plasmavault PROPERTIES OUTPUT_NAME plasmavault ) kcoreaddons_desktop_to_json ( kded_plasmavault plasmavault.desktop ) target_link_libraries ( kded_plasmavault Qt5::Core Qt5::DBus Qt5::Widgets KF5::Activities KF5::ConfigCore KF5::ConfigWidgets KF5::CoreAddons KF5::DBusAddons KF5::I18n KF5::KIOCore KF5::KIOWidgets KF5::SysGuard KF5::WidgetsAddons KF5::ProcessCore - KF5::NetworkManagerQt ) +if (HAVE_NETWORKMANAGER) + target_link_libraries ( + kded_plasmavault + KF5::NetworkManagerQt + ) +endif () install ( TARGETS kded_plasmavault DESTINATION ${PLUGIN_INSTALL_DIR}/kf5/kded) diff --git a/kded/config-plasma-vault.cmake b/kded/config-plasma-vault.cmake new file mode 100644 index 0000000..35d0003 --- /dev/null +++ b/kded/config-plasma-vault.cmake @@ -0,0 +1 @@ +#cmakedefine HAVE_NETWORKMANAGER diff --git a/kded/service.cpp b/kded/service.cpp index 33ce52d..099d3f9 100644 --- a/kded/service.cpp +++ b/kded/service.cpp @@ -1,427 +1,443 @@ /* * Copyright 2017 by Ivan Cukic * * 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) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "service.h" #include #include #include #include #include #include #include "engine/vault.h" #include "engine/commandresult.h" #include "ui/vaultcreationwizard.h" #include "ui/vaultconfigurationwizard.h" #include "ui/mountdialog.h" #include +#include +#ifdef HAVE_NETWORKMANAGER #include +#else +namespace NetworkManager +{ + bool isNetworkingEnabled() + { + return true; + } + + void setNetworkingEnabled(bool enabled) + { + Q_UNUSED(enabled); + } +} +#endif K_PLUGIN_FACTORY_WITH_JSON(PlasmaVaultServiceFactory, "plasmavault.json", registerPlugin();) using namespace PlasmaVault; using AsynQt::Expected; class PlasmaVaultService::Private { public: QHash knownVaults; QSet openVaults; KActivities::Consumer kamd; struct NetworkingState { bool wasNetworkingEnabled; QVector devicesInhibittingNetworking; }; // Ideally, this would be std::optional... lovely C++17 Expected savedNetworkingState = Expected::error(0); void saveNetworkingState() { // Ignore the request if we already have a saved state if (savedNetworkingState) { return; } savedNetworkingState = Expected::success( NetworkingState { NetworkManager::isNetworkingEnabled() || true, {} }); } void restoreNetworkingState() { // Ignore the request if we do not have a state saved // or if there are more devices inhibitting networking if (!savedNetworkingState || !savedNetworkingState->devicesInhibittingNetworking.isEmpty()) { return; } NetworkManager::setNetworkingEnabled(savedNetworkingState->wasNetworkingEnabled); } Vault* vaultFor(const QString &device_) const { const Device device(device_); if (!knownVaults.contains(device)) { return nullptr; } return knownVaults[device]; } }; PlasmaVaultService::PlasmaVaultService(QObject * parent, const QVariantList&) : KDEDModule(parent) , d(new Private()) { connect(this, &KDEDModule::moduleRegistered, this, &PlasmaVaultService::slotRegistered); connect(&d->kamd, &KActivities::Consumer::currentActivityChanged, this, &PlasmaVaultService::onCurrentActivityChanged); init(); } PlasmaVaultService::~PlasmaVaultService() { } void PlasmaVaultService::init() { for (const Device &device: Vault::availableDevices()) { registerVault(new Vault(device, this)); } } PlasmaVault::VaultInfoList PlasmaVaultService::availableDevices() const { PlasmaVault::VaultInfoList result; for (const auto &vault: d->knownVaults.values()) { const auto vaultData = vault->info(); result << vaultData; } return result; } void PlasmaVaultService::requestNewVault() { const auto dialog = new VaultCreationWizard(); connect(dialog, &VaultCreationWizard::createdVault, this, &PlasmaVaultService::registerVault); dialog->show(); } void PlasmaVaultService::slotRegistered(const QDBusObjectPath &path) { if (path.path() == QLatin1String("/modules/plasmavault")) { emit registered(); } } void PlasmaVaultService::registerVault(Vault *vault) { if (!vault->isValid()) { qWarning() << "Warning: Trying to register an invalid vault: " << vault->device(); return; } if (d->knownVaults.contains(vault->device())) { qWarning() << "Warning: This one is already registered: " << vault->device(); return; } vault->setParent(this); d->knownVaults[vault->device()] = vault; connect(vault, &Vault::statusChanged, this, &PlasmaVaultService::onVaultStatusChanged); connect(vault, &Vault::messageChanged, this, &PlasmaVaultService::onVaultMessageChanged); connect(vault, &Vault::infoChanged, this, &PlasmaVaultService::onVaultInfoChanged); emit vaultAdded(vault->info()); if (vault->status() == VaultInfo::Opened) { d->openVaults << vault->device(); } } void PlasmaVaultService::forgetVault(Vault* vault) { // Can not be open // d->openVaults.remove(vault.device()); // and therefore can not inhibit networking // ... d->savedNetworkingState ... emit vaultRemoved(vault->device().data()); d->knownVaults.remove(vault->device()); vault->deleteLater(); } void PlasmaVaultService::onVaultStatusChanged(VaultInfo::Status status) { const auto vault = qobject_cast(sender()); if (status == VaultInfo::Dismantled) { forgetVault(vault); } else if (status == VaultInfo::Opened) { d->openVaults << vault->device(); if (d->openVaults.size() == 1) { emit hasOpenVaultsChanged(true); } } else { d->openVaults.remove(vault->device()); if (d->openVaults.isEmpty()) { emit hasOpenVaultsChanged(false); } } if (vault->isOfflineOnly()) { d->saveNetworkingState(); auto& devicesInhibittingNetworking = d->savedNetworkingState->devicesInhibittingNetworking; // We need to check whether this vault // should be added or removed from the // inhibitors list const bool alreadyInhibiting = devicesInhibittingNetworking.contains(vault->device()); if (status == VaultInfo::Opened && !alreadyInhibiting) { devicesInhibittingNetworking << vault->device(); } if (status != VaultInfo::Opened && alreadyInhibiting) { devicesInhibittingNetworking.removeAll(vault->device()); } // qDebug() << "Vaults inhibitting networking: " << devicesInhibittingNetworking; // Now, let's handle the networking part if (!devicesInhibittingNetworking.isEmpty()) { NetworkManager::setNetworkingEnabled(false); } d->restoreNetworkingState(); } emit vaultChanged(vault->info()); } void PlasmaVaultService::onVaultInfoChanged() { const auto vault = qobject_cast(sender()); emit vaultChanged(vault->info()); } void PlasmaVaultService::onVaultMessageChanged(const QString &message) { Q_UNUSED(message); const auto vault = qobject_cast(sender()); emit vaultChanged(vault->info()); } void showPasswordMountDialog(Vault *vault, const std::function &function) { auto dialog = new MountDialog(vault, function); dialog->open(); } //^ void PlasmaVaultService::openVault(const QString &device) { if (auto vault = d->vaultFor(device)) { if (vault->isOpened()) return; showPasswordMountDialog(vault, [this, vault] { emit vaultChanged(vault->info()); }); } } void PlasmaVaultService::closeVault(const QString &device) { if (auto vault = d->vaultFor(device)) { if (!vault->isOpened()) return; vault->close(); } } void PlasmaVaultService::configureVault(const QString &device) { if (auto vault = d->vaultFor(device)) { const auto dialog = new VaultConfigurationWizard(vault); // connect(dialog, &VaultConfigurationWizard::configurationChanged, // this, &PlasmaVaultService::registerVault); dialog->show(); } } void PlasmaVaultService::forceCloseVault(const QString &device) { if (auto vault = d->vaultFor(device)) { if (!vault->isOpened()) return; vault->forceClose(); } } void PlasmaVaultService::openVaultInFileManager(const QString &device) { if (auto vault = d->vaultFor(device)) { if (vault->isOpened()) { new KRun(QUrl::fromLocalFile((QString)vault->mountPoint()), nullptr); } else { showPasswordMountDialog(vault, [this, vault] { emit vaultChanged(vault->info()); new KRun(QUrl::fromLocalFile((QString)vault->mountPoint()), nullptr); }); } } } void PlasmaVaultService::onCurrentActivityChanged( const QString ¤tActivity) { for (auto* vault: d->knownVaults.values()) { const auto vaultActivities = vault->activities(); if (!vaultActivities.isEmpty() && !vaultActivities.contains(currentActivity)) { vault->close(); } } } bool PlasmaVaultService::hasOpenVaults() const { return !d->openVaults.isEmpty(); } void PlasmaVaultService::closeAllVaults() { for (const auto& device: d->openVaults) { closeVault(device.data()); } } void PlasmaVaultService::forceCloseAllVaults() { for (const auto& device: d->openVaults) { forceCloseVault(device.data()); } } void PlasmaVaultService::deleteVault(const QString &device, const QString &name) { if (!d->knownVaults.contains(Device(device))) { qWarning() << "The specified vault does not exist: " << device; return; } auto vault = d->knownVaults[Device(device)]; if (vault->status() == VaultInfo::Opened) { qWarning() << "Can not delete an open vault: " << device; return; } if (vault->name() != name) { qWarning() << "Name is not correct: " << device; return; } vault->dismantle({}); } #include "service.moc"