feat: 修改开发库so名称,删除旧版本菜单扩展,重新实现上下文菜单扩展

This commit is contained in:
hewenfei 2023-12-11 10:43:25 +08:00
parent 3fc780d666
commit c7fc015f27
17 changed files with 490 additions and 880 deletions

View File

@ -49,12 +49,12 @@ set(SingleApplication "qtsingleapplication")
# include
include_directories(src)
include_directories(src/menu)
include_directories(src/model)
include_directories(src/appdata)
include_directories(src/settings)
include_directories(src/uiconfig)
include_directories(src/windows)
include_directories(src/extension)
include_directories(src/utils)
include_directories(3rd-parties/qtsingleapplication/src)
@ -75,7 +75,8 @@ set(UKUI_MENU_CONTEXT_MENU_DIR "${UKUI_MENU_SO_DIR}/context-menu")
set(UKUI_MENU_LIBRARY_VERSION 1.0.0)
set(UKUI_MENU_LIBRARY_API_VERSION 1)
#set(UKUI_MENU_LIBRARY_NAME "ukui-menu${UKUI_MENU_LIBRARY_API_VERSION}")
set(UKUI_MENU_LIBRARY_NAME "ukui-menu-interface")
set(UKUI_MENU_LIBRARY_NAME "ukui-menu")
set(UKUI_MENU_LIBRARY_TARGET "libukui-menu")
set(PC_INSTALL_DIR "/usr/lib/pkgconfig")
set(CMAKE_CONFIG_INSTALL_DIR "/usr/share/cmake/${UKUI_MENU_LIBRARY_NAME}")
@ -110,23 +111,21 @@ set(SOURCE_FILES
src/appdata/plugin/app-search-plugin.cpp src/appdata/plugin/app-search-plugin.h
src/appdata/plugin/app-category-plugin.cpp src/appdata/plugin/app-category-plugin.h
src/appdata/plugin/app-letter-sort-plugin.cpp src/appdata/plugin/app-letter-sort-plugin.h
src/extension/menu-extension.cpp src/extension/menu-extension.h
src/extension/extensions/favorite-extension.cpp src/extension/extensions/favorite-extension.h
src/utils/app-page-header-utils.cpp src/utils/app-page-header-utils.h
src/utils/power-button.cpp src/utils/power-button.h
src/utils/app-manager.cpp src/utils/app-manager.h
src/utils/event-track.cpp src/utils/event-track.h
src/utils/sidebar-button-utils.cpp src/utils/sidebar-button-utils.h
src/menu/menu-provider.h
src/menu/menu-manager.cpp src/menu/menu-manager.h
src/items/theme-icon.h src/items/theme-icon.cpp
src/settings/user-config.cpp src/settings/user-config.h
src/extension/menu-extension-plugin.cpp src/extension/menu-extension-plugin.h
src/extension/menu-extension-loader.cpp src/extension/menu-extension-loader.h
src/extension/widget-extension.cpp src/extension/widget-extension.h
src/extension/context-menu-extension.cpp src/extension/context-menu-extension.h
src/extension/menu-extension-loader.cpp src/extension/menu-extension-loader.h
src/extension/menu-extension-plugin.cpp src/extension/menu-extension-plugin.h
src/extension/context-menu-manager.cpp src/extension/context-menu-manager.h
src/extension/widget-extension-model.cpp src/extension/widget-extension-model.h
src/extension/widget-model.cpp src/extension/widget-model.h
src/extension/menu/app-menu-plugin.cpp src/extension/menu/app-menu-plugin.h
)
@ -139,14 +138,14 @@ endif()
# library sources
set(LIBRARY_SOURCES
src/data-entity.cpp
src/extension/menu-extension-iface.h
)
src/extension/menu-extension-plugin.cpp
src/extension/widget-extension.cpp
src/extension/context-menu-extension.cpp
)
set(LIBRARY_HEADERS_DIR "/usr/include/${UKUI_MENU_LIBRARY_NAME}")
set(LIBRARY_HEADERS
src/data-entity.h
src/menu/menu-provider.h
src/extension/menu-extension-iface.h
src/extension/menu-extension-plugin.h
src/extension/widget-extension.h
src/extension/context-menu-extension.h
@ -170,12 +169,13 @@ qt5_create_translation(QM_FILES ${PROJECT_SOURCE_DIR} ${TS_FILES})
# add_custom_target(GEN_TS ALL DEPENDS ${TS_FILES})
# add_custom_target(generate_qm ALL DEPENDS ${QM_FILES})
add_library(${UKUI_MENU_LIBRARY_NAME} SHARED ${LIBRARY_SOURCES})
set_target_properties(${UKUI_MENU_LIBRARY_NAME} PROPERTIES
add_library(${UKUI_MENU_LIBRARY_TARGET} SHARED ${LIBRARY_SOURCES})
set_target_properties(${UKUI_MENU_LIBRARY_TARGET} PROPERTIES
VERSION ${UKUI_MENU_LIBRARY_VERSION}
SOVERSION ${UKUI_MENU_LIBRARY_API_VERSION}
OUTPUT_NAME "ukui-menu"
)
target_link_libraries(${UKUI_MENU_LIBRARY_NAME} PRIVATE Qt5::Core)
target_link_libraries(${UKUI_MENU_LIBRARY_TARGET} PRIVATE Qt5::Core Qt5::Gui Qt5::Widgets)
add_executable(
${PROJECT_NAME}
@ -198,12 +198,12 @@ target_link_libraries(${PROJECT_NAME}
Qt5Xdg
${SingleApplication}
${UKUI_MENU_EXTERNAL_LIBS}
${UKUI_MENU_LIBRARY_NAME}
${UKUI_MENU_LIBRARY_TARGET}
)
# ukui-menu
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "/usr/bin")
install(TARGETS ${UKUI_MENU_LIBRARY_NAME}
install(TARGETS ${UKUI_MENU_LIBRARY_TARGET}
EXPORT ${UKUI_MENU_LIBRARY_NAME}
PUBLIC_HEADER DESTINATION ${LIBRARY_HEADERS_DIR}
LIBRARY DESTINATION "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}"

View File

@ -17,7 +17,7 @@
*/
#include "app-folder-helper.h"
#include "menu-manager.h"
#include "context-menu-manager.h"
#include "app-data-manager.h"
#include "model-manager.h"
#include "app-model.h"
@ -36,125 +36,125 @@
namespace UkuiMenu {
class FolderMenuProvider : public MenuProvider
{
public:
FolderMenuProvider();
int index() override { return 256; }
bool isSupport(const RequestType &type) override;
QList<QAction *> generateActions(QObject *parent, const QVariant &data, const MenuInfo::Location &location, const QString &locationId) override;
private:
static void folderMenuForNormal(QObject *parent, const QString &appId, QList<QAction *> &list);
static void dissolveFolder(QObject *parent, const QString &folderId, QList<QAction *> &list);
static void renameFolder(QObject *parent, const QString &folderId, QList<QAction *> &list);
};
//class FolderMenuProvider : public MenuProvider
//{
//public:
// FolderMenuProvider();
// int index() override { return 256; }
// bool isSupport(const RequestType &type) override;
// QList<QAction *> generateActions(QObject *parent, const QVariant &data, const MenuInfo::Location &location, const QString &locationId) override;
//private:
// static void folderMenuForNormal(QObject *parent, const QString &appId, QList<QAction *> &list);
// static void dissolveFolder(QObject *parent, const QString &folderId, QList<QAction *> &list);
// static void renameFolder(QObject *parent, const QString &folderId, QList<QAction *> &list);
//};
FolderMenuProvider::FolderMenuProvider()
{
}
bool FolderMenuProvider::isSupport(const MenuProvider::RequestType &type)
{
return type == DataType;
}
QList<QAction *>
FolderMenuProvider::generateActions(QObject *parent, const QVariant &data, const MenuInfo::Location &location,
const QString &locationId)
{
if (!parent) {
return {};
}
DataEntity app = data.value<DataEntity>();
QList<QAction *> list;
switch (location) {
case MenuInfo::FullScreen: {
if (app.type() == DataType::Folder) {
dissolveFolder(parent, app.id(), list);
break;
}
}
case MenuInfo::AppList: {
if (app.type() == DataType::Folder) {
renameFolder(parent, app.id(), list);
dissolveFolder(parent, app.id(), list);
break;
}
if (app.type() != DataType::Normal || locationId != "all") {
break;
}
}
case MenuInfo::FullScreenFolder:
case MenuInfo::FolderPage: {
if (app.type() == DataType::Normal) {
folderMenuForNormal(parent, app.id(), list);
}
break;
}
case MenuInfo::Extension:
default:
break;
}
return list;
}
void FolderMenuProvider::folderMenuForNormal(QObject *parent, const QString &appId, QList<QAction *> &list)
{
Folder folder;
if (AppFolderHelper::instance()->searchFolderByAppName(appId, folder)) {
//从当前文件夹移除
list << new QAction(QObject::tr("Remove from folder"), parent);
QObject::connect(list.last(), &QAction::triggered, parent, [appId, folder] {
AppFolderHelper::instance()->removeAppFromFolder(appId, folder.getId());
AppFolderHelper::instance()->forceSync();
});
return;
}
QMenu *menu = static_cast<QMenu*>(parent);
//添加到应用组
QMenu *subMenu = new QMenu(QObject::tr("Add to folder"), menu);
QAction* newAct = new QAction(QObject::tr("Add to new folder"), subMenu);
QObject::connect(newAct, &QAction::triggered, parent, [appId] {
AppFolderHelper::instance()->addAppToNewFolder(appId, "");
AppFolderHelper::instance()->forceSync();
});
subMenu->addAction(newAct);
QList<Folder> folders = AppFolderHelper::instance()->folderData();
for (const Folder &f : folders) {
QString name = QObject::tr("Add to \"%1\"").arg(f.getName());
QAction* act = new QAction(name, subMenu);
QObject::connect(act, &QAction::triggered, parent, [appId, f] {
AppFolderHelper::instance()->addAppToFolder(appId, f.getId());
});
subMenu->addAction(act);
}
menu->addMenu(subMenu);
}
void FolderMenuProvider::dissolveFolder(QObject *parent, const QString &folderId, QList<QAction *> &list)
{
list << new QAction(QObject::tr("Dissolve folder"), parent);
QObject::connect(list.last(), &QAction::triggered, parent, [folderId] {
AppFolderHelper::instance()->deleteFolder(folderId.toInt());
AppFolderHelper::instance()->forceSync();
});
}
void FolderMenuProvider::renameFolder(QObject *parent, const QString &folderId, QList<QAction *> &list)
{
list << new QAction(QObject::tr("Rename"), parent);
QObject::connect(list.last(), &QAction::triggered, parent, [folderId] {
ModelManager::instance()->getAppModel()->toRenameFolder(folderId);
});
}
//FolderMenuProvider::FolderMenuProvider()
//{
//
//}
//
//bool FolderMenuProvider::isSupport(const MenuProvider::RequestType &type)
//{
// return type == DataType;
//}
//
//QList<QAction *>
//FolderMenuProvider::generateActions(QObject *parent, const QVariant &data, const MenuInfo::Location &location,
// const QString &locationId)
//{
// if (!parent) {
// return {};
// }
//
// DataEntity app = data.value<DataEntity>();
// QList<QAction *> list;
//
// switch (location) {
// case MenuInfo::FullScreen: {
// if (app.type() == DataType::Folder) {
// dissolveFolder(parent, app.id(), list);
// break;
// }
// }
// case MenuInfo::AppList: {
// if (app.type() == DataType::Folder) {
// renameFolder(parent, app.id(), list);
// dissolveFolder(parent, app.id(), list);
// break;
// }
//
// if (app.type() != DataType::Normal || locationId != "all") {
// break;
// }
// }
// case MenuInfo::FullScreenFolder:
// case MenuInfo::FolderPage: {
// if (app.type() == DataType::Normal) {
// folderMenuForNormal(parent, app.id(), list);
// }
// break;
// }
// case MenuInfo::Extension:
// default:
// break;
// }
//
// return list;
//}
//
//void FolderMenuProvider::folderMenuForNormal(QObject *parent, const QString &appId, QList<QAction *> &list)
//{
// Folder folder;
// if (AppFolderHelper::instance()->searchFolderByAppName(appId, folder)) {
// //从当前文件夹移除
// list << new QAction(QObject::tr("Remove from folder"), parent);
// QObject::connect(list.last(), &QAction::triggered, parent, [appId, folder] {
// AppFolderHelper::instance()->removeAppFromFolder(appId, folder.getId());
// AppFolderHelper::instance()->forceSync();
// });
// return;
// }
//
// QMenu *menu = static_cast<QMenu*>(parent);
// //添加到应用组
// QMenu *subMenu = new QMenu(QObject::tr("Add to folder"), menu);
//
// QAction* newAct = new QAction(QObject::tr("Add to new folder"), subMenu);
// QObject::connect(newAct, &QAction::triggered, parent, [appId] {
// AppFolderHelper::instance()->addAppToNewFolder(appId, "");
// AppFolderHelper::instance()->forceSync();
// });
// subMenu->addAction(newAct);
//
// QList<Folder> folders = AppFolderHelper::instance()->folderData();
// for (const Folder &f : folders) {
// QString name = QObject::tr("Add to \"%1\"").arg(f.getName());
// QAction* act = new QAction(name, subMenu);
// QObject::connect(act, &QAction::triggered, parent, [appId, f] {
// AppFolderHelper::instance()->addAppToFolder(appId, f.getId());
// });
// subMenu->addAction(act);
// }
// menu->addMenu(subMenu);
//}
//
//void FolderMenuProvider::dissolveFolder(QObject *parent, const QString &folderId, QList<QAction *> &list)
//{
// list << new QAction(QObject::tr("Dissolve folder"), parent);
// QObject::connect(list.last(), &QAction::triggered, parent, [folderId] {
// AppFolderHelper::instance()->deleteFolder(folderId.toInt());
// AppFolderHelper::instance()->forceSync();
// });
//}
//
//void FolderMenuProvider::renameFolder(QObject *parent, const QString &folderId, QList<QAction *> &list)
//{
// list << new QAction(QObject::tr("Rename"), parent);
// QObject::connect(list.last(), &QAction::triggered, parent, [folderId] {
// ModelManager::instance()->getAppModel()->toRenameFolder(folderId);
// });
//}
QString AppFolderHelper::s_folderConfigFile = QDir::homePath() + "/" + FOLDER_FILE_PATH + FOLDER_FILE_NAME;
@ -167,7 +167,6 @@ AppFolderHelper *AppFolderHelper::instance()
AppFolderHelper::AppFolderHelper()
{
qRegisterMetaType<Folder>("Folder");
MenuManager::instance()->registerMenuProvider(new FolderMenuProvider);
if (!QFile::exists(s_folderConfigFile)) {
QDir dir;

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#include "context-menu-manager.h"
#include "app-data-manager.h"
#include "menu-extension-loader.h"
#include <QMenu>
#include <QCursor>
#include <QPointer>
#include <QWindow>
using namespace UkuiMenu;
ContextMenuManager *ContextMenuManager::instance()
{
static ContextMenuManager manager;
return &manager;
}
class MenuManagerPrivate
{
public:
QPointer<QMenu> contextMenu;
QWindow *mainWindow {nullptr};
QList<ContextMenuExtension*> extensions;
};
ContextMenuManager::ContextMenuManager() : d(new MenuManagerPrivate)
{
d->extensions = MenuExtensionLoader::instance()->menus();
}
ContextMenuManager::~ContextMenuManager()
{
for (auto &provider : d->extensions) {
delete provider;
provider = nullptr;
}
}
void ContextMenuManager::showMenu(const QString &appid, const MenuInfo::Location location, const QString &lid, const QPoint &point)
{
DataEntity app;
if (AppDataManager::instance()->getApp(appid, app)) {
showMenu(app, location, lid, point);
}
}
void ContextMenuManager::showMenu(const DataEntity &data, MenuInfo::Location location, const QString &lid, const QPoint &point)
{
if (closeMenu()) {
return;
}
auto menu = new QMenu;
QList<QAction*> actions;
for (const auto &extension : d->extensions) {
actions.append(extension->actions(data, menu, 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 ContextMenuManager::setMainWindow(QWindow *mainWindow)
{
d->mainWindow = mainWindow;
}
bool ContextMenuManager::closeMenu()
{
if (d->contextMenu) {
d->contextMenu.data()->close();
return true;
}
return false;
}
inline QPoint ContextMenuManager::checkPoint(const QPoint &rawPoint)
{
if (rawPoint.isNull()) {
return QCursor::pos();
}
return rawPoint;
}

View File

@ -16,36 +16,34 @@
*
*/
#ifndef UKUI_MENU_MENU_MANAGER_H
#define UKUI_MENU_MENU_MANAGER_H
#ifndef UKUI_MENU_CONTEXT_MENU_MANAGER_H
#define UKUI_MENU_CONTEXT_MENU_MANAGER_H
#include <QObject>
#include <QPoint>
#include "data-entity.h"
#include "menu-provider.h"
#include "context-menu-extension.h"
class QWindow;
class MenuManagerPrivate;
namespace UkuiMenu {
class MenuManager : public QObject
class ContextMenuManager : public QObject
{
Q_OBJECT
public:
static MenuManager *instance();
~MenuManager() override;
void registerMenuProvider(MenuProvider *provider);
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 MenuProvider::RequestType &type, QVariant data, MenuInfo::Location location, const QString& lid = QString(), const QPoint &point = QPoint());
static ContextMenuManager *instance();
~ContextMenuManager() override;
Q_INVOKABLE void showMenu(const QString &appid, MenuInfo::Location location, const QString& lid = QString(), const QPoint &point = QPoint());
void showMenu(const DataEntity &data, MenuInfo::Location location, const QString& lid = QString(), const QPoint &point = QPoint());
void setMainWindow(QWindow *mainWindow);
bool closeMenu();
private:
MenuManager();
void loadMenus();
ContextMenuManager();
inline QPoint checkPoint(const QPoint &rawPoint);
private:
@ -54,4 +52,4 @@ private:
} // UkuiMenu
#endif //UKUI_MENU_MENU_MANAGER_H
#endif //UKUI_MENU_CONTEXT_MENU_MANAGER_H

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2022, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_MENU_EXTENSION_I_FACE_H
#define UKUI_MENU_MENU_EXTENSION_I_FACE_H
#define UKUI_MENU_EXTENSION_TYPE "UKUI_MENU_EXTENSION"
#define UKUI_MENU_EXTENSION_IFACE_IID "org.ukui.menu.extension"
#define UKUI_MENU_EXTENSION_IFACE_VERSION "1.0.1"
#include <QObject>
#include <QUrl>
#include <QString>
#include <QVariant>
#include <QtPlugin>
namespace UkuiMenu {
class Q_DECL_EXPORT MenuExtensionIFace : public QObject
{
Q_OBJECT
public:
enum Option {
HideBottomBar,
HideFullScreenButton
};
Q_ENUM(Option)
explicit MenuExtensionIFace(QObject *parent = nullptr) : QObject(parent) {};
virtual int index() = 0;
virtual QString name() = 0;
virtual QUrl url() = 0;
virtual QVariantMap data() = 0;
virtual QVariantList options() { return {}; };
virtual void receive(QVariantMap data) = 0;
Q_SIGNALS:
void dataUpdated();
};
}
Q_DECLARE_INTERFACE(UkuiMenu::MenuExtensionIFace, UKUI_MENU_EXTENSION_IFACE_IID)
#endif //UKUI_MENU_MENU_EXTENSION_I_FACE_H

View File

@ -1,190 +0,0 @@
/*
* Copyright (C) 2022, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#include "menu-extension.h"
#include "extensions/favorite-extension.h"
#include <utility>
#include <QDir>
#include <QPluginLoader>
#include <QDebug>
#include <QtQml/qqml.h>
namespace UkuiMenu {
MenuExtension *MenuExtension::instance()
{
static MenuExtension menuExtension;
return &menuExtension;
}
MenuExtension::MenuExtension()
{
qRegisterMetaType<ExtensionModel*>("ExtensionModel*");
qmlRegisterUncreatableType<MenuExtensionIFace>("org.ukui.menu.extension", 1, 0, "MenuExtension", "");
// TODO load extension from filesystem.
loadExtensions();
// register extension.
registerExtension(new FavoriteExtension(this));
initModel();
}
void MenuExtension::registerExtension(MenuExtensionIFace *extension)
{
if (!extension) {
return;
}
extension->setParent(this);
if (m_extensions.contains(extension->name())) {
return;
}
m_extensions.insert(extension->name(), extension);
}
ExtensionModel *MenuExtension::extensionModel()
{
return m_model;
}
void MenuExtension::initModel()
{
QVector<MenuExtensionIFace*> data;
QMap<QString, MenuExtensionIFace*>::const_iterator iterator = m_extensions.constBegin();
for (; iterator != m_extensions.constEnd(); ++iterator) {
MenuExtensionIFace* extension = iterator.value();
data.append(extension);
}
std::sort(data.begin(), data.end(), [](MenuExtensionIFace* a, MenuExtensionIFace* b) {
return a->index() <= b->index();
});
m_model = new ExtensionModel(data, this);
if (!m_model) {
qWarning() << "MenuExtension: unable to init the model of menu-extension.";
}
}
void MenuExtension::loadExtensions()
{
QDir pluginsDir(UKUI_MENU_EXTENSION_DIR);
pluginsDir.setFilter(QDir::Files);
for(const QString& fileName : pluginsDir.entryList(QDir::Files)) {
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QJsonObject metaData = pluginLoader.metaData().value("MetaData").toObject();
QString type = metaData.value("Type").toString();
QString version = metaData.value("Version").toString();
if(type != UKUI_MENU_EXTENSION_TYPE) {
continue;
}
if(version != UKUI_MENU_EXTENSION_IFACE_VERSION) {
qWarning() << "UKUI_MENU_EXTENSION version check failed:" << fileName << "version:" << version << "iface version : " << UKUI_MENU_EXTENSION_IFACE_VERSION;
continue;
}
QObject *obj = pluginLoader.instance();
if (!obj) {
continue;
}
MenuExtensionIFace *plugin = qobject_cast<MenuExtensionIFace*>(obj);
if (!plugin) {
continue;
}
registerExtension(plugin);
}
}
ExtensionModel::ExtensionModel(const QVector<MenuExtensionIFace*> &extensions, QObject *parent)
: QAbstractListModel(parent), m_extensions(extensions)
{
m_roleNames.insert(Name, "name");
m_roleNames.insert(Url, "url");
m_roleNames.insert(Data, "data");
m_roleNames.insert(Options, "options");
for (int i = 0; i < m_extensions.size(); ++i) {
connect(m_extensions.at(i), &MenuExtensionIFace::dataUpdated, this, [this, i] {
extensionDataChanged(i);
});
}
}
int ExtensionModel::rowCount(const QModelIndex &parent) const
{
return m_extensions.size();
}
QVariant ExtensionModel::data(const QModelIndex &index, int role) const
{
int row = index.row();
if (row < 0 || row >= m_extensions.size()) {
return {};
}
switch (role) {
case Name:
return m_extensions.at(row)->name();
case Url:
return m_extensions.at(row)->url();
case Data: {
return m_extensions.at(row)->data();
}
case Options:
return m_extensions.at(row)->options();
default:
break;
}
return {};
}
QHash<int, QByteArray> ExtensionModel::roleNames() const
{
return m_roleNames;
}
void ExtensionModel::send(int index, QVariantMap data)
{
if (index < 0 || index >= m_extensions.size()) {
return;
}
m_extensions.at(index)->receive(std::move(data));
}
void ExtensionModel::extensionDataChanged(int index)
{
if (index < 0 || index >= m_extensions.size()) {
return;
}
QVector<int> roles(1, Data);
QModelIndex modelIndex = createIndex(index, 0);
Q_EMIT dataChanged(modelIndex, modelIndex, roles);
}
} // UkuiMenu

View File

@ -1,82 +0,0 @@
/*
* Copyright (C) 2022, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_MENU_EXTENSION_H
#define UKUI_MENU_MENU_EXTENSION_H
#include <QObject>
#include <QHash>
#include <QString>
#include <QVector>
#include <QVariant>
#include <QAbstractListModel>
#include "menu-extension-iface.h"
namespace UkuiMenu {
class ExtensionModel;
class MenuExtension : public QObject
{
Q_OBJECT
public:
static MenuExtension *instance();
void registerExtension(MenuExtensionIFace *extension);
Q_INVOKABLE ExtensionModel *extensionModel();
private:
MenuExtension();
void loadExtensions();
void initModel();
private:
ExtensionModel *m_model{nullptr};
QMap<QString, MenuExtensionIFace*> m_extensions;
};
class ExtensionModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Name {
Name,
Url,
Data,
Options
};
explicit ExtensionModel(const QVector<MenuExtensionIFace*> &extensions, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void send(int index, QVariantMap data);
private:
void extensionDataChanged(int index);
private:
QHash<int, QByteArray> m_roleNames;
QVector<MenuExtensionIFace*> m_extensions;
};
} // UkuiMenu
#endif //UKUI_MENU_MENU_EXTENSION_H

View File

@ -0,0 +1,184 @@
/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#include "app-menu-plugin.h"
#include "app-data-manager.h"
#include "settings.h"
#include "app-manager.h"
#include "../context-menu-extension.h"
#include <QStringLiteral>
#include <QDBusInterface>
#include <QDBusReply>
#include <QStandardPaths>
#include <QFileInfo>
#include <QProcess>
namespace UkuiMenu {
class AppContentMenu : public ContextMenuExtension
{
public:
int index() const override;
QList<QAction *> actions(const DataEntity &data, QMenu *parent, const MenuInfo::Location &location,
const QString &locationId) override;
private:
static void addToTop(QObject *parent, const QString &appId, const int &appTop, QList<QAction *> &list);
static void addToPanelAction(QObject *parent, const QString &appId, QList<QAction *> &list);
static void addToDesktopAction(QObject *parent, const QString &appId, QList<QAction *> &list);
static void addUninstall(QObject *parent, const QString &appId, QList<QAction *> &list);
};
int AppContentMenu::index() const
{
return ContextMenuExtension::index();
}
QList<QAction *> AppContentMenu::actions(const DataEntity &data, QMenu *parent, const MenuInfo::Location &location,
const QString &locationId)
{
if (!parent || (data.type() != DataType::Normal)) {
return {};
}
QList<QAction *> list;
QString appId = data.id();
int appTop = data.top();
switch (location) {
case MenuInfo::AppList: {
//置顶
if (locationId == "all") {
addToTop(parent, appId, appTop, list);
}
}
case MenuInfo::Extension:
case MenuInfo::FolderPage:
case MenuInfo::FullScreen:
case MenuInfo::FullScreenFolder:
// 卸载
addToPanelAction(parent, appId, list);
// 添加到任务栏
addUninstall(parent, appId, list);
//添加到桌面快捷方式
addToDesktopAction(parent, appId, list);
break;
default:
break;
}
return list;
}
void AppContentMenu::addToTop(QObject *parent, const QString &appId, const int &appTop, QList<QAction *> &list)
{
QString actionName = (appTop == 0) ? QObject::tr("Fixed to all applications") : QObject::tr("Unfixed from all applications");
list << new QAction(actionName, parent);
QObject::connect(list.last(), &QAction::triggered, parent, [appId, appTop] {
AppDataManager::instance()->fixToTop(appId, appTop);
});
}
void AppContentMenu::addToPanelAction(QObject *parent, const QString &appId, QList<QAction *> &list)
{
QDBusInterface iface("com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus());
if (!iface.isValid()) {
qWarning() << "Panel desktop dbusinterface error";
return;
}
iface.setTimeout(1);
QDBusReply<bool> isFixedOnTaskBar = iface.call("CheckIfExist", appId);
if (!isFixedOnTaskBar.isValid()) {
qWarning() << "Panel desktop dbusinterface call CheckIfExist timeout";
return;
}
QString actionName = isFixedOnTaskBar ? QObject::tr("Remove from taskbar") : QObject::tr("Add to taskbar");
QString functionName = isFixedOnTaskBar ? "RemoveFromTaskbar" : "AddToTaskbar";
list << new QAction(actionName, parent);
QObject::connect(list.last(), &QAction::triggered, parent, [appId, functionName] {
QDBusInterface iface("com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus());
if (!iface.isValid()) {
qWarning() << "Panel desktop dbusinterface error";
return;
}
iface.setTimeout(1);
QDBusReply<bool> ret = iface.call(functionName, appId);
if (!ret.isValid() || !ret) {
qWarning() << "Add/Remove from taskbar error";
}
});
}
void AppContentMenu::addToDesktopAction(QObject *parent, const QString &appId, QList<QAction *> &list)
{
list << new QAction(QObject::tr("Add to desktop shortcuts"), parent);
QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString path = QString(desktopPath + "/" + QFileInfo(appId).fileName());
if (QFile::exists(path)) {
list.last()->setEnabled(false);
return;
}
QObject::connect(list.last(), &QAction::triggered, parent, [appId, path] {
QFile file(appId);
bool ret = file.copy(path);
if (ret) {
QProcess::startDetached("chmod a+x ", {path});
}
});
}
void AppContentMenu::addUninstall(QObject *parent, const QString &appId, QList<QAction *> &list)
{
bool isSystemApp = GlobalSetting::instance()->isSystemApp(appId);
if (!isSystemApp) {
list << new QAction(QObject::tr("Uninstall"), parent); //QIcon::fromTheme("edit-delete-symbolic")
QObject::connect(list.last(), &QAction::triggered, parent, [appId] {
AppManager::instance()->launchBinaryApp("kylin-uninstaller", appId);
});
}
}
// ====== AppMenuPlugin ====== //
QString AppMenuPlugin::id()
{
return QStringLiteral("app-menu");
}
WidgetExtension *AppMenuPlugin::createWidgetExtension()
{
return nullptr;
}
ContextMenuExtension *AppMenuPlugin::createContextMenuExtension()
{
return new AppContentMenu;
}
} // UkuiMenu

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_APP_MENU_PLUGIN_H
#define UKUI_MENU_APP_MENU_PLUGIN_H
#include "../menu-extension-plugin.h"
namespace UkuiMenu {
class AppMenuPlugin : public MenuExtensionPlugin
{
Q_OBJECT
public:
QString id() override;
WidgetExtension *createWidgetExtension() override;
ContextMenuExtension *createContextMenuExtension() override;
};
} // UkuiMenu
#endif //UKUI_MENU_APP_MENU_PLUGIN_H

View File

@ -1,325 +0,0 @@
/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#include "menu-manager.h"
#include "app-manager.h"
#include "app-data-manager.h"
#include "settings.h"
#include <QMenu>
#include <QCursor>
#include <QDBusInterface>
#include <QDBusReply>
#include <QSettings>
#include <QFile>
#include <QDebug>
#include <QStandardPaths>
#include <QFileInfo>
#include <QProcess>
#include <QDir>
#include <QPluginLoader>
#include <QJsonObject>
#include <QPointer>
#include <QWindow>
using namespace UkuiMenu;
class AppMenuProvider : public MenuProvider
{
public:
AppMenuProvider();
int index() override { return 1024; }
bool isSupport(const RequestType &type) override;
QList<QAction *> generateActions(QObject *parent, const QVariant &data, const MenuInfo::Location &location, const QString &locationId) override;
private:
void addToTop(QObject *parent, const QString &appId, const int &appTop, QList<QAction *> &list);
void addToPanelAction(QObject *parent, const QString &appId, QList<QAction *> &list);
void addToDesktopAction(QObject *parent, const QString &appId, QList<QAction *> &list);
void addUninstall(QObject *parent, const QString &appId, QList<QAction *> &list);
};
AppMenuProvider::AppMenuProvider()
{
}
bool AppMenuProvider::isSupport(const MenuProvider::RequestType &type)
{
return type == DataType;
}
QList<QAction *>
AppMenuProvider::generateActions(QObject *parent, const QVariant &data, const MenuInfo::Location &location,
const QString &locationId)
{
if (!parent) {
return {};
}
DataEntity app = data.value<DataEntity>();
if (app.type() != DataType::Normal) {
return {};
}
QList<QAction *> list;
QString appId = app.id();
int appTop = app.top();
switch (location) {
case MenuInfo::AppList: {
//置顶
if (locationId == "all") {
addToTop(parent, appId, appTop, list);
}
}
case MenuInfo::Extension:
case MenuInfo::FolderPage:
case MenuInfo::FullScreen:
case MenuInfo::FullScreenFolder:
// 卸载
addToPanelAction(parent, appId, list);
// 添加到任务栏
addUninstall(parent, appId, list);
//添加到桌面快捷方式
addToDesktopAction(parent, appId, list);
break;
default:
break;
}
return list;
}
void AppMenuProvider::addToTop(QObject *parent, const QString &appId, const int &appTop, QList<QAction *> &list)
{
QString actionName = (appTop == 0) ? QObject::tr("Fixed to all applications") : QObject::tr("Unfixed from all applications");
list << new QAction(actionName, parent);
QObject::connect(list.last(), &QAction::triggered, parent, [appId, appTop] {
AppDataManager::instance()->fixToTop(appId, appTop);
});
}
void AppMenuProvider::addToPanelAction(QObject *parent, const QString &appId, QList<QAction *> &list)
{
QDBusInterface iface("com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus());
if (!iface.isValid()) {
qWarning() << "Panel desktop dbusinterface error";
return;
}
iface.setTimeout(1);
QDBusReply<bool> isFixedOnTaskBar = iface.call("CheckIfExist", appId);
if (!isFixedOnTaskBar.isValid()) {
qWarning() << "Panel desktop dbusinterface call CheckIfExist timeout";
return;
}
QString actionName = isFixedOnTaskBar ? QObject::tr("Remove from taskbar") : QObject::tr("Add to taskbar");
QString functionName = isFixedOnTaskBar ? "RemoveFromTaskbar" : "AddToTaskbar";
list << new QAction(actionName, parent);
QObject::connect(list.last(), &QAction::triggered, parent, [appId, functionName] {
QDBusInterface iface("com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus());
if (!iface.isValid()) {
qWarning() << "Panel desktop dbusinterface error";
return;
}
iface.setTimeout(1);
QDBusReply<bool> ret = iface.call(functionName, appId);
if (!ret.isValid() || !ret) {
qWarning() << "Add/Remove from taskbar error";
}
});
}
void AppMenuProvider::addToDesktopAction(QObject *parent, const QString &appId, QList<QAction *> &list)
{
list << new QAction(QObject::tr("Add to desktop shortcuts"), parent);
QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString path = QString(desktopPath + "/" + QFileInfo(appId).fileName());
if (QFile::exists(path)) {
list.last()->setEnabled(false);
return;
}
QObject::connect(list.last(), &QAction::triggered, parent, [appId, path] {
QFile file(appId);
bool ret = file.copy(path);
if (ret) {
QProcess::startDetached("chmod a+x " + path);
}
});
}
void AppMenuProvider::addUninstall(QObject *parent, const QString &appId, QList<QAction *> &list)
{
bool isSystemApp = GlobalSetting::instance()->isSystemApp(appId);
if (!isSystemApp) {
list << new QAction(QObject::tr("Uninstall"), parent); //QIcon::fromTheme("edit-delete-symbolic")
QObject::connect(list.last(), &QAction::triggered, parent, [appId] {
AppManager::instance()->launchBinaryApp("kylin-uninstaller", appId);
});
}
}
MenuManager *MenuManager::instance()
{
static MenuManager manager;
return &manager;
}
class MenuManagerPrivate
{
public:
QPointer<QMenu> contextMenu;
QWindow *mainWindow {nullptr};
QList<MenuProvider*> providers;
};
MenuManager::MenuManager() : d(new MenuManagerPrivate)
{
registerMenuProvider(new AppMenuProvider);
loadMenus();
}
MenuManager::~MenuManager()
{
for (auto &provider : d->providers) {
delete provider;
provider = nullptr;
}
}
void MenuManager::registerMenuProvider(MenuProvider *provider)
{
if (!provider) {
return;
}
d->providers.append(provider);
std::sort(d->providers.begin(), d->providers.end(), [=] (MenuProvider *a, MenuProvider *b) {
return a->index() < b->index();
});
}
void MenuManager::showMenu(const QString &appid, const MenuInfo::Location location, const QString &lid, const QPoint &point)
{
DataEntity app;
if (AppDataManager::instance()->getApp(appid, app)) {
showMenu(MenuProvider::DataType, QVariant::fromValue(app), location, lid, point);
}
}
void MenuManager::showMenu(const DataEntity &entity, const MenuInfo::Location location, const QString &lid,
const QPoint &point)
{
showMenu(MenuProvider::DataType, QVariant::fromValue(entity), location, lid, point);
}
void MenuManager::showMenu(const MenuProvider::RequestType &type, QVariant data, const MenuInfo::Location location, const QString &lid, const QPoint &point)
{
if (closeMenu()) {
return;
}
QMenu *menu = new QMenu;
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)
{
if (rawPoint.isNull()) {
return QCursor::pos();
}
return rawPoint;
}
void MenuManager::loadMenus()
{
QDir pluginsDir(UKUI_MENU_CONTEXT_MENU_DIR);
pluginsDir.setFilter(QDir::Files);
for(const QString& fileName : pluginsDir.entryList(QDir::Files)) {
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QJsonObject metaData = pluginLoader.metaData().value("MetaData").toObject();
QString type = metaData.value("Type").toString();
QString version = metaData.value("Version").toString();
if(type != UKUI_MENU_CONTEXTMENU_TYPE) {
continue;
}
if(version != UKUI_MENU_CONTEXTMENU_IFACE_VERSION) {
qWarning() << "UKUI_MENU_CONTEXTMENU version check failed:" << fileName << "version:" << version << "iface version : " << UKUI_MENU_CONTEXTMENU_IFACE_VERSION;
continue;
}
QObject *obj = pluginLoader.instance();
if (!obj) {
continue;
}
MenuProvider *provider = qobject_cast<MenuProvider*>(obj);
if (!provider) {
continue;
}
registerMenuProvider(provider);
}
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_MENU_PROVIDER_H
#define UKUI_MENU_MENU_PROVIDER_H
#include <QtPlugin>
#include <QAction>
#define UKUI_MENU_CONTEXTMENU_TYPE "UKUI_MENU_CONTEXTMENU"
#define UKUI_MENU_CONTEXTMENU_IFACE_IID "org.ukui.menu.contextMenu"
#define UKUI_MENU_CONTEXTMENU_IFACE_VERSION "1.0.0"
namespace UkuiMenu {
class MenuInfo
{
Q_GADGET
public:
enum Location {
AppList = 0,
Extension,
FolderPage,
FullScreen,
FullScreenFolder,
};
Q_ENUM(Location)
};
class MenuProvider
{
public:
enum RequestType {
DataType = 0,
Custom,
};
virtual ~MenuProvider() = default;
virtual int index() = 0;
virtual bool isSupport(const RequestType &type) = 0;
virtual QList<QAction*> generateActions(QObject *parent, const QVariant &data, const MenuInfo::Location &location, const QString &locationId) = 0;
};
} // UkuiMenu
Q_DECLARE_INTERFACE(UkuiMenu::MenuProvider, UKUI_MENU_CONTEXTMENU_IFACE_IID)
#endif //UKUI_MENU_MENU_PROVIDER_H

View File

@ -18,7 +18,7 @@
#include "app-model.h"
#include "app-manager.h"
#include "menu-manager.h"
#include "context-menu-manager.h"
#include "app-folder-helper.h"
#include "settings.h"
@ -212,7 +212,7 @@ void AppModel::openMenu(const int &index, MenuInfo::Location location)
return;
}
MenuManager::instance()->showMenu(m_apps.at(index), location, DataProviderManager::instance()->activatedProvider());
ContextMenuManager::instance()->showMenu(m_apps.at(index), location, DataProviderManager::instance()->activatedProvider());
}
void AppModel::renameFolder(const QString &index, const QString &folderName)

View File

@ -24,8 +24,8 @@
#include "commons.h"
#include "data-provider-manager.h"
#include "menu-provider.h"
#include "settings.h"
#include "context-menu-extension.h"
namespace UkuiMenu {

View File

@ -24,12 +24,11 @@
#include "theme-palette.h"
#include "app-icon-provider.h"
#include "menu-main-window.h"
#include "extension/menu-extension.h"
#include "app-page-header-utils.h"
#include "power-button.h"
#include "items/theme-icon.h"
#include "app-manager.h"
#include "menu-manager.h"
#include "context-menu-manager.h"
#include "data-provider-manager.h"
#include "event-track.h"
#include "sidebar-button-utils.h"
@ -97,9 +96,8 @@ void UkuiMenuApplication::initQmlEngine()
context->setContextProperty("themePalette", ThemePalette::getInstance());
context->setContextProperty("menuSetting", MenuSetting::instance());
context->setContextProperty("modelManager", ModelManager::instance());
context->setContextProperty("extensionManager", MenuExtension::instance());
context->setContextProperty("appPageHeaderUtils", new AppPageHeaderUtils(this));
context->setContextProperty("menuManager", MenuManager::instance());
context->setContextProperty("menuManager", ContextMenuManager::instance());
context->setContextProperty("appManager", AppManager::instance());
// MenuMainWindow

View File

@ -18,7 +18,7 @@
#include "menu-main-window.h"
#include "settings.h"
#include "menu-manager.h"
#include "context-menu-manager.h"
#include <QGuiApplication>
#include <QQuickItem>
@ -421,7 +421,7 @@ void MenuWindow::init()
updateGeometry();
MenuManager::instance()->setMainWindow(this);
ContextMenuManager::instance()->setMainWindow(this);
}
void MenuWindow::updateGeometry()
@ -520,7 +520,7 @@ bool MenuWindow::event(QEvent *event)
WindowHelper::removeHeaderBar(this);
}
if (event->type() == QEvent::MouseButtonPress) {
MenuManager::instance()->closeMenu();
ContextMenuManager::instance()->closeMenu();
}
return QQuickView::event(event);