diff --git a/docs/util/ddesktopservices.h.zh_CN.dox b/docs/util/ddesktopservices.h.zh_CN.dox new file mode 100644 index 00000000..2001596a --- /dev/null +++ b/docs/util/ddesktopservices.h.zh_CN.dox @@ -0,0 +1,164 @@ +/*! +@~chinese +@file include/util/ddesktopservices.h +@ingroup DesktopServices +@brief Dtk 提供常见桌面服务的方法工具类 + +@namespace Dtk::Gui::DDesktopServices ddesktopservices.h +@details 用于提供一些接口,包括在文件管理器中显示目录,显示文件,显示文件属性,移入回收站,播放系统音效等。 + +@enum Dtk::Gui::DDesktopServices::SystemSoundEffect +@brief 系统音效的枚举 +@var Dtk::Gui::DDesktopServices::SSE_Notifications +@brief 显示通知的音效 +@var Dtk::Gui::DDesktopServices::SEE_Screenshot +@brief 截屏的音效 +@var Dtk::Gui::DDesktopServices::SSE_EmptyTrash +@brief 清空回收站的音效 +@var Dtk::Gui::DDesktopServices::SSE_SendFileComplete +@brief 完成发送文件(到桌面)的音效 +@var Dtk::Gui::DDesktopServices::SSE_BootUp +@brief 开机的音效 +@var Dtk::Gui::DDesktopServices::SSE_Shutdown +@brief 关机的音效 +@var Dtk::Gui::DDesktopServices::SSE_Logout +@brief 注销的音效 +@var Dtk::Gui::DDesktopServices::SSE_WakeUp +@brief 唤醒的音效 +@var Dtk::Gui::DDesktopServices::SSE_VolumeChange +@brief 音量调节的音效 +@var Dtk::Gui::DDesktopServices::SSE_LowBattery +@brief 低电量的音效 +@var Dtk::Gui::DDesktopServices::SSE_PlugIn +@brief 电源接入的音效 +@var Dtk::Gui::DDesktopServices::SSE_PlugOut +@brief 电源移除的音效 +@var Dtk::Gui::DDesktopServices::SSE_DeviceAdded +@brief 移动设备接入的音效 +@var Dtk::Gui::DDesktopServices::SSE_DeviceRemoved +@brief 移动设备移除的音效 +@var Dtk::Gui::DDesktopServices::SSE_Error +@brief 错误提示的音效 + +@fn Dtk::Gui::DDesktopServices::showFolder(const QString &localFilePath, const QString &startupId = QString()) +@details 通过文件管理器显示目录 +@param[in] localFilePath 要显示的目录路径 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFolders(const QList &localFilePaths, const QString &startupId = QString()) +@details 通过文件管理器显示多个目录 +@param[in] localFilePaths 要显示的目录路径列表 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFolder(const QUrl &url, const QString &startupId = QString()) +@details 通过文件管理器显示目录 +@param[in] url 要显示的目录 QUrl 形式路径 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFolders(const QList &urls, const QString &startupId = QString()) +@details 通过文件管理器显示多个目录 +@param[in] urls 要显示的目录路径 url 列表 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItemProperty(const QString &localFilePath, const QString &startupId = QString()) +@details 通过文件管理器显示文件的属性 +@param[in] localFilePath 要显示的文件路径 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItemProperties(const QList &localFilePaths, const QString &startupId = QString()) +@details 通过文件管理器显示多个文件的属性 +@param[in] localFilePaths 要显示的文件路径列表 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItemProperty(const QUrl &url, const QString &startupId = QString()) +@details 通过文件管理器显示文件的属性 +@param[in] url 要显示的文件 QUrl 形式路径 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItemProperties(const QList &urls, const QString &startupId = QString()) +@details 通过文件管理器显示多个文件的属性 +@param[in] urls 要显示的目录路径 url 列表 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItem(const QString &localFilePath, const QString &startupId = QString()) +@details 通过文件管理器在父目录中显示并选中文件(目录) +@param[in] localFilePath 要显示(选中)的文件(目录)路径 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItems(const QList &localFilePaths, const QString &startupId = QString()) +@details 通过文件管理器父目录中显示并选中多个文件(目录) +@param[in] localFilePaths 要显示(选中)的文件(目录)路径列表 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItem(const QUrl &url, const QString &startupId = QString()) +@details 通过文件管理器在父目录中显示并选中文件(目录) +@param[in] url 要显示(选中)的文件(目录)QUrl 形式路径 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::showFileItems(const QList &urls, const QString &startupId = QString()) +@details 通过文件管理器父目录中显示并选中多个文件(目录) +@param[in] urls 要显示选中)的文件(目录)路径 url 列表 +@param[in] startupId 本次启动的id, 默认为空 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::trash(const QString &localFilePath) +@details 通过文件管理器将文件移入回收站 +@param[in] localFilePath 要移入回收站的文件路径 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::trash(const QList &localFilePaths) +@details 通过文件管理器将多个文件移入回收站 +@param[in] localFilePaths 要移入回收站的文件路径列表 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::trash(const QUrl &url) +@details 通过文件管理器将文件移入回收站 +@param[in] url 要移入回收站的文件 url 路径 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::trash(const QList &urls) +@details 通过文件管理器将多个文件移入回收站 +@param[in] urls 要移入回收站的文件路径 url 列表 +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::playSystemSoundEffect(const SystemSoundEffect &effect) +@details 播放系统音效。如果系统音效被禁用或者要播放音效被禁用将播放失败 +@param[in] effect 要播放的音效,见枚举 Dtk::Gui::DDesktopServices::SystemSoundEffect +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::playSystemSoundEffect(const QString &name) +@details 根据音效名播放系统音效。如果系统音效被禁用或者要播放音效被禁用将播放失败 +@param[in] name 要播放的音效名称,见 Dtk::Gui::DDesktopServices::getNameByEffectType +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::previewSystemSoundEffect(const SystemSoundEffect &effect) +@details 系统音效预览。 +@param[in] effect 要播放的音效,见枚举 Dtk::Gui::DDesktopServices::SystemSoundEffect +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::previewSystemSoundEffect(const QString &name) +@details 根据音效名预览系统音效。 +@param[in] name 要播放的音效名称,见 Dtk::Gui::DDesktopServices::getNameByEffectType +@return 调用成功返回 true, 否则返回 false + +@fn Dtk::Gui::DDesktopServices::getNameByEffectType(const SystemSoundEffect &effect) +@details 根据音效名预览系统音效。 +@param[in] effect 要获取名称的音效,见枚举 Dtk::Gui::DDesktopServices::SystemSoundEffect +@return QString effect 对应的音效名称 + +@fn Dtk::Gui::DDesktopServices::errorMessage() +@details 文件管理器相关调用出错时可以通过此接口获取错误信息 +@return 错误信息 + +*/ diff --git a/include/DtkGui/DDesktopServices b/include/DtkGui/DDesktopServices new file mode 100644 index 00000000..6d5336c3 --- /dev/null +++ b/include/DtkGui/DDesktopServices @@ -0,0 +1 @@ +#include "ddesktopservices.h" diff --git a/include/util/ddesktopservices.h b/include/util/ddesktopservices.h new file mode 100644 index 00000000..5b38acbf --- /dev/null +++ b/include/util/ddesktopservices.h @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +#include +#include + +DGUI_BEGIN_NAMESPACE + +class DDesktopServices +{ +public: + + enum SystemSoundEffect { + SSE_Notifications, + SEE_Screenshot, + SSE_EmptyTrash, + SSE_SendFileComplete, + SSE_BootUp, + SSE_Shutdown, + SSE_Logout, + SSE_WakeUp, + SSE_VolumeChange, + SSE_LowBattery, + SSE_PlugIn, + SSE_PlugOut, + SSE_DeviceAdded, + SSE_DeviceRemoved, + SSE_Error, + }; + + static bool showFolder(const QString &localFilePath, const QString &startupId = QString()); + static bool showFolders(const QList &localFilePaths, const QString &startupId = QString()); + static bool showFolder(const QUrl &url, const QString &startupId = QString()); + static bool showFolders(const QList &urls, const QString &startupId = QString()); + + static bool showFileItemProperty(const QString &localFilePath, const QString &startupId = QString()); + static bool showFileItemProperties(const QList &localFilePaths, const QString &startupId = QString()); + static bool showFileItemProperty(const QUrl &url, const QString &startupId = QString()); + static bool showFileItemProperties(const QList &urls, const QString &startupId = QString()); + + static bool showFileItem(const QString &localFilePath, const QString &startupId = QString()); + static bool showFileItems(const QList &localFilePaths, const QString &startupId = QString()); + static bool showFileItem(const QUrl &url, const QString &startupId = QString()); + static bool showFileItems(const QList &urls, const QString &startupId = QString()); + + static bool trash(const QString &localFilePath); + static bool trash(const QList &localFilePaths); + static bool trash(const QUrl &url); + static bool trash(const QList &urls); + + static bool playSystemSoundEffect(const SystemSoundEffect &effect); + static bool playSystemSoundEffect(const QString &name); + static bool previewSystemSoundEffect(const SystemSoundEffect &effect); + static bool previewSystemSoundEffect(const QString &name); + static QString getNameByEffectType(const SystemSoundEffect &effect); + + static QString errorMessage(); +}; + +DGUI_END_NAMESPACE + +#ifdef Q_OS_LINUX +Q_DECLARE_METATYPE(DTK_GUI_NAMESPACE::DDesktopServices::SystemSoundEffect) +#endif + diff --git a/src/util/ddesktopservices_linux.cpp b/src/util/ddesktopservices_linux.cpp new file mode 100644 index 00000000..71839e6c --- /dev/null +++ b/src/util/ddesktopservices_linux.cpp @@ -0,0 +1,217 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "ddesktopservices.h" +#include +#include +#include + +DGUI_BEGIN_NAMESPACE + +#define EASY_CALL_DBUS(name) \ + QDBusInterface *interface = fileManager1DBusInterface(); \ + return interface && \ + interface->call(#name, urls2uris(urls), startupId).type() != \ + QDBusMessage::ErrorMessage; + +static const QStringList SOUND_EFFECT_LIST { + "message", + "camera-shutter", + "trash-empty", + "x-deepin-app-sent-to-desktop", + "desktop-login", + "system-shutdown", + "desktop-logout", + "suspend-resume", + "audio-volume-change", + "power-unplug-battery-low", + "power-plug", + "power-unplug", + "device-added", + "device-removed", + "dialog-error", +}; + +static QDBusInterface *fileManager1DBusInterface() +{ + static QDBusInterface interface(QStringLiteral("org.freedesktop.FileManager1"), + QStringLiteral("/org/freedesktop/FileManager1"), + QStringLiteral("org.freedesktop.FileManager1")); + return &interface; +} + +static QStringList urls2uris(const QList &urls) +{ + QStringList list; + + list.reserve(urls.size()); + + for (const QUrl &url : urls) { + list << url.toString(); + } + + return list; +} + +static QList path2urls(const QList &paths) +{ + QList list; + + list.reserve(paths.size()); + + for (const QString &path : paths) { + list << QUrl::fromLocalFile(path); + } + + return list; +} + +static QDBusInterface soundEffectInterface() +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const auto& infc = QDBusConnection::sessionBus().interface(); + QStringList activatableServiceNames = infc->activatableServiceNames(); + bool isNewInterface = activatableServiceNames.contains(QLatin1String("org.deepin.dde.SoundEffect1")); +#else + bool isNewInterface = false; // Qt 5.14 以下就直接用旧的接口 +#endif + const QLatin1String service(isNewInterface ? "org.deepin.dde.SoundEffect1" :"com.deepin.daemon.SoundEffect"); + const QLatin1String path(isNewInterface ? "/org/deepin/dde/SoundEffect1" : "/com/deepin/daemon/SoundEffect"); + const QLatin1String interface(isNewInterface ? "org.deepin.dde.SoundEffect1" :"com.deepin.daemon.SoundEffect"); + + // 使用后端 dbus 接口播放系统音频,音频存放目录: /usr/share/sounds/deepin/stereo/ + return QDBusInterface(service, path, interface); +} + +static bool systemSoundEffectEnabled(const QString &name) +{ + auto soundEffect = soundEffectInterface(); + if (!soundEffect.property("Enabled").toBool()) + return false; + + QDBusReply reply = soundEffect.call("IsSoundEnabled", name); + + return reply.isValid() && reply.value(); +} + +bool DDesktopServices::showFolder(const QString &localFilePath, const QString &startupId) +{ + return showFolder(QUrl::fromLocalFile(localFilePath), startupId); +} + +bool DDesktopServices::showFolders(const QList &localFilePaths, const QString &startupId) +{ + return showFolders(path2urls(localFilePaths), startupId); +} + +bool DDesktopServices::showFolder(const QUrl &url, const QString &startupId) +{ + return showFolders(QList() << url, startupId); +} + +bool DDesktopServices::showFolders(const QList &urls, const QString &startupId) +{ + EASY_CALL_DBUS(ShowFolders) +} + +bool DDesktopServices::showFileItemProperty(const QString &localFilePath, const QString &startupId) +{ + return showFileItemProperty(QUrl::fromLocalFile(localFilePath), startupId); +} + +bool DDesktopServices::showFileItemProperties(const QList &localFilePaths, const QString &startupId) +{ + return showFileItemProperties(path2urls(localFilePaths), startupId); +} + +bool DDesktopServices::showFileItemProperty(const QUrl &url, const QString &startupId) +{ + return showFileItemProperties(QList() << url, startupId); +} + +bool DDesktopServices::showFileItemProperties(const QList &urls, const QString &startupId) +{ + EASY_CALL_DBUS(ShowItemProperties) +} + +bool DDesktopServices::showFileItem(const QString &localFilePath, const QString &startupId) +{ + return showFileItem(QUrl::fromLocalFile(localFilePath), startupId); +} + +bool DDesktopServices::showFileItems(const QList &localFilePaths, const QString &startupId) +{ + return showFileItems(path2urls(localFilePaths), startupId); +} + +bool DDesktopServices::showFileItem(const QUrl &url, const QString &startupId) +{ + return showFileItems(QList() << url, startupId); +} + +bool DDesktopServices::showFileItems(const QList &urls, const QString &startupId) +{ + EASY_CALL_DBUS(ShowItems) +} + +bool DDesktopServices::trash(const QString &localFilePath) +{ + return trash(QUrl::fromLocalFile(localFilePath)); +} + +bool DDesktopServices::trash(const QList &localFilePaths) +{ + return trash(path2urls(localFilePaths)); +} + +bool DDesktopServices::trash(const QUrl &url) +{ + return trash(QList() << url); +} + +bool DDesktopServices::trash(const QList &urls) +{ + QDBusInterface *interface = fileManager1DBusInterface(); + return interface && interface->call("Trash", urls2uris(urls)).type() != QDBusMessage::ErrorMessage; +} + +bool DDesktopServices::playSystemSoundEffect(const DDesktopServices::SystemSoundEffect &effect) +{ + return playSystemSoundEffect(SOUND_EFFECT_LIST.at(static_cast(effect))); +} + +bool DDesktopServices::playSystemSoundEffect(const QString &name) +{ + if (!systemSoundEffectEnabled(name)) + return false; + + return previewSystemSoundEffect(name); +} + +bool DDesktopServices::previewSystemSoundEffect(const DDesktopServices::SystemSoundEffect &effect) +{ + return previewSystemSoundEffect(SOUND_EFFECT_LIST.at(static_cast(effect))); +} + +bool DDesktopServices::previewSystemSoundEffect(const QString &name) +{ + if (name.isEmpty()) { + return false; + } + + // 使用后端 dbus 接口播放系统音频,音频存放目录: /usr/share/sounds/deepin/stereo/ + return soundEffectInterface().call("PlaySound", name).type() != QDBusMessage::ErrorMessage; +} + +QString DDesktopServices::getNameByEffectType(const DDesktopServices::SystemSoundEffect &effect) +{ + return SOUND_EFFECT_LIST.at(static_cast(effect)); +} + +QString DDesktopServices::errorMessage() +{ + return fileManager1DBusInterface()->lastError().message(); +} + +DGUI_END_NAMESPACE