From 2c77395f40e890ed1be3806bdd706e00712aa6da Mon Sep 17 00:00:00 2001 From: gjq Date: Thu, 16 Mar 2023 14:14:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=9C=80=E8=BF=91=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=8F=B3=E9=94=AE=E8=8F=9C=E5=8D=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- qml/extensions/RecentFileExtension.qml | 5 +- .../extensions/recent-file-extension.cpp | 165 ++++++++++++++++-- .../extensions/recent-file-extension.h | 15 +- 3 files changed, 163 insertions(+), 22 deletions(-) diff --git a/qml/extensions/RecentFileExtension.qml b/qml/extensions/RecentFileExtension.qml index 195a637..e648dcd 100644 --- a/qml/extensions/RecentFileExtension.qml +++ b/qml/extensions/RecentFileExtension.qml @@ -99,6 +99,7 @@ UkuiMenuExtension { MouseArea { id: itemArea property bool hovered + acceptedButtons: Qt.LeftButton | Qt.RightButton anchors.fill: parent hoverEnabled: true onEntered: { @@ -109,8 +110,10 @@ UkuiMenuExtension { } onClicked: { var data = { - "url": model.uri + "url": model.uri, + "index": model.index } + data["action"] = mouse.button === Qt.RightButton ? "right" : "" send(data) } } diff --git a/src/extension/extensions/recent-file-extension.cpp b/src/extension/extensions/recent-file-extension.cpp index aaca486..e0804bd 100644 --- a/src/extension/extensions/recent-file-extension.cpp +++ b/src/extension/extensions/recent-file-extension.cpp @@ -21,15 +21,18 @@ #include #include #include -#include #include #include +#include #include "recent-file-extension.h" -#define KYLIN_APP_MANAGER_NAME "com.kylin.AppManager" -#define KYLIN_APP_MANAGER_PATH "/com/kylin/AppManager" -#define KYLIN_APP_MANAGER_INTERFACE "com.kylin.AppManager" +#define KYLIN_APP_MANAGER_NAME "com.kylin.AppManager" +#define KYLIN_APP_MANAGER_PATH "/com/kylin/AppManager" +#define KYLIN_APP_MANAGER_INTERFACE "com.kylin.AppManager" +#define FREEDESKTOP_FILEMANAGER_NAME "org.freedesktop.FileManager1" +#define FREEDESKTOP_FILEMANAGER_PATH "/org/freedesktop/FileManager1" +#define FREEDESKTOP_FILEMANAGER_INTERFACE "org.freedesktop.FileManager1" namespace UkuiMenu { @@ -38,18 +41,76 @@ class GVFSRecentFileData { public: static int s_queryFileNum; - static GCancellable *s_cancellable; + static GFile *s_recentFileRootDir; + static GFileMonitor *s_recentFileMonitor; static void loadRecentFileASync(RecentFileProvider *p_recentFileProvider); + static void fileMonitor(RecentFileProvider *p_recentFileProvider); + static void removeRecentFileByInfoId(const QString &infoId); private: - static GFile *s_recentFileRootDir; static GAsyncReadyCallback enumerateFinish(GFile *file, GAsyncResult *res, RecentFileProvider *p_recentFileProvider); static GAsyncReadyCallback parseRecentFiles(GFileEnumerator *enumerator, GAsyncResult *res, RecentFileProvider *p_recentFileProvider); + static void fileChangedCallback(GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + RecentFileProvider *p_recentFileProvider); }; int GVFSRecentFileData::s_queryFileNum = 100; -GCancellable *GVFSRecentFileData::s_cancellable = g_cancellable_new(); GFile *GVFSRecentFileData::s_recentFileRootDir = g_file_new_for_uri("recent:///"); +GFileMonitor *GVFSRecentFileData::s_recentFileMonitor = nullptr; + +void GVFSRecentFileData::fileMonitor(RecentFileProvider *p_recentFileProvider) +{ + GError *error = nullptr; + s_recentFileMonitor = g_file_monitor_directory(GVFSRecentFileData::s_recentFileRootDir, + G_FILE_MONITOR_NONE, + nullptr, + &error); + + if (error) { + qWarning() << "recentFile monitor creat error"; + g_error_free(error); + return; + } + + g_signal_connect(s_recentFileMonitor, "changed", G_CALLBACK(fileChangedCallback), p_recentFileProvider); +} + +void GVFSRecentFileData::fileChangedCallback(GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + RecentFileProvider *p_recentFileProvider) +{ + Q_UNUSED(monitor); + Q_UNUSED(file); + Q_UNUSED(other_file); + + switch (event_type) { + case G_FILE_MONITOR_EVENT_DELETED: + case G_FILE_MONITOR_EVENT_CREATED: { + loadRecentFileASync(p_recentFileProvider); + break; + } + default: + break; + } +} + +void GVFSRecentFileData::removeRecentFileByInfoId(const QString &infoId) +{ + GFile *file = g_file_new_for_uri(infoId.toUtf8().constData()); + GError *err = nullptr; + + g_file_delete(file, nullptr, &err); + + g_object_unref(file); + if (err) { + qWarning() << "Recentfile Delete Error"; + } +} void GVFSRecentFileData::loadRecentFileASync(RecentFileProvider *p_recentFileProvider) { @@ -61,7 +122,7 @@ void GVFSRecentFileData::loadRecentFileASync(RecentFileProvider *p_recentFilePro g_file_enumerate_children_async(s_recentFileRootDir, "*", G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, - s_cancellable, GAsyncReadyCallback(enumerateFinish), + nullptr, GAsyncReadyCallback(enumerateFinish), p_recentFileProvider); } @@ -77,7 +138,7 @@ GVFSRecentFileData::enumerateFinish(GFile *file, GAsyncResult *res, RecentFilePr } g_file_enumerator_next_files_async(enumerator, s_queryFileNum, G_PRIORITY_DEFAULT, - s_cancellable, GAsyncReadyCallback(parseRecentFiles), p_recentFileProvider); + nullptr, GAsyncReadyCallback(parseRecentFiles), p_recentFileProvider); g_object_unref(enumerator); @@ -95,15 +156,19 @@ GVFSRecentFileData::parseRecentFiles(GFileEnumerator *enumerator, GAsyncResult * return nullptr; } + QVector recentFiles; if (!fileList) { + p_recentFileProvider->dataProcess(recentFiles); return nullptr; } - QVector recentFiles; auto listIterator = fileList; while (listIterator) { RecentFile recentFile; GFileInfo *info = static_cast(listIterator->data); + GFile *file = g_file_enumerator_get_child(enumerator, info); + recentFile.infoId = g_file_get_uri(file); + g_object_unref(file); char *attribute = g_file_info_get_attribute_as_string(info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI); if (attribute) { @@ -141,7 +206,7 @@ GVFSRecentFileData::parseRecentFiles(GFileEnumerator *enumerator, GAsyncResult * } recentFiles.append(recentFile); - g_object_unref(info); + info = nullptr; listIterator = listIterator->next; } g_list_free(fileList); @@ -177,6 +242,7 @@ RecentFileExtension::RecentFileExtension(QObject *parent) : MenuExtensionIFace(p m_data.insert("recentFilesModel", QVariant::fromValue(m_recentFilesModel)); initFileDbus(); + GVFSRecentFileData::fileMonitor(m_recentFileProvider); Q_EMIT loadRecentFiles(); } @@ -191,6 +257,14 @@ RecentFileExtension::~RecentFileExtension() delete m_recentFileProvider; m_recentFileProvider = nullptr; } + + if (GVFSRecentFileData::s_recentFileRootDir) { + g_object_unref(GVFSRecentFileData::s_recentFileRootDir); + } + + if (GVFSRecentFileData::s_recentFileMonitor) { + g_object_unref(GVFSRecentFileData::s_recentFileMonitor); + } } int RecentFileExtension::index() @@ -216,6 +290,11 @@ QVariantMap RecentFileExtension::data() void RecentFileExtension::receive(QVariantMap data) { QString path = data.value("url").toString(); + if (data.value("action").toString() == "right") { + int index = data.value("index").toInt(); + creatMenu(path, index); + return; + } if (!openFile(path)) { Q_EMIT openFileASync(path); } @@ -228,9 +307,17 @@ void RecentFileExtension::initFileDbus() KYLIN_APP_MANAGER_INTERFACE, QDBusConnection::sessionBus()); + m_fileManagerDbusInterface = new QDBusInterface(FREEDESKTOP_FILEMANAGER_NAME, + FREEDESKTOP_FILEMANAGER_PATH, + FREEDESKTOP_FILEMANAGER_INTERFACE, + QDBusConnection::sessionBus()); + if (!m_appManagerDbusInterface) { qWarning() << "recentfile open failed: appmanager dbus does not exists."; } + if (!m_fileManagerDbusInterface) { + qWarning() << "recentfile directory open failed: filemanager dbus does not exists."; + } } bool RecentFileExtension::openFile(const QString &desktopFile) @@ -244,6 +331,48 @@ bool RecentFileExtension::openFile(const QString &desktopFile) } } +void RecentFileExtension::creatMenu(const QString &path, const int &index) +{ + QMenu menu; + + QAction open(QIcon::fromTheme("document-open-symbolic"), tr("Open")); + QAction remove(QIcon::fromTheme("edit-clear-symbolic"), tr("Remove from recent")); + QAction clear(QIcon::fromTheme("edit-delete-symbolic"), tr("Clear list")); + QAction directory(tr("Open the directory where the file is located")); + + connect(&open, &QAction::triggered, this, [this, path]() { + if (!openFile(path)) { + Q_EMIT openFileASync(path); + } + }); + + connect(&remove, &QAction::triggered, this, [this, index]() { + GVFSRecentFileData::removeRecentFileByInfoId(m_recentFilesModel->getInfoId(index)); + }); + + connect(&clear, &QAction::triggered, this, [this]() { + QStringList infoIdList = m_recentFilesModel->getAllInfoId(); + for (const QString &infoId : infoIdList) { + GVFSRecentFileData::removeRecentFileByInfoId(infoId); + } + }); + + connect(&directory, &QAction::triggered, this, [this, path]() { + if (!m_fileManagerDbusInterface) { return; } + QStringList pathList; + pathList.append(path); + m_fileManagerDbusInterface->call("ShowFolders", pathList, "arg"); + }); + + menu.addAction(&open); + menu.addSeparator(); + menu.addAction(&remove); + menu.addAction(&clear); + menu.addSeparator(); + menu.addAction(&directory); + menu.exec(QCursor::pos()); +} + RecentFilesModel::RecentFilesModel(QObject *parent) : QAbstractListModel(parent) { @@ -284,6 +413,20 @@ QHash RecentFilesModel::roleNames() const return names; } +QString RecentFilesModel::getInfoId(const int &index) +{ + return m_recentFileData.at(index).infoId; +} + +QStringList RecentFilesModel::getAllInfoId() +{ + QStringList infoIdList; + for (const RecentFile &data : m_recentFileData) { + infoIdList.append(data.infoId); + } + return infoIdList; +} + void RecentFilesModel::updateData() { Q_EMIT updateRecentData(); diff --git a/src/extension/extensions/recent-file-extension.h b/src/extension/extensions/recent-file-extension.h index 8c46e4b..d8d6152 100644 --- a/src/extension/extensions/recent-file-extension.h +++ b/src/extension/extensions/recent-file-extension.h @@ -29,21 +29,12 @@ namespace UkuiMenu { class RecentFile { - Q_GADGET - Q_PROPERTY(QString uri READ getUri) - Q_PROPERTY(QString name READ getName) - Q_PROPERTY(QString icon READ getIcon) - -public: - QString getUri() { return uri; } - QString getName() { return name; } - QString getIcon() { return icon; } - public: quint64 accessTime{0}; QString uri; QString name; QString icon; + QString infoId; }; class RecentFileProvider : public QObject @@ -77,6 +68,8 @@ public: QVariant data(const QModelIndex &index, int role) const override; QHash roleNames() const override; + QString getInfoId(const int &index); + QStringList getAllInfoId(); Q_INVOKABLE void updateData(); public Q_SLOT: @@ -109,9 +102,11 @@ private: RecentFilesModel *m_recentFilesModel = nullptr; QThread *m_recentFilesProviderThread = nullptr; RecentFileProvider *m_recentFileProvider = nullptr; + QDBusInterface *m_fileManagerDbusInterface = nullptr; void initFileDbus(); bool openFile(const QString& desktopFile); + void creatMenu(const QString &path, const int &index); Q_SIGNALS: void loadRecentFiles();