diff --git a/CMakeLists.txt b/CMakeLists.txt index 66dd0fc..6d05248 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,53 +1,58 @@ project(dolphin-plugins) cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) include(FeatureSummary) set(QT_MIN_VERSION "5.8.0") set(KF5_MIN_VERSION "5.0.0") find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Core Widgets Network ) find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS XmlGui I18n KIO TextWidgets + CoreAddons + Solid ) find_package(DolphinVcs) set_package_properties(DolphinVcs PROPERTIES DESCRIPTION "the Dolphin version control plugin library" URL "https://kde.org/applications/system/org.kde.dolphin" TYPE REQUIRED PURPOSE "Provides the version control plugin interface." ) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings) include(ECMMarkNonGuiExecutable) include(ECMOptionalAddSubdirectory) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_definitions(-DQT_NO_URL_CAST_FROM_STRING) ecm_optional_add_subdirectory(svn) ecm_optional_add_subdirectory(git) ecm_optional_add_subdirectory(bazaar) ecm_optional_add_subdirectory(dropbox) ecm_optional_add_subdirectory(hg) +if(UNIX AND NOT APPLE) + ecm_optional_add_subdirectory(mountiso) +endif() install(FILES org.kde.dolphin-plugins.metainfo.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/mountiso/CMakeLists.txt b/mountiso/CMakeLists.txt new file mode 100644 index 0000000..6e4e23e --- /dev/null +++ b/mountiso/CMakeLists.txt @@ -0,0 +1,12 @@ +project(mountisoplugin) + +kcoreaddons_add_plugin( + mountisoaction + SOURCES mountisoaction.cpp + JSON mountisoaction.json + INSTALL_NAMESPACE "kf5/kfileitemaction") + +target_link_libraries(mountisoaction + KF5::I18n + KF5::KIOWidgets + KF5::Solid) diff --git a/mountiso/mountisoaction.cpp b/mountiso/mountisoaction.cpp new file mode 100644 index 0000000..ebe8da8 --- /dev/null +++ b/mountiso/mountisoaction.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2020 Kwon-Young Choi + * + * 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 "mountisoaction.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +K_PLUGIN_CLASS_WITH_JSON(MountIsoAction, "mountisoaction.json") + +MountIsoAction::MountIsoAction(QObject *parent, const QVariantList &) + : KAbstractFileItemActionPlugin(parent) +{ +} + +/** + * Get block device udi ("/org/freedesktop/UDisks2/block_devices/loop0") using + * its backing file name. + * + * Use the Solid framework to iterate through all block devices to check if the + * backing file correspond to the given backingFile. + * + * Warning: The use of GenericInterface makes this function non portable, + * especially to non Unix-like OS. + * + * @backingFile: backing file of the device we want. + * + * @return: device udi of the found block device. If no corresponding device + * was found, return a null QString. + */ +const QString getDeviceFromBackingFile(const QString &backingFile) +{ + const QList blockDevices = + Solid::Device::listFromQuery("[ IS Block AND IS GenericInterface ]"); + + for (const Solid::Device &device : blockDevices) { + QMap properties = device.as()->allProperties(); + if (properties.contains("BackingFile") + && backingFile == properties["BackingFile"].value()) { + return device.udi(); + } + } + return QString(); +} + +/** + * Callback function for mounting an iso file as a loop device + * + * Uses UDisks2 Manager DBus api to mount the iso file + * + * @file: iso file path to mount + */ +void mount(const QString &file) +{ + const int fd = open(file.toLocal8Bit().data(), O_RDONLY); + if (fd == -1) { + qWarning() << "Error opening " << file << ": " << strerror(errno); + return; + } + auto qtFd = QDBusUnixFileDescriptor(fd); + int res = close(fd); + if (res == -1) { + qWarning() << "Error closing " << file << ": " << strerror(errno); + return; + } + QMap options; + options["read-only"] = QVariant::fromValue(true); + + QDBusInterface manager( + "org.freedesktop.UDisks2", + "/org/freedesktop/UDisks2/Manager", + "org.freedesktop.UDisks2.Manager", + QDBusConnection::systemBus()); + QDBusReply reply = + manager.call("LoopSetup", QVariant::fromValue(qtFd), options); + + if (!reply.isValid()) { + qWarning() << "Error mounting " << file << ":" << reply.error().name() + << reply.error().message(); + } +} + +/** + * Callback function for deleting a loop device + * + * Uses UDisks2 DBus api to delete a loop device + * + * @file: iso file to mount + */ +void unmount(const QString &device) +{ + // Empty argument required for Loop Delete method to work + QMap options; + + QDBusInterface manager( + "org.freedesktop.UDisks2", + device, + "org.freedesktop.UDisks2.Loop", + QDBusConnection::systemBus()); + manager.call("Delete", options); +} + +QList MountIsoAction::actions(const KFileItemListProperties &fileItemInfos, + QWidget *parentWidget) +{ + if (fileItemInfos.urlList().size() != 1 + || fileItemInfos.mimeType() != QLatin1String("application/x-cd-image") + || !fileItemInfos.isLocal()) { + return {}; + }; + + auto file = fileItemInfos.urlList().at(0).toLocalFile(); + + // Check if dbus can handle file descriptor + auto connection = QDBusConnection::sessionBus(); + QDBusConnection::ConnectionCapabilities capabilities = connection.connectionCapabilities(); + if (!(capabilities & QDBusConnection::UnixFileDescriptorPassing)) { + return {}; + } + + const QString device = getDeviceFromBackingFile(file); + + if (device.isEmpty()) { + const QIcon icon = QIcon::fromTheme(QStringLiteral("media-mount")); + const QString title = i18nc("@action Action to mount an iso image", "Mount this iso image"); + + QAction *action = new QAction(icon, title, parentWidget); + + connect(action, &QAction::triggered, this, [file]() { mount(file); }); + return { action }; + } else { + // fileItem is mounted on device + const QIcon icon = QIcon::fromTheme(QStringLiteral("media-eject")); + const QString title = + i18nc("@action Action to unmount an iso image", "Unmount this iso image"); + QAction *action = new QAction(icon, title, parentWidget); + + connect(action, &QAction::triggered, this, [device]() { unmount(device); }); + return { action }; + } + + return {}; +} + +#include "mountisoaction.moc" diff --git a/mountiso/mountisoaction.h b/mountiso/mountisoaction.h new file mode 100644 index 0000000..a339fe6 --- /dev/null +++ b/mountiso/mountisoaction.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 Kwon-Young Choi + * + * 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. + * + */ + +#ifndef MOUNTISOACTION_H +#define MOUNTISOACTION_H + +#include +#include + +class QAction; +class QWidget; + +class KFileItemListProperties; + +/** + * File item action plugin to mount and unmount an iso file. + * + * This class adds a mount or unmount entry to an iso file contextual menu. If + * the iso file is already mounted, only the unmount entry will be shown while + * if the iso file is not mounted, only the mount entry will be shown. + * + * The current implementation uses a loop device to mount the iso file. + * + */ +class MountIsoAction : public KAbstractFileItemActionPlugin +{ + + Q_OBJECT + +public: + MountIsoAction(QObject *parent, const QVariantList &args); + + /** + * Adds a mount or unmount entry to the contextual menu of an iso file. + * + * For a menu entry to be shown, only one file should be selected, the + * mimetype of the file should be "application/x-cd-image" and the file + * should be local. Then, the mount state of the iso file is checked and if + * the iso file is already mounted, we get the corresponding block device. + * If the iso file is not already mounted, we show a mount entry and create + * a callback to mount the iso file using udisksctl. + * If the iso file is already mounted, we show a unmount entry and create a + * callback to unmount the iso file using udisksctl. + */ + QList actions(const KFileItemListProperties &fileItemInfos, + QWidget *parentWidget) override; +}; + +#endif diff --git a/mountiso/mountisoaction.json b/mountiso/mountisoaction.json new file mode 100644 index 0000000..8f2cfdb --- /dev/null +++ b/mountiso/mountisoaction.json @@ -0,0 +1,13 @@ +{ + "KPlugin": { + "Icon": "application-x-cd-image", + "MimeTypes": [ + "application/x-cd-image" + ], + "Name": "Mount and unmount iso image", + "ServiceTypes": [ + "KFileItemAction/Plugin" + ] + }, + "MimeType": "application/x-cd-image;" +} diff --git a/org.kde.dolphin-plugins.metainfo.xml b/org.kde.dolphin-plugins.metainfo.xml index 491df9c..cd8bb2c 100644 --- a/org.kde.dolphin-plugins.metainfo.xml +++ b/org.kde.dolphin-plugins.metainfo.xml @@ -1,91 +1,91 @@ org.kde.dolphin_plugins CC0-1.0 GPL-2.0+ org.kde.dolphin.desktop Dolphin Plugins Connectors del Dolphin Connectors del Dolphin Moduly pro Dolphin Dolphin-Module Dolphin Plugins Complementos de Dolphin Dolphini pluginad Modules externes de Dolphin Complementos de Dolphin Estensioni per Dolphin Dolphin 플러그인 Plug-ins van Dolphin Dolphin-tillegg Wtyczki Dolphina 'Plugins' do Dolphin Plug-ins do Dolphin Модули Dolphin Pluginy Dolphinu Dolphinovi vtičniki Dolphin insticksprogram Додатки до Dolphin xxDolphin Pluginsxx Dolphin 插件 - Dolphin integration for revision control systems and Dropbox + Dolphin integration for revision control systems, Dropbox, and disk images. Integració al Dolphin per a sistemes de control de revisions i Dropbox Integració al Dolphin per a sistemes de control de revisions i Dropbox Integration von Versionsverwaltungssysteme und Dropbox in Dolphin Dolphin integration for revision control systems and Dropbox Integración en Dolphin de sistemas de control de versiones y de Dropbox Dolphini lõimimine versioonihaldussüsteemide ja Dropboxiga Intégration des systèmes de gestion de version et de Dropbox à Dolphin Integración de Dolphin con sistemas de control de revisións e Dropbox Integrazione con Dolphin per i sistemi di controllo di revisione e per Dropbox Dolphin용 버전 관리 시스템과 Dropbox 통합 Integratie van Dolphin voor besturingssystemen voor revisie en Dropbox Dolphin-integrering med versjonskontrollsystem og Dropbox Integracja Dolphina z systemami do zarządzania wersjami oraz Dropbox Integração do Dolphin com sistemas de controlo de versões e com o Dropbox Integração para o Dolphin para sistemas de controle de versão e Dropbox Поддержка работы с системами управления версиями, а также с Dropbox Integrátor Dolphinu pre systémy na správu revízií a Dropbox Dolphinova integracija za nadzorne sisteme verzij izvornih programov in Dropbox Integrering av versionshanteringssystemen och Dropbox i Dolphin Інтеграція Dolphin з системами керування версіями та Dropbox xxDolphin integration for revision control systems and Dropboxxx Dolphin 文件版本控制系统和 Dropbox 集成 -

These plugins integrate Dolphin with the revision control systems Bazaar, Mercurial and Git. A Dropbox plugin gives action items to keep your files synced to the Dropbox service.

+

These plugins integrate Dolphin with the revision control systems Bazaar, Mercurial and Git. A Dropbox plugin gives action items to keep your files synced to the Dropbox service. A disk image integration plugin adds a mount or unmount action.

Aquests connectors integren el Dolphin amb els sistemes de control de revisions Bazaar, Mercurial i Git. I un connector de Dropbox proporciona elements d'acció per a mantenir els vostres fitxers sincronitzats amb el servei de Dropbox.

Aquests connectors integren el Dolphin amb els sistemes de control de revisions Bazaar, Mercurial i Git. I un connector de Dropbox proporciona elements d'acció per a mantindre els vostres fitxers sincronitzats amb el servei de Dropbox.

Diese Module integrieren die Versionsverwaltungssysteme Bazaar, Mercurial und Git. Ein Dropbox-Modul stellt Aktionen zum Abgleichen von Dateien mit dem Dropbox-Dienst bereit.

These plugins integrate Dolphin with the revision control systems Bazaar, Mercurial and Git. A Dropbox plugin gives action items to keep your files synced to the Dropbox service.

Este complemento proporciona a Dolphin los sistemas de control de versiones Bazaar, Mercurial y Git. El complemento de Dropbox proporciona acciones para mantener archivos sincronizados mediante el servicio Dropbox.

Need pluginad lõimivad Dolphini versioonihaldussüsteemidega Bazaar, Mercurial ja Git. Dropboxi plugin võimaldab hoida faile sünkroonis Dropboxi teenusega.

Ces modules externes intègrent Dolphin avec les systèmes de gestion de version Bazaar, Mercurial et Git. Un module externe Dropbox ajoute des éléments d'action permettant de synchroniser vos fichiers au service Dropbox.

Estes complementos integran Dolphin cos sistemas de control de revisións Bazaar, Mercurial e Git. Un complemento de Dropbox fornece elementos de acción para manter os seus ficheiros sincronizados co servizo Dropbox.

Queste estensioni integrano Dolphin con i sistemi di controllo di revisione Bazaar, Mercurial e Git. Un'estensione per Dropbox fornisce le voci per le azioni che mantengono i tuoi file sincronizzati con il servizio Dropbox.

이 플러그인은 Dolphin에 Bazaar, Mercurial, Git와 같은 버전 관리 시스템을 통합합니다. Dropbox 플러그인을 사용하여 내 파일을 Dropbox에 동기화할 수 있습니다.

Deze plug-ins integreren Dolphin met het besturen van de revisiesystemen Bazaar, Mercurial en Git. Een Dropbox-plug-in geeft actie-items om uw bestanden gesynchroniseerd te houden met de Dropbox service.

Desse programtillegga gjev integrasjon mellom Dolphin og versjonskontroll­system som Bazaar, Mercurial og Git. Dropbox-tillegget legg til handlingar for å halda filene synkroniserte med Dropbox-tenesta.

Te wtyczki integrują Dolphina z systemami do zarządzania wersjami takimi jak Bazaar, Mercurial oraz Git. Wtyczka Dropbox daje elementy działania do synchronizacji z usługą Dropbox.

Estes 'plugins' integram o Dolphin com os sistemas de controlo de versões Bazaar, Mercurial e Git. Um 'plugin' do Dropbox oferece itens de acção para manter os seus ficheiros sincronizado com o serviço do Dropbox.

Estes plugins integram o Dolphin com os sistemas de controle de versão como Bazaar, Mercurial e Git. Um plugin Dropbox fornece itens de ação para manter seus arquivos sincronizados com o serviço Dropbox.

Эти модули Dolphin обеспечивают поддержку систем управления версиями Bazaar, Mercurial и Git. Модуль поддержки Dropbox позволяет выполнять синхронизацию файлы со службой Dropbox.

Tieto pluginy integrujú Dolphin so systémami kontroly revízii Bazaar, Mercurial a Git. Doplnok Dropbox poskytuje akčné položky na udržanie súborov synchronizovaných so službou Dropbox.

Ti vtičniki integrirajo Dolphin s sistemi za nadzor verzij izvornih programov Bazaar, Mercurial in Git. Vtičnik Dropbox pa nudi ukrepe, s katerimi lahko datoteke sinhronizirate s storitvijo Dropbox.

Insticksprogrammen integrerar Dolphin med versionshanteringssystemen Bazaar, Mercurial och Git. Ett Dropbox-insticksprogram ger åtgärdsobjekt för att hålla filer synkroniserade med Dropbox-tjänsten.

За допомогою цих додатків можна інтегрувати Dolphin із системами керування версіями Bazaar, Mercurial та Git. Додаток Dropbox надасть у ваше розпорядження пункти меню дій, які допоможуть підтримувати синхронізацію ваших файлів із службою Dropbox.

xxThese plugins integrate Dolphin with the revision control systems Bazaar, Mercurial and Git. A Dropbox plugin gives action items to keep your files synced to the Dropbox service.xx

这些插件使 Dolphin 整合版本控制系统(Bazaar、Mercurial、Git) 。Dropbox 插件提供菜单项以同步文件到 Dropbox 服务。

https://www.kde.org https://bugs.kde.org/enter_bug.cgi?format=guided&product=dolphin https://cdn.kde.org/screenshots/dolphin-plugins/dolphin-plugins.png KDE System system-file-manager