feat: 修改开发库so名称,删除旧版本菜单扩展,重新实现上下文菜单扩展
This commit is contained in:
parent
3fc780d666
commit
c7fc015f27
|
@ -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}"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue