修复wayland环境会打开多个菜单问题

This commit is contained in:
hewenfei 2023-06-27 16:18:14 +08:00
parent ea35c8fd75
commit 3327d93700
7 changed files with 113 additions and 39 deletions

View File

@ -43,6 +43,13 @@ UkuiMenuExtension {
} }
} }
onClicked: {
var data = {
"action": "closeMenu"
}
send(data);
}
AppControls2.StyleBackground { AppControls2.StyleBackground {
anchors.top: parent.top anchors.top: parent.top
width: parent.width; height: 1 width: parent.width; height: 1
@ -157,7 +164,7 @@ UkuiMenuExtension {
"url": model.uri, "url": model.uri,
"index": model.index "index": model.index
} }
data["action"] = mouse.button === Qt.RightButton ? "right" : "" data["action"] = mouse.button === Qt.RightButton ? "right" : "openFile"
send(data) send(data)
} }
} }

View File

@ -350,14 +350,20 @@ QVariantMap RecentFileExtension::data()
void RecentFileExtension::receive(QVariantMap data) void RecentFileExtension::receive(QVariantMap data)
{ {
QString path = data.value("url").toString();
if (data.value("action").toString() == "right") { if (data.value("action").toString() == "right") {
QString path = data.value("url").toString();
int index = data.value("index").toInt(); int index = data.value("index").toInt();
creatMenu(path, index); creatMenu(path, index);
return; return;
} else if (m_contextMenu) {
m_contextMenu.data()->close();
} }
openFile(path); if (data.value("action").toString() == "openFile") {
QString path = data.value("url").toString();
openFile(path);
}
} }
void RecentFileExtension::openFile(const QString &fileUrl) void RecentFileExtension::openFile(const QString &fileUrl)
@ -378,29 +384,35 @@ void RecentFileExtension::openFile(const QString &fileUrl)
void RecentFileExtension::creatMenu(const QString &path, const int &index) void RecentFileExtension::creatMenu(const QString &path, const int &index)
{ {
QMenu menu; if (m_contextMenu) {
m_contextMenu.data()->close();
return;
}
QAction open(QIcon::fromTheme("document-open-symbolic"), tr("Open")); QMenu *menu = new QMenu;
QAction remove(QIcon::fromTheme("edit-clear-symbolic"), tr("Remove from list")); menu->setAttribute(Qt::WA_DeleteOnClose);
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]() { QAction *open = new QAction(QIcon::fromTheme("document-open-symbolic"), tr("Open"), menu);
QAction *remove = new QAction(QIcon::fromTheme("edit-clear-symbolic"), tr("Remove from list"), menu);
QAction *clear = new QAction(QIcon::fromTheme("edit-delete-symbolic"), tr("Clear list"), menu);
QAction *directory = new QAction(tr("Open the directory where the file is located"), menu);
connect(open, &QAction::triggered, this, [this, path]() {
openFile(path); openFile(path);
}); });
connect(&remove, &QAction::triggered, this, [this, index]() { connect(remove, &QAction::triggered, this, [this, index]() {
GVFSRecentFileData::removeRecentFileByInfoId(m_recentFilesModel->getInfoId(index)); GVFSRecentFileData::removeRecentFileByInfoId(m_recentFilesModel->getInfoId(index));
}); });
connect(&clear, &QAction::triggered, this, [this]() { connect(clear, &QAction::triggered, this, [this]() {
QStringList infoIdList = m_recentFilesModel->getAllInfoId(); QStringList infoIdList = m_recentFilesModel->getAllInfoId();
for (const QString &infoId : infoIdList) { for (const QString &infoId : infoIdList) {
GVFSRecentFileData::removeRecentFileByInfoId(infoId); GVFSRecentFileData::removeRecentFileByInfoId(infoId);
} }
}); });
connect(&directory, &QAction::triggered, this, [this, path]() { connect(directory, &QAction::triggered, this, [this, path]() {
QDBusMessage message = QDBusMessage::createMethodCall(FREEDESKTOP_FILEMANAGER_NAME, QDBusMessage message = QDBusMessage::createMethodCall(FREEDESKTOP_FILEMANAGER_NAME,
FREEDESKTOP_FILEMANAGER_PATH, FREEDESKTOP_FILEMANAGER_PATH,
FREEDESKTOP_FILEMANAGER_INTERFACE, "ShowFolders"); FREEDESKTOP_FILEMANAGER_INTERFACE, "ShowFolders");
@ -408,13 +420,16 @@ void RecentFileExtension::creatMenu(const QString &path, const int &index)
QDBusConnection::sessionBus().asyncCall(message); QDBusConnection::sessionBus().asyncCall(message);
}); });
menu.addAction(&open); menu->addAction(open);
menu.addSeparator(); menu->addSeparator();
menu.addAction(&remove); menu->addAction(remove);
menu.addAction(&clear); menu->addAction(clear);
menu.addSeparator(); menu->addSeparator();
menu.addAction(&directory); menu->addAction(directory);
menu.exec(QCursor::pos());
m_contextMenu = menu;
menu->popup(QCursor::pos());
} }
RecentFilesModel::RecentFilesModel(QObject *parent) : QAbstractListModel(parent) RecentFilesModel::RecentFilesModel(QObject *parent) : QAbstractListModel(parent)

View File

@ -19,6 +19,9 @@
#ifndef UKUI_MENU_RECENT_FILE_EXTENSION_H #ifndef UKUI_MENU_RECENT_FILE_EXTENSION_H
#define UKUI_MENU_RECENT_FILE_EXTENSION_H #define UKUI_MENU_RECENT_FILE_EXTENSION_H
#include <QMenu>
#include <QPointer>
class QThread; class QThread;
#include "menu-extension-iface.h" #include "menu-extension-iface.h"
@ -53,6 +56,7 @@ public:
void receive(QVariantMap data) override; void receive(QVariantMap data) override;
private: private:
QPointer<QMenu> m_contextMenu;
QVector<RecentFile> m_recentFile; QVector<RecentFile> m_recentFile;
QVariantMap m_data; QVariantMap m_data;
RecentFilesModel *m_recentFilesModel = nullptr; RecentFilesModel *m_recentFilesModel = nullptr;

53
src/menu/menu-manager.cpp Normal file → Executable file
View File

@ -34,6 +34,8 @@
#include <QDir> #include <QDir>
#include <QPluginLoader> #include <QPluginLoader>
#include <QJsonObject> #include <QJsonObject>
#include <QPointer>
#include <QWindow>
using namespace UkuiMenu; using namespace UkuiMenu;
@ -192,6 +194,8 @@ MenuManager *MenuManager::instance()
class MenuManagerPrivate class MenuManagerPrivate
{ {
public: public:
QPointer<QMenu> contextMenu;
QWindow *mainWindow {nullptr};
QList<MenuProvider*> providers; QList<MenuProvider*> providers;
}; };
@ -238,21 +242,46 @@ void MenuManager::showMenu(const DataEntity &entity, const MenuInfo::Location lo
void MenuManager::showMenu(const MenuProvider::RequestType &type, QVariant data, const MenuInfo::Location location, const QString &lid, const QPoint &point) void MenuManager::showMenu(const MenuProvider::RequestType &type, QVariant data, const MenuInfo::Location location, const QString &lid, const QPoint &point)
{ {
QMenu menu; if (closeMenu()) {
QList<QAction*> actions;
for (const auto &provider : d->providers) {
if (provider->isSupport(type)) {
actions.append(provider->generateActions(&menu, data, location, lid));
}
}
if (actions.isEmpty() && menu.isEmpty()) {
return; return;
} }
menu.addActions(actions); QMenu *menu = new QMenu;
menu.exec(checkPoint(point)); QList<QAction*> actions;
for (const auto &provider : d->providers) {
if (provider->isSupport(type)) {
actions.append(provider->generateActions(menu, data, location, lid));
}
}
if (actions.isEmpty() && menu->isEmpty()) {
delete menu;
return;
}
d->contextMenu = menu;
menu->setAttribute(Qt::WA_DeleteOnClose);
if (menu->winId()) {
menu->windowHandle()->setTransientParent(d->mainWindow);
}
menu->addActions(actions);
menu->popup(checkPoint(point));
}
void MenuManager::setMainWindow(QWindow *mainWindow)
{
d->mainWindow = mainWindow;
}
bool MenuManager::closeMenu()
{
if (d->contextMenu) {
d->contextMenu.data()->close();
return true;
}
return false;
} }
inline QPoint MenuManager::checkPoint(const QPoint &rawPoint) inline QPoint MenuManager::checkPoint(const QPoint &rawPoint)

View File

@ -25,6 +25,7 @@
#include "data-entity.h" #include "data-entity.h"
#include "menu-provider.h" #include "menu-provider.h"
class QWindow;
class MenuManagerPrivate; class MenuManagerPrivate;
namespace UkuiMenu { namespace UkuiMenu {
@ -39,6 +40,8 @@ public:
Q_INVOKABLE void showMenu(const QString &appid, MenuInfo::Location, const QString& lid = QString(), const QPoint &point = QPoint()); Q_INVOKABLE void showMenu(const QString &appid, MenuInfo::Location, const QString& lid = QString(), const QPoint &point = QPoint());
void showMenu(const DataEntity &entity, MenuInfo::Location location, const QString& lid = QString(), const QPoint &point = QPoint()); void showMenu(const DataEntity &entity, MenuInfo::Location location, const QString& lid = QString(), const QPoint &point = QPoint());
void showMenu(const MenuProvider::RequestType &type, QVariant data, MenuInfo::Location location, const QString& lid = QString(), const QPoint &point = QPoint()); void showMenu(const MenuProvider::RequestType &type, QVariant data, MenuInfo::Location location, const QString& lid = QString(), const QPoint &point = QPoint());
void setMainWindow(QWindow *mainWindow);
bool closeMenu();
private: private:
MenuManager(); MenuManager();

View File

@ -24,6 +24,7 @@
#include <QQmlEngine> #include <QQmlEngine>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QMenu> #include <QMenu>
#include <QPointer>
namespace UkuiMenu { namespace UkuiMenu {
@ -54,6 +55,7 @@ private:
private: private:
int m_currentIndex = 0; int m_currentIndex = 0;
QPointer<QMenu> m_menu;
QString m_currentId; QString m_currentId;
QVector<ProviderInfo> m_providers; QVector<ProviderInfo> m_providers;
QHash<int, QByteArray> m_roleNames; QHash<int, QByteArray> m_roleNames;
@ -148,27 +150,34 @@ QString ProviderModel::currentProviderIcon()
void ProviderModel::openMenu(int offset, int mouseX, int mouseY) void ProviderModel::openMenu(int offset, int mouseX, int mouseY)
{ {
QMenu menu; if (m_menu) {
m_menu.data()->close();
return;
}
QMenu *menu = new QMenu;
menu->setAttribute(Qt::WA_DeleteOnClose);
if (m_providers.isEmpty()) { if (m_providers.isEmpty()) {
return; return;
} }
for (const ProviderInfo &info : m_providers) { for (const ProviderInfo &info : m_providers) {
QAction *action = new QAction(info.name, &menu); QAction *action = new QAction(info.name, menu);
action->setCheckable(true); action->setCheckable(true);
connect(action, &QAction::triggered, &menu, [info]() { connect(action, &QAction::triggered, menu, [info]() {
DataProviderManager::instance()->activateProvider(info.id); DataProviderManager::instance()->activateProvider(info.id);
}); });
menu.addAction(action); menu->addAction(action);
} }
menu.actions().at(m_currentIndex)->setChecked(true); menu->actions().at(m_currentIndex)->setChecked(true);
int x = mouseX - menu.sizeHint().width(); int x = mouseX - menu->sizeHint().width();
int y = mouseY + offset; int y = mouseY + offset;
menu.exec(QPoint(x, y));
Q_EMIT menuClosed(); m_menu = menu;
connect(menu, &QMenu::aboutToHide, this, &ProviderModel::menuClosed);
menu->popup(QPoint(x, y));
} }
void ProviderModel::reactivateProvider() void ProviderModel::reactivateProvider()

View File

@ -18,6 +18,7 @@
#include "menu-main-window.h" #include "menu-main-window.h"
#include "settings.h" #include "settings.h"
#include "menu-manager.h"
#include <QGuiApplication> #include <QGuiApplication>
#include <QQuickItem> #include <QQuickItem>
@ -416,6 +417,8 @@ void MenuWindow::init()
}); });
updateGeometry(); updateGeometry();
MenuManager::instance()->setMainWindow(this);
} }
void MenuWindow::updateGeometry() void MenuWindow::updateGeometry()
@ -515,6 +518,10 @@ bool MenuWindow::event(QEvent *event)
if (event->type() == QEvent::UpdateRequest) { if (event->type() == QEvent::UpdateRequest) {
WindowHelper::removeHeaderBar(this); WindowHelper::removeHeaderBar(this);
} }
if (event->type() == QEvent::MouseButtonPress) {
MenuManager::instance()->closeMenu();
}
return QQuickView::event(event); return QQuickView::event(event);
} }