diff --git a/.gitignore b/.gitignore index 75e419f14..28981b52e 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ CMakeLists.txt.user* # binary file dde-dock .vscode + +*/dbusinterface/generation_dbus_interface/ +*/*/dbusinterface/generation_dbus_interface/ +.transifexrc diff --git a/.project b/.project index 97bc60c00..5199dabb7 100644 --- a/.project +++ b/.project @@ -2,6 +2,5 @@ "type": "homebrew" | "opensource", "3rdparty: ["*.xml"], "ignore": ["CHANGELOG.md", "./debian", "README.md", "./cmake", "technology-overview.md", "CMakeLists.txt", "CMakeLists.txt.user", "./plugins/plugin-guide", "./.tx", "*.qrc", "*.svg", "*.png", "*.qm", "*.ts"], - "license": ["LICENSE"], - "importantFile": ["gschema/com.deepin.dde.dock.module.gschema.xml", "interfaces/constants.h", "interfaces/pluginproxyinterface.h", "interfaces/pluginsiteminterface.h"] + "license": ["LICENSE"] } diff --git a/.reuse/dep5 b/.reuse/dep5 index 547538e9d..6307eb089 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -39,7 +39,7 @@ Copyright: None License: CC0-1.0 # xml toml json policy yaml -Files: gschema/*.xml plugins/*.xml frame/*.xml .clog.toml plugins/*.json configs/*.json .packit.yaml .tx/config plugins/overlay-warning/com.deepin.dde.dock.overlay.policy plugins/dcc-dock-plugin/.tx/config +Files: gschema/*.xml plugins/*.xml frame/*.xml .clog.toml plugins/*.json configs/*.json .packit.yaml .tx/config .tx/deepin.conf plugins/overlay-warning/com.deepin.dde.dock.overlay.policy plugins/dcc-dock-plugin/.tx/config Copyright: None License: CC0-1.0 @@ -56,4 +56,9 @@ License: CC0-1.0 # xml2cpp Files: frame/dbus/* plugins/disk-mount/dbus/dbusdiskmount.* plugins/power/dbus/dbuspower.* plugins/shutdown/dbus/dbuspowermanager.* plugins/tray/dbus/dbustraymanager.* Copyright: The Qt Company Ltd. -License: CC0-1.0 \ No newline at end of file +License: CC0-1.0 + +# policy kit +Files: plugins/overlay-warning/org.deepin.dde.dock.overlay.policy +Copyright: UnionTech Software Technology Co., Ltd. +License: LGPL-3.0-or-later diff --git a/.tx/config b/.tx/config index ce45604d8..3eee9a38a 100644 --- a/.tx/config +++ b/.tx/config @@ -1,10 +1,10 @@ [main] host = https://www.transifex.com -minimum_perc = 80 -mode = developer [deepin-desktop-environment.dde-dock] file_filter = translations/dde-dock_.ts +minimum_perc = 0 source_file = translations/dde-dock.ts source_lang = en type = QT + diff --git a/.tx/deepin.conf b/.tx/deepin.conf new file mode 100644 index 000000000..45cd054c3 --- /dev/null +++ b/.tx/deepin.conf @@ -0,0 +1,2 @@ +[transifex] +branch = m20 \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index bec4fa612..bc9a2d608 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,11 @@ endif() project(dde-dock) +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(CMAKE_HAVE_THREADS_LIBRARY 1) +set(CMAKE_USE_PTHREADS_INIT 1) +set(CMAKE_PREFER_PTHREAD_FLAG ON) + #set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_CXX_STANDARD 14) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -45,6 +50,25 @@ if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "sw_64") add_definitions(-DDISABLE_SHOW_ANIMATION) endif() +function(generation_dbus_interface xmldir outdir) + IF(EXISTS ${outdir}) + file(REMOVE_RECURSE ${outdir}) + ENDIF() + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${outdir}) + file(GLOB_RECURSE allXmls ${xmldir}/*.xml) + foreach(XMLFILE ${allXmls}) + string(FIND ${XMLFILE} "/" INDEX REVERSE) + string(SUBSTRING ${XMLFILE} ${INDEX} -1 classname) + string(REPLACE "/" "" classname ${classname}) + string(REPLACE ".xml" "" classname ${classname}) + string(REPLACE "." "_" classname ${classname}) + string(TOLOWER ${classname} filename) + + execute_process(COMMAND qdbusxml2cpp-fix -c ${classname} -p ${outdir}/${filename} ${XMLFILE} + WORKING_DIRECTORY ${outdir}) + endforeach() +endfunction(generation_dbus_interface) + file(GLOB INTERFACES "interfaces/*.h") #因为单元测试需要直接测试源代码,而主程序代码中include的单元使用了相对路径 @@ -59,9 +83,12 @@ include_directories( frame/item frame/item/components frame/item/resources + frame/model frame/util frame/window frame/window/components + frame/window/tray + frame/window/tray/widgets frame/xcb ../widgets ../interfaces @@ -72,11 +99,14 @@ aux_source_directory(frame/dbus DBUS) aux_source_directory(frame/dbus/sni SNI) aux_source_directory(frame/display DISPLAY) aux_source_directory(frame/item ITEM) +aux_source_directory(frame/model MODEL) aux_source_directory(frame/item/components ITEMCOMPONENTS) aux_source_directory(frame/item/resources RESOURCES) aux_source_directory(frame/util UTIL) aux_source_directory(frame/window WINDOW) aux_source_directory(frame/window/components WINDOWCOMPONENTS) +aux_source_directory(frame/window/tray WINDOWTRAY) +aux_source_directory(frame/window/tray/widgets WINDOWTRAYWIDGET) aux_source_directory(frame/xcb XCB) file(GLOB SRC_PATH @@ -86,16 +116,19 @@ file(GLOB SRC_PATH ${SNI} ${DISPLAY} ${ITEM} + ${MODEL} ${ITEMCOMPONENTS} ${UTIL} ${WINDOW} ${WINDOWCOMPONENTS} + ${WINDOWTRAY} + ${WINDOWTRAYWIDGET} ${XCB} ) add_subdirectory("frame") add_subdirectory("plugins") -add_subdirectory("tests") +#add_subdirectory("tests") # Install settings if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) @@ -125,6 +158,10 @@ install(FILES "cmake/DdeDock/DdeDockConfig.cmake" install(FILES gschema/com.deepin.dde.dock.module.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas) +#dconfig +file(GLOB DCONFIG_FILES "configs/*.json") +install(FILES ${DCONFIG_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/dsg/configs/dde-dock/) + # Address Sanitizer 内存错误检测工具,打开下面的编译选项可以看到调试信息,正常运行时不需要这些信息 #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address -O2") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -O2") diff --git a/configs/com.deepin.dde.dock.dconfig.json b/configs/com.deepin.dde.dock.dconfig.json new file mode 100644 index 000000000..6b1f34a47 --- /dev/null +++ b/configs/com.deepin.dde.dock.dconfig.json @@ -0,0 +1,40 @@ +{ + "magic":"dsg.config.meta", + "version":"1.0", + "contents":{ + "Dock_Show_Window_name":{ + "value":0, + "serial":0, + "flags":"", + "name":"小窗口显示窗口名称", + "name[zh_CN]":"小窗口显示窗口名称", + "description[zh_CN]":"提供鼠标悬停小窗口标题显示配置,默认为悬停显示: \ + 当配置为全部显示时,鼠标悬停在任务栏图标位置时所有预览窗口显示标题信息; \ + 当配置为悬停显示时,鼠标仅在悬停在预览小窗口时在当前窗口显示标题信息; \ + 当配置为不显示时,鼠标悬停应用位置和预览小窗口位置时都不显示标题信息;", + "description":"0 Mouse over show;1 Always show; 2 Always hide", + "permissions":"readwrite", + "visibility":"public" + }, + "Dock_Quick_Plugins": { + "value": ["power", "network", "shutdown", "trash"], + "serial": 0, + "flags": [], + "name": "显示在任务栏上的快捷插件", + "name[zh_CN]": "*****", + "description": "记录哪些插件的图标在任务栏启动的时候显示在任务栏上", + "permissions": "readwrite", + "visibility": "private" + }, + "Dock_Quick_Tray_Name": { + "value": ["fcitx", "indicator:keybord_layout"], + "serial": 0, + "flags": [], + "name": "显示在任务栏上的托盘图标", + "name[zh_CN]": "任务栏上固定的托盘图标", + "description": "记录哪些托盘的图标在任务栏启动的时候显示在任务栏上", + "permissions": "readwrite", + "visibility": "private" + } + } +} diff --git a/configs/org.deepin.dde.dock.json b/configs/org.deepin.dde.dock.json deleted file mode 100644 index c6e511246..000000000 --- a/configs/org.deepin.dde.dock.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "magic":"dsg.config.meta", - "version":"1.0", - "contents":{ - "showWindowName":{ - "value":0, - "serial":0, - "flags":[], - "name":"小窗口显示窗口名称", - "name[zh_CN]":"小窗口显示窗口名称", - "description[zh_CN]":"提供鼠标悬停小窗口标题显示配置,默认为悬停显示: \ - 当配置为全部显示时,鼠标悬停在任务栏图标位置时所有预览窗口显示标题信息; \ - 当配置为悬停显示时,鼠标仅在悬停在预览小窗口时在当前窗口显示标题信息; \ - 当配置为不显示时,鼠标悬停应用位置和预览小窗口位置时都不显示标题信息;", - "description":"0 Mouse over show;1 Always show; 2 Always hide", - "permissions":"readwrite", - "visibility":"private" - }, - "alwaysHideDock":{ - "value": false, - "serial": 0, - "flags":[], - "name":"alwaysHideDock", - "name[zh_CN]":"一直隐藏", - "description[zh_CN]":"当设置为true时,即使鼠标放在任务栏区域也不会显示任务栏;配置即时生效", - "description":"ture: Dock is hidden all the time, false: Depend on other settings of dock", - "permissions":"readwrite", - "visibility":"private" - }, - "toggleDesktopInterval":{ - "value": 0, - "serial": 0, - "flags":[], - "name":"toggleDesktopInterval", - "name[zh_CN]":"显示(或恢复)桌面的悬浮时间间隔", - "description[zh_CN]":"显示(或恢复)桌面将在悬停间隔后切换(以毫秒为单位)", - "description":"show(or restore) desktop will toggle after the hover interval (in milliseconds)", - "permissions":"readwrite", - "visibility":"private" - }, - "delayIntervalOnHide":{ - "value": 0, - "serial": 0, - "flags":[], - "name":"delayIntervalOnHide", - "name[zh_CN]":"任务栏隐藏状态时,从当前屏幕显示时的延时显示时间", - "description[zh_CN]":"任务栏智能隐藏或一直隐藏时,鼠标移动到当前所在屏幕边缘过一段时间再唤起任务栏(以毫秒为单位)", - "description":"When the dock is hidden, move the mouse to the edge of the current screen and then recall the dock (in milliseconds)", - "permissions":"readwrite", - "visibility":"private" - } - } -} diff --git a/configs/org.deepin.dde.dock.plugin.power.json b/configs/org.deepin.dde.dock.plugin.power.json deleted file mode 100644 index 932e822f8..000000000 --- a/configs/org.deepin.dde.dock.plugin.power.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "magic":"dsg.config.meta", - "version":"1.0", - "contents":{ - "contextMenu":{ - "value": ["Shutdown", "Reboot", "Suspend", "Hibernate", "Lock", "Logout", "SwitchUser", "PowerSettings"], - "serial": 0, - "flags": [], - "name": "ContextMenu", - "name[zh_CN]": "电源按钮右键菜单", - "description[zh_CN]": "电源界面的右键菜单内容,如需不显示某个选项,移除即可;默认值:\"Shutdown\", \"Reboot\", \"Suspend\", \"Hibernate\", \"Lock\", \"Logout\", \"SwitchUser\", \"PowerSettings\";", - "description":"", - "permissions":"readwrite", - "visibility":"private" - } - } -} \ No newline at end of file diff --git a/debian/changelog b/debian/changelog index fd6e4b309..95717d0e4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,257 @@ -dde-dock (3.0.12) unstable; urgency=low +dde-dock (6.0.9.2) unstable; urgency=medium + + [ TagBuilder ] + * fix: 修复拖动插件到任务栏后所有插件都显示的问题(Bug: 181945)(Influence: 默认所有的快捷面板中的插件都在任务栏显示,从控制中心取消所有插件的勾选,然后从快捷面板拖动一个插件到任务栏,观察任务栏插件显示情况) + * fix: 修复切换主题快捷面板插件主题颜色没有变化(Bug: 184085)(Influence: 打开快捷面板,切换主题,观察图标颜色显示是否正常) + + -- lvpeilong Thu, 02 Feb 2023 13:30:36 +0800 + +dde-dock (6.0.9.1) unstable; urgency=medium + + [ TagBuilder ] + * chore: 更新changelog(Task: 227573)(Influence: 版本号) + * fix: 修复移除蓝牙设备后任务栏插件不消失的问题(Bug: 181945)(Influence: 插上蓝牙,从控制中心勾选该插件,在任务栏显示,然后移除蓝牙设备,观察任务栏的蓝牙图标是否消失) + * fix: 修复从任务栏向上拖动插件引起任务栏崩溃的问题(Bug: 181945)(Influence: 从任务栏向上拖动插件,观察任务栏是否正常) + * fix: 修复从托盘拖动图标到任务栏引起崩溃的问题(Bug: 181945)(Influence: 将托盘图标拖动到任务栏) + * fix: 修改插件区域出现重复的电池图标问题(Bug: 184085)(Influence: 任务栏-电池图标状态刷新) + * fix: 修复高缩放率下图标显示异常的问题(Bug: 183543, 184089)(Influence: 高分屏,高缩放率,观察任务栏插件区域的图标) + * fix: 修复系统主题变化后快捷面板电池颜色显示错误的问题(Bug: 184085)(Influence: 打开快捷面板,在控制中心更改系统颜色,观察快捷面板中系统电池图标是否跟随系统颜色变化) + * fix: 更新翻译文案(Task: 226203)(Influence: 从笔记本上观察控制中心个性化中电池的文案) + + -- lvpeilong Wed, 01 Feb 2023 15:26:25 +0800 + +dde-dock (6.0.8.1) unstable; urgency=medium + + [ TagBuilder ] + * style: 解决编译不通过的问题(Task: 96831)(Influence: gerrit打包) + * fix: 修复键盘布局插件不响应键盘布局变化的问题(Task: 225011)(Influence: 社区版,从控制中心不断新增和删除键盘布局,观察布局插件是否显示隐藏) + * feat: 加载插件流程移动到插件里单独加载(Task: 222353)(Influence: 加载插件) + * feat: 加载基本插件(Task: 222353)(Influence: 插件加载) + * fix: 点击插件弹出自己的列表(Task: 222353)(Influence: 点击插件,观察是否弹出插件自己对应的列表,如果没有弹出列表,则触发这个插件的功能) + * chore: 删除多余的文件(Task: 222353)(Influence: 无) + * fix: 调整插件的尺寸(Task: 222353)(Influence: 观察任务栏插件是否对齐) + * fix: 修复移除蓝牙后弹框依然显示的问题(Bug: 181945)(Influence: 点击任务栏的蓝牙图标,弹出蓝牙弹窗,然后移除蓝牙,观察蓝牙的弹窗是否存在) + * fix: 优化插件图标样式(Task: 181945)(Influence: 图标样式) + * feat: 高效模式下最右侧增加显示桌面区域(Bug: 180859)(Influence: 进入高效模式,鼠标进入最右侧,点击,观察是否可以正常显示桌面) + * fix: 修复高缩放率下固定区域图标和回收站图标显示异常的问题(Bug: 182673)(Influence: 1.25倍缩放率下,选择非默认主题,观察任务栏显示桌面、多任务试图和回收站的图标大小是否正常) + * fix: 修复高缩放率下插件图标显示异常的问题(Bug: 183543)(Influence: 高分屏,设置缩放率为最高,观察任务栏插件区域的图标显示是否正常) + * fix: 修复展开托盘无法通过菜单移除U盘的问题(Bug: 182299)(Influence: 插入U盘,打开托盘区,右键菜单,点击,观察功能是否生效) + * fix: 解决任务栏时间日期文字显示异常的问题(Bug: 181387)(Influence: 时间和日期显示) + * fix: 修复图标异常问题(Bug: 181723)(Influence: 高缩放率下,观察组合图标显示是否正常) + * fix: 根据设计图调整插件位置(Bug: 181251)(Influence: 声音、亮度调整和媒体播放的显示位置) + * fix: 修复任务栏适应不同的主题(Bug: 179377)(Influence: 从控制中心修改主题颜色,观察任务栏快捷面板的主题颜色是否发生变化) + * fix: 修复快捷面板插件子面板无法关闭主面板的问题(Bug: 222353)(Influence: 进入快捷面板的蓝牙子界面点击设置,进入声音子界面点击设置,进入亮度调整子界面点击设置,在弹出对应的功能后,观察快捷面板是否隐藏) + * fix: 修复高效模式下无法打开企业微信的问题(Bug: 182065)(Influence: 进入高效模式,打开企业微信和微信等应用,观察是否正常打开窗口) + + -- zhaoyingzhen Fri, 13 Jan 2023 11:37:21 +0800 + +dde-dock (6.0.7) unstable; urgency=medium + + [ TagBuilder ] + * fix: 修复插件显示尺寸问题(Bug: 179083)(Influence: 截图-查看截图计时插件是否正常显示) + * fix: 任务栏协同不显示安卓设备。(Task: 233323)(Influence: 设备列表不显示安卓设备。) + * fix: 修复文案显示错误(Bug: 180959)(Influence: 任务栏最右侧的电源按钮) + * fix: 更新翻译文件(Bug: 180959)(Influence: 任务栏-电源,观察电源的文本) + + -- lvpeilong Fri, 06 Jan 2023 16:32:53 +0800 + +dde-dock (6.0.6.1) unstable; urgency=medium + + [ TagBuilder ] + * fix: 修复向上拖动图标引起任务栏崩溃的问题(Bug: 179427)(Influence: 从任务栏向上拖动快捷图标,观察任务栏是否正常) + * fix: 声音插件滚轮调节音量(Bug: 172417)(Influence: 将鼠标放在任务栏声音图标上,滚动滚轮,观察音量大小是否调节) + * fix: 增加强制在任务栏显示插件的接口(Task: 226407)(Bug: 179083)(Influence: 截图,观察任务栏是否有计时的图标) + * fix: 修复高缩放率下显示问题(Bug: 176421)(Influence: 设置高缩放率,观察开始菜单的位置,任务栏图标占满区域,左右位置,观察任务栏图标是否拥挤) + + -- zhaoyingzhen Thu, 29 Dec 2022 15:13:58 +0800 + +dde-dock (6.0.5.1) unstable; urgency=medium + + [ TagBuilder ] + * feat: 蓝牙插件适应快捷插件接口(Task: 121387)(Influence: 任务栏-快捷设置-蓝牙) + * fix: 修复高缩放率下启动器位置显示错误和无法设置智能隐藏的问题(Bug: 154513, 157413)(Influence: 前提:屏幕分辨率设置为1.25;1、任务栏设置为智能隐藏,将窗口拖动到任务栏下方,观察任务栏是否隐藏;2、观察启动器的位置是否正确) + * fix: 修复从任务栏拖动图标分屏后鼠标回到任务栏遮罩不消失的问题(Task: 181523)(Influence: 从任务栏拖动图标到桌面,不松手,然后再回到任务栏,观察遮罩是否消失) + * fix: 修复部分托盘无图标的问题(Bug: 160761)(Influence: 安全中心、授权管理等应用的托盘图标) + * fix: 修复跨端协同设备数量变化时列表页面显示不全的问题。(Influence: 跨端协同设备变化时,页面显示。) + * feat: 高效模式增加加载插件的功能(Task: 112073)(Influence: 高效模式下加载插件) + * feat: 适配v20插件加载(Task: 112073)(Influence: 加载v20插件) + * fix: 加载系统托盘插件(Task: 112073)(Influence: 插入U盘,查看托盘区域是否有U盘图标) + * fix: 托盘跟随高效模式调整任务栏位置(Task: 112073)(Influence: 高效模式下,调整任务栏位置,观察托盘区域是否正常) + * fix: 修复任务栏没有加载显示桌面和多任务视图的问题(Task: 112073)(Influence: 任务栏查看是否存在显示桌面和多任务栏视图的插件) + * feat: 图标增加toolTip和菜单(Task: 112073)(Influence: 鼠标放入到托盘区域、快捷插件区域,关机区域,观察是否存在toolTip,右键,观察是否弹出菜单) + * fix: 实现高效模式下托盘和快捷插件拖动功能(Task: 112073)(Influence: 高效模式,从托盘或快捷面板拖动图标到任务栏) + * feat: 快捷面板支持插件控制区域的显示(Task: 208579)(Influence: 快捷面板,观察声音、亮度调整和音乐播放等功能是否显示正常) + * feat: 声音插件适配v23(Task: 210309)(Influence: 观察任务栏是否存在声音插件) + * style: 消除编译警告信息(Task: 96831)(Influence: 无) + * fix: 删除编译警告(Task: 96831)(Influence: 无) + * style: 修改快捷区域key值(Task: 96831)(Influence: 无) + * fix: 修复快捷面板应用打开详细页面位置错误的问题(Task: 211641)(Influence: 从快捷面板展开蓝牙或者网络右侧的展开按钮,观察是否显示正常) + * fix: 解决任务栏跨端协同在paired状态变化后主动请求协同连接的问题。(Influence: 任务栏设备协同连接功能。) + * style: 枚举变量的信号传递去掉引用(Task: 96831)(Influence: 无) + * fix: 修复快捷面板没有刷新最新状态图的问题(Task: 208069)(Influence: 笔记本上打开快捷面板,拔掉电源或插上电源,观察电池状态是否发生变化) + * fix: 修改任务栏加载老版本插件的方式(Task: 112073)(Influence: 任务栏启动的时候,观察老版本的插件(例如U盘插件等其他v20插件)是否正常加载) + * fix: 优化快捷面板显示插件区域的方式(Task: 189527)(Influence: 打开快捷面板,观察插件是否正常显示) + * feat: 完善onboard插件的接口(Task: 212611)(Influence: 快捷面板观察onboard插件是否正常显示) + * fix: 修复时尚模型下图标铺满任务栏的显示问题(Task: 150049)(Influence: 时尚模式下,不断向任务栏添加图标,知道铺满,观察任务栏是否在屏幕可见区域内) + * fix: 适配最新版本的dtk(Task: 213083)(Influence: 无) + * fix: 修复声音设置错误(Task: 210309)(Influence: 打开快捷设置面板,通过滑动条来调整声音,观察声音是否在设置的范围内,同时观察主面板和子面板两边的声音滑动条是否同步) + * fix: 修复鼠标放到任务栏上拖动区域尺寸错误的问题(Task: 213103)(Influence: 任务栏在下方的时候,鼠标放入任务栏上方的位置,观察鼠标形状是否正常) + * fix: 修复关机图标与插件区域间距过大的问题(Task: 112073)(Influence: 高效模式下,观察关机图标与左右侧插件和时间的距离) + * fix: 修复高效模式下关机按钮显示文本的问题(Task: 112073)(Influence: 高效模式下,调整任务栏到最高,观察关机按钮的显示) + * fix: 修复托盘图标显示异常的问题(Task: 213361)(Influence: 观察输入法是否正常显示,将托盘图标从托盘拖动到任务栏,观察该图标是否在展开托盘图标和输入法中间) + * fix: 修复部分命令无法执行的问题(Task: 213403)(Influence: 任务栏关机命令观察是否正常执行) + * fix: 修复wayland下部分托盘的tooltips显示异常(Bug: 157821)(Influence: 进入wayland,打开音乐,鼠标放入到音乐图标上,观察是否正常显示提示消息) + * fix: 修复已打开应用缩略图显示位置偏差(Bug: 165775)(Influence: 鼠标放入到已经打开的应用的上方,观察预览图的位置显示是否正常) + * fix: 修复右键插件区域再单击弹出菜单的问题(Bug: 171559)(Influence: 右键插件区域,再左键,观察插件区域菜单是否正常显示) + * fix: 修复插件右键菜单不响应的问题(Bug: 164381)(Influence: 右键菜单区域,点击某个菜单项,观察是否正常响应) + * fix: 修复任务栏点击时间设置崩溃的问题(Bug: 171511)(Influence: 任务栏右键时间区域,打开时间设置,观察是否正常打开控制中心的时间设置) + * fix: 修复拖动无打开窗口触发分屏后自动打开应用的问题(Bug: 154349)(Influence: 从任务栏拖动一个没有打开窗口的应用,观察是否打开应用(正常情况下不会打开应用),释放鼠标,观察应用图标是否回到任务栏上) + * fix: 修复wayland下打开快捷面板tooltip没有隐藏的问题(Bug: 171551)(Influence: 进入wayland,鼠标放在任务栏的插件上,点击应用弹出快捷面板,观察toolTip是否消失) + * fix: 修复点击快捷面板之外的区域快捷面板不关闭的问题(Bug: 171545, 171583)(Influence: 进入wayland,打开快捷面板,点击快捷面板之外的其他区域,观察快捷面板是否关闭) + * fix: 去掉部分插件的右键菜单(Bug: 171753)(Influence: 右键蓝牙、声音等插件,观察是否有右键菜单) + * fix: 修复任务栏中拖拽图标到桌面区域图标消失的问题(Bug: 171539)(Influence: 将托盘图标从任务栏快速向上拖动,观察任务栏托盘的图标是否还存在) + * style: 修改函数接口调用(Task: 96831)(Influence: 无) + * fix: 同步启动器的修改(Bug: 147753)(Influence: 从启动器应用列表-拖拽到任务栏-回收站-卸载应用功能正常) + * fix: 修复从托盘拖动应用到任务栏上面图标显示异常的问题(Bug: 171493)(Influence: 将安全中心等图标从托盘拖动到任务栏,观察图标是否重复) + * feat: 增加返回给控制中心设置插件和托盘应用的接口(Task: 216841)(Influence: 无) + * fix: 修复移除插件后快捷面板显示异常的问题(Bug: 171579)(Influence: 不断插入或者移除蓝牙设备,观察快捷面板是否显示正常) + * fix: 修复关闭窗口特效下启动器按钮被遮挡的问题(Task: 216977)(Influence: 关闭窗口特效的时候,观察启动器按钮是否正常显示) + * fix: 修复快捷面板弹出位置不准确的问题(Bug: 172213)(Influence: 从任务栏不同的插件图标点击,观察弹出快捷面板的位置) + * fix: 电池插件不显示在快捷面板(Bug: 171713)(Influence: 从笔记本上,打开快捷面板,观察是否存在电池图标) + * fix: 修复高缩放率下无法点击快捷面板的问题(Task: 218215)(Influence: 在1.25倍缩放率下,展开快捷面板,点击网络插件展开按钮,观察是否可以展开) + * fix: 修复蓝牙列表中设备顺序与控制中心不一致的问题(Bug: 171513)(Influence: 打开快捷面板中的蓝牙列表,在多个设备同时存在的情况下,观察设备顺序是否和控制中心一致) + * chore: 设置日志格式(Task: 124695)(Influence: 无) + * fix: 修复音量插件调节最小刻度不是%2的问题(Bug: 172417)(Influence: 音量插件调节) + * fix: 修复亮度插件无法调整到100的问题(Bug: 171869)(Influence: 任务栏-亮度插件调节) + * fix: 修复插件展开列表名称显示错误的问题(Task: 218733)(Influence: 从快捷面板打开网络列表,观察标题是否为网络) + * fix: 修复快捷面板中音量调节不响应音量增强设置的问题(Bug: 171869)(Influence: 任务栏-音量插件-音量增强时的交互) + * fix: 解決协同连接设备时关闭协同服务总开关导致任务栏崩溃的问题。(Bug: 171741)(Influence: 协同连接设备.) + * fix: 从任务栏移除托盘图标后放入托盘区(Bug: 171497, 171539)(Influence: 将图标从任务栏移出,松手后图标自动移到托盘区) + * fix: 增加对控制中心设置不同主题下图标的接口(Bug: 172365)(Influence: 在控制中心切换主题,观察图标是否发生变化) + * fix: 去掉电池的右键菜单(Bug: 171753)(Influence: 右键电池插件,观察是否存在菜单) + * fix: 修复移除蓝牙设备后快捷面板依然显示的问题(Bug: 171533)(Influence: 从电脑上移除蓝牙设备,观察快捷区域和快捷面板是否还有蓝牙图标) + * fix: 修复从控制中心第一次连接需要密码的网络没有弹出网络面板的问题(Bug: 150395)(Influence: 从控制中心第一次连接需要密码的网络,观察任务栏是否显示网络列表) + * fix: 适配v20插件在任务栏的显示(Task: 112073)(Influence: 任务栏显示v20插件) + * fix: 修复插入新的蓝牙设备后其他蓝牙设备自动关闭的问题(Bug: 171477)(Influence: 系统中已经存在一个蓝牙设备,且是打开状态,打开快捷面板,进入蓝牙详情页面,插入新的蓝牙设备,观察之前的蓝牙设备是否自动关闭) + * fix: 修复快捷面板展开后点击任务栏应用无法打开的问题(Bug: 166029)(Influence: 打开快捷面板,再打开任务栏应用,观察是否在关闭快捷面板的同时打开了任务栏的应用) + * fix: 修复任务栏插件音量设备显示错误的问题(Bug: 165853)(Influence: 从任务栏打开音量,进入音量的详情页面,观察是否和控制中心一致) + * fix: 修复快捷面板蓝牙状态显示错误的问题(Bug: 171419)(Influence: 点击蓝牙图标,观察快捷面板蓝牙的打开或者关闭的状态) + * fix: 完善音量功能(Bug: 172429)(Influence: 从控制中心关闭设备,观察任务栏设备状态是否发生变化) + * feat: 插件增加标记(Task: 220099)(Influence: 任务栏插件) + * fix: 插件根据标记来决定插件的类型(Task: 220099)(Influence: 任务栏插件类型) + * feat: 增加display插件(Task: 220489)(Influence: 展开任务栏快捷面板,观察是否有亮度设置相关的功能) + * fix: 移除代码中对显示相关的插件的引用(Task: 220489)(Influence: 无) + * fix: 修复wayland下无法拖动任务栏的问题(Task: 220523)(Influence: 进入wayland,鼠标移动到任务栏边缘,观察鼠标形状是否改变,能否正常调整任务栏尺寸) + * fix: 修复快捷面板没有自动刷新图标的问题(Task: 220599)(Influence: 执行快捷面板中的截图图标,观察图标是否发生变化) + * fix: 新增或移除显示屏插件自动添加或删除(Task: 220489)(Influence: 拔出显示屏后再插入显示屏,观察任务栏快捷面板中的亮度设置插件是否发生变化) + * fix: 修复音量增强未响应的问题(Bug: 171869)(Influence: 任务栏-音量-音量增强) + * feat: 将音乐播放功能提取为单独的插件(Task: 220489)(Influence: 无) + * fix: dock代码中移除音乐插件(Task: 220489)(Influence: 打开音乐播放器,任务栏快捷面板中显示音乐播放面板) + * fix: 修复控制中心显示多条重复控件的问题(Bug: 171581)(Influence: 控制中心-个性化,观察蓝牙或者任务栏等插件是否只显示一次) + * feat: 增加回收站和电源插件在控制中心的显示和隐藏(Task: 216841)(Influence: 从控制中心勾选或者取消勾选回收站和电源插件,观察任务栏的变化) + * fix: 修复wayland下智能隐藏偶尔失效的问题(Bug: 154513)(Influence: 进入wayland,任务栏设置为智能隐藏,从任务栏打开一个窗口,观察智能隐藏是否有效果) + * fix: 修复wayland下高效模式设置任务栏struct失效的问题(Bug: 150637)(Influence: 进入wayland-任务栏设置为一直隐藏或智能隐藏,窗体最大化,让任务栏显示隐藏,观察任务栏窗体是否发生变化) + * docs: 更新插件开发文档(Task: 221667)(Influence: 无) + * feat: 任务栏适配不同主题的插件图标(Task: 222025)(Influence: 切换不同的主题,观察图标是否发生变化) + * fix: 插件适配不同主题图标(Task: 222025)(Influence: 切换主题,观察任务栏的图标和控制中心个性化中的图标是否发生了变化) + * fix: 去掉插件中读取禁用当前插件的配置(Bug: 175085)(Influence: 插入蓝牙观察是否有蓝牙图标) + * fix: 修复从任务栏拖出托盘应用后托盘不弹出的问题(Bug: 171497)(Influence: 从任务栏拖动微信或企业微信,观察托盘是否弹出) + * fix: 修改插件接口(Task: 222025)(Influence: 无) + * fix: 修复音量调节控件幅度不正确的问题(Bug: 172417)(Influence: 音量控件调节幅度) + * feat: 声音插件滚轮调节音量(Bug: 172417)(Influence: 将鼠标放在任务栏声音图标上,滚动滚轮,观察音量大小是否调节) + * fix: 修复U盘插件不显示的问题(Task: 223159)(Influence: 系统中使用v20的U盘插件,插入U盘,查看U盘图标是否显示) + * fix: 修复调整任务栏位置后显示错误的问题(Task: 218981)(Influence: 时尚模式下,将任务栏从下方调整在左侧,观察托盘面板显示是否正常) + * fix: 修复控制中心调整任务栏尺寸缓慢显示的问题(Bug: 171799)(Influence: 从控制中心个性化调整任务栏尺寸,观察任务栏的尺寸是否正常调整) + * chore: V23接口改造适配(Task: 207483)(Influence: 无) + * fix: 点击任务栏时间显示窗口呼出小组件面板(Task: 165407)(Influence: 点击任务栏时间窗口小组件是否显示。) + * fix: 声音调整改成新接口(Bug: 172417)(Influence: 鼠标移动到任务栏的声音图标,滚动鼠标,声音跟着调整) + * fix: 修复无法通过蓝牙主面板开启关闭蓝牙的问题(Bug: 171419)(Influence: 打开快捷面板,点击蓝牙图标,观察蓝牙是否正常开启和关闭) + * fix: 修复黑色背景下蓝牙列表名称颜色显示错误(Bug: 167961)(Influence: 改变主题,观察蓝牙列表设备名称的颜色是否改变) + * fix: 修复反复开关蓝牙导致的崩溃问题(Task: 226123)(Influence: 蓝牙开关功能) + * fix: 修复控制中心调节透明度对任务栏无作用的问题(Task: 226127)(Influence: 任务栏透明度调节) + * fix: 适配协同后端接口变化修改。(Bug: 176323)(Influence: 协同设备列表显示) + + -- zhaoyingzhen Tue, 13 Dec 2022 21:15:48 +0800 + +dde-dock (6.0.4) unstable; urgency=medium + + [ Deepin Packages Builder ] + * fix: 修复托盘图标提示信息显示异常的问题(Bug: 150521)(Influence: 托盘提示信息显示) + * fix: 时尚模式时间日期tips有wayland默认tittle(Bug: 149173)(Influence: 任务栏时尚模式下时间日期tips是否显示正常) + * fix: 修复多任务视图界面点击任意处均导致任务栏显示右键菜单的问题(Bug: 150507)(Influence: 任务栏右键菜单显示的时机) + * feat: 拖动任务栏图标实现分屏效果(Task: 163465)(Influence: 从任务栏拖动图标到屏幕上方,查看是否有分屏功能) + * feat: 开启AM宏(Task: 162227)(Influence: 无) + * fix: 修复从任务栏无法打开控制中心问题(Bug: 149189)(Influence: 任务栏-任务栏设置-打开控制中心 任务栏-蓝牙-蓝牙设置 任务栏-日期-日期时间设置 任务栏-电源-电源设置 任务栏-关机-关机设置 任务栏-声音-声音设置 观察是否正常打开控制中心) + * fix: 时尚模式下日期时间增加右键菜单(Task: 162235)(Influence: 任务栏-时尚模式,右键查看日期时间是否存在时间日期菜单) + * fix: 修复从最近使用区域移除驻留后应用图标没有驻留到应用区域最末尾(Bug: 147643)(Influence: 任务栏时尚模式下,在最近使用区域移除驻留,观察移除的驻留是否在区域的末尾) + * feat: 增加适配控制中心设置是否使用最近区域的功能(Bug: 147717)(Influence: 开关是否显示最近使用应用,时尚模式下观察最近使用应用是否显示或隐藏) + * feat: 增加窗口多开的功能(Task: 170977)(Influence: 控制中心开启多开窗口显示,观察应用打开的窗口是否在对应的位置显示) + * feat: 任务栏应用拖动到移除驻留(Bug: 147699)(Influence: 拖动任务栏应用到回收站,观察是否可以移除驻留) + * fix: 修复wayland环境下应用打开窗口无法显示预览的问题(Bug: 140919)(Influence: wayland-任务栏打开一个应用窗口,鼠标放入到窗口上,查看预览图) + * fix: 任务栏代码结构优化解耦(Bug: 137267, 140029, 134527, 146743, 150293)(Influence: 打开任务栏,观察时尚模式下圆角,左右侧区域中间是否连接在一起等) + * feat: 删除插件基类的isPrimary接口(Task: 121387)(Influence: 安装网络插件,查看网络插件是否在快捷设置面板中显示两列图标) + * fix: 修改v20的接口为v23的接口(Task: 182009)(Influence: 打开控制中心,鼠标移动唤醒任务栏等操作) + * fix: 删除任务栏对libdframeworkdbus-dev库的依赖(Task: 182009)(Influence: 打开控制中心,鼠标移动唤醒任务栏、加载插件等,观察相关功能是否正常) + * fix: 修复部分托盘服务对应进程状态异常时导致任务栏卡死问题(Bug: 121947)(Influence: 托盘服务) + * feat: 添加任务栏跨端协同操作功能。(Task: 119639)(Influence: 任务栏跨端协同功能。) + * fix: 修复任务栏在副屏上方鼠标跟随未移动到左侧的问题(Bug: 147641)(Influence: 开启鼠标跟随,任务栏默认在主屏,鼠标移动到副屏幕,任务栏跟随到副屏幕,改变任务栏位置为上,此时任务栏在副屏幕的上方,将鼠标移动到主屏幕的上方,观察任务栏是否移动到主屏幕的上方) + * feat: 删除任务栏中控制中心设置插件(Task: 130353)(Influence: 无) + * fix: 时尚模式增加阴影(Bug: 137267)(Influence: 时尚模式观察阴影) + * feat: 支持通过环境变量的形式指定插件的路径(Issue: 3402)(Influence: 影响插件加载,对旧插件保持兼容) + * fix: 修复wayland环境时尚模式下打开企业微信崩溃的问题(Task: 196629)(Influence: 进入wayland桌面,进入时尚模式,打开企业微信,双击,观察企业微信是否正常打开) + * fix: 修复高效模式下托盘入口图标没有跟随位置变化而变化(Bug: 147743)(Influence: 时尚模式下改变任务栏位置,观察托盘入口是否发生变化) + * style: 优化CMakeList.txt文件(Task: 96831)(Influence: 无) + * fix: 修复开启启动器后鼠标再次点击无法关闭启动器的问题(Task: 198183)(Influence: 从任务栏点击鼠标开启启动器,再次点击鼠标,观察启动器是否收缩) + * fix: 修复wayland下窗口预览为空的问题(Bug: 140919, 150475)(Influence: 进入wayland,鼠标放入任务栏已经打开的窗口图标上,观察预览图是否显示) + * fix: 修复任务栏在右侧智能隐藏失败(Bug: 154513)(Influence: 任务栏右侧智能隐藏,将窗口拖动到任务栏的右侧,观察任务栏是否隐藏) + * fix: 修复跨端协同设备列表数量显示不对的问题。(Bug: 203831)(Influence: 跨端协同设备数量,及设备协同连接。) + * fix: 修复时尚模式下快捷设置面板显示设置子页面显示不全,导致跨端协同设备列表显示异常问题。(Bug: 160587, 160599)(Influence: 时尚模式下显示设置子页面显示问题。) + + -- baodi Wed, 19 Oct 2022 12:57:31 +0800 + +dde-dock (6.0.3) unstable; urgency=medium + + [ TagBuilder ] + * fix: 修复debian打包使用AM宏不生效的问题(Task: 133075)(Influence: 任务栏是否使用AM服务) + * fix: 修复wayland环境下任务栏右键菜单带有标题栏的问题(Bug: 140873)(Influence: wayland下查看任务栏图表的右键菜单) + * fix: 修复任务栏在高缩放率下防呆位置错误(Influence: 高缩放率下,查看防呆区域) + * fix: 删除任务栏启动时候用ldd检测libdtk库(Task: 157235)(Influence: 任务栏启动的时候检测是否有ldd报错信息) + * feat: 暂时取消使用AM宏(Task: 162227)(Influence: 无) + * feat: 增加最近使用应用的功能(Task: 158441)(Influence: 控制中心最近使用区域开启情况下,时尚模式,打开一个没有驻留在任务栏的应用,查看新打开的应用是否在最近打开应用区域) + * feat: 增加工具区域的使用(Task: 152867)(Influence: 时尚模式下,查看最近打开区域右侧是否显示回收站,来回切换时尚模式与高效模式,查看回收站位置是否发生变化) + * feat: recompile(Influence: recompile) + * feat: 点击任务栏时间显示窗口呼出小组件面板。(Task: 165407)(Influence: 点击任务栏时间窗口小组件是否显示。) + * fix: 修复拖拽托盘窗口图标至任务栏托盘区域经常失败的问题。(Bug: 147789)(Influence: 拖拽托盘窗口图标至任务栏托盘区域。) + * chore: 优化有关slider等相关的操作代码(Influence: 快捷设置面板slider操作。) + * fix: 修复从任务栏或其他应用打开控制中心卡死的问题(Bug: 149189)(Influence: 任务栏-任务栏设置-打开控制中心,观察打开的时间) + + -- caixiangrong Mon, 25 Jul 2022 13:10:23 +0800 + +dde-dock (6.0.2) unstable; urgency=low + + * release 6.0.2 + + -- fanpengcheng Tue, 21 Jun 2022 16:55:39 +0800 + +dde-dock (6.0.1) unstable; urgency=low + + * release Tag 6.0.1 + + -- fanpengcheng Tue, 21 Jun 2022 16:24:49 +0800 + +dde-dock (6.0.0.1) unstable; urgency=low + + * release Tag 6.0.0.1 + + -- donghualin Wed, 1 Jun 2022 21:34:29 +0800 + +dde-dock (6.0.0.0) unstable; urgency=low + + * release Tag 6.0.0.0 + + -- donghualin Wed, 1 Jun 2022 10:11:29 +0800 + +dde-dock (3.0.12-1) unstable; urgency=low * Autobuild Tag 3.0.12 @@ -134,4 +387,4 @@ dde-dock (0.0~git20150824-1) unstable; urgency=low * Initial release - -- Deepin Packages Builder Mon, 24 Aug 2015 19:03:01 +0800 + -- Deepin Packages Builder Mon, 24 Aug 2015 19:03:01 +0000 diff --git a/debian/control b/debian/control index a2b50592b..fa1f3b86e 100644 --- a/debian/control +++ b/debian/control @@ -20,14 +20,16 @@ Build-Depends: debhelper (>= 8.0.0), libdtkcore-dev (>=5.4.14), libdtkcore5-bin (>=5.4.14), libdtkgui-dev (>=5.4.13), - libdframeworkdbus-dev (>=5.4.6), libgsettings-qt-dev, libdbusmenu-qt5-dev, libgtest-dev, libgmock-dev, qttools5-dev, - dde-control-center-dev, - libxcursor-dev + libxcursor-dev, + libqt5waylandclient5-dev, + qtwayland5-private-dev, + libxdamage-dev, + libdwayland-dev Standards-Version: 3.9.8 Homepage: http://www.deepin.org/ @@ -35,20 +37,16 @@ Package: dde-dock Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, deepin-desktop-schemas (>=5.9.14), - libdtkwidget5 (>=5.4.19), - libdtkcore5 (>=5.4.14), - libdtkgui5 (>=5.4.13), - libdframeworkdbus2 (>=5.4.6), dde-qt5xcb-plugin (>=5.0.25), dde-daemon (>=5.13.12), startdde (>=5.8.9), lastore-daemon (>=5.2.9), - qtxdg-dev-tools + qtxdg-dev-tools, + dbus-bin Recommends: dde-disk-mount-plugin, dde-dock-onboard-plugin, dock-network-plugin, - dcc-dock-plugin, dde-network-dialog Conflicts: dde-workspace (<< 2.90.5), @@ -71,9 +69,3 @@ Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, onboard Description: deepin desktop-environment - dock plugin for onboard Dock plugin for onboard of deepin desktop-environment - -Package: dcc-dock-plugin -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, onboard -Description: deepin desktop-environment - dcc plugin for dock settings - Dcc plugin for dock settings of deepin desktop-environment diff --git a/debian/copyright b/debian/copyright index e7d2b5cff..dc5e387f5 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,7 +3,7 @@ Upstream-Name: dde-dock Files: * Copyright: 2015 Deepin Technology Co., Ltd. -License: LGPL-3.0-or-later +License: GPL-3+ This package 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 diff --git a/debian/dcc-dock-plugin.install b/debian/dcc-dock-plugin.install deleted file mode 100644 index 140ba65be..000000000 --- a/debian/dcc-dock-plugin.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/dde-control-center/modules/libdcc-dock-plugin.so diff --git a/debian/dde-dock.install b/debian/dde-dock.install index 38d420a23..f10faa542 100644 --- a/debian/dde-dock.install +++ b/debian/dde-dock.install @@ -1,12 +1,12 @@ usr/share usr/bin etc/dde-dock -usr/lib/dde-dock/plugins/libdatetime.so +usr/lib/dde-dock/plugins/loader/libpluginmanager.so usr/lib/dde-dock/plugins/libshutdown.so usr/lib/dde-dock/plugins/libtrash.so -usr/lib/dde-dock/plugins/libtray.so usr/lib/dde-dock/plugins/liboverlay-warning.so -usr/lib/dde-dock/plugins/system-trays +usr/lib/dde-dock/plugins/quick-trays usr/lib/dde-dock/plugins/libmultitasking.so usr/lib/dde-dock/plugins/libshow-desktop.so -usr/lib/dde-dock/plugins/system-trays/libkeyboard-layout.so +usr/lib/dde-dock/plugins/libkeyboard-layout.so +usr/share/dsg/configs/dde-dock/ diff --git a/frame/CMakeLists.txt b/frame/CMakeLists.txt index 88c9e0c4b..87dcc7607 100644 --- a/frame/CMakeLists.txt +++ b/frame/CMakeLists.txt @@ -5,12 +5,14 @@ set(BIN_NAME dde-dock) configure_file(environments.h.in environments.h @ONLY) if (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address -O2") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -O2") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address -O0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -O0") endif() +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + # Sources files -file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../widgets/*.h" "../widgets/*.cpp") +file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../widgets/*.h" "../widgets/*.cpp" "../interfaces/*.h") # Find the library find_package(PkgConfig REQUIRED) @@ -19,14 +21,19 @@ find_package(Qt5Concurrent REQUIRED) find_package(Qt5X11Extras REQUIRED) find_package(Qt5DBus REQUIRED) find_package(Qt5Svg REQUIRED) +find_package(Qt5WaylandClient REQUIRED) +find_package(Qt5XkbCommonSupport REQUIRED) find_package(DtkWidget REQUIRED) find_package(DtkCMake REQUIRED) +find_package(dbusmenu-qt5 REQUIRED) -pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) +pkg_check_modules(XCB_EWMH REQUIRED xcb-image xcb-ewmh xcb-composite xtst x11 dbusmenu-qt5 xext xcursor) pkg_check_modules(QGSettings REQUIRED gsettings-qt) pkg_check_modules(DtkGUI REQUIRED dtkgui) +set(Wayland_INCLUDE_DIRS /usr/include/DWayland/Client) +set(Wayland_LIBRARIES /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/libDWaylandClient.so) + # driver-manager add_executable(${BIN_NAME} ${SRCS} @@ -37,23 +44,36 @@ add_executable(${BIN_NAME} target_include_directories(${BIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} ${XCB_EWMH_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} ${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${PROJECT_BINARY_DIR} ${QGSettings_INCLUDE_DIRS} ${DtkGUI_INCLUDE_DIRS} ${Qt5Svg_INCLUDE_DIRS} + ${dbusmenu-qt5_INCLUDE_DIRS} + ${Wayland_INCLUDE_DIRS} + ${Qt5WaylandClient_INCLUDE_DIRS} + ${Qt5WaylandClient_PRIVATE_INCLUDE_DIRS} + ${Qt5XkbCommonSupport_PRIVATE_INCLUDE_DIRS} ../interfaces ../widgets + ./dbusinterface/generation_dbus_interface + ./qtdbusextended/ + ./dbusinterface accessible controller dbus display item item/components + model + pluginadapter + screenspliter util window window/components + window/tray + window/tray/widgets + drag xcb ../plugins/tray ../plugins/show-desktop @@ -67,7 +87,6 @@ target_include_directories(${BIN_NAME} PUBLIC target_link_libraries(${BIN_NAME} PRIVATE ${XCB_EWMH_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} ${DtkWidget_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Gui_LIBRARIES} @@ -77,6 +96,11 @@ target_link_libraries(${BIN_NAME} PRIVATE ${QGSettings_LIBRARIES} ${DtkGUI_LIBRARIES} ${Qt5Svg_LIBRARIES} + ${Wayland_LIBRARIES} + ${Qt5Wayland_LIBRARIES} + ${Qt5WaylandClient_LIBRARIES} + ${Qt5XkbCommonSupport_LIBRARIES} + -lpthread -lm ) if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "sw_64") @@ -92,6 +116,4 @@ if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") endif() # bin -install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) - -dconfig_meta_files(APPID org.deepin.dde.dock FILES ../configs/org.deepin.dde.dock.json) +install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/frame/accessible/accessible.h b/frame/accessible/accessible.h index a5d97460c..5fe76b301 100644 --- a/frame/accessible/accessible.h +++ b/frame/accessible/accessible.h @@ -1,165 +1,195 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later -#include -#include -#include -#include -#include -#include +#include "accessibledefine.h" -inline QString getAccessibleName(QWidget *w, QAccessible::Role r, const QString &fallback) -{ -#define SEPARATOR "_" - const QString lowerFallback = fallback.toLower(); - // 避免重复生成 - static QMap objnameMap; - if (!objnameMap[w].isEmpty()) - return objnameMap[w]; +#include "mainwindow.h" +#include "mainpanelcontrol.h" +#include "desktop_widget.h" +#include "tipswidget.h" +#include "dockpopupwindow.h" +#include "dragwidget.h" - static QMap< QAccessible::Role, QList< QString > > accessibleMap; - QString oldAccessName = w->accessibleName().toLower(); - oldAccessName.replace(SEPARATOR, ""); +#include "launcheritem.h" +#include "appitem.h" +#include "components/previewcontainer.h" +#include "pluginsitem.h" +#include "traypluginitem.h" +#include "placeholderitem.h" +#include "components/appdragwidget.h" +#include "components/appsnapshot.h" +#include "components/floatingpreview.h" - // 按照类型添加固定前缀 - QMetaEnum metaEnum = QMetaEnum::fromType(); - QByteArray prefix = metaEnum.valueToKeys(r); - switch (r) { - case QAccessible::Button: prefix = "Btn"; break; - case QAccessible::StaticText: prefix = "Label"; break; - default: break; - } +#include "snitraywidget.h" +#include "abstracttraywidget.h" +#include "indicatortraywidget.h" +#include "xembedtraywidget.h" +#include "system-trays/systemtrayitem.h" +#include "fashiontray/fashiontrayitem.h" +#include "fashiontray/fashiontraywidgetwrapper.h" +#include "fashiontray/fashiontraycontrolwidget.h" +#include "fashiontray/containers/attentioncontainer.h" +#include "fashiontray/containers/holdcontainer.h" +#include "fashiontray/containers/normalcontainer.h" +#include "fashiontray/containers/spliteranimated.h" - // 再加上标识 - QString accessibleName = QString::fromLatin1(prefix) + SEPARATOR; - QString objectName = w->objectName().toLower(); - accessibleName += oldAccessName.isEmpty() ? (objectName.isEmpty() ?lowerFallback : objectName) : oldAccessName; - // 检查名称是否唯一 - if (accessibleMap[r].contains(accessibleName)) { - if (!objnameMap.key(accessibleName)) { - objnameMap.remove(objnameMap.key(accessibleName)); - objnameMap.insert(w, accessibleName); - return accessibleName; - } - // 获取编号,然后+1 - int pos = accessibleName.indexOf(SEPARATOR); - int id = accessibleName.mid(pos + 1).toInt(); +// 这部分由sound插件单独维护,这样做是因为在标记volumeslider这个类时,需要用到其setValue的实现, +// 但插件的源文件dock这边并没有包含,不想引入复杂的包含关系,其实最好的做法就是像sound插件这样,谁维护谁的 +//#include "../plugins/sound/sounditem.h" +//#include "../plugins/sound/soundapplet.h" +//#include "../plugins/sound/sinkinputwidget.h" +//#include "../plugins/sound/componments/volumeslider.h" +//#include "../plugins/sound/componments/horizontalseparator.h" - QString newAccessibleName; - do { - // 一直找到一个不重复的名字 - newAccessibleName = accessibleName + SEPARATOR + QString::number(++id); - } while (accessibleMap[r].contains(newAccessibleName)); +#include "showdesktopwidget.h" +#include "datetimewidget.h" +#include "onboarditem.h" +#include "trashwidget.h" +#include "popupcontrolwidget.h" +#include "shutdownwidget.h" +#include "multitaskingwidget.h" +#include "overlaywarningwidget.h" +#include "horizontalseperator.h" - accessibleMap[r].append(newAccessibleName); - objnameMap.insert(w, newAccessibleName); +#include +#include +#include +#include +#include +#include +#include - // 对象销毁后移除占用名称 - QObject::connect(w, &QWidget::destroyed, [ = ] (QObject *obj) { - objnameMap.remove(obj); - accessibleMap[r].removeOne(newAccessibleName); - }); - return newAccessibleName; - } else { - accessibleMap[r].append(accessibleName); - objnameMap.insert(w, accessibleName); +#include - // 对象销毁后移除占用名称 - QObject::connect(w, &QWidget::destroyed, [ = ] (QObject *obj) { - objnameMap.remove(obj); - accessibleMap[r].removeOne(accessibleName); - }); - return accessibleName; - } -} +DWIDGET_USE_NAMESPACE +using namespace Dock; -class Accessible : public QAccessibleWidget { -public: - Accessible(QWidget *parent, QAccessible::Role r, const QString &accessibleName) - : QAccessibleWidget(parent, r) - , w(parent) - , accessibleName(accessibleName) - {} - - // 对于使用dogtail的AT自动化测试工作,实际上只需要使用我们提供的text方法获取控件唯一ID,,然后再通过QAccessibleWidget的rect方法找到其坐标,模拟点击即可 - // rect没必要重新实现,text方法通过getAccessibleName确定返回唯一值 - QString text(QAccessible::Text t) const override { - switch (t) { - case QAccessible::Name: - return getAccessibleName(w, this->role(), accessibleName); - default: - return QString(); - } - } - -private: - QWidget *w; - QString accessibleName; -}; +// 添加accessible +SET_FORM_ACCESSIBLE(MainWindow, "mainwindow") +SET_BUTTON_ACCESSIBLE(MainPanelControl, "mainpanelcontrol") +SET_LABEL_ACCESSIBLE(TipsWidget, "tips") +SET_FORM_ACCESSIBLE(DockPopupWindow, "popupwindow") +SET_BUTTON_ACCESSIBLE(LauncherItem, "launcheritem") +SET_BUTTON_ACCESSIBLE(AppItem, "appitem") +SET_BUTTON_ACCESSIBLE(PreviewContainer, "previewcontainer") +SET_BUTTON_ACCESSIBLE(PluginsItem, m_w->pluginName()) +SET_BUTTON_ACCESSIBLE(TrayPluginItem, m_w->pluginName()) +SET_BUTTON_ACCESSIBLE(PlaceholderItem, "placeholderitem") +SET_BUTTON_ACCESSIBLE(AppDragWidget, "appdragwidget") +SET_BUTTON_ACCESSIBLE(AppSnapshot, "appsnapshot") +SET_BUTTON_ACCESSIBLE(FloatingPreview, "floatingpreview") +SET_BUTTON_ACCESSIBLE(XEmbedTrayWidget, m_w->itemKeyForConfig().replace("sni:", "")) +SET_BUTTON_ACCESSIBLE(IndicatorTrayWidget, m_w->itemKeyForConfig().replace("sni:", "")) +SET_BUTTON_ACCESSIBLE(SNITrayWidget, m_w->itemKeyForConfig().replace("sni:", "")) +SET_BUTTON_ACCESSIBLE(AbstractTrayWidget, m_w->itemKeyForConfig().replace("sni:", "")) +SET_BUTTON_ACCESSIBLE(SystemTrayItem, m_w->itemKeyForConfig().replace("sni:", "")) +SET_FORM_ACCESSIBLE(FashionTrayItem, "fashiontrayitem") +SET_FORM_ACCESSIBLE(FashionTrayWidgetWrapper, "fashiontraywrapper") +SET_BUTTON_ACCESSIBLE(FashionTrayControlWidget, "fashiontraycontrolwidget") +SET_FORM_ACCESSIBLE(AttentionContainer, "attentioncontainer") +SET_FORM_ACCESSIBLE(HoldContainer, "holdcontainer") +SET_FORM_ACCESSIBLE(NormalContainer, "normalcontainer") +SET_FORM_ACCESSIBLE(SpliterAnimated, "spliteranimated") +SET_FORM_ACCESSIBLE(DatetimeWidget, "plugin-datetime") +SET_FORM_ACCESSIBLE(OnboardItem, "plugin-onboard") +SET_FORM_ACCESSIBLE(TrashWidget, "plugin-trash") +SET_BUTTON_ACCESSIBLE(PopupControlWidget, "popupcontrolwidget") +SET_FORM_ACCESSIBLE(ShutdownWidget, "plugin-shutdown") +SET_FORM_ACCESSIBLE(MultitaskingWidget, "plugin-multitasking") +SET_FORM_ACCESSIBLE(ShowDesktopWidget, "plugin-showdesktop") +SET_FORM_ACCESSIBLE(OverlayWarningWidget, "plugin-overlaywarningwidget") +SET_FORM_ACCESSIBLE(QWidget, m_w->objectName().isEmpty() ? "widget" : m_w->objectName()) +SET_LABEL_ACCESSIBLE(QLabel, m_w->objectName() == "notifications" ? m_w->objectName() : m_w->text().isEmpty() ? m_w->objectName().isEmpty() ? "text" : m_w->objectName() : m_w->text()) +SET_BUTTON_ACCESSIBLE(DIconButton, m_w->objectName().isEmpty() ? "imagebutton" : m_w->objectName()) +SET_BUTTON_ACCESSIBLE(DSwitchButton, m_w->text().isEmpty() ? "switchbutton" : m_w->text()) +SET_BUTTON_ACCESSIBLE(DesktopWidget, "desktopWidget"); +SET_FORM_ACCESSIBLE(HorizontalSeperator, "HorizontalSeperator"); +// 几个没什么用的标记,但为了提醒大家不要遗漏标记控件,还是不要去掉 +SET_FORM_ACCESSIBLE(DBlurEffectWidget, "DBlurEffectWidget") +SET_FORM_ACCESSIBLE(DListView, "DListView") +SET_FORM_ACCESSIBLE(DLoadingIndicator, "DLoadingIndicator") +SET_FORM_ACCESSIBLE(DSpinner, "DSpinner") +SET_FORM_ACCESSIBLE(QMenu, "QMenu") +SET_FORM_ACCESSIBLE(QPushButton, "QPushButton") +SET_FORM_ACCESSIBLE(QSlider, "QSlider") +SET_FORM_ACCESSIBLE(QScrollBar, "QScrollBar") +SET_FORM_ACCESSIBLE(QScrollArea, "QScrollArea") +SET_FORM_ACCESSIBLE(QFrame, "QFrame") +SET_FORM_ACCESSIBLE(QGraphicsView, "QGraphicsView") +SET_FORM_ACCESSIBLE(DragWidget, "DragWidget") QAccessibleInterface *accessibleFactory(const QString &classname, QObject *object) { - Q_UNUSED(classname); + // 自动化标记确定不需要的控件,方可加入忽略列表 + const static QStringList ignoreLst = {"WirelessItem", "WiredItem", "SsidButton", "WirelessList", "AccessPointWidget"}; - static QMap s_roleMap = { - {"MainWindow", QAccessible::Role::Form} - , {"MainPanelControl", QAccessible::Role::Button} - , {"Dock::TipsWidget", QAccessible::Role::StaticText} - , {"DockPopupWindow", QAccessible::Role::Form} - , {"LauncherItem", QAccessible::Role::Button} - , {"AppItem", QAccessible::Role::Button} - , {"PreviewContainer", QAccessible::Role::Button} - , {"PluginsItem", QAccessible::Role::Button} - , {"TrayPluginItem", QAccessible::Role::Button} - , {"PlaceholderItem", QAccessible::Role::Button} - , {"AppDragWidget", QAccessible::Role::Button} - , {"AppSnapshot", QAccessible::Role::Button} - , {"FloatingPreview", QAccessible::Role::Button} - , {"XEmbedTrayWidget", QAccessible::Role::Button} - , {"IndicatorTrayWidget", QAccessible::Role::Button} - , {"SNITrayWidget", QAccessible::Role::Button} - , {"AbstractTrayWidget", QAccessible::Role::Button} - , {"SystemTrayItem", QAccessible::Role::Button} - , {"FashionTrayItem", QAccessible::Role::Form} - , {"FashionTrayWidgetWrapper", QAccessible::Role::Form} - , {"FashionTrayControlWidget", QAccessible::Role::Button} - , {"AttentionContainer", QAccessible::Role::Form} - , {"HoldContainer", QAccessible::Role::Form} - , {"NormalContainer", QAccessible::Role::Form} - , {"SpliterAnimated", QAccessible::Role::Form} - , {"DatetimeWidget", QAccessible::Role::Form} - , {"OnboardItem", QAccessible::Role::Form} - , {"TrashWidget", QAccessible::Role::Form} - , {"PopupControlWidget", QAccessible::Role::Button} - , {"ShutdownWidget", QAccessible::Role::Form} - , {"MultitaskingWidget", QAccessible::Role::Form} - , {"ShowDesktopWidget", QAccessible::Role::Form} - , {"OverlayWarningWidget", QAccessible::Role::Form} - , {"QWidget", QAccessible::Role::Form} - , {"QLabel", QAccessible::Role::StaticText} - , {"Dtk::Widget::DIconButton", QAccessible::Role::Button} - , {"Dtk::Widget::DSwitchButton", QAccessible::Role::Button} - , {"DesktopWidget", QAccessible::Role::Button} - , {"HorizontalSeperator", QAccessible::Role::Form} - }; + QAccessibleInterface *interface = nullptr; - static QMap s_classNameMap = { - {"Dock::TipsWidget", "tips"} - , {"DatetimeWidget", "plugin-datetime"} - , {"OnboardItem", "plugin-onboard"} - , {"TrashWidget", "plugin-trash"} - , {"ShutdownWidget", "plugin-shutdown"} - , {"MultitaskingWidget", "plugin-multitasking"} - , {"ShowDesktopWidget", "plugin-showdesktop"} - , {"OverlayWarningWidget", "plugin-overlaywarningwidget"} - , {"SoundItem", "plugin-sounditem"} - }; + USE_ACCESSIBLE(classname, MainWindow) + ELSE_USE_ACCESSIBLE(classname, MainPanelControl) + ELSE_USE_ACCESSIBLE(QString(classname).replace("Dock::", ""), TipsWidget) + ELSE_USE_ACCESSIBLE(classname, DockPopupWindow) + ELSE_USE_ACCESSIBLE(classname, LauncherItem) + ELSE_USE_ACCESSIBLE(classname, AppItem) + ELSE_USE_ACCESSIBLE(classname, PreviewContainer) + ELSE_USE_ACCESSIBLE(classname, PluginsItem) + ELSE_USE_ACCESSIBLE(classname, TrayPluginItem) + ELSE_USE_ACCESSIBLE(classname, PlaceholderItem) + ELSE_USE_ACCESSIBLE(classname, AppDragWidget) + ELSE_USE_ACCESSIBLE(classname, AppSnapshot) + ELSE_USE_ACCESSIBLE(classname, FloatingPreview) + ELSE_USE_ACCESSIBLE(classname, SNITrayWidget) + ELSE_USE_ACCESSIBLE(classname, AbstractTrayWidget) + ELSE_USE_ACCESSIBLE(classname, SystemTrayItem) + ELSE_USE_ACCESSIBLE(classname, FashionTrayItem) + ELSE_USE_ACCESSIBLE(classname, FashionTrayWidgetWrapper) + ELSE_USE_ACCESSIBLE(classname, FashionTrayControlWidget) + ELSE_USE_ACCESSIBLE(classname, AttentionContainer) + ELSE_USE_ACCESSIBLE(classname, HoldContainer) + ELSE_USE_ACCESSIBLE(classname, NormalContainer) + ELSE_USE_ACCESSIBLE(classname, SpliterAnimated) + ELSE_USE_ACCESSIBLE(classname, IndicatorTrayWidget) + ELSE_USE_ACCESSIBLE(classname, XEmbedTrayWidget) + ELSE_USE_ACCESSIBLE(classname, DesktopWidget) + ELSE_USE_ACCESSIBLE(classname, DatetimeWidget) + ELSE_USE_ACCESSIBLE(classname, OnboardItem) + ELSE_USE_ACCESSIBLE(classname, TrashWidget) + ELSE_USE_ACCESSIBLE(classname, PopupControlWidget) + ELSE_USE_ACCESSIBLE(classname, ShutdownWidget) + ELSE_USE_ACCESSIBLE(classname, MultitaskingWidget) + ELSE_USE_ACCESSIBLE(classname, ShowDesktopWidget) + ELSE_USE_ACCESSIBLE(classname, OverlayWarningWidget) + ELSE_USE_ACCESSIBLE(classname, QWidget) + ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classname, QLabel, "spliter_fix") + ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classname, QLabel, "spliter_app") + ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classname, QLabel, "spliter_tray") + ELSE_USE_ACCESSIBLE(classname, QLabel) + ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(QString(classname).replace("Dtk::Widget::", ""), DIconButton, "closebutton-2d") + ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(QString(classname).replace("Dtk::Widget::", ""), DIconButton, "closebutton-3d") + ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(QString(classname).replace("Dtk::Widget::", ""), DSwitchButton, "") + ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DBlurEffectWidget) + ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DListView) + ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DLoadingIndicator) + ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DSpinner) + ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DSwitchButton) + ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DIconButton) + ELSE_USE_ACCESSIBLE(classname, QMenu) + ELSE_USE_ACCESSIBLE(classname, QPushButton) + ELSE_USE_ACCESSIBLE(classname, QSlider) + ELSE_USE_ACCESSIBLE(classname, QScrollBar) + ELSE_USE_ACCESSIBLE(classname, QScrollArea) + ELSE_USE_ACCESSIBLE(classname, QFrame) + ELSE_USE_ACCESSIBLE(classname, QGraphicsView) + ELSE_USE_ACCESSIBLE(classname, DragWidget) + ELSE_USE_ACCESSIBLE(classname, HorizontalSeperator); - if (object->isWidgetType()) - return new Accessible(qobject_cast(object) - , s_roleMap.value(classname, QAccessible::Role::Form) - , s_classNameMap.value(object->metaObject()->className(), object->metaObject()->className())); + if (!interface && object->inherits("QWidget") && !ignoreLst.contains(classname)) { + QWidget *w = static_cast(object); + // 如果你看到这里的输出,说明代码中仍有控件未兼顾到accessible功能,请帮忙添加 + if (w->accessibleName().isEmpty()) + qWarning() << "accessibleFactory()" + QString("Class: " + classname + " cannot access"); + } - return nullptr; + return interface; } diff --git a/frame/accessible/accessibledefine.h b/frame/accessible/accessibledefine.h new file mode 100644 index 000000000..b65f816ae --- /dev/null +++ b/frame/accessible/accessibledefine.h @@ -0,0 +1,405 @@ +// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +// 为了方便使用,把相关定义独立出来,如有需要,直接包含这个头文件,然后使用SET_*的宏去设置,USE_*宏开启即可 +// 注意:对项目中出现的所有的QWidget的派生类都要再启用一次accessiblity,包括qt的原生控件[qt未限制其标记名称为空的情况] +// 注意:使用USE_ACCESSIBLE_BY_OBJECTNAME开启accessiblity的时候,一定要再对这个类用一下USE_ACCESSIBLE,否则标记可能会遗漏 + +#ifndef ACCESSIBLEINTERFACE_H +#define ACCESSIBLEINTERFACE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEPARATOR "_" + +inline QString getAccessibleName(QWidget *w, QAccessible::Role r, const QString &fallback) +{ + const QString lowerFallback = fallback.toLower(); + // 避免重复生成 + static QMap< QObject *, QString > objnameMap; + if (!objnameMap[w].isEmpty()) + return objnameMap[w]; + + static QMap< QAccessible::Role, QList< QString > > accessibleMap; + QString oldAccessName = w->accessibleName().toLower(); + oldAccessName.replace(SEPARATOR, ""); + + // 按照类型添加固定前缀 + QMetaEnum metaEnum = QMetaEnum::fromType(); + QByteArray prefix = metaEnum.valueToKeys(r); + switch (r) { + case QAccessible::Button: prefix = "Btn"; break; + case QAccessible::StaticText: prefix = "Label"; break; + default: break; + } + + // 再加上标识 + QString accessibleName = QString::fromLatin1(prefix) + SEPARATOR; + QString objectName = w->objectName().toLower(); + accessibleName += oldAccessName.isEmpty() ? (objectName.isEmpty() ?lowerFallback : objectName) : oldAccessName; + // 检查名称是否唯一 + if (accessibleMap[r].contains(accessibleName)) { + if (!objnameMap.key(accessibleName)) { + objnameMap.remove(objnameMap.key(accessibleName)); + objnameMap.insert(w, accessibleName); + return accessibleName; + } + // 获取编号,然后+1 + int pos = accessibleName.indexOf(SEPARATOR); + int id = accessibleName.mid(pos + 1).toInt(); + + QString newAccessibleName; + do { + // 一直找到一个不重复的名字 + newAccessibleName = accessibleName + SEPARATOR + QString::number(++id); + } while (accessibleMap[r].contains(newAccessibleName)); + + accessibleMap[r].append(newAccessibleName); + objnameMap.insert(w, newAccessibleName); + + // 对象销毁后移除占用名称 + QObject::connect(w, &QWidget::destroyed, [ = ] (QObject *obj) { + objnameMap.remove(obj); + accessibleMap[r].removeOne(newAccessibleName); + }); + return newAccessibleName; + } else { + accessibleMap[r].append(accessibleName); + objnameMap.insert(w, accessibleName); + + // 对象销毁后移除占用名称 + QObject::connect(w, &QWidget::destroyed, [ = ] (QObject *obj) { + objnameMap.remove(obj); + accessibleMap[r].removeOne(accessibleName); + }); + return accessibleName; + } +} + +// 公共的功能 +#define FUNC_CREATE(classname,accessibletype,accessdescription) explicit Accessible##classname(classname *w) \ + : QAccessibleWidget(w,accessibletype,#classname)\ + , m_w(w)\ + , m_description(accessdescription)\ +{}\ + +#define FUNC_TEXT(classname,accessiblename) QString Accessible##classname::text(QAccessible::Text t) const{\ + switch (t) {\ + case QAccessible::Name:\ + return getAccessibleName(m_w, this->role(), accessiblename);\ + case QAccessible::Description:\ + return m_description;\ + default:\ + return QString();\ + }\ + }\ + +// button控件特有功能 +#define FUNC_ACTIONNAMES(classname) QStringList Accessible##classname::actionNames() const{\ + if(!m_w->isEnabled())\ + return QStringList();\ + return QStringList() << pressAction()<< showMenuAction();\ + }\ + +#define FUNC_DOACTION(classname) void Accessible##classname::doAction(const QString &actionName){\ + if(actionName == pressAction())\ +{\ + QPointF localPos = m_w->geometry().center();\ + QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);\ + qApp->sendEvent(m_w,&event);\ + }\ + else if(actionName == showMenuAction())\ +{\ + QPointF localPos = m_w->geometry().center();\ + QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::RightButton,Qt::RightButton,Qt::NoModifier);\ + qApp->sendEvent(m_w,&event);\ + }\ + }\ + +// Label控件特有功能 +#define FUNC_TEXT_(classname) QString Accessible##classname::text(int startOffset, int endOffset) const{\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + return m_w->text();\ + }\ + +// Slider控件特有功能 +#define FUNC_CURRENTVALUE(classname) QVariant Accessible##classname::currentValue() const{\ + return m_w->value();\ + }\ + +#define FUNC_SETCURRENTVALUE(classname) void Accessible##classname::setCurrentValue(const QVariant &value){\ + return m_w->setValue(value.toInt());\ + }\ + +#define FUNC_MAXMUMVALUE(classname) QVariant Accessible##classname::maximumValue() const{\ + return QVariant(m_w->maximum());\ + }\ + +#define FUNC_FUNC_MINIMUMVALUE(classname) QVariant Accessible##classname::minimumValue() const{\ + return QVariant(m_w->minimum());\ + }\ + +// DSlider控件特有功能函数 +#define FUNC_FUNC_MINIMUMSTEPSIZE(classname) QVariant Accessible##classname::minimumStepSize() const{\ + return QVariant(m_w->pageStep());\ + }\ + +#define SET_FORM_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\ +{\ + public:\ + FUNC_CREATE(classname,QAccessible::Form,accessdescription)\ + QString text(QAccessible::Text t) const override;\ + void *interface_cast(QAccessible::InterfaceType t) override{\ + switch (t) {\ + case QAccessible::ActionInterface:\ + return static_cast(this);\ + default:\ + return nullptr;\ + }\ + }\ + private:\ + classname *m_w;\ + QString m_description;\ + };\ + FUNC_TEXT(classname,accessiblename)\ + +#define SET_BUTTON_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\ +{\ + public:\ + FUNC_CREATE(classname,QAccessible::Button,accessdescription)\ + QString text(QAccessible::Text t) const override;\ + void *interface_cast(QAccessible::InterfaceType t) override{\ + switch (t) {\ + case QAccessible::ActionInterface:\ + return static_cast(this);\ + default:\ + return nullptr;\ + }\ + }\ + QStringList actionNames() const override;\ + void doAction(const QString &actionName) override;\ + private:\ + classname *m_w;\ + QString m_description;\ + };\ + FUNC_TEXT(classname,accessiblename)\ + FUNC_ACTIONNAMES(classname)\ + FUNC_DOACTION(classname)\ + +#define SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleTextInterface\ +{\ + public:\ + FUNC_CREATE(classname,QAccessible::StaticText,accessdescription)\ + QString text(QAccessible::Text t) const override;\ + void *interface_cast(QAccessible::InterfaceType t) override{\ + switch (t) {\ + case QAccessible::ActionInterface:\ + return static_cast(this);\ + case QAccessible::TextInterface:\ + return static_cast(this);\ + default:\ + return nullptr;\ + }\ + }\ + QString text(int startOffset, int endOffset) const override;\ + void selection(int selectionIndex, int *startOffset, int *endOffset) const override {\ + Q_UNUSED(selectionIndex)\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + }\ + int selectionCount() const override { return 0; }\ + void addSelection(int startOffset, int endOffset) override {\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + }\ + void removeSelection(int selectionIndex) override {\ + Q_UNUSED(selectionIndex)\ + }\ + void setSelection(int selectionIndex, int startOffset, int endOffset) override {\ + Q_UNUSED(selectionIndex)\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + }\ + int cursorPosition() const override { return 0; }\ + void setCursorPosition(int position) override {\ + Q_UNUSED(position)\ + }\ + int characterCount() const override { return 0; }\ + QRect characterRect(int offset) const override {\ + Q_UNUSED(offset)\ + return QRect();\ + }\ + int offsetAtPoint(const QPoint &point) const override {\ + Q_UNUSED(point)\ + return 0;\ + }\ + void scrollToSubstring(int startIndex, int endIndex) override {\ + Q_UNUSED(startIndex)\ + Q_UNUSED(endIndex)\ + }\ + QString attributes(int offset, int *startOffset, int *endOffset) const override {\ + Q_UNUSED(offset)\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + return QString();\ + }\ + private:\ + classname *m_w;\ + QString m_description;\ + };\ + FUNC_TEXT(classname,accessiblename)\ + FUNC_TEXT_(classname)\ + +#define SET_SLIDER_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleValueInterface\ +{\ + public:\ + FUNC_CREATE(classname,QAccessible::Slider,accessdescription)\ + QString text(QAccessible::Text t) const override;\ + void *interface_cast(QAccessible::InterfaceType t) override{\ + switch (t) {\ + case QAccessible::ActionInterface:\ + return static_cast(this);\ + case QAccessible::ValueInterface:\ + return static_cast(this);\ + default:\ + return nullptr;\ + }\ + }\ + QVariant currentValue() const override;\ + void setCurrentValue(const QVariant &value) override;\ + QVariant maximumValue() const override;\ + QVariant minimumValue() const override;\ + QVariant minimumStepSize() const override;\ + private:\ + classname *m_w;\ + QString m_description;\ + };\ + FUNC_TEXT(classname,accessiblename)\ + FUNC_CURRENTVALUE(classname)\ + FUNC_SETCURRENTVALUE(classname)\ + FUNC_MAXMUMVALUE(classname)\ + FUNC_FUNC_MINIMUMVALUE(classname)\ + FUNC_FUNC_MINIMUMSTEPSIZE(classname)\ + +#define SET_EDITABLE_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleEditableTextInterface, public QAccessibleTextInterface\ +{\ + public:\ + FUNC_CREATE(classname,QAccessible::EditableText,accessdescription)\ + QString text(QAccessible::Text t) const override;\ + QAccessibleInterface *child(int index) const override { Q_UNUSED(index); return nullptr; }\ + void *interface_cast(QAccessible::InterfaceType t) override{\ + switch (t) {\ + case QAccessible::ActionInterface:\ + return static_cast(this);\ + case QAccessible::TextInterface:\ + return static_cast(this);\ + case QAccessible::EditableTextInterface:\ + return static_cast(this);\ + default:\ + return nullptr;\ + }\ + }\ + QString text(int startOffset, int endOffset) const override;\ + void selection(int selectionIndex, int *startOffset, int *endOffset) const override {\ + Q_UNUSED(selectionIndex)\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + }\ + int selectionCount() const override { return 0; }\ + void addSelection(int startOffset, int endOffset) override {\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + }\ + void removeSelection(int selectionIndex) override { Q_UNUSED(selectionIndex);}\ + void setSelection(int selectionIndex, int startOffset, int endOffset) override {\ + Q_UNUSED(selectionIndex)\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + }\ + int cursorPosition() const override { return 0; }\ + void setCursorPosition(int position) override {\ + Q_UNUSED(position)\ + }\ + int characterCount() const override { return 0; }\ + QRect characterRect(int offset) const override { \ + Q_UNUSED(offset)\ + return QRect(); }\ + int offsetAtPoint(const QPoint &point) const override {\ + Q_UNUSED(point)\ + return 0; }\ + void scrollToSubstring(int startIndex, int endIndex) override {\ + Q_UNUSED(startIndex)\ + Q_UNUSED(endIndex)\ + }\ + QString attributes(int offset, int *startOffset, int *endOffset) const override {\ + Q_UNUSED(offset)\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + return QString(); }\ + void insertText(int offset, const QString &text) override {\ + Q_UNUSED(offset)\ + Q_UNUSED(text)\ + }\ + void deleteText(int startOffset, int endOffset) override {\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + }\ + void replaceText(int startOffset, int endOffset, const QString &text) override {\ + Q_UNUSED(startOffset)\ + Q_UNUSED(endOffset)\ + Q_UNUSED(text)\ + }\ + private:\ + classname *m_w;\ + QString m_description;\ + };\ + FUNC_TEXT(classname,accessiblename)\ + FUNC_TEXT_(classname)\ + +#define USE_ACCESSIBLE(classnamestring,classname) if (classnamestring == QLatin1String(#classname) && object && object->isWidgetType())\ +{\ + interface = new Accessible##classname(static_cast(object));\ + }\ + +#define ELSE_USE_ACCESSIBLE(classnamestring,classname) else if (classnamestring == QLatin1String(#classname) && object && object->isWidgetType())\ +{\ + interface = new Accessible##classname(static_cast(object));\ + }\ + + +// [指定objectname]---适用同一个类,但objectname不同的情况 +#define USE_ACCESSIBLE_BY_OBJECTNAME(classnamestring,classname,objectname) if (classnamestring == QLatin1String(#classname) && object && (object->objectName() == objectname) && object->isWidgetType())\ +{\ + interface = new Accessible##classname(static_cast(object));\ + }\ + +#define ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classnamestring,classname,objectname) else if (classnamestring == QLatin1String(#classname) && object && (object->objectName() == objectname) && object->isWidgetType())\ +{\ + interface = new Accessible##classname(static_cast(object));\ + }\ + +/*******************************************简化使用*******************************************/ +#define SET_FORM_ACCESSIBLE(classname,accessiblename) SET_FORM_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"") + +#define SET_BUTTON_ACCESSIBLE(classname,accessiblename) SET_BUTTON_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"") + +#define SET_LABEL_ACCESSIBLE(classname,accessiblename) SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"") + +#define SET_SLIDER_ACCESSIBLE(classname,accessiblename) SET_SLIDER_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"") + +#define SET_EDITABLE_ACCESSIBLE(classname,accessiblename) SET_EDITABLE_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"") +/************************************************************************************************/ + +#endif // ACCESSIBLEINTERFACE_H diff --git a/frame/controller/dockitemmanager.cpp b/frame/controller/dockitemmanager.cpp index 7da638ff2..4992470e5 100644 --- a/frame/controller/dockitemmanager.cpp +++ b/frame/controller/dockitemmanager.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,6 +9,8 @@ #include "pluginsitem.h" #include "traypluginitem.h" #include "utils.h" +#include "appmultiitem.h" +#include "quicksettingcontroller.h" #include #include @@ -21,41 +24,46 @@ const QGSettings *DockItemManager::m_dockedSettings = Utils::ModuleSettingsPtr(" DockItemManager::DockItemManager(QObject *parent) : QObject(parent) - , m_appInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) - , m_pluginsInter(new DockPluginsController(this)) + , m_appInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) + , m_loadFinished(false) { //固定区域:启动器 m_itemList.append(new LauncherItem); // 应用区域 for (auto entry : m_appInter->entries()) { - AppItem *it = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, entry); + AppItem *it = new AppItem(m_appInter, m_appSettings, m_activeSettings, m_dockedSettings, entry); manageItem(it); - connect(it, &AppItem::requestActivateWindow, m_appInter, &DBusDock::ActivateWindow, Qt::QueuedConnection); - connect(it, &AppItem::requestPreviewWindow, m_appInter, &DBusDock::PreviewWindow); - connect(it, &AppItem::requestCancelPreview, m_appInter, &DBusDock::CancelPreviewWindow); - connect(it, &AppItem::requestUpdateItemMinimizedGeometry, this, [=](const QRect r){ - Q_EMIT requestUpdateItemMinimizedGeometry(it, r); - }); + connect(it, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection); + connect(it, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow); + connect(it, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow); + connect(it, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged); connect(this, &DockItemManager::requestUpdateDockItem, it, &AppItem::requestUpdateEntryGeometries); m_itemList.append(it); + updateMultiItems(it); } // 托盘区域和插件区域 由DockPluginsController获取 + QuickSettingController *quickController = QuickSettingController::instance(); + connect(quickController, &QuickSettingController::pluginInserted, this, [ = ](PluginsItemInterface *itemInter, const QuickSettingController::PluginAttribute pluginAttr) { + if (pluginAttr != QuickSettingController::PluginAttribute::Fixed) + return; + + m_pluginItems << itemInter; + pluginItemInserted(quickController->pluginItemWidget(itemInter)); + }); + + connect(quickController, &QuickSettingController::pluginRemoved, this, &DockItemManager::onPluginItemRemoved); + connect(quickController, &QuickSettingController::pluginUpdated, this, &DockItemManager::onPluginUpdate); + connect(quickController, &QuickSettingController::pluginLoaderFinished, this, &DockItemManager::onPluginLoadFinished, Qt::QueuedConnection); // 应用信号 - connect(m_appInter, &DBusDock::EntryAdded, this, &DockItemManager::appItemAdded); - connect(m_appInter, &DBusDock::EntryRemoved, this, static_cast(&DockItemManager::appItemRemoved), Qt::QueuedConnection); - connect(m_appInter, &DBusDock::ServiceRestarted, this, &DockItemManager::reloadAppItems); - - // 插件信号 - connect(m_pluginsInter, &DockPluginsController::pluginItemInserted, this, &DockItemManager::pluginItemInserted, Qt::QueuedConnection); - connect(m_pluginsInter, &DockPluginsController::pluginItemRemoved, this, &DockItemManager::pluginItemRemoved, Qt::QueuedConnection); - connect(m_pluginsInter, &DockPluginsController::pluginItemUpdated, this, &DockItemManager::itemUpdated, Qt::QueuedConnection); - connect(m_pluginsInter, &DockPluginsController::trayVisableCountChanged, this, &DockItemManager::trayVisableCountChanged, Qt::QueuedConnection); - connect(m_pluginsInter, &DockPluginsController::pluginLoaderFinished, this, &DockItemManager::onPluginLoadFinished, Qt::QueuedConnection); + connect(m_appInter, &DockInter::EntryAdded, this, &DockItemManager::appItemAdded); + connect(m_appInter, &DockInter::EntryRemoved, this, static_cast(&DockItemManager::appItemRemoved), Qt::QueuedConnection); + connect(m_appInter, &DockInter::ServiceRestarted, this, &DockItemManager::reloadAppItems); + connect(m_appInter, &DockInter::ShowMultiWindowChanged, this, &DockItemManager::onShowMultiWindowChanged); DApplication *app = qobject_cast(qApp); if (app) { @@ -64,6 +72,13 @@ DockItemManager::DockItemManager(QObject *parent) connect(qApp, &QApplication::aboutToQuit, this, &QObject::deleteLater); + // 读取已经加载的固定区域插件 + QList plugins = quickController->pluginItems(QuickSettingController::PluginAttribute::Fixed); + for (PluginsItemInterface *plugin : plugins) { + m_pluginItems << plugin; + pluginItemInserted(quickController->pluginItemWidget(plugin)); + } + // 刷新图标 QMetaObject::invokeMethod(this, "refreshItemsIcon", Qt::QueuedConnection); } @@ -81,22 +96,11 @@ const QList> DockItemManager::itemList() const return m_itemList; } -const QList DockItemManager::pluginList() const -{ - return m_pluginsInter->pluginsMap().keys(); -} - bool DockItemManager::appIsOnDock(const QString &appDesktop) const { return m_appInter->IsOnDock(appDesktop); } -void DockItemManager::startLoadPlugins() const -{ - int delay = Utils::SettingValue("com.deepin.dde.dock", "/com/deepin/dde/dock/", "delay-plugins-time", 0).toInt(); - QTimer::singleShot(delay, m_pluginsInter, &DockPluginsController::startLoader); -} - void DockItemManager::refreshItemsIcon() { for (auto item : m_itemList) { @@ -184,7 +188,7 @@ void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index) ++insertIndex; } - AppItem *item = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, path); + AppItem *item = new AppItem(m_appInter, m_appSettings, m_activeSettings, m_dockedSettings, path); if (m_appIDist.contains(item->appId())) { delete item; @@ -193,23 +197,23 @@ void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index) manageItem(item); - connect(item, &AppItem::requestActivateWindow, m_appInter, &DBusDock::ActivateWindow, Qt::QueuedConnection); - connect(item, &AppItem::requestPreviewWindow, m_appInter, &DBusDock::PreviewWindow); - connect(item, &AppItem::requestCancelPreview, m_appInter, &DBusDock::CancelPreviewWindow); - connect(item, &AppItem::requestUpdateItemMinimizedGeometry, this, [=](const QRect r){ - Q_EMIT requestUpdateItemMinimizedGeometry(item, r); - }); + connect(item, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection); + connect(item, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow); + connect(item, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow); + connect(item, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged); connect(this, &DockItemManager::requestUpdateDockItem, item, &AppItem::requestUpdateEntryGeometries); m_itemList.insert(insertIndex, item); m_appIDist.append(item->appId()); - if (index != -1) { - emit itemInserted(insertIndex - 1, item); - return; - } + int itemIndex = insertIndex; + if (index != -1) + itemIndex = insertIndex - 1; - emit itemInserted(insertIndex, item); + // 插入dockItem + emit itemInserted(itemIndex, item); + // 向后插入多开窗口 + updateMultiItems(item, true); } void DockItemManager::appItemRemoved(const QString &appId) @@ -243,6 +247,24 @@ void DockItemManager::appItemRemoved(AppItem *appItem) appItem->deleteLater(); } +void DockItemManager::reloadAppItems() +{ + // remove old item + for (auto item : m_itemList) + if (item->itemType() == DockItem::App) + appItemRemoved(static_cast(item.data())); + + // append new item + for (auto path : m_appInter->entries()) + appItemAdded(path, -1); +} + +void DockItemManager::manageItem(DockItem *item) +{ + connect(item, &DockItem::requestRefreshWindowVisible, this, &DockItemManager::requestRefershWindowVisible, Qt::UniqueConnection); + connect(item, &DockItem::requestWindowAutoHide, this, &DockItemManager::requestWindowAutoHide, Qt::UniqueConnection); +} + void DockItemManager::pluginItemInserted(PluginsItem *item) { manageItem(item); @@ -292,44 +314,155 @@ void DockItemManager::pluginItemInserted(PluginsItem *item) m_itemList.insert(insertIndex, item); if(pluginType == DockItem::FixedPlugin) - { insertIndex ++; - } if (!Utils::SettingValue(QString("com.deepin.dde.dock.module.") + item->pluginName(), QByteArray(), "enable", true).toBool()) item->setVisible(false); + else + item->setVisible(true); emit itemInserted(insertIndex - firstPluginPosition, item); } -void DockItemManager::pluginItemRemoved(PluginsItem *item) +void DockItemManager::onPluginItemRemoved(PluginsItemInterface *itemInter) { + if (!m_pluginItems.contains(itemInter)) + return; + + PluginsItem *item = QuickSettingController::instance()->pluginItemWidget(itemInter); item->hidePopup(); + item->hide(); emit itemRemoved(item); m_itemList.removeOne(item); + + if (m_loadFinished) { + updatePluginsItemOrderKey(); + } } -void DockItemManager::reloadAppItems() +void DockItemManager::onPluginUpdate(PluginsItemInterface *itemInter) { - // remove old item - for (auto item : m_itemList) - if (item->itemType() == DockItem::App) - appItemRemoved(static_cast(item.data())); + if (!m_pluginItems.contains(itemInter)) + return; - // append new item - for (auto path : m_appInter->entries()) - appItemAdded(path, -1); -} - -void DockItemManager::manageItem(DockItem *item) -{ - connect(item, &DockItem::requestRefreshWindowVisible, this, &DockItemManager::requestRefershWindowVisible, Qt::UniqueConnection); - connect(item, &DockItem::requestWindowAutoHide, this, &DockItemManager::requestWindowAutoHide, Qt::UniqueConnection); + Q_EMIT itemUpdated(QuickSettingController::instance()->pluginItemWidget(itemInter)); } void DockItemManager::onPluginLoadFinished() { updatePluginsItemOrderKey(); + m_loadFinished = true; +} + +void DockItemManager::onAppWindowCountChanged() +{ + AppItem *appItem = static_cast(sender()); + updateMultiItems(appItem, true); +} + +void DockItemManager::updateMultiItems(AppItem *appItem, bool emitSignal) +{ + // 如果系统设置不开启应用多窗口拆分,则无需之后的操作 + if (!m_appInter->showMultiWindow()) + return; + + // 如果开启了多窗口拆分,则同步窗口和多窗口应用的信息 + const WindowInfoMap &windowInfoMap = appItem->windowsMap(); + QList removeItems; + // 同步当前已经存在的多开窗口的列表,删除不存在的多开窗口 + for (int i = 0; i < m_itemList.size(); i++) { + QPointer dockItem = m_itemList[i]; + AppMultiItem *multiItem = qobject_cast(dockItem.data()); + if (!multiItem || multiItem->appItem() != appItem) + continue; + + // 如果查找到的当前的应用的窗口不需要移除,则继续下一个循环 + if (!needRemoveMultiWindow(multiItem)) + continue; + + removeItems << multiItem; + } + // 从itemList中移除多开窗口 + for (AppMultiItem *dockItem : removeItems) + m_itemList.removeOne(dockItem); + if (emitSignal) { + // 移除发送每个多开窗口的移除信号 + for (AppMultiItem *dockItem : removeItems) + Q_EMIT itemRemoved(dockItem); + } + qDeleteAll(removeItems); + + // 遍历当前APP打开的所有窗口的列表,如果不存在多开窗口的应用,则新增,同时发送信号 + for (auto it = windowInfoMap.begin(); it != windowInfoMap.end(); it++) { + if (multiWindowExist(it.key())) + continue; + + const WindowInfo &windowInfo = it.value(); + // 如果不存在这个窗口对应的多开窗口,则新建一个窗口,同时发送窗口新增的信号 + AppMultiItem *multiItem = new AppMultiItem(appItem, it.key(), windowInfo); + m_itemList << multiItem; + if (emitSignal) + Q_EMIT itemInserted(-1, multiItem); + } +} + +// 检查对应的窗口是否存在多开窗口 +bool DockItemManager::multiWindowExist(quint32 winId) const +{ + for (QPointer dockItem : m_itemList) { + AppMultiItem *multiItem = qobject_cast(dockItem.data()); + if (!multiItem) + continue; + + if (multiItem->winId() == winId) + return true; + } + + return false; +} + +// 检查当前多开窗口是否需要移除 +// 如果当前多开窗口图标对应的窗口在这个窗口所属的APP中所有打开窗口中不存在,那么则认为该多窗口已经被关闭 +bool DockItemManager::needRemoveMultiWindow(AppMultiItem *multiItem) const +{ + // 查找多分窗口对应的窗口在应用所有的打开的窗口中是否存在,只要它对应的窗口存在,就无需删除 + // 只要不存在,就需要删除 + AppItem *appItem = multiItem->appItem(); + const WindowInfoMap &windowInfoMap = appItem->windowsMap(); + for (auto it = windowInfoMap.begin(); it != windowInfoMap.end(); it++) { + if (it.key() == multiItem->winId()) + return false; + } + + return true; +} + +void DockItemManager::onShowMultiWindowChanged() +{ + if (m_appInter->showMultiWindow()) { + // 如果当前设置支持窗口多开,那么就依次对每个APPItem加载多开窗口 + for (int i = 0; i < m_itemList.size(); i++) { + const QPointer &dockItem = m_itemList[i]; + if (dockItem->itemType() != DockItem::ItemType::App) + continue; + + updateMultiItems(static_cast(dockItem.data()), true); + } + } else { + // 如果当前设置不支持窗口多开,则删除所有的多开窗口 + QList multiWindows; + for (const QPointer &dockItem : m_itemList) { + if (dockItem->itemType() != DockItem::AppMultiWindow) + continue; + + multiWindows << dockItem.data(); + } + for (DockItem *multiItem : multiWindows) { + m_itemList.removeOne(multiItem); + Q_EMIT itemRemoved(multiItem); + multiItem->deleteLater(); + } + } } diff --git a/frame/controller/dockitemmanager.h b/frame/controller/dockitemmanager.h index 926261c56..2314d47d5 100644 --- a/frame/controller/dockitemmanager.h +++ b/frame/controller/dockitemmanager.h @@ -1,21 +1,21 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DOCKITEMMANAGER_H #define DOCKITEMMANAGER_H -#include "dockpluginscontroller.h" #include "pluginsiteminterface.h" #include "dockitem.h" #include "appitem.h" #include "placeholderitem.h" - -#include +#include "dbusutil.h" #include -using DBusDock = com::deepin::dde::daemon::Dock; +class AppMultiItem; +class PluginsItem; /** * @brief The DockItemManager class @@ -29,9 +29,7 @@ public: static DockItemManager *instance(QObject *parent = nullptr); const QList > itemList() const; - const QList pluginList() const; bool appIsOnDock(const QString &appDesktop) const; - void startLoadPlugins() const; signals: void itemInserted(const int index, DockItem *item) const; @@ -40,8 +38,8 @@ signals: void trayVisableCountChanged(const int &count) const; void requestWindowAutoHide(const bool autoHide) const; void requestRefershWindowVisible() const; + void requestUpdateDockItem() const; - void requestUpdateItemMinimizedGeometry(AppItem *item, const QRect) const; public slots: void refreshItemsIcon(); @@ -50,26 +48,36 @@ public slots: private Q_SLOTS: void onPluginLoadFinished(); + void onPluginItemRemoved(PluginsItemInterface *itemInter); + void onPluginUpdate(PluginsItemInterface *itemInter); + + void onAppWindowCountChanged(); + void onShowMultiWindowChanged(); private: explicit DockItemManager(QObject *parent = nullptr); void appItemAdded(const QDBusObjectPath &path, const int index); void appItemRemoved(const QString &appId); void appItemRemoved(AppItem *appItem); - void pluginItemInserted(PluginsItem *item); - void pluginItemRemoved(PluginsItem *item); void updatePluginsItemOrderKey(); void reloadAppItems(); void manageItem(DockItem *item); + void pluginItemInserted(PluginsItem *item); + + void updateMultiItems(AppItem *appItem, bool emitSignal = false); + bool multiWindowExist(quint32 winId) const; + bool needRemoveMultiWindow(AppMultiItem *multiItem) const; private: - DBusDock *m_appInter; - DockPluginsController *m_pluginsInter; + DockInter *m_appInter; static DockItemManager *INSTANCE; QList> m_itemList; QList m_appIDist; + QList m_pluginItems; + + bool m_loadFinished; // 记录所有插件是否加载完成 static const QGSettings *m_appSettings; static const QGSettings *m_activeSettings; diff --git a/frame/controller/dockpluginscontroller.cpp b/frame/controller/dockpluginscontroller.cpp deleted file mode 100644 index 552d086d2..000000000 --- a/frame/controller/dockpluginscontroller.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "dockpluginscontroller.h" -#include "pluginsiteminterface.h" -#include "traypluginitem.h" - -#include -#include -#include - -DockPluginsController::DockPluginsController(QObject *parent) - : AbstractPluginsController(parent) -{ - setObjectName("DockPlugin"); -} - -void DockPluginsController::itemAdded(PluginsItemInterface *const itemInter, const QString &itemKey) -{ - QMap> &mPluginsMap = pluginsMap(); - - // check if same item added - if (mPluginsMap.contains(itemInter)) - if (mPluginsMap[itemInter].contains(itemKey)) - return; - - // 取 plugin api - QPluginLoader *pluginLoader = qobject_cast(mPluginsMap[itemInter].value("pluginloader")); - if (!pluginLoader) { - return; - } - const QJsonObject &meta = pluginLoader->metaData().value("MetaData").toObject(); - const QString &pluginApi = meta.value("api").toString(); - - PluginsItem *item = nullptr; - if (itemInter->pluginName() == "tray") { - item = new TrayPluginItem(itemInter, itemKey, pluginApi); - if (item->graphicsEffect()) { - item->graphicsEffect()->setEnabled(false); - } - connect(static_cast(item), &TrayPluginItem::trayVisableCountChanged, - this, &DockPluginsController::trayVisableCountChanged, Qt::UniqueConnection); - } else { - item = new PluginsItem(itemInter, itemKey, pluginApi); - } - - mPluginsMap[itemInter][itemKey] = item; - - emit pluginItemInserted(item); -} - -void DockPluginsController::itemUpdate(PluginsItemInterface *const itemInter, const QString &itemKey) -{ - PluginsItem *item = static_cast(pluginItemAt(itemInter, itemKey)); - if (!item) - return; - - item->update(); - - emit pluginItemUpdated(item); -} - -void DockPluginsController::itemRemoved(PluginsItemInterface *const itemInter, const QString &itemKey) -{ - PluginsItem *item = static_cast(pluginItemAt(itemInter, itemKey)); - if (!item) - return; - - item->detachPluginWidget(); - - emit pluginItemRemoved(item); - - QMap> &mPluginsMap = pluginsMap(); - mPluginsMap[itemInter].remove(itemKey); - - // do not delete the itemWidget object(specified in the plugin interface) - item->centralWidget()->setParent(nullptr); - - if (item->isDragging()) { - QDrag::cancel(); - } - - // just delete our wrapper object(PluginsItem) - item->deleteLater(); -} - -void DockPluginsController::requestWindowAutoHide(PluginsItemInterface *const itemInter, const QString &itemKey, const bool autoHide) -{ - PluginsItem *item = static_cast(pluginItemAt(itemInter, itemKey)); - if (!item) - return; - - Q_EMIT item->requestWindowAutoHide(autoHide); -} - -void DockPluginsController::requestRefreshWindowVisible(PluginsItemInterface *const itemInter, const QString &itemKey) -{ - PluginsItem *item = static_cast(pluginItemAt(itemInter, itemKey)); - if (!item) - return; - - Q_EMIT item->requestRefreshWindowVisible(); -} - -void DockPluginsController::requestSetAppletVisible(PluginsItemInterface *const itemInter, const QString &itemKey, const bool visible) -{ - PluginsItem *item = static_cast(pluginItemAt(itemInter, itemKey)); - if (!item) - return; - - if (visible) { - // 在弹出界面前先隐藏其他插件的tips - QMap> &mPluginsMap = pluginsMap(); - foreach (auto interface, mPluginsMap.keys()) { - if (interface != itemInter) { - foreach (auto oldItemKey, mPluginsMap[interface].keys()) { - if (oldItemKey != "pluginloader") { - PluginsItem *oldItem = qobject_cast(pluginItemAt(interface, oldItemKey)); - if (oldItem) { - oldItem->hidePopup(); - } - } - } - } - } - - item->showPopupApplet(itemInter->itemPopupApplet(itemKey)); - } else { - item->hidePopup(); - } -} - -void DockPluginsController::startLoader() -{ - loadLocalPlugins(); - loadSystemPlugins(); -} - -void DockPluginsController::loadLocalPlugins() -{ - QString pluginsDir(QString("%1/.local/lib/dde-dock/plugins/").arg(QDir::homePath())); - - if (!QDir(pluginsDir).exists()) { - return; - } - - qDebug() << "using dock local plugins dir:" << pluginsDir; - - AbstractPluginsController::startLoader(new PluginLoader(pluginsDir, this)); -} - -void DockPluginsController::loadSystemPlugins() -{ - QString pluginsDir(qApp->applicationDirPath() + "/../plugins"); -#ifndef QT_DEBUG - pluginsDir = "/usr/lib/dde-dock/plugins"; -#endif - qDebug() << "using dock plugins dir:" << pluginsDir; - - AbstractPluginsController::startLoader(new PluginLoader(pluginsDir, this)); -} diff --git a/frame/controller/dockpluginscontroller.h b/frame/controller/dockpluginscontroller.h deleted file mode 100644 index 67423e1e3..000000000 --- a/frame/controller/dockpluginscontroller.h +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef DOCKPLUGINSCONTROLLER_H -#define DOCKPLUGINSCONTROLLER_H - -#include "pluginsitem.h" -#include "pluginproxyinterface.h" -#include "abstractpluginscontroller.h" - -#include - -#include -#include -#include -#include - -class PluginsItemInterface; -class DockPluginsController : public AbstractPluginsController -{ - Q_OBJECT - - friend class DockItemController; - friend class DockItemManager; - -public: - explicit DockPluginsController(QObject *parent = nullptr); - - // implements PluginProxyInterface - void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override; - void itemUpdate(PluginsItemInterface * const itemInter, const QString &itemKey) override; - void itemRemoved(PluginsItemInterface * const itemInter, const QString &itemKey) override; - void requestWindowAutoHide(PluginsItemInterface * const itemInter, const QString &itemKey, const bool autoHide) override; - void requestRefreshWindowVisible(PluginsItemInterface * const itemInter, const QString &itemKey) override; - void requestSetAppletVisible(PluginsItemInterface * const itemInter, const QString &itemKey, const bool visible) override; - - void startLoader(); - -signals: - void pluginItemInserted(PluginsItem *pluginItem) const; - void pluginItemRemoved(PluginsItem *pluginItem) const; - void pluginItemUpdated(PluginsItem *pluginItem) const; - void trayVisableCountChanged(const int &count) const; - -private: - void loadLocalPlugins(); - void loadSystemPlugins(); -}; - -#endif // DOCKPLUGINSCONTROLLER_H diff --git a/frame/controller/multiwindowhelper.cpp b/frame/controller/multiwindowhelper.cpp new file mode 100644 index 000000000..3fc972264 --- /dev/null +++ b/frame/controller/multiwindowhelper.cpp @@ -0,0 +1,139 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "multiwindowhelper.h" +#include "appmultiitem.h" +#include "appitem.h" + +MultiWindowHelper::MultiWindowHelper(QWidget *appWidget, QWidget *multiWindowWidget, QObject *parent) + : QObject(parent) + , m_appWidget(appWidget) + , m_multiWindowWidget(multiWindowWidget) + , m_displayMode(Dock::DisplayMode::Efficient) +{ + m_appWidget->installEventFilter(this); + m_multiWindowWidget->installEventFilter(this); +} + +void MultiWindowHelper::setDisplayMode(Dock::DisplayMode displayMode) +{ + if (m_displayMode == displayMode) + return; + + m_displayMode = displayMode; + resetMultiItemPosition(); +} + +void MultiWindowHelper::addMultiWindow(int, AppMultiItem *item) +{ + int index = itemIndex(item); + if (m_displayMode == Dock::DisplayMode::Efficient) { + // 将多开窗口项目插入到对应的APP的后面 + insertChildWidget(m_appWidget, index, item); + } else { + // 将多开窗口插入到工具区域的前面 + insertChildWidget(m_multiWindowWidget, index, item); + } +} + +void MultiWindowHelper::removeMultiWindow(AppMultiItem *item) +{ + if (m_appWidget->children().contains(item)) + m_appWidget->layout()->removeWidget(item); + else + m_multiWindowWidget->layout()->removeWidget(item); +} + +bool MultiWindowHelper::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_appWidget || watched == m_multiWindowWidget) { + switch(event->type()) { + case QEvent::ChildAdded: + case QEvent::ChildRemoved: { + /* 这里用异步的方式,因为收到QEvent::ChildAdded信号的时候, + 此时应用还没有插入到Widget中,收到QEvent::ChildRemoved信号的时候, + 此时应用还未从任务栏上移除,通过异步的方式保证同步新增或移除成功后才执行,这样更新的界面才是最准确的 + */ + QMetaObject::invokeMethod(this, &MultiWindowHelper::requestUpdate, Qt::QueuedConnection); + break; + } + default: + break; + } + } + + return QObject::eventFilter(watched, event); +} + +int MultiWindowHelper::itemIndex(AppMultiItem *item) +{ + if (m_displayMode != Dock::DisplayMode::Efficient) + return -1; + + // 高效模式,查找对应的应用或者这个应用所有的子窗口所在的位置,然后插入到最大的值的后面 + int lastIndex = -1; + for (int i = 0; i < m_appWidget->layout()->count(); i++) { + DockItem *dockItem = qobject_cast(m_appWidget->layout()->itemAt(i)->widget()); + if (!dockItem) + continue; + + if (dockItem != item->appItem()) { + AppMultiItem *multiItem = qobject_cast(dockItem); + if (!multiItem || multiItem->appItem() != item->appItem()) + continue; + } + + lastIndex = i; + } + + if (lastIndex >= 0) + return ++lastIndex; + + return -1; +} + +void MultiWindowHelper::insertChildWidget(QWidget *parentWidget, int index, AppMultiItem *item) +{ + QBoxLayout *layout = static_cast(parentWidget->layout()); + if (index >= 0) + layout->insertWidget(index, item); + else + layout->addWidget(item); +} + +void MultiWindowHelper::resetMultiItemPosition() +{ + QWidget *fromWidget = nullptr; + QWidget *toWidget = nullptr; + + if (m_displayMode == Dock::DisplayMode::Efficient) { + // 从时尚模式变换为高效模式 + fromWidget = m_multiWindowWidget; + toWidget = m_appWidget; + } else { + // 从高效模式变换到时尚模式 + fromWidget = m_appWidget; + toWidget = m_multiWindowWidget; + } + + QList moveWidgetItem; + for (int i = 0; i < fromWidget->layout()->count(); i++) { + AppMultiItem *multiItem = qobject_cast(fromWidget->layout()->itemAt(i)->widget()); + if (!multiItem) + continue; + + moveWidgetItem << multiItem; + } + + QBoxLayout *toLayout = static_cast(toWidget->layout()); + for (AppMultiItem *item : moveWidgetItem) { + fromWidget->layout()->removeWidget(item); + int index = itemIndex(item); + if (index >= 0) + toLayout->insertWidget(index, item); + else + toLayout->addWidget(item); + } +} diff --git a/frame/controller/multiwindowhelper.h b/frame/controller/multiwindowhelper.h new file mode 100644 index 000000000..7597e8263 --- /dev/null +++ b/frame/controller/multiwindowhelper.h @@ -0,0 +1,43 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef MULTIWINDOWHELPER_H +#define MULTIWINDOWHELPER_H + +#include "constants.h" + +#include + +class AppMultiItem; + +class MultiWindowHelper : public QObject +{ + Q_OBJECT + +public: + explicit MultiWindowHelper(QWidget *appWidget, QWidget *multiWindowWidget, QObject *parent = nullptr); + + void setDisplayMode(Dock::DisplayMode displayMode); + void addMultiWindow(int, AppMultiItem *item); + void removeMultiWindow(AppMultiItem *item); + +Q_SIGNALS: + void requestUpdate(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + int itemIndex(AppMultiItem *item); + void insertChildWidget(QWidget *parentWidget, int index, AppMultiItem *item); + void resetMultiItemPosition(); + +private: + QWidget *m_appWidget; + QWidget *m_multiWindowWidget; + Dock::DisplayMode m_displayMode; +}; + +#endif // MULTIWINDOWHELPER_H diff --git a/frame/controller/quicksettingcontroller.cpp b/frame/controller/quicksettingcontroller.cpp new file mode 100644 index 000000000..2db69d83e --- /dev/null +++ b/frame/controller/quicksettingcontroller.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "quicksettingcontroller.h" +#include "pluginsitem.h" +#include "pluginmanagerinterface.h" + +#include +#include + +QuickSettingController::QuickSettingController(QObject *parent) + : AbstractPluginsController(parent) +{ + qApp->installEventFilter(this); + // 只有在非安全模式下才加载插件,安全模式会在等退出安全模式后通过接受事件的方式来加载插件 + if (!qApp->property("safeMode").toBool()) + QMetaObject::invokeMethod(this, &QuickSettingController::startLoader, Qt::QueuedConnection); +} + +QuickSettingController::~QuickSettingController() +{ +} + +bool QuickSettingController::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == qApp && event->type() == PluginLoadEvent::eventType()) { + // 如果收到的是重新加载插件的消息(一般是在退出安全模式后),则直接加载插件即可 + startLoader(); + } + + return AbstractPluginsController::eventFilter(watched, event); +} + +void QuickSettingController::startLoader() +{ +#ifdef QT_DEBUG + AbstractPluginsController::startLoader(new PluginLoader(QString("%1/..%2").arg(qApp->applicationDirPath()).arg("/plugins/loader"), this)); +#else + AbstractPluginsController::startLoader(new PluginLoader("/usr/lib/dde-dock/plugins/loader", this)); +#endif +} + +void QuickSettingController::itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) +{ + // 根据读取到的metaData数据获取当前插件的类型,提供给外部 + PluginAttribute pluginAttr = pluginAttribute(itemInter); + m_quickPlugins[pluginAttr] << itemInter; + + emit pluginInserted(itemInter, pluginAttr); +} + +void QuickSettingController::itemUpdate(PluginsItemInterface * const itemInter, const QString &) +{ + updateDockInfo(itemInter, DockPart::QuickPanel); + updateDockInfo(itemInter, DockPart::QuickShow); + updateDockInfo(itemInter, DockPart::SystemPanel); +} + +void QuickSettingController::itemRemoved(PluginsItemInterface * const itemInter, const QString &) +{ + for (auto it = m_quickPlugins.begin(); it != m_quickPlugins.end(); it++) { + QList &plugins = m_quickPlugins[it.key()]; + if (!plugins.contains(itemInter)) + continue; + + plugins.removeOne(itemInter); + if (plugins.isEmpty()) { + QuickSettingController::PluginAttribute pluginclass = it.key(); + m_quickPlugins.remove(pluginclass); + } + + break; + } + + Q_EMIT pluginRemoved(itemInter); +} + +void QuickSettingController::requestSetAppletVisible(PluginsItemInterface * const itemInter, const QString &itemKey, const bool visible) +{ + // 设置插件列表可见事件 + Q_EMIT requestAppletVisible(itemInter, itemKey, visible); +} + +void QuickSettingController::updateDockInfo(PluginsItemInterface * const itemInter, const DockPart &part) +{ + Q_EMIT pluginUpdated(itemInter, part); +} + +QuickSettingController::PluginAttribute QuickSettingController::pluginAttribute(PluginsItemInterface * const itemInter) const +{ + // 工具插件,例如回收站 + if (itemInter->flags() & PluginFlag::Type_Tool) + return PluginAttribute::Tool; + + // 系统插件,例如关机按钮 + if (itemInter->flags() & PluginFlag::Type_System) + return PluginAttribute::System; + + // 托盘插件,例如磁盘图标 + if (itemInter->flags() & PluginFlag::Type_Tray) + return PluginAttribute::Tray; + + // 固定插件,例如显示桌面和多任务试图 + if (itemInter->flags() & PluginFlag::Type_Fixed) + return PluginAttribute::Fixed; + + // 通用插件,一般的插件都是通用插件,就是放在快捷插件区域的那些插件 + if (itemInter->flags() & PluginFlag::Type_Common) + return PluginAttribute::Quick; + + // 基本插件,不在任务栏上显示的插件 + return PluginAttribute::None; +} + +QString QuickSettingController::itemKey(PluginsItemInterface *pluginItem) const +{ + PluginManagerInterface *pManager = pluginManager(); + if (pManager) + return pManager->itemKey(pluginItem); + + return QString(); +} + +QuickSettingController *QuickSettingController::instance() +{ + static QuickSettingController instance; + return &instance; +} + +QList QuickSettingController::pluginItems(const PluginAttribute &pluginClass) const +{ + return m_quickPlugins.value(pluginClass); +} + +QJsonObject QuickSettingController::metaData(PluginsItemInterface *pluginItem) +{ + PluginManagerInterface *pManager = pluginManager(); + if (pManager) + return pManager->metaData(pluginItem); + + return QJsonObject(); +} + +PluginsItem *QuickSettingController::pluginItemWidget(PluginsItemInterface *pluginItem) +{ + if (m_pluginItemWidgetMap.contains(pluginItem)) + return m_pluginItemWidgetMap[pluginItem]; + + PluginsItem *widget = new PluginsItem(pluginItem, itemKey(pluginItem), metaData(pluginItem)); + m_pluginItemWidgetMap[pluginItem] = widget; + return widget; +} + +QList QuickSettingController::pluginInSettings() +{ + PluginManagerInterface *pManager = pluginManager(); + if (!pManager) + return QList(); + + // 返回可用于在控制中心显示的插件 + return pManager->pluginsInSetting(); +} diff --git a/frame/controller/quicksettingcontroller.h b/frame/controller/quicksettingcontroller.h new file mode 100644 index 000000000..9aa1a5b78 --- /dev/null +++ b/frame/controller/quicksettingcontroller.h @@ -0,0 +1,64 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef QUICKSETTINGCONTROLLER_H +#define QUICKSETTINGCONTROLLER_H + +#include "abstractpluginscontroller.h" +#include "pluginsiteminterface.h" + +class QuickSettingItem; +class PluginsItem; + +class QuickSettingController : public AbstractPluginsController +{ + Q_OBJECT + +public: + enum class PluginAttribute { + None = 0, // 不在任何区域显示的插件 + Quick, // 快捷区域插件 + Tool, // 工具插件(回收站和窗管开发的另一套插件) + System, // 系统插件(关机插件) + Tray, // 托盘插件(U盘图标等) + Fixed // 固定区域插件(显示桌面和多任务视图) + }; + +public: + static QuickSettingController *instance(); + QList pluginItems(const PluginAttribute &pluginClass) const; + QJsonObject metaData(PluginsItemInterface *pluginItem); + PluginsItem *pluginItemWidget(PluginsItemInterface *pluginItem); + QList pluginInSettings(); + PluginAttribute pluginAttribute(PluginsItemInterface * const itemInter) const; + QString itemKey(PluginsItemInterface *pluginItem) const; + +Q_SIGNALS: + void pluginInserted(PluginsItemInterface *itemInter, const PluginAttribute); + void pluginRemoved(PluginsItemInterface *itemInter); + void pluginUpdated(PluginsItemInterface *, const DockPart); + void requestAppletVisible(PluginsItemInterface * itemInter, const QString &itemKey, bool visible); + +protected: + explicit QuickSettingController(QObject *parent = Q_NULLPTR); + ~QuickSettingController() override; + bool eventFilter(QObject *watched, QEvent *event) override; + + void startLoader(); + +protected: + void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override; + void itemUpdate(PluginsItemInterface * const itemInter, const QString &) override; + void itemRemoved(PluginsItemInterface * const itemInter, const QString &) override; + void requestSetAppletVisible(PluginsItemInterface * const itemInter, const QString &itemKey, const bool visible) override; + + void updateDockInfo(PluginsItemInterface * const itemInter, const DockPart &part) override; + +private: + QMap> m_quickPlugins; + QMap m_pluginItemWidgetMap; +}; + +#endif // CONTAINERPLUGINSCONTROLLER_H diff --git a/frame/controller/recentapphelper.cpp b/frame/controller/recentapphelper.cpp new file mode 100644 index 000000000..b1bf51f93 --- /dev/null +++ b/frame/controller/recentapphelper.cpp @@ -0,0 +1,234 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "recentapphelper.h" +#include "appitem.h" + +#include + +#define ENTRY_NONE 0 +#define ENTRY_NORMAL 1 +#define ENTRY_RECENT 2 + +RecentAppHelper::RecentAppHelper(QWidget *appWidget, QWidget *recentWidget, DockInter *dockInter, QObject *parent) + : QObject(parent) + , m_appWidget(appWidget) + , m_recentWidget(recentWidget) + , m_dockInter(dockInter) +{ + m_appWidget->installEventFilter(this); + m_recentWidget->installEventFilter(this); +} + +void RecentAppHelper::setDisplayMode(Dock::DisplayMode displayMode) +{ + bool lastVisible = dockAppIsVisible(); + m_displayMode = displayMode; + updateRecentVisible(); + updateDockAppVisible(lastVisible); +} + +// 当在应用区域调整位置的时候,需要重新设置索引 +void RecentAppHelper::resetAppInfo() +{ + +} + +void RecentAppHelper::addAppItem(int index, DockItem *dockItem) +{ + if (appInRecent(dockItem)) { + addRecentAreaItem(index, dockItem); + updateRecentVisible(); + } else { + bool lastVisible = dockAppIsVisible(); + addAppAreaItem(index, dockItem); + updateDockAppVisible(lastVisible); + } + + AppItem *appItem = qobject_cast(dockItem); + + connect(appItem, &AppItem::modeChanged, this, &RecentAppHelper::onModeChanged); +} + +void RecentAppHelper::removeAppItem(DockItem *dockItem) +{ + if (m_recentWidget->children().contains(dockItem)) + removeRecentAreaItem(dockItem); + else + removeAppAreaItem(dockItem); +} + +bool RecentAppHelper::recentIsVisible() const +{ + return m_recentWidget->isVisible(); +} + +bool RecentAppHelper::dockAppIsVisible() const +{ + return (m_displayMode == Dock::DisplayMode::Efficient + || m_appWidget->layout()->count() > 0); +} + +void RecentAppHelper::updateDockInter(DockInter *dockInter) +{ + m_dockInter = dockInter; +} + +bool RecentAppHelper::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_appWidget || watched == m_recentWidget) { + switch(event->type()) { + case QEvent::ChildAdded: + case QEvent::ChildRemoved: { + QMetaObject::invokeMethod(this, [ this ] { + /* 这里用异步的方式,因为收到QEvent::ChildAdded信号的时候, + 此时应用还没有插入到Widget中,收到QEvent::ChildRemoved信号的时候, + 此时应用还未从任务栏上移除,通过异步的方式保证同步新增或移除成功后才执行,这样更新的界面才是最准确的 + */ + Q_EMIT requestUpdate(); + }, Qt::QueuedConnection); + } + break; + default: + break; + } + } + + return QObject::eventFilter(watched, event); +} + +void RecentAppHelper::onModeChanged(int mode) +{ + AppItem *appItem = qobject_cast(sender()); + if (!appItem) + return; + + auto moveItemToWidget = [ = ](QWidget *widget) { + int index = getEntryIndex(appItem, widget); + removeAppItem(appItem); + QBoxLayout *layout = static_cast(widget->layout()); + layout->insertWidget(index, appItem); + }; + + if (mode == ENTRY_NORMAL) { + // 添加到应用区域 + moveItemToWidget(m_appWidget); + } else if (mode == ENTRY_RECENT) { + // 添加到最近打开应用区域 + moveItemToWidget(m_recentWidget); + } + updateRecentVisible(); +} + +bool RecentAppHelper::appInRecent(DockItem *item) const +{ + AppItem *appItem = qobject_cast(item); + if (!appItem) + return false; + + return (appItem->mode() == ENTRY_RECENT); +} + +void RecentAppHelper::addAppAreaItem(int index, DockItem *wdg) +{ + QBoxLayout *boxLayout = static_cast(m_appWidget->layout()); + boxLayout->insertWidget(index, wdg); +} + +void RecentAppHelper::addRecentAreaItem(int index, DockItem *wdg) +{ + QBoxLayout *recentLayout = static_cast(m_recentWidget->layout()); + recentLayout->insertWidget(index, wdg); +} + +void RecentAppHelper::updateRecentVisible() +{ + bool lastRecentVisible = m_recentWidget->isVisible(); + bool recentVisible = lastRecentVisible; + + if (m_displayMode == Dock::DisplayMode::Efficient) { + // 如果是高效模式,不显示最近打开应用区域 + m_recentWidget->setVisible(false); + recentVisible = false; + } else { + QBoxLayout *recentLayout = static_cast(m_recentWidget->layout()); + qInfo() << "recent Widget count:" << recentLayout->count() << ", app Widget count" << m_appWidget->layout()->count(); + // 如果是时尚模式,则判断当前打开应用数量是否为0,为0则不显示,否则显示 + recentVisible = (recentLayout->count() > 0); + m_recentWidget->setVisible(recentVisible); + } + + if (lastRecentVisible != recentVisible) + Q_EMIT recentVisibleChanged(recentVisible); +} + +void RecentAppHelper::updateDockAppVisible(bool lastVisible) +{ + bool visible = dockAppIsVisible(); + if (lastVisible != visible) + Q_EMIT dockAppVisibleChanged(visible); +} + +void RecentAppHelper::removeRecentAreaItem(DockItem *wdg) +{ + QBoxLayout *recentLayout = static_cast(m_recentWidget->layout()); + recentLayout->removeWidget(wdg); + updateRecentVisible(); +} + +void RecentAppHelper::removeAppAreaItem(DockItem *wdg) +{ + QBoxLayout *boxLayout = static_cast(m_appWidget->layout()); + bool lastVisible = dockAppIsVisible(); + boxLayout->removeWidget(wdg); + updateDockAppVisible(lastVisible); +} + +int RecentAppHelper::getEntryIndex(DockItem *dockItem, QWidget *widget) const +{ + AppItem *appItem = qobject_cast(dockItem); + if (!appItem) + return -1; + + // 查找当前的应用在所有的应用中的排序 + QStringList entryIds = m_dockInter->GetEntryIDs(); + int index = entryIds.indexOf(appItem->appId()); + if (index < 0) + return -1; + + QList filterAppItems = appItems(widget); + // 获取当前在最近应用中的所有的APP,并计算它的位置 + int lastIndex = -1; + // 从后面向前面遍历,找到对应的位置,插入 + for (int i = filterAppItems.size() - 1; i >= 0; i--) { + AppItem *item = filterAppItems[i]; + // 如果所在的索引在要查找的APP索引的后面,说明当前的索引在要查找的索引之后,跳过即可 + // 如果所在索引不在列表中(一般情况下不存在,这里是容错处理),也跳过 + int curIndex = entryIds.indexOf(item->appId()); + if (item == appItem || curIndex < 0 || curIndex >= index) + continue; + + if (lastIndex < curIndex) + lastIndex = curIndex; + } + + return ++lastIndex; +} + +QList RecentAppHelper::appItems(QWidget *widget) const +{ + QLayout *layout = widget->layout(); + + QList dockItems; + for (int i = 0; i < layout->count(); i++) { + AppItem *dockItem = qobject_cast(layout->itemAt(i)->widget()); + if (!dockItem) + continue; + + dockItems << dockItem; + } + + return dockItems; +} diff --git a/frame/controller/recentapphelper.h b/frame/controller/recentapphelper.h new file mode 100644 index 000000000..9e11413c4 --- /dev/null +++ b/frame/controller/recentapphelper.h @@ -0,0 +1,68 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef RECENTAPPHELPER_H +#define RECENTAPPHELPER_H + +#include "constants.h" +#include "dbusutil.h" + +#include + +class DockItem; +class AppItem; +class QWidget; + +/** 用来管理最近打开区域和APP应用区域交互的类 + * @brief The RecentAppManager class + */ + +class RecentAppHelper : public QObject +{ + Q_OBJECT + +public: + explicit RecentAppHelper(QWidget *appWidget, QWidget *recentWidget, DockInter *dockInter, QObject *parent = nullptr); + void setDisplayMode(Dock::DisplayMode displayMode); + void resetAppInfo(); + void addAppItem(int index, DockItem *appItem); + void removeAppItem(DockItem *dockItem); + bool recentIsVisible() const; + bool dockAppIsVisible() const; + void updateDockInter(DockInter *dockInter); + +Q_SIGNALS: + void requestUpdate(); + void recentVisibleChanged(bool); // 最近区域是否可见发生变化的信号 + void dockAppVisibleChanged(bool); // 驻留应用区域是否可见发生变化的信号 + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + bool appInRecent(DockItem *item) const; + void addAppAreaItem(int index, DockItem *wdg); + void addRecentAreaItem(int index, DockItem *wdg); + void updateRecentVisible(); + void updateDockAppVisible(bool lastVisible); + + void removeRecentAreaItem(DockItem *wdg); + void removeAppAreaItem(DockItem *wdg); + + int getEntryIndex(DockItem *dockItem, QWidget *widget) const; + + QList appItems(QWidget *widget) const; + +private Q_SLOTS: + void onModeChanged(int mode); + +private: + QWidget *m_appWidget; + QWidget *m_recentWidget; + Dock::DisplayMode m_displayMode; + DockInter *m_dockInter; +}; + +#endif // RECENTAPPHELPER_H diff --git a/frame/controller/toolapphelper.cpp b/frame/controller/toolapphelper.cpp new file mode 100644 index 000000000..f3ab387f1 --- /dev/null +++ b/frame/controller/toolapphelper.cpp @@ -0,0 +1,203 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "toolapphelper.h" +#include "dockitem.h" +#include "pluginsitem.h" +#include "quicksettingcontroller.h" + +#include +#include + +ToolAppHelper::ToolAppHelper(QWidget *toolAreaWidget, QObject *parent) + : QObject(parent) + , m_toolAreaWidget(toolAreaWidget) + , m_displayMode(DisplayMode::Efficient) + , m_position(Dock::Position::Bottom) +{ + connect(QuickSettingController::instance(), &QuickSettingController::pluginInserted, this, [ = ](PluginsItemInterface *itemInter, const QuickSettingController::PluginAttribute pluginAttr) { + if (pluginAttr != QuickSettingController::PluginAttribute::Tool) + return; + + pluginItemAdded(itemInter); + }); + connect(QuickSettingController::instance(), &QuickSettingController::pluginRemoved, this, [ = ](PluginsItemInterface *itemInter) { + pluginItemRemoved(itemInter); + }); + + QList pluginItems = QuickSettingController::instance()->pluginItems(QuickSettingController::PluginAttribute::Tool); + for (PluginsItemInterface *pluginItem : pluginItems) + pluginItemAdded(pluginItem); + + updateToolArea(); +} + +void ToolAppHelper::setDisplayMode(DisplayMode displayMode) +{ + m_displayMode = displayMode; + moveToolWidget(); + updateWidgetStatus(); +} + +void ToolAppHelper::setPosition(Position position) +{ + m_toolAreaWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + m_position = position; +} + +bool ToolAppHelper::toolIsVisible() const +{ + return m_toolAreaWidget->isVisible(); +} + +void ToolAppHelper::appendToToolArea(int index, DockItem *dockItem) +{ + dockItem->setParent(m_toolAreaWidget); + QBoxLayout *boxLayout = static_cast(m_toolAreaWidget->layout()); + if (index >= 0) + boxLayout->insertWidget(index, dockItem); + else + boxLayout->addWidget(dockItem); + + Q_EMIT requestUpdate(); +} + +bool ToolAppHelper::removeToolArea(PluginsItemInterface *itemInter) +{ + QBoxLayout *boxLayout = static_cast(m_toolAreaWidget->layout()); + for (int i = 0; i < boxLayout->count(); i++) { + PluginsItem *dockItem = qobject_cast(boxLayout->itemAt(i)->widget()); + if (dockItem && dockItem->pluginItem() == itemInter) { + boxLayout->removeWidget(dockItem); + return true; + } + } + + return false; +} + +void ToolAppHelper::moveToolWidget() +{ + for (int i = m_toolAreaWidget->layout()->count() - 1; i >= 0; i--) { + QLayoutItem *layoutItem = m_toolAreaWidget->layout()->itemAt(i); + if (!layoutItem) + continue; + + PluginsItem *pluginWidget = qobject_cast(layoutItem->widget()); + if (!pluginWidget) + continue; + + m_toolAreaWidget->layout()->removeWidget(pluginWidget); + } + + if (m_displayMode == Dock::DisplayMode::Fashion) { + QuickSettingController *quickController = QuickSettingController::instance(); + QList plugins = quickController->pluginItems(QuickSettingController::PluginAttribute::Tool); + for (PluginsItemInterface *plugin : plugins) { + PluginsItem *pluginWidget = quickController->pluginItemWidget(plugin); + m_toolAreaWidget->layout()->addWidget(pluginWidget); + } + } +} + +void ToolAppHelper::updateToolArea() +{ + bool oldVisible = m_toolAreaWidget->isVisible(); + QLayout *layout = m_toolAreaWidget->layout(); + if (m_position == Dock::Position::Bottom || m_position == Dock::Position::Top) { + int size = 0; + for (int i = 0; i < layout->count(); i++) { + PluginsItem *dockItem = qobject_cast(layout->itemAt(i)->widget()); + if (!dockItem) + continue; + + size += dockItem->width(); + } + m_toolAreaWidget->setFixedWidth(size); + m_toolAreaWidget->setVisible(size > 0); + } else { + int size = 0; + for (int i = 0; i < layout->count(); i++) { + PluginsItem *dockItem = qobject_cast(layout->itemAt(i)->widget()); + if (!dockItem) + continue; + + size += dockItem->height(); + } + m_toolAreaWidget->setFixedHeight(size); + m_toolAreaWidget->setVisible(size > 0); + } + bool isVisible = m_toolAreaWidget->isVisible(); + if (oldVisible != isVisible) + Q_EMIT toolVisibleChanged(isVisible); +} + +void ToolAppHelper::updateWidgetStatus() +{ + bool oldVisible = toolIsVisible(); + if (m_displayMode == DisplayMode::Efficient) { + // 高效模式 + m_toolAreaWidget->setVisible(false); + } else { + // 时尚模式 + m_toolAreaWidget->setVisible(m_toolAreaWidget->layout()->count() > 0); + } + bool visible = toolIsVisible(); + if (oldVisible != visible) + Q_EMIT toolVisibleChanged(visible); +} + +bool ToolAppHelper::pluginInTool(PluginsItemInterface *itemInter) const +{ + return (QuickSettingController::instance()->pluginAttribute(itemInter) == QuickSettingController::PluginAttribute::Tool); +} + +void ToolAppHelper::pluginItemAdded(PluginsItemInterface *itemInter) +{ + if (m_displayMode != Dock::DisplayMode::Fashion || pluginExists(itemInter)) + return; + + QuickSettingController *quickController = QuickSettingController::instance(); + if (pluginInTool(itemInter)) { + PluginsItem *pluginItem = quickController->pluginItemWidget(itemInter); + appendToToolArea(0, pluginItem); + updateToolArea(); + Q_EMIT requestUpdate(); + } +} + +void ToolAppHelper::pluginItemRemoved(PluginsItemInterface *itemInter) +{ + QuickSettingController *quickController = QuickSettingController::instance(); + if (pluginInTool(itemInter)) { + PluginsItem *pluginItem = quickController->pluginItemWidget(itemInter); + removeToolArea(pluginItem->pluginItem()); + updateToolArea(); + Q_EMIT requestUpdate(); + } +} + +bool ToolAppHelper::pluginExists(PluginsItemInterface *itemInter) const +{ + QBoxLayout *boxLayout = static_cast(m_toolAreaWidget->layout()); + if (!boxLayout) + return false; + + for (int i = 0; i < boxLayout->count() ; i++) { + QLayoutItem *layoutItem = boxLayout->itemAt(i); + if (!layoutItem) + continue; + + PluginsItem *pluginItem = qobject_cast(layoutItem->widget()); + if (!pluginItem) + continue; + + // 如果当前的插件的接口已经存在,则无需再次插入 + if (pluginItem->pluginItem() == itemInter) + return true; + } + + return false; +} diff --git a/frame/controller/toolapphelper.h b/frame/controller/toolapphelper.h new file mode 100644 index 000000000..0b6aa185a --- /dev/null +++ b/frame/controller/toolapphelper.h @@ -0,0 +1,54 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TOOLAPPHELPER_H +#define TOOLAPPHELPER_H + +#include "constants.h" + +#include + +class QWidget; +class DockItem; +class PluginsItem; +class PluginsItemInterface; + +using namespace Dock; + +class ToolAppHelper : public QObject +{ + Q_OBJECT + +public: + explicit ToolAppHelper(QWidget *toolAreaWidget, QObject *parent = nullptr); + + void setDisplayMode(DisplayMode displayMode); + void setPosition(Dock::Position position); + bool toolIsVisible() const; + +Q_SIGNALS: + void requestUpdate(); + void toolVisibleChanged(bool); + +private: + void appendToToolArea(int index, DockItem *dockItem); + bool removeToolArea(PluginsItemInterface *itemInter); + void moveToolWidget(); + void updateToolArea(); + + void updateWidgetStatus(); + bool pluginInTool(PluginsItemInterface *itemInter) const; + void pluginItemAdded(PluginsItemInterface *itemInter); + void pluginItemRemoved(PluginsItemInterface *itemInter); + bool pluginExists(PluginsItemInterface *itemInter) const; + +private: + QWidget *m_toolAreaWidget; + DisplayMode m_displayMode; + Dock::Position m_position; + QList m_sequentPluginItems; +}; + +#endif // TOOLAPPHELPER_H diff --git a/frame/dbus/dbusclientmanager.cpp b/frame/dbus/dbusclientmanager.cpp deleted file mode 100644 index ead7b6905..000000000 --- a/frame/dbus/dbusclientmanager.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusClientManager -p dbusclientmanager dde-dock-ClientManager.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "dbusclientmanager.h" - -/* - * Implementation of interface class DBusClientManager - */ - -DBusClientManager::DBusClientManager(QObject *parent) - : QDBusAbstractInterface("com.deepin.daemon.Dock", "/dde/dock/ClientManager", staticInterfaceName(), QDBusConnection::sessionBus(), parent) -{ - QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); -} - -DBusClientManager::~DBusClientManager() -{ - QDBusConnection::sessionBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); -} - diff --git a/frame/dbus/dbusclientmanager.h b/frame/dbus/dbusclientmanager.h deleted file mode 100644 index 4ccf9b2a0..000000000 --- a/frame/dbus/dbusclientmanager.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusClientManager -p dbusclientmanager dde-dock-ClientManager.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ - -#ifndef DBUSCLIENTMANAGER_H_1465195317 -#define DBUSCLIENTMANAGER_H_1465195317 - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Proxy class for interface dde.dock.ClientManager - */ -class DBusClientManager: public QDBusAbstractInterface -{ - Q_OBJECT - - Q_SLOT void __propertyChanged__(const QDBusMessage& msg) - { - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="dde.dock.ClientManager") - return; - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - foreach(const QString &prop, changedProps.keys()) { - const QMetaObject* self = metaObject(); - for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { - QMetaProperty p = self->property(i); - if (p.name() == prop) { - Q_EMIT p.notifySignal().invoke(this); - } - } - } - } -public: - static inline const char *staticInterfaceName() - { return "dde.dock.ClientManager"; } - -public: - explicit DBusClientManager(QObject *parent = 0); - - ~DBusClientManager(); - -public Q_SLOTS: // METHODS - inline QDBusPendingReply ActivateWindow(uint in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("ActivateWindow"), argumentList); - } - - inline QDBusPendingReply CloseWindow(uint in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("CloseWindow"), argumentList); - } - - inline QDBusPendingReply CurrentActiveWindow() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("CurrentActiveWindow"), argumentList); - } - -Q_SIGNALS: // SIGNALS - void ActiveWindowChanged(uint activeWinId); -// begin property changed signals -}; - -namespace dde { - namespace dock { - typedef ::DBusClientManager ClientManager; - } -} -#endif diff --git a/frame/dbus/dbusdisplay.cpp b/frame/dbus/dbusdisplay.cpp index 4ab7f5aa4..9cb7adf5d 100644 --- a/frame/dbus/dbusdisplay.cpp +++ b/frame/dbus/dbusdisplay.cpp @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p DBusDisplay -c DBusDisplay com.deepin.daemon.Display.xml + * Command line was: qdbusxml2cpp -p DBusDisplay -c DBusDisplay org.deepin.dde.Display1.xml * * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). * diff --git a/frame/dbus/dbusdisplay.h b/frame/dbus/dbusdisplay.h index ced30d75d..e99cdabab 100644 --- a/frame/dbus/dbusdisplay.h +++ b/frame/dbus/dbusdisplay.h @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p DBusDisplay -c DBusDisplay com.deepin.daemon.Display.xml + * Command line was: qdbusxml2cpp -p DBusDisplay -c DBusDisplay org.deepin.dde.Display1.xml * * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). * @@ -44,7 +44,7 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, DisplayRect &rect QDebug operator<<(QDebug deg, const DisplayRect &rect); /* - * Proxy class for interface com.deepin.daemon.Display + * Proxy class for interface org.deepin.dde.Display1 */ class DBusDisplay: public QDBusAbstractInterface { @@ -56,7 +56,7 @@ class DBusDisplay: public QDBusAbstractInterface if (3 != arguments.count()) return; QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.daemon.Display") + if (interfaceName !="org.deepin.dde.Display1") return; QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); QStringList keys = changedProps.keys(); @@ -72,11 +72,11 @@ class DBusDisplay: public QDBusAbstractInterface } public: static inline const char *staticInterfaceName() - { return "com.deepin.daemon.Display"; } + { return "org.deepin.dde.Display1"; } static inline const char *staticServiceName() - { return "com.deepin.daemon.Display"; } + { return "org.deepin.dde.Display1"; } static inline const char *staticObjectPath() - { return "/com/deepin/daemon/Display"; } + { return "/org/deepin/dde/Display1"; } public: explicit DBusDisplay(QObject *parent = 0); diff --git a/frame/dbus/dbusdockadaptors.cpp b/frame/dbus/dbusdockadaptors.cpp index abce11017..fda09b05d 100644 --- a/frame/dbus/dbusdockadaptors.cpp +++ b/frame/dbus/dbusdockadaptors.cpp @@ -1,31 +1,81 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later +/* + * Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * 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 + * 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 . + */ #include "dbusdockadaptors.h" #include "utils.h" #include "dockitemmanager.h" +#include "windowmanager.h" +#include "quicksettingcontroller.h" +#include "pluginsitem.h" +#include "settingconfig.h" +#include "customevent.h" + +#include #include #include #include +#include -DBusDockAdaptors::DBusDockAdaptors(MainWindow* parent) +const QSize defaultIconSize = QSize(20, 20); + +QDebug operator<<(QDebug argument, const DockItemInfo &info) +{ + argument << "name:" << info.name << ", displayName:" << info.displayName + << "itemKey:" << info.itemKey << "SettingKey:" << info.settingKey + << "icon_light:" << info.iconLight << "icon_dark:" << info.iconDark << "visible:" << info.visible; + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &arg, const DockItemInfo &info) +{ + arg.beginStructure(); + arg << info.name << info.displayName << info.itemKey << info.settingKey << info.iconLight << info.iconDark << info.visible; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, DockItemInfo &info) +{ + arg.beginStructure(); + arg >> info.name >> info.displayName >> info.itemKey >> info.settingKey >> info.iconLight >> info.iconDark >> info.visible; + arg.endStructure(); + return arg; +} + +void registerPluginInfoMetaType() +{ + qRegisterMetaType("DockItemInfo"); + qDBusRegisterMetaType(); + qRegisterMetaType("DockItemInfos"); + qDBusRegisterMetaType(); +} + +DBusDockAdaptors::DBusDockAdaptors(WindowManager* parent) : QDBusAbstractAdaptor(parent) , m_gsettings(Utils::SettingsPtr("com.deepin.dde.dock.mainwindow", QByteArray(), this)) + , m_windowManager(parent) { - connect(parent, &MainWindow::panelGeometryChanged, this, [=] { + connect(parent, &WindowManager::panelGeometryChanged, this, [ = ] { emit DBusDockAdaptors::geometryChanged(geometry()); - - // 手动触发PropertiesChanged信号,可能是qt不支持属性自动触发 - QDBusMessage msg = QDBusMessage::createSignal("/com/deepin/dde/Dock", "org.freedesktop.DBus.Properties", "PropertiesChanged"); - QList arguments; - arguments.push_back("com.deepin.dde.Dock"); - QVariantMap changedProps; - changedProps.insert("geometry", geometry()); - arguments.push_back(changedProps); - msg.setArguments(arguments); - QDBusConnection::connectToBus(QDBusConnection::SessionBus, "com.deepin.dde.Dock").send(msg); }); if (m_gsettings) { @@ -36,12 +86,13 @@ DBusDockAdaptors::DBusDockAdaptors(MainWindow* parent) }); } + QList allPlugin = localPlugins(); connect(DockItemManager::instance(), &DockItemManager::itemInserted, this, [ = ] (const int index, DockItem *item) { Q_UNUSED(index); if (item->itemType() == DockItem::Plugins || item->itemType() == DockItem::FixedPlugin) { PluginsItem *pluginItem = static_cast(item); - for (auto *p : DockItemManager::instance()->pluginList()) { + for (auto *p : allPlugin) { if (p->pluginName() == pluginItem->pluginName()) { Q_EMIT pluginVisibleChanged(p->pluginDisplayName(), getPluginVisible(p->pluginDisplayName())); } @@ -53,13 +104,15 @@ DBusDockAdaptors::DBusDockAdaptors(MainWindow* parent) if (item->itemType() == DockItem::Plugins || item->itemType() == DockItem::FixedPlugin) { PluginsItem *pluginItem = static_cast(item); - for (auto *p : DockItemManager::instance()->pluginList()) { + for (auto *p : allPlugin) { if (p->pluginName() == pluginItem->pluginName()) { Q_EMIT pluginVisibleChanged(p->pluginDisplayName(), getPluginVisible(p->pluginDisplayName())); } } } }); + + registerPluginInfoMetaType(); } DBusDockAdaptors::~DBusDockAdaptors() @@ -67,27 +120,31 @@ DBusDockAdaptors::~DBusDockAdaptors() } -MainWindow *DBusDockAdaptors::parent() const -{ - return static_cast(QObject::parent()); -} - void DBusDockAdaptors::callShow() { - return parent()->callShow(); + m_windowManager->callShow(); } void DBusDockAdaptors::ReloadPlugins() { - return parent()->relaodPlugins(); + if (qApp->property("PLUGINSLOADED").toBool()) + return; + + // 发送事件,通知代理来加载插件 + PluginLoadEvent event; + QCoreApplication::sendEvent(qApp, &event); + + qApp->setProperty("PLUGINSLOADED", true); + // 退出安全模式 + qApp->setProperty("safeMode", false); } QStringList DBusDockAdaptors::GetLoadedPlugins() { - auto pluginList = DockItemManager::instance()->pluginList(); + QList allPlugin = localPlugins(); QStringList nameList; QMap map; - for (auto plugin : pluginList) { + for (auto plugin : allPlugin) { // 托盘本身也是一个插件,这里去除掉这个特殊的插件,还有一些没有实际名字的插件 if (plugin->pluginName() == "tray" || plugin->pluginDisplayName().isEmpty() @@ -99,7 +156,7 @@ QStringList DBusDockAdaptors::GetLoadedPlugins() } // 排序,保持和原先任务栏右键菜单中的插件列表顺序一致 - qSort(nameList.begin(), nameList.end(), [ = ] (const QString &name1, const QString &name2) { + std::sort(nameList.begin(), nameList.end(), [ = ] (const QString &name1, const QString &name2) { return name1 > name2; }); @@ -111,15 +168,53 @@ QStringList DBusDockAdaptors::GetLoadedPlugins() return newList; } +DockItemInfos DBusDockAdaptors::plugins() +{ +#define DOCK_QUICK_PLUGINS "Dock_Quick_Plugins" + // 获取本地加载的插件 + QList allPlugin = localPlugins(); + DockItemInfos pluginInfos; + QStringList quickSettingKeys = SETTINGCONFIG->value(DOCK_QUICK_PLUGINS).toStringList(); + for (PluginsItemInterface *plugin : allPlugin) { + DockItemInfo info; + info.name = plugin->pluginName(); + info.displayName = plugin->pluginDisplayName(); + info.itemKey = plugin->pluginName(); + info.settingKey = DOCK_QUICK_PLUGINS; + info.visible = quickSettingKeys.contains(info.itemKey); + QSize pixmapSize; + QIcon lightIcon = getSettingIcon(plugin, pixmapSize, DGuiApplicationHelper::ColorType::LightType); + if (!lightIcon.isNull()) { + QBuffer buffer(&info.iconLight); + if (buffer.open(QIODevice::WriteOnly)) { + QPixmap pixmap = lightIcon.pixmap(pixmapSize); + pixmap.save(&buffer, "png"); + } + } + QIcon darkIcon = getSettingIcon(plugin, pixmapSize, DGuiApplicationHelper::ColorType::DarkType); + if (!darkIcon.isNull()) { + QBuffer buffer(&info.iconDark); + if (buffer.open(QIODevice::WriteOnly)) { + QPixmap pixmap = darkIcon.pixmap(pixmapSize); + pixmap.save(&buffer, "png"); + } + } + pluginInfos << info; + } + + return pluginInfos; +} + void DBusDockAdaptors::resizeDock(int offset, bool dragging) { - parent()->resizeDock(offset, dragging); + m_windowManager->resizeDock(offset, dragging); } // 返回每个插件的识别Key(所以此值应始终不变),供个性化插件根据key去匹配每个插件对应的图标 QString DBusDockAdaptors::getPluginKey(const QString &pluginName) { - for (auto plugin : DockItemManager::instance()->pluginList()) { + QList allPlugin = localPlugins(); + for (auto plugin : allPlugin) { if (plugin->pluginDisplayName() == pluginName) return plugin->pluginName(); } @@ -129,7 +224,8 @@ QString DBusDockAdaptors::getPluginKey(const QString &pluginName) bool DBusDockAdaptors::getPluginVisible(const QString &pluginName) { - for (auto *p : DockItemManager::instance()->pluginList()) { + QList allPlugin = localPlugins(); + for (auto *p : allPlugin) { if (!p->pluginIsAllowDisable()) continue; @@ -150,7 +246,8 @@ bool DBusDockAdaptors::getPluginVisible(const QString &pluginName) void DBusDockAdaptors::setPluginVisible(const QString &pluginName, bool visible) { - for (auto *p : DockItemManager::instance()->pluginList()) { + QList allPlugin = localPlugins(); + for (auto *p : allPlugin) { if (!p->pluginIsAllowDisable()) continue; @@ -172,9 +269,20 @@ void DBusDockAdaptors::setPluginVisible(const QString &pluginName, bool visible) qInfo() << "Unable to set information for this plugin"; } +void DBusDockAdaptors::setItemOnDock(const QString settingKey, const QString &itemKey, bool visible) +{ + QStringList settings = SETTINGCONFIG->value(settingKey).toStringList(); + if (visible && !settings.contains(itemKey)) + settings << itemKey; + else if (!visible && settings.contains(itemKey)) + settings.removeOne(itemKey); + + SETTINGCONFIG->setValue(settingKey, settings); +} + QRect DBusDockAdaptors::geometry() const { - return parent()->geometry(); + return m_windowManager->geometry(); } bool DBusDockAdaptors::showInPrimary() const @@ -198,17 +306,67 @@ bool DBusDockAdaptors::isPluginValid(const QString &name) if (!Utils::SettingValue("com.deepin.dde.dock.module." + name, QByteArray(), "enable", true).toBool()) return false; - // 在非wayland环境下,未开启窗口特效时,不显示多任务视图插件 - if (name == "multitasking" && !DWindowManagerHelper::instance()->hasComposite() && !Utils::IS_WAYLAND_DISPLAY) + // 未开启窗口特效时,不显示多任务视图插件 + if (name == "multitasking" && !DWindowManagerHelper::instance()->hasComposite()) return false; // 录屏插件不显示,插件名如果有变化,建议发需求,避免任务栏反复适配 if (name == "deepin-screen-recorder-plugin") return false; - // 远程助手只有在启动时才会加载在任务栏,不需要在控制中心加载 - if (name == "uos-remote-assistance") - return false; - return true; } + +QList DBusDockAdaptors::localPlugins() const +{ + return QuickSettingController::instance()->pluginInSettings(); +} + +QIcon DBusDockAdaptors::getSettingIcon(PluginsItemInterface *plugin, QSize &pixmapSize, DGuiApplicationHelper::ColorType colorType) const +{ + auto iconSize = [](const QIcon &icon) { + QList iconSizes = icon.availableSizes(); + if (iconSizes.size() > 0) + return iconSizes[0]; + + return defaultIconSize; + }; + // 先获取控制中心的设置图标 + QIcon icon = plugin->icon(DockPart::DCCSetting, colorType); + if (!icon.isNull()) { + pixmapSize = iconSize(icon); + return icon; + } + + // 如果插件中没有设置图标,则根据插件的类型,获取其他的图标 + QuickSettingController::PluginAttribute pluginAttr = QuickSettingController::instance()->pluginAttribute(plugin); + switch(pluginAttr) { + case QuickSettingController::PluginAttribute::System: { + icon = plugin->icon(DockPart::SystemPanel, colorType); + pixmapSize = defaultIconSize; + QList iconSizes = icon.availableSizes(); + if (iconSizes.size() > 0) + pixmapSize = iconSizes[0]; + break; + } + case QuickSettingController::PluginAttribute::Quick: { + icon = plugin->icon(DockPart::QuickShow, colorType); + if (icon.isNull()) + icon = plugin->icon(DockPart::QuickPanel, colorType); + pixmapSize = defaultIconSize; + QList iconSizes = icon.availableSizes(); + if (iconSizes.size() > 0) + pixmapSize = iconSizes[0]; + break; + } + default: + break; + } + + if (icon.isNull()) { + icon = QIcon(":/icons/resources/dcc_dock_plug_in.svg"); + pixmapSize = QSize(20, 20); + } + + return icon; +} diff --git a/frame/dbus/dbusdockadaptors.h b/frame/dbus/dbusdockadaptors.h index 04156f658..18f060e39 100644 --- a/frame/dbus/dbusdockadaptors.h +++ b/frame/dbus/dbusdockadaptors.h @@ -1,24 +1,68 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later +/* + * Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * 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 + * 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 . + */ #ifndef DBUSDOCKADAPTORS_H #define DBUSDOCKADAPTORS_H -#include - #include "mainwindow.h" +#include +#include + /* - * Adaptor class for interface com.deepin.dde.Dock + * Adaptor class for interface org.deepin.dde.Dock1 */ class QGSettings; +class WindowManager; +class PluginsItemInterface; + +struct DockItemInfo +{ + QString name; + QString displayName; + QString itemKey; + QString settingKey; + QByteArray iconLight; + QByteArray iconDark; + bool visible; +}; + +QDebug operator<<(QDebug argument, const DockItemInfo &info); +QDBusArgument &operator<<(QDBusArgument &arg, const DockItemInfo &info); +const QDBusArgument &operator>>(const QDBusArgument &arg, DockItemInfo &info); + +Q_DECLARE_METATYPE(DockItemInfo) + +typedef QList DockItemInfos; + +Q_DECLARE_METATYPE(DockItemInfos) + +void registerPluginInfoMetaType(); + class DBusDockAdaptors: public QDBusAbstractAdaptor { Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "com.deepin.dde.Dock") + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Dock1") Q_CLASSINFO("D-Bus Introspection", "" - " \n" + " \n" " \n" " \n" " " @@ -26,6 +70,10 @@ class DBusDockAdaptors: public QDBusAbstractAdaptor " " " " " " + " >" + " " + " \n" + " " " " " " " " @@ -42,6 +90,10 @@ class DBusDockAdaptors: public QDBusAbstractAdaptor " " " " " " + " " + " " + " " + " " " " " " " " @@ -52,16 +104,15 @@ class DBusDockAdaptors: public QDBusAbstractAdaptor Q_PROPERTY(bool showInPrimary READ showInPrimary WRITE setShowInPrimary NOTIFY showInPrimaryChanged) public: - explicit DBusDockAdaptors(MainWindow *parent); + explicit DBusDockAdaptors(WindowManager *parent); virtual ~DBusDockAdaptors(); - MainWindow *parent() const; - public Q_SLOTS: // METHODS void callShow(); void ReloadPlugins(); QStringList GetLoadedPlugins(); + DockItemInfos plugins(); void resizeDock(int offset, bool dragging); @@ -69,6 +120,7 @@ public Q_SLOTS: // METHODS bool getPluginVisible(const QString &pluginName); void setPluginVisible(const QString &pluginName, bool visible); + void setItemOnDock(const QString settingKey, const QString &itemKey, bool visible); public: // PROPERTIES QRect geometry() const; @@ -83,9 +135,12 @@ signals: private: bool isPluginValid(const QString &name); + QList localPlugins() const; + QIcon getSettingIcon(PluginsItemInterface *plugin, QSize &pixmapSize, DGuiApplicationHelper::ColorType colorType) const; private: QGSettings *m_gsettings; + WindowManager *m_windowManager; }; #endif //DBUSDOCKADAPTORS diff --git a/frame/dbus/dbusmenu.cpp b/frame/dbus/dbusmenu.cpp index e02faf34e..a50f7a106 100644 --- a/frame/dbus/dbusmenu.cpp +++ b/frame/dbus/dbusmenu.cpp @@ -1,6 +1,34 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later +/* + * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * 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 + * 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 . + */ + +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c DBusMenu -p dbusmenu com.deepin.menu.Menu.xml + * + * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ #include "dbusmenu.h" diff --git a/frame/dbus/dbusmenu.h b/frame/dbus/dbusmenu.h index 178c004a8..f18acdae5 100644 --- a/frame/dbus/dbusmenu.h +++ b/frame/dbus/dbusmenu.h @@ -1,6 +1,33 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later +/* + * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * 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 + * 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 . + */ + +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c DBusMenu -p dbusmenu com.deepin.menu.Menu.xml + * + * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ #ifndef DBUSMENU_H_1436158836 #define DBUSMENU_H_1436158836 diff --git a/frame/dbus/dbusmenumanager.cpp b/frame/dbus/dbusmenumanager.cpp index 7d52a5aa4..cb5fa1920 100644 --- a/frame/dbus/dbusmenumanager.cpp +++ b/frame/dbus/dbusmenumanager.cpp @@ -1,6 +1,34 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later +/* + * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * 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 + * 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 . + */ + +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c DBusMenuManager -p dbusmenumanager com.deepin.menu.Manager.xml + * + * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ #include "dbusmenumanager.h" diff --git a/frame/dbus/dbusmenumanager.h b/frame/dbus/dbusmenumanager.h index f91380d8a..8e3ca793c 100644 --- a/frame/dbus/dbusmenumanager.h +++ b/frame/dbus/dbusmenumanager.h @@ -1,6 +1,33 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later +/* + * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: sbw + * + * Maintainer: sbw + * + * 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 + * 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 . + */ + +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c DBusMenuManager -p dbusmenumanager com.deepin.menu.Manager.xml + * + * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ #ifndef DBUSMENUMANAGER_H_1436158928 #define DBUSMENUMANAGER_H_1436158928 diff --git a/frame/dbus/dockinterface.cpp b/frame/dbus/dockinterface.cpp new file mode 100644 index 000000000..05f16acd4 --- /dev/null +++ b/frame/dbus/dockinterface.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 + * 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 . + */ + +#include "dockinterface.h" + +#include "org_deepin_dde_daemon_dock1.h" + +// 因为 types/dockrect.h 文件中定义了DockRect类,而在此处也定义了DockRect, +// 所以在此处先加上DOCKRECT_H宏(types/dockrect.h文件中定义的宏)来禁止包含types/dockrect.h头文件 +// 否则会出现重复定义的错误 +#define DOCKRECT_H + +/* + * Implementation of interface class __Dock + */ + +class DockPrivate +{ +public: + DockPrivate() = default; + + // begin member variables + int DisplayMode; + QStringList DockedApps; + QList Entries; + DockRect FrontendWindowRect; + int HideMode; + int HideState; + uint HideTimeout; + uint IconSize; + double Opacity; + int Position; + uint ShowTimeout; + uint WindowSize; + uint WindowSizeEfficient; + uint WindowSizeFashion; + +public: + QMap m_processingCalls; + QMap> m_waittingCalls; +}; + +// 窗管中提供的ActiveWindow接口,MinimizeWindow目前还在开发过程中,因此,关于这两个接口暂时使用v23的后端接口 +// 等窗管完成了这几个接口后,删除此处v20的接口,改成v23提供的新接口即可 +using DockInter = org::deepin::dde::daemon::Dock1; +/** + * @brief 任务栏的部分DBUS接口是通过窗管获取的,由于AM后端并未提供窗管的相关接口,因此, + * 此处先将窗管的接口集成进来,作为私有类,只提供任务栏接口使用 + */ +class WM : public QDBusAbstractInterface +{ +public: + static inline const char *staticInterfaceName() + { return "com.deepin.wm"; } + +public: + explicit WM(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = Q_NULLPTR); + ~WM(); + +public Q_SLOTS: // METHODS + + inline QDBusPendingReply<> ActivateWindow(uint in0) + { + return m_dockInter->ActivateWindow(in0); + } + + QDBusPendingReply<> MinimizeWindow(uint in0) + { + return m_dockInter->MinimizeWindow(in0); + } + + inline QDBusPendingReply<> CancelPreviewWindow() + { + return asyncCallWithArgumentList(QStringLiteral("CancelPreviewWindow"), QList()); + } + + inline QDBusPendingReply<> PreviewWindow(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("CancelPreviewWindow"), argumentList); + } + +private: + DockInter *m_dockInter; +}; + +WM::WM(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) + , m_dockInter(new DockInter("org.deepin.dde.daemon.Dock1", "/org/deepin/dde/daemon/Dock1", QDBusConnection::sessionBus(), this)) +{ +} + +WM::~WM() +{ +} + +Dde_Dock::Dde_Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) + , d_ptr(new DockPrivate) + , m_wm(new WM("com.deepin.wm", "/com/deepin/wm", QDBusConnection::sessionBus(), this)) +{ + QDBusConnection::sessionBus().connect(this->service(), this->path(), + "org.freedesktop.DBus.Properties", + "PropertiesChanged","sa{sv}as", + this, + SLOT(onPropertyChanged(const QDBusMessage &))); + + if (QMetaType::type("DockRect") == QMetaType::UnknownType) + registerDockRectMetaType(); +} + +Dde_Dock::~Dde_Dock() +{ + qDeleteAll(d_ptr->m_processingCalls.values()); + delete d_ptr; +} + +void Dde_Dock::onPropertyChanged(const QDBusMessage& msg) +{ + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName != staticInterfaceName()) + return; + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + QStringList keys = changedProps.keys(); + foreach(const QString &prop, keys) { + const QMetaObject* self = metaObject(); + for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { + QMetaProperty p = self->property(i); + if (p.name() == prop) + Q_EMIT p.notifySignal().invoke(this); + } + } +} + +int Dde_Dock::displayMode() +{ + return qvariant_cast(property("DisplayMode")); +} + +void Dde_Dock::setDisplayMode(int value) +{ + setProperty("DisplayMode", QVariant::fromValue(value)); +} + +QStringList Dde_Dock::dockedApps() +{ + return qvariant_cast(property("DockedApps")); +} + +QList Dde_Dock::entries() +{ + return qvariant_cast>(property("Entries")); +} + +DockRect Dde_Dock::frontendWindowRect() +{ + return qvariant_cast(property("FrontendWindowRect")); +} + +int Dde_Dock::hideMode() +{ + return qvariant_cast(property("HideMode")); +} + +void Dde_Dock::setHideMode(int value) +{ + internalPropSet("HideMode", QVariant::fromValue(value)); +} + +int Dde_Dock::hideState() +{ + return qvariant_cast(property("HideState")); +} + +uint Dde_Dock::hideTimeout() +{ + return qvariant_cast(property("HideTimeout")); +} + +void Dde_Dock::setHideTimeout(uint value) +{ + setProperty("HideTimeout", QVariant::fromValue(value)); +} + +uint Dde_Dock::iconSize() +{ + return qvariant_cast(property("IconSize")); +} + +void Dde_Dock::setIconSize(uint value) +{ + setProperty("IconSize", QVariant::fromValue(value)); +} + +double Dde_Dock::opacity() +{ + return qvariant_cast(property("Opacity")); +} + +void Dde_Dock::setOpacity(double value) +{ + setProperty("Opacity", QVariant::fromValue(value)); +} + +int Dde_Dock::position() +{ + return qvariant_cast(property("Position")); +} + +void Dde_Dock::setPosition(int value) +{ + setProperty("Position", QVariant::fromValue(value)); +} + +uint Dde_Dock::showTimeout() +{ + return qvariant_cast(property("ShowTimeout")); +} + +void Dde_Dock::setShowTimeout(uint value) +{ + setProperty("ShowTimeout", QVariant::fromValue(value)); +} + +uint Dde_Dock::windowSize() +{ + return qvariant_cast(property("WindowSize")); +} + +void Dde_Dock::setWindowSize(uint value) +{ + setProperty("WindowSize", QVariant::fromValue(value)); +} + +uint Dde_Dock::windowSizeEfficient() +{ + return qvariant_cast(property("WindowSizeEfficient")); +} + +void Dde_Dock::setWindowSizeEfficient(uint value) +{ + setProperty("WindowSizeEfficient", QVariant::fromValue(value)); +} + +uint Dde_Dock::windowSizeFashion() +{ + return qvariant_cast(property("WindowSizeFashion")); +} + +void Dde_Dock::setWindowSizeFashion(uint value) +{ + setProperty("WindowSizeFashion", QVariant::fromValue(value)); +} + +bool Dde_Dock::showRecent() const +{ + return qvariant_cast(property("ShowRecent")); +} + +bool Dde_Dock::showMultiWindow() const +{ + return qvariant_cast(property("ShowMultiWindow")); +} + +QDBusPendingReply<> Dde_Dock::ActivateWindow(uint in0) +{ + return m_wm->ActivateWindow(in0); +} + +QDBusPendingReply<> Dde_Dock::PreviewWindow(uint in0) +{ + return m_wm->PreviewWindow(in0); +} + +QDBusPendingReply<> Dde_Dock::CancelPreviewWindow() +{ + return m_wm->CancelPreviewWindow(); +} + +QDBusPendingReply<> Dde_Dock::MinimizeWindow(uint in0) +{ + return m_wm->MinimizeWindow(in0); +} + +void Dde_Dock::CallQueued(const QString &callName, const QList &args) +{ + if (d_ptr->m_waittingCalls.contains(callName)) { + d_ptr->m_waittingCalls[callName] = args; + return; + } + + if (d_ptr->m_processingCalls.contains(callName)) { + d_ptr->m_waittingCalls.insert(callName, args); + } else { + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCallWithArgumentList(callName, args)); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Dde_Dock::onPendingCallFinished); + d_ptr->m_processingCalls.insert(callName, watcher); + } +} + +void Dde_Dock::onPendingCallFinished(QDBusPendingCallWatcher *w) +{ + w->deleteLater(); + const auto callName = d_ptr->m_processingCalls.key(w); + Q_ASSERT(!callName.isEmpty()); + if (callName.isEmpty()) + return; + + d_ptr->m_processingCalls.remove(callName); + if (!d_ptr->m_waittingCalls.contains(callName)) + return; + + const auto args = d_ptr->m_waittingCalls.take(callName); + CallQueued(callName, args); +} \ No newline at end of file diff --git a/frame/dbus/dockinterface.h b/frame/dbus/dockinterface.h new file mode 100644 index 000000000..44530470a --- /dev/null +++ b/frame/dbus/dockinterface.h @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 + * 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 . + */ + +#ifndef DOCK_INTERFACE +#define DOCK_INTERFACE + +#include "types/dockrect.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Proxy class for interface org.deepin.dde.daemon.Dock1 + */ +class DockPrivate; +class WM; + +void registerDockRectMetaType(); + +class Dde_Dock : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + static inline const char *staticInterfaceName() + { return "org.deepin.dde.daemon.Dock1"; } + +public: + explicit Dde_Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~Dde_Dock(); + + Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged) + int displayMode(); + void setDisplayMode(int value); + + Q_PROPERTY(QStringList DockedApps READ dockedApps NOTIFY DockedAppsChanged) + QStringList dockedApps(); + + Q_PROPERTY(QList Entries READ entries NOTIFY EntriesChanged) + QList entries(); + + Q_PROPERTY(DockRect FrontendWindowRect READ frontendWindowRect NOTIFY FrontendWindowRectChanged) + DockRect frontendWindowRect(); + + Q_PROPERTY(int HideMode READ hideMode WRITE setHideMode NOTIFY HideModeChanged) + int hideMode(); + void setHideMode(int value); + + Q_PROPERTY(int HideState READ hideState NOTIFY HideStateChanged) + int hideState(); + + Q_PROPERTY(uint HideTimeout READ hideTimeout WRITE setHideTimeout NOTIFY HideTimeoutChanged) + uint hideTimeout(); + void setHideTimeout(uint value); + + Q_PROPERTY(uint IconSize READ iconSize WRITE setIconSize NOTIFY IconSizeChanged) + uint iconSize(); + void setIconSize(uint value); + + Q_PROPERTY(double Opacity READ opacity WRITE setOpacity NOTIFY OpacityChanged) + double opacity(); + void setOpacity(double value); + + Q_PROPERTY(int Position READ position WRITE setPosition NOTIFY PositionChanged) + int position(); + void setPosition(int value); + + Q_PROPERTY(uint ShowTimeout READ showTimeout WRITE setShowTimeout NOTIFY ShowTimeoutChanged) + uint showTimeout(); + void setShowTimeout(uint value); + + Q_PROPERTY(uint WindowSize READ windowSize WRITE setWindowSize NOTIFY WindowSizeChanged) + uint windowSize(); + void setWindowSize(uint value); + + Q_PROPERTY(uint WindowSizeEfficient READ windowSizeEfficient WRITE setWindowSizeEfficient NOTIFY WindowSizeEfficientChanged) + uint windowSizeEfficient(); + void setWindowSizeEfficient(uint value); + + Q_PROPERTY(uint WindowSizeFashion READ windowSizeFashion WRITE setWindowSizeFashion NOTIFY WindowSizeFashionChanged) + uint windowSizeFashion(); + void setWindowSizeFashion(uint value); + + Q_PROPERTY(bool ShowRecent READ showRecent NOTIFY showRecentChanged) + bool showRecent() const; + + Q_PROPERTY(bool ShowMultiWindow READ showMultiWindow NOTIFY ShowMultiWindowChanged) + bool showMultiWindow() const; + +public Q_SLOTS: // METHODS + QDBusPendingReply<> ActivateWindow(uint in0); + + QDBusPendingReply<> PreviewWindow(uint in0); + + QDBusPendingReply<> CancelPreviewWindow(); + + QDBusPendingReply<> MinimizeWindow(uint in0); + + inline void ActivateWindowQueued(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + + CallQueued(QStringLiteral("ActivateWindow"), argumentList); + } + + inline QDBusPendingReply<> CloseWindow(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("CloseWindow"), argumentList); + } + + inline void CloseWindowQueued(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + + CallQueued(QStringLiteral("CloseWindow"), argumentList); + } + + inline QDBusPendingReply GetDockedAppsDesktopFiles() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetDockedAppsDesktopFiles"), argumentList); + } + + inline QDBusPendingReply GetEntryIDs() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetEntryIDs"), argumentList); + } + + inline QDBusPendingReply GetPluginSettings() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetPluginSettings"), argumentList); + } + + inline QDBusPendingReply IsDocked(const QString &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("IsDocked"), argumentList); + } + + inline QDBusPendingReply IsOnDock(const QString &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("IsOnDock"), argumentList); + } + + inline QDBusPendingReply<> MergePluginSettings(const QString &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("MergePluginSettings"), argumentList); + } + + inline void MergePluginSettingsQueued(const QString &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + + CallQueued(QStringLiteral("MergePluginSettings"), argumentList); + } + + inline QDBusPendingReply<> MoveEntry(int in0, int in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("MoveEntry"), argumentList); + } + + inline void MoveEntryQueued(int in0, int in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + + CallQueued(QStringLiteral("MoveEntry"), argumentList); + } + + inline void MoveWindowQueued(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + + CallQueued(QStringLiteral("MoveWindow"), argumentList); + } + + inline QDBusPendingReply QueryWindowIdentifyMethod(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("QueryWindowIdentifyMethod"), argumentList); + } + + inline QDBusPendingReply<> RemovePluginSettings(const QString &in0, const QStringList &in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("RemovePluginSettings"), argumentList); + } + + inline void RemovePluginSettingsQueued(const QString &in0, const QStringList &in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + + CallQueued(QStringLiteral("RemovePluginSettings"), argumentList); + } + + inline QDBusPendingReply RequestDock(const QString &in0, int in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("RequestDock"), argumentList); + } + + inline QDBusPendingReply RequestUndock(const QString &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("RequestUndock"), argumentList); + } + + inline void SetShowRecent(bool in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + + CallQueued(QStringLiteral("SetShowRecent"), argumentList); + } + + inline QDBusPendingReply<> SetFrontendWindowRect(int in0, int in1, uint in2, uint in3) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3); + return asyncCallWithArgumentList(QStringLiteral("SetFrontendWindowRect"), argumentList); + } + + inline void SetFrontendWindowRectQueued(int in0, int in1, uint in2, uint in3) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3); + + CallQueued(QStringLiteral("SetFrontendWindowRect"), argumentList); + } + + inline QDBusPendingReply<> SetPluginSettings(const QString &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("SetPluginSettings"), argumentList); + } + + inline void SetPluginSettingsQueued(const QString &in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + + CallQueued(QStringLiteral("SetPluginSettings"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void DockAppSettingsSynced(); + void EntryAdded(const QDBusObjectPath &in0, int in1); + void EntryRemoved(const QString &in0); + void PluginSettingsSynced(); + void ServiceRestarted(); + // begin property changed signals + void DisplayModeChanged(int value) const; + void DockedAppsChanged(const QStringList &value) const; + void EntriesChanged(const QList &value) const; + void FrontendWindowRectChanged(DockRect value) const; + void HideModeChanged(int value) const; + void HideStateChanged(int value) const; + void HideTimeoutChanged(uint value) const; + void IconSizeChanged(uint value) const; + void OpacityChanged(double value) const; + void PositionChanged(int value) const; + void ShowTimeoutChanged(uint value) const; + void WindowSizeChanged(uint value) const; + void WindowSizeEfficientChanged(uint value) const; + void WindowSizeFashionChanged(uint value) const; + void showRecentChanged(bool) const; + void ShowMultiWindowChanged(bool) const; + +public Q_SLOTS: + void CallQueued(const QString &callName, const QList &args); + +private Q_SLOTS: + void onPendingCallFinished(QDBusPendingCallWatcher *w); + void onPropertyChanged(const QDBusMessage& msg); + +private: + DockPrivate *d_ptr; + WM *m_wm; +}; + +namespace org { + namespace deepin { + namespace dde { + namespace daemon { + typedef ::Dde_Dock DdeDock; + } + } + } +} + + +#endif // DOCK_INTERFACE diff --git a/frame/dbus/entryinterface.cpp b/frame/dbus/entryinterface.cpp new file mode 100644 index 000000000..3d7e1e276 --- /dev/null +++ b/frame/dbus/entryinterface.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 + * 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 . + */ + +#include "entryinterface.h" + +/* + * Implementation of interface class __Entry + */ +void registerWindowListMetaType() +{ + qRegisterMetaType(); + qDBusRegisterMetaType(); +} + +void registerWindowInfoMapMetaType() +{ + registerWindowInfoMetaType(); + + qRegisterMetaType("WindowInfoMap"); + qDBusRegisterMetaType(); +} + +void registerWindowInfoMetaType() +{ + qRegisterMetaType("WindowInfo"); + qDBusRegisterMetaType(); +} + +QDebug operator<<(QDebug argument, const WindowInfo &info) +{ + argument << '(' << info.title << ',' << info.attention << info.uuid << ')'; + + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info) +{ + argument.beginStructure(); + argument << info.title << info.attention << info.uuid; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info) +{ + argument.beginStructure(); + argument >> info.title >> info.attention >> info.uuid; + argument.endStructure(); + + return argument; +} + +bool WindowInfo::operator==(const WindowInfo &rhs) const +{ + return (attention == rhs.attention && + title == rhs.title && + uuid == rhs.uuid); +} + +class EntryPrivate +{ +public: + EntryPrivate() + : CurrentWindow(0) + , IsActive(false) + , IsDocked(false) + , mode(0) + {} + + // begin member variables + uint CurrentWindow; + QString DesktopFile; + QString Icon; + QString Id; + bool IsActive; + bool IsDocked; + QString Menu; + QString Name; + + WindowInfoMap WindowInfos; + int mode; + +public: + QMap m_processingCalls; + QMap> m_waittingCalls; +}; + +Dock_Entry::Dock_Entry(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) + , d_ptr(new EntryPrivate) +{ + QDBusConnection::sessionBus().connect(this->service(), this->path(), + "org.freedesktop.DBus.Properties", + "PropertiesChanged","sa{sv}as", + this, + SLOT(onPropertyChanged(const QDBusMessage &))); + + if (QMetaType::type("WindowList") == QMetaType::UnknownType) + registerWindowListMetaType(); + if (QMetaType::type("WindowInfoMap") == QMetaType::UnknownType) + registerWindowInfoMapMetaType(); +} + +Dock_Entry::~Dock_Entry() +{ + qDeleteAll(d_ptr->m_processingCalls.values()); + delete d_ptr; +} + +void Dock_Entry::onPropertyChanged(const QString &propName, const QVariant &value) +{ + if (propName == QStringLiteral("CurrentWindow")) { + const uint &CurrentWindow = qvariant_cast(value); + if (d_ptr->CurrentWindow != CurrentWindow) { + d_ptr->CurrentWindow = CurrentWindow; + Q_EMIT CurrentWindowChanged(d_ptr->CurrentWindow); + } + return; + } + + if (propName == QStringLiteral("DesktopFile")) { + const QString &DesktopFile = qvariant_cast(value); + if (d_ptr->DesktopFile != DesktopFile) { + d_ptr->DesktopFile = DesktopFile; + Q_EMIT DesktopFileChanged(d_ptr->DesktopFile); + } + return; + } + + if (propName == QStringLiteral("Icon")) { + const QString &Icon = qvariant_cast(value); + if (d_ptr->Icon != Icon) + { + d_ptr->Icon = Icon; + Q_EMIT IconChanged(d_ptr->Icon); + } + return; + } + + if (propName == QStringLiteral("IsActive")) { + const bool &IsActive = qvariant_cast(value); + if (d_ptr->IsActive != IsActive) { + d_ptr->IsActive = IsActive; + Q_EMIT IsActiveChanged(d_ptr->IsActive); + } + return; + } + + if (propName == QStringLiteral("IsDocked")) { + const bool &IsDocked = qvariant_cast(value); + if (d_ptr->IsDocked != IsDocked) { + d_ptr->IsDocked = IsDocked; + Q_EMIT IsDockedChanged(d_ptr->IsDocked); + } + return; + } + + if (propName == QStringLiteral("Menu")) { + const QString &Menu = qvariant_cast(value); + if (d_ptr->Menu != Menu) { + d_ptr->Menu = Menu; + Q_EMIT MenuChanged(d_ptr->Menu); + } + return; + } + + if (propName == QStringLiteral("Name")) { + const QString &Name = qvariant_cast(value); + if (d_ptr->Name != Name) { + d_ptr->Name = Name; + Q_EMIT NameChanged(d_ptr->Name); + } + return; + } + + if (propName == QStringLiteral("WindowInfos")) { + const WindowInfoMap &WindowInfos = qvariant_cast(value); + if (d_ptr->WindowInfos != WindowInfos) { + d_ptr->WindowInfos = WindowInfos; + Q_EMIT WindowInfosChanged(d_ptr->WindowInfos); + } + return; + } + + if (propName == QStringLiteral("Mode")) { + const int mode = qvariant_cast(value); + if (d_ptr->mode != mode) { + d_ptr->mode = mode; + Q_EMIT ModeChanged(d_ptr->mode); + } + } + + qWarning() << "property not handle: " << propName; + return; +} + +uint Dock_Entry::currentWindow() +{ + return qvariant_cast(property("CurrentWindow")); +} + +QString Dock_Entry::desktopFile() +{ + return qvariant_cast(property("DesktopFile")); +} + +QString Dock_Entry::icon() +{ + return qvariant_cast(property("Icon")); +} + +QString Dock_Entry::id() +{ + return qvariant_cast(property("Id")); +} + +bool Dock_Entry::isActive() +{ + return qvariant_cast(property("IsActive")); +} + +bool Dock_Entry::isDocked() +{ + return qvariant_cast(property("IsDocked")); +} + +int Dock_Entry::mode() const +{ + return qvariant_cast(property("Mode")); +} + +QString Dock_Entry::menu() +{ + return qvariant_cast(property("Menu")); +} + +QString Dock_Entry::name() +{ + return qvariant_cast(property("Name")); +} + +WindowInfoMap Dock_Entry::windowInfos() +{ + return qvariant_cast(property("WindowInfos")); +} + +void Dock_Entry::CallQueued(const QString &callName, const QList &args) +{ + if (d_ptr->m_waittingCalls.contains(callName)) { + d_ptr->m_waittingCalls[callName] = args; + return; + } + if (d_ptr->m_processingCalls.contains(callName)) { + d_ptr->m_waittingCalls.insert(callName, args); + } else { + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCallWithArgumentList(callName, args)); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Dock_Entry::onPendingCallFinished); + d_ptr->m_processingCalls.insert(callName, watcher); + } +} + +void Dock_Entry::onPendingCallFinished(QDBusPendingCallWatcher *w) +{ + w->deleteLater(); + const auto callName = d_ptr->m_processingCalls.key(w); + Q_ASSERT(!callName.isEmpty()); + if (callName.isEmpty()) + return; + + d_ptr->m_processingCalls.remove(callName); + if (!d_ptr->m_waittingCalls.contains(callName)) + return; + + const auto args = d_ptr->m_waittingCalls.take(callName); + CallQueued(callName, args); +} diff --git a/frame/dbus/entryinterface.h b/frame/dbus/entryinterface.h new file mode 100644 index 000000000..e0af4497e --- /dev/null +++ b/frame/dbus/entryinterface.h @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 + * 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 . + */ + +#ifndef DOCK_ENTRY_H +#define DOCK_ENTRY_H + +#define WINDOWLIST_H +#define WINDOWINFOLIST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef QList WindowList; + +void registerWindowListMetaType(); + +class WindowInfo +{ +public: + friend QDebug operator<<(QDebug argument, const WindowInfo &info); + friend QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info); + friend const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info); + + bool operator==(const WindowInfo &rhs) const; + +public: + bool attention; + QString title; + QString uuid; +}; + +Q_DECLARE_METATYPE(WindowInfo) + +typedef QMap WindowInfoMap; +Q_DECLARE_METATYPE(WindowInfoMap) + +void registerWindowInfoMetaType(); +void registerWindowInfoMapMetaType(); + +/* + * Proxy class for interface org.deepin.dde.daemon.Dock1.Entry + */ +class EntryPrivate; + +class Dock_Entry : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + static inline const char *staticInterfaceName() + { return "org.deepin.dde.daemon.Dock1.Entry"; } + +public: + explicit Dock_Entry(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~Dock_Entry(); + + Q_PROPERTY(uint CurrentWindow READ currentWindow NOTIFY CurrentWindowChanged) + uint currentWindow(); + + Q_PROPERTY(QString DesktopFile READ desktopFile NOTIFY DesktopFileChanged) + QString desktopFile(); + + Q_PROPERTY(QString Icon READ icon NOTIFY IconChanged) + QString icon(); + + Q_PROPERTY(QString Id READ id) + QString id(); + + Q_PROPERTY(bool IsActive READ isActive NOTIFY IsActiveChanged) + bool isActive(); + + Q_PROPERTY(bool IsDocked READ isDocked NOTIFY IsDockedChanged) + bool isDocked(); + + Q_PROPERTY(QString Menu READ menu NOTIFY MenuChanged) + QString menu(); + + Q_PROPERTY(QString Name READ name NOTIFY NameChanged) + QString name(); + + Q_PROPERTY(WindowInfoMap WindowInfos READ windowInfos NOTIFY WindowInfosChanged) + WindowInfoMap windowInfos(); + + Q_PROPERTY(int Mode READ mode NOTIFY ModeChanged) + int mode() const; + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> Activate(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("Activate"), argumentList); + } + + inline void ActivateQueued(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + CallQueued(QStringLiteral("Activate"), argumentList); + } + + inline QDBusPendingReply<> Check() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Check"), argumentList); + } + + inline void CheckQueued() + { + QList argumentList; + CallQueued(QStringLiteral("Check"), argumentList); + } + + inline QDBusPendingReply<> ForceQuit() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("ForceQuit"), argumentList); + } + + inline QDBusPendingReply<> ActiveWindow(quint32 in0) + { + QList argumentList; + argumentList << in0; + return asyncCallWithArgumentList(QStringLiteral("ActiveWindow"), argumentList); + } + + inline void ForceQuitQueued() + { + QList argumentList; + CallQueued(QStringLiteral("ForceQuit"), argumentList); + } + + inline QDBusPendingReply GetAllowedCloseWindows() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("GetAllowedCloseWindows"), argumentList); + } + + inline QDBusPendingReply<> HandleDragDrop(uint in0, const QStringList &in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("HandleDragDrop"), argumentList); + } + + inline void HandleDragDropQueued(uint in0, const QStringList &in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + CallQueued(QStringLiteral("HandleDragDrop"), argumentList); + } + + inline QDBusPendingReply<> HandleMenuItem(uint in0, const QString &in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("HandleMenuItem"), argumentList); + } + + inline void HandleMenuItemQueued(uint in0, const QString &in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + CallQueued(QStringLiteral("HandleMenuItem"), argumentList); + } + + inline QDBusPendingReply<> NewInstance(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("NewInstance"), argumentList); + } + + inline void NewInstanceQueued(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + CallQueued(QStringLiteral("NewInstance"), argumentList); + } + + inline QDBusPendingReply<> PresentWindows() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("PresentWindows"), argumentList); + } + + inline void PresentWindowsQueued() + { + QList argumentList; + CallQueued(QStringLiteral("PresentWindows"), argumentList); + } + + inline QDBusPendingReply<> RequestDock() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("RequestDock"), argumentList); + } + + inline void RequestDockQueued() + { + QList argumentList; + CallQueued(QStringLiteral("RequestDock"), argumentList); + } + + inline QDBusPendingReply<> RequestUndock() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("RequestUndock"), argumentList); + } + + inline void RequestUndockQueued() + { + QList argumentList; + CallQueued(QStringLiteral("RequestUndock"), argumentList); + } + +Q_SIGNALS: // SIGNALS + // begin property changed signals + void IsActiveChanged(bool value) const; + void IsDockedChanged(bool value) const; + void MenuChanged(const QString &value) const; + void IconChanged(const QString &value) const; + void NameChanged(const QString &value) const; + void DesktopFileChanged(const QString &value) const; + void CurrentWindowChanged(uint32_t value) const; + + void WindowInfosChanged(WindowInfoMap value) const; + void ModeChanged(int value) const; + +private: + QVariant asyncProperty(const QString &propertyName); + +public Q_SLOTS: + void CallQueued(const QString &callName, const QList &args); + +private Q_SLOTS: + void onPendingCallFinished(QDBusPendingCallWatcher *w); + void onPropertyChanged(const QString &propName, const QVariant &value); + +private: + EntryPrivate *d_ptr; +}; + +namespace org { + namespace deepin { + namespace dde { + namespace daemon { + namespace dock { + typedef ::Dock_Entry DockEntry; + } + } + } + } +} + +#endif // DOCK_ENTRY_H diff --git a/frame/dbus/com.deepin.dde.daemon.Dock.xml b/frame/dbus/org.deepin.dde.daemon.Dock1.xml similarity index 96% rename from frame/dbus/com.deepin.dde.daemon.Dock.xml rename to frame/dbus/org.deepin.dde.daemon.Dock1.xml index dc10e442b..4b81b9dea 100644 --- a/frame/dbus/com.deepin.dde.daemon.Dock.xml +++ b/frame/dbus/org.deepin.dde.daemon.Dock1.xml @@ -1,4 +1,4 @@ - + diff --git a/frame/dbusinterface/types/arealist.cpp b/frame/dbusinterface/types/arealist.cpp new file mode 100644 index 000000000..0b3ed4f15 --- /dev/null +++ b/frame/dbusinterface/types/arealist.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "arealist.h" + +bool MonitRect::operator ==(const MonitRect &rect) +{ + return x1 == rect.x1 && y1 == rect.y1 && x2 == rect.x2 && y2 == rect.y2; +} + +QDBusArgument &operator<<(QDBusArgument &arg, const MonitRect &rect) +{ + arg.beginStructure(); + arg << rect.x1 << rect.y1 << rect.x2 << rect.y2; + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, MonitRect &rect) +{ + arg.beginStructure(); + arg >> rect.x1 >> rect.y1 >> rect.x2 >> rect.y2; + arg.endStructure(); + + return arg; +} + +void registerAreaListMetaType() +{ + qRegisterMetaType("MonitRect"); + qDBusRegisterMetaType(); + + qRegisterMetaType("AreaList"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/arealist.h b/frame/dbusinterface/types/arealist.h new file mode 100644 index 000000000..f75a0e53f --- /dev/null +++ b/frame/dbusinterface/types/arealist.h @@ -0,0 +1,32 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef AREALIST_H +#define AREALIST_H + +#include +#include +#include + +struct MonitRect { + int x1; + int y1; + int x2; + int y2; + + bool operator ==(const MonitRect& rect); +}; + +typedef QList AreaList; + +Q_DECLARE_METATYPE(MonitRect) +Q_DECLARE_METATYPE(AreaList) + +QDBusArgument &operator<<(QDBusArgument &arg, const MonitRect &rect); +const QDBusArgument &operator>>(const QDBusArgument &arg, MonitRect &rect); + +void registerAreaListMetaType(); + +#endif // AREALIST_H diff --git a/frame/dbusinterface/types/audioport.cpp b/frame/dbusinterface/types/audioport.cpp new file mode 100644 index 000000000..2d5d489a9 --- /dev/null +++ b/frame/dbusinterface/types/audioport.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include + +#include "audioport.h" + +void registerAudioPortMetaType() +{ + qRegisterMetaType("AudioPort"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/audioport.h b/frame/dbusinterface/types/audioport.h new file mode 100644 index 000000000..f87d17bf3 --- /dev/null +++ b/frame/dbusinterface/types/audioport.h @@ -0,0 +1,56 @@ +// Copyright (C) 2016 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef AUDIOPORT_H +#define AUDIOPORT_H + +#include +#include +#include +#include + +class AudioPort +{ +public: + QString name; + QString description; + uchar availability; // 0 for Unknown, 1 for Not Available, 2 for Available. + + friend QDebug operator<<(QDebug argument, const AudioPort &port) { + argument << port.description; + + return argument; + } + + friend QDBusArgument &operator<<(QDBusArgument &argument, const AudioPort &port) { + argument.beginStructure(); + argument << port.name << port.description << port.availability; + argument.endStructure(); + + return argument; + } + + friend const QDBusArgument &operator>>(const QDBusArgument &argument, AudioPort &port) { + argument.beginStructure(); + argument >> port.name >> port.description >> port.availability; + argument.endStructure(); + + return argument; + } + + bool operator==(const AudioPort what) const { + return what.name == name && what.description == description && what.availability == availability; + } + + bool operator!=(const AudioPort what) const { + return what.name != name || what.description != description || what.availability != availability; + } +}; + +Q_DECLARE_METATYPE(AudioPort) + +void registerAudioPortMetaType(); + +#endif // AUDIOPORT_H diff --git a/frame/dbusinterface/types/audioportlist.cpp b/frame/dbusinterface/types/audioportlist.cpp new file mode 100644 index 000000000..5d0586c39 --- /dev/null +++ b/frame/dbusinterface/types/audioportlist.cpp @@ -0,0 +1,12 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "audioportlist.h" + +void registerAudioPortListMetaType() +{ + qRegisterMetaType("AudioPortList"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/audioportlist.h b/frame/dbusinterface/types/audioportlist.h new file mode 100644 index 000000000..304714734 --- /dev/null +++ b/frame/dbusinterface/types/audioportlist.h @@ -0,0 +1,20 @@ +// Copyright (C) 2016 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef AUDIOPORTLIST_H +#define AUDIOPORTLIST_H + +#include +#include + +#include "audioport.h" + +typedef QList AudioPortList; + +Q_DECLARE_METATYPE(AudioPortList) + +void registerAudioPortListMetaType(); + +#endif // AUDIOPORTLIST_H diff --git a/frame/dbusinterface/types/brightnessmap.cpp b/frame/dbusinterface/types/brightnessmap.cpp new file mode 100644 index 000000000..b534737f5 --- /dev/null +++ b/frame/dbusinterface/types/brightnessmap.cpp @@ -0,0 +1,12 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "brightnessmap.h" + +void registerBrightnessMapMetaType() +{ + qRegisterMetaType("BrightnessMap"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/brightnessmap.h b/frame/dbusinterface/types/brightnessmap.h new file mode 100644 index 000000000..e3ac39e51 --- /dev/null +++ b/frame/dbusinterface/types/brightnessmap.h @@ -0,0 +1,16 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef BRIGHTNESSMAP_H +#define BRIGHTNESSMAP_H + +#include +#include + +typedef QMap BrightnessMap; + +void registerBrightnessMapMetaType(); + +#endif // BRIGHTNESSMAP_H diff --git a/frame/dbusinterface/types/dbusimagelist.cpp b/frame/dbusinterface/types/dbusimagelist.cpp new file mode 100644 index 000000000..4d7fd5364 --- /dev/null +++ b/frame/dbusinterface/types/dbusimagelist.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dbusimagelist.h" + +QDBusArgument &operator<<(QDBusArgument &argument, const DBusImage &image) +{ + argument.beginStructure(); + argument << image.width << image.height << image.pixels; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImage &image) +{ + argument.beginStructure(); + argument >> image.width >> image.height >> image.pixels; + argument.endStructure(); + return argument; +} + +void registerDBusImageListMetaType() +{ + qRegisterMetaType("DBusImage"); + qDBusRegisterMetaType(); + + qRegisterMetaType("DBusImageList"); + qDBusRegisterMetaType(); +} + +bool operator ==(const DBusImage &a, const DBusImage &b) +{ + return a.width == b.width + && a.height == b.height + && a.pixels == b.pixels; +} + +bool operator !=(const DBusImage &a, const DBusImage &b) +{ + return !(a == b); +} diff --git a/frame/dbusinterface/types/dbusimagelist.h b/frame/dbusinterface/types/dbusimagelist.h new file mode 100644 index 000000000..12b7084e0 --- /dev/null +++ b/frame/dbusinterface/types/dbusimagelist.h @@ -0,0 +1,32 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DBUSIMAGELIST_H +#define DBUSIMAGELIST_H + +#include +#include +#include + +struct DBusImage +{ + int width; + int height; + QByteArray pixels; +}; +Q_DECLARE_METATYPE(DBusImage) + +typedef QList DBusImageList; +Q_DECLARE_METATYPE(DBusImageList) + +QDBusArgument &operator<<(QDBusArgument&, const DBusImage&); +const QDBusArgument &operator>>(const QDBusArgument&, DBusImage&); + +bool operator ==(const DBusImage&, const DBusImage&); +bool operator !=(const DBusImage&, const DBusImage&); + +void registerDBusImageListMetaType(); + +#endif // DBUSIMAGELIST_H diff --git a/frame/dbusinterface/types/dbustooltip.cpp b/frame/dbusinterface/types/dbustooltip.cpp new file mode 100644 index 000000000..88164a8b6 --- /dev/null +++ b/frame/dbusinterface/types/dbustooltip.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dbustooltip.h" + +QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTip &tip) +{ + argument.beginStructure(); + argument << tip.iconName << tip.iconPixmap << tip.title << tip.description; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTip &tip) +{ + argument.beginStructure(); + argument >> tip.iconName >> tip.iconPixmap >> tip.title >> tip.description; + argument.endStructure(); + return argument; +} + +bool operator ==(const DBusToolTip &a, const DBusToolTip &b) +{ + return a.iconName == b.iconName + && a.iconPixmap == b.iconPixmap + && a.title == b.title + && a.description == b.description; +} + +bool operator !=(const DBusToolTip &a, const DBusToolTip &b) +{ + return !(a == b); +} + +void registerDBusToolTipMetaType() +{ + qRegisterMetaType("DBusToolTip"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/dbustooltip.h b/frame/dbusinterface/types/dbustooltip.h new file mode 100644 index 000000000..891be0565 --- /dev/null +++ b/frame/dbusinterface/types/dbustooltip.h @@ -0,0 +1,32 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DBUSTOOLTIP_H +#define DBUSTOOLTIP_H + +#include "dbusimagelist.h" + +#include +#include +#include + +struct DBusToolTip +{ + QString iconName; + DBusImageList iconPixmap; + QString title; + QString description; +}; +Q_DECLARE_METATYPE(DBusToolTip) + +QDBusArgument &operator<<(QDBusArgument&, const DBusToolTip&); +const QDBusArgument &operator>>(const QDBusArgument&, DBusToolTip&); + +bool operator ==(const DBusToolTip&, const DBusToolTip&); +bool operator !=(const DBusToolTip&, const DBusToolTip&); + +void registerDBusToolTipMetaType(); + +#endif // DBUSTOOLTIP_H diff --git a/frame/dbusinterface/types/dockrect.cpp b/frame/dbusinterface/types/dockrect.cpp new file mode 100644 index 000000000..d8b168bf8 --- /dev/null +++ b/frame/dbusinterface/types/dockrect.cpp @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dockrect.h" +#include + +DockRect::DockRect() + : x(0) + , y(0) + , w(0) + , h(0) +{ + +} + +QDebug operator<<(QDebug debug, const DockRect &rect) +{ + debug << QString("DockRect(%1, %2, %3, %4)").arg(rect.x) + .arg(rect.y) + .arg(rect.w) + .arg(rect.h); + + return debug; +} + +DockRect::operator QRect() const +{ + return QRect(x, y, w, h); +} + +QDBusArgument &operator<<(QDBusArgument &arg, const DockRect &rect) +{ + arg.beginStructure(); + arg << rect.x << rect.y << rect.w << rect.h; + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, DockRect &rect) +{ + arg.beginStructure(); + arg >> rect.x >> rect.y >> rect.w >> rect.h; + arg.endStructure(); + + return arg; +} + +void registerDockRectMetaType() +{ + qRegisterMetaType("DockRect"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/dockrect.h b/frame/dbusinterface/types/dockrect.h new file mode 100644 index 000000000..1f18dc718 --- /dev/null +++ b/frame/dbusinterface/types/dockrect.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DOCKRECT_H +#define DOCKRECT_H + +#include +#include + +struct DockRect +{ +public: + DockRect(); + operator QRect() const; + + friend QDebug operator<<(QDebug debug, const DockRect &rect); + friend const QDBusArgument &operator>>(const QDBusArgument &arg, DockRect &rect); + friend QDBusArgument &operator<<(QDBusArgument &arg, const DockRect &rect); + +private: + int x; + int y; + uint w; + uint h; +}; + +Q_DECLARE_METATYPE(DockRect) + +void registerDockRectMetaType(); + +#endif // DOCKRECT_H diff --git a/frame/dbusinterface/types/keyboardlayoutlist.cpp b/frame/dbusinterface/types/keyboardlayoutlist.cpp new file mode 100644 index 000000000..d5a51a41e --- /dev/null +++ b/frame/dbusinterface/types/keyboardlayoutlist.cpp @@ -0,0 +1,12 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "keyboardlayoutlist.h" + +void registerKeyboardLayoutListMetaType() +{ + qRegisterMetaType("KeyboardLayoutList"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/keyboardlayoutlist.h b/frame/dbusinterface/types/keyboardlayoutlist.h new file mode 100644 index 000000000..aa0c33aba --- /dev/null +++ b/frame/dbusinterface/types/keyboardlayoutlist.h @@ -0,0 +1,18 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef KEYBOARDLAYOUTLIST_H +#define KEYBOARDLAYOUTLIST_H + +#include +#include +#include +#include + +typedef QMap KeyboardLayoutList; + +void registerKeyboardLayoutListMetaType(); + +#endif // KEYBOARDLAYOUTLIST_H diff --git a/frame/dbusinterface/types/resolution.cpp b/frame/dbusinterface/types/resolution.cpp new file mode 100644 index 000000000..1932fbe6c --- /dev/null +++ b/frame/dbusinterface/types/resolution.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "resolution.h" + +#include + +void registerResolutionMetaType() +{ + qRegisterMetaType("Resolution"); + qDBusRegisterMetaType(); +} + +Resolution::Resolution() +{ + +} + +bool Resolution::operator!=(const Resolution &other) const +{ + return m_width != other.m_width || m_height != other.m_height || m_rate != other.m_rate; +} + +bool Resolution::operator==(const Resolution &other) const +{ + return !(other != *this); +} + +QDBusArgument &operator<<(QDBusArgument &arg, const Resolution &value) +{ + arg.beginStructure(); + arg << quint32(value.id()) << quint16(value.width()) << quint16(value.height()) << value.rate(); + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, Resolution &value) +{ + quint32 id; + quint16 w, h; + double rate; + + arg.beginStructure(); + arg >> id >> w >> h >> rate; + arg.endStructure(); + + value.setId(id); + value.setWidth(w); + value.setHeight(h); + value.setRate(rate); + + return arg; +} diff --git a/frame/dbusinterface/types/resolution.h b/frame/dbusinterface/types/resolution.h new file mode 100644 index 000000000..91512ff07 --- /dev/null +++ b/frame/dbusinterface/types/resolution.h @@ -0,0 +1,45 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef RESOLUTION_H +#define RESOLUTION_H + +#include + +class Resolution +{ +public: + friend QDBusArgument &operator<<(QDBusArgument &arg, const Resolution &value); + friend const QDBusArgument &operator>>(const QDBusArgument &arg, Resolution &value); + + explicit Resolution(); + + bool operator!=(const Resolution &other) const; + bool operator==(const Resolution &other) const; + + int id() const { return m_id; } + int width() const { return m_width; } + int height() const { return m_height; } + double rate() const { return m_rate; } + +private: + void setId(const int id) { m_id = id; } + void setWidth(const int w) { m_width = w; } + void setHeight(const int h) { m_height = h; } + void setRate(const double rate) { m_rate = rate; } + +private: + int m_id; + int m_width; + int m_height; + double m_rate; +}; + + +Q_DECLARE_METATYPE(Resolution) + +void registerResolutionMetaType(); + +#endif // RESOLUTION_H diff --git a/frame/dbusinterface/types/resolutionlist.cpp b/frame/dbusinterface/types/resolutionlist.cpp new file mode 100644 index 000000000..25b18ee98 --- /dev/null +++ b/frame/dbusinterface/types/resolutionlist.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "resolutionlist.h" + +void registerResolutionListMetaType() +{ + registerResolutionMetaType(); + + qRegisterMetaType("ResolutionList"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/resolutionlist.h b/frame/dbusinterface/types/resolutionlist.h new file mode 100644 index 000000000..8ada85044 --- /dev/null +++ b/frame/dbusinterface/types/resolutionlist.h @@ -0,0 +1,17 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef RESOLUTIONLIST_H +#define RESOLUTIONLIST_H + +#include "resolution.h" + +#include + +typedef QList ResolutionList; + +void registerResolutionListMetaType(); + +#endif // RESOLUTIONLIST_H diff --git a/frame/dbusinterface/types/screenrect.cpp b/frame/dbusinterface/types/screenrect.cpp new file mode 100644 index 000000000..30a245cf9 --- /dev/null +++ b/frame/dbusinterface/types/screenrect.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "screenrect.h" + +ScreenRect::ScreenRect() + : x(0), + y(0), + w(0), + h(0) +{ + +} + +QDebug operator<<(QDebug debug, const ScreenRect &rect) +{ + debug << QString("ScreenRect(%1, %2, %3, %4)").arg(rect.x) + .arg(rect.y) + .arg(rect.w) + .arg(rect.h); + + return debug; +} + +ScreenRect::operator QRect() const +{ + return QRect(x, y, w, h); +} + +QDBusArgument &operator<<(QDBusArgument &arg, const ScreenRect &rect) +{ + arg.beginStructure(); + arg << rect.x << rect.y << rect.w << rect.h; + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, ScreenRect &rect) +{ + arg.beginStructure(); + arg >> rect.x >> rect.y >> rect.w >> rect.h; + arg.endStructure(); + + return arg; +} + +void registerScreenRectMetaType() +{ + qRegisterMetaType("ScreenRect"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/screenrect.h b/frame/dbusinterface/types/screenrect.h new file mode 100644 index 000000000..64d12dcbd --- /dev/null +++ b/frame/dbusinterface/types/screenrect.h @@ -0,0 +1,35 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SCREENRECT_H +#define SCREENRECT_H + +#include +#include +#include +#include + +struct ScreenRect +{ +public: + ScreenRect(); + operator QRect() const; + + friend QDebug operator<<(QDebug debug, const ScreenRect &rect); + friend const QDBusArgument &operator>>(const QDBusArgument &arg, ScreenRect &rect); + friend QDBusArgument &operator<<(QDBusArgument &arg, const ScreenRect &rect); + +private: + qint16 x; + qint16 y; + quint16 w; + quint16 h; +}; + +Q_DECLARE_METATYPE(ScreenRect) + +void registerScreenRectMetaType(); + +#endif // SCREENRECT_H diff --git a/frame/dbusinterface/types/touchscreeninfolist.cpp b/frame/dbusinterface/types/touchscreeninfolist.cpp new file mode 100644 index 000000000..5bbb18315 --- /dev/null +++ b/frame/dbusinterface/types/touchscreeninfolist.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "touchscreeninfolist.h" + +QDBusArgument &operator<<(QDBusArgument &arg, const TouchscreenInfo &info) +{ + arg.beginStructure(); + arg << info.id << info.name << info.deviceNode << info.serialNumber; + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, TouchscreenInfo &info) +{ + arg.beginStructure(); + arg >> info.id >> info.name >> info.deviceNode >> info.serialNumber; + arg.endStructure(); + + return arg; +} + +bool TouchscreenInfo::operator==(const TouchscreenInfo &info) +{ + return id == info.id && name == info.name && deviceNode == info.deviceNode && serialNumber == info.serialNumber; +} + +void registerTouchscreenInfoMetaType() +{ + qRegisterMetaType("TouchscreenInfo"); + qDBusRegisterMetaType(); +} + +void registerTouchscreenInfoListMetaType() +{ + registerTouchscreenInfoMetaType(); + + qRegisterMetaType("TouchscreenInfoList"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/touchscreeninfolist.h b/frame/dbusinterface/types/touchscreeninfolist.h new file mode 100644 index 000000000..cc6551d63 --- /dev/null +++ b/frame/dbusinterface/types/touchscreeninfolist.h @@ -0,0 +1,32 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TOUCHSCREENINFOLIST_H +#define TOUCHSCREENINFOLIST_H + +#include +#include +#include + +struct TouchscreenInfo { + qint32 id; + QString name; + QString deviceNode; + QString serialNumber; + + bool operator ==(const TouchscreenInfo& info); +}; + +typedef QList TouchscreenInfoList; + +Q_DECLARE_METATYPE(TouchscreenInfo) +Q_DECLARE_METATYPE(TouchscreenInfoList) + +QDBusArgument &operator<<(QDBusArgument &arg, const TouchscreenInfo &info); +const QDBusArgument &operator>>(const QDBusArgument &arg, TouchscreenInfo &info); + +void registerTouchscreenInfoListMetaType(); + +#endif // !TOUCHSCREENINFOLIST_H diff --git a/frame/dbusinterface/types/touchscreeninfolist_v2.cpp b/frame/dbusinterface/types/touchscreeninfolist_v2.cpp new file mode 100644 index 000000000..722d8d924 --- /dev/null +++ b/frame/dbusinterface/types/touchscreeninfolist_v2.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "touchscreeninfolist_v2.h" + +QDBusArgument &operator<<(QDBusArgument &arg, const TouchscreenInfo_V2 &info) +{ + arg.beginStructure(); + arg << info.id << info.name << info.deviceNode << info.serialNumber << info.UUID; + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, TouchscreenInfo_V2 &info) +{ + arg.beginStructure(); + arg >> info.id >> info.name >> info.deviceNode >> info.serialNumber >> info.UUID; + arg.endStructure(); + + return arg; +} + +bool TouchscreenInfo_V2::operator==(const TouchscreenInfo_V2 &info) +{ + return id == info.id && name == info.name && deviceNode == info.deviceNode && serialNumber == info.serialNumber && UUID == info.UUID; +} + +void registerTouchscreenInfoV2MetaType() +{ + qRegisterMetaType("TouchscreenInfo_V2"); + qDBusRegisterMetaType(); +} + +void registerTouchscreenInfoList_V2MetaType() +{ + registerTouchscreenInfoV2MetaType(); + + qRegisterMetaType("TouchscreenInfoList_V2"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/touchscreeninfolist_v2.h b/frame/dbusinterface/types/touchscreeninfolist_v2.h new file mode 100644 index 000000000..e67a170fd --- /dev/null +++ b/frame/dbusinterface/types/touchscreeninfolist_v2.h @@ -0,0 +1,33 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TOUCHSCREENINFOLISTV2_H +#define TOUCHSCREENINFOLISTV2_H + +#include +#include +#include + +struct TouchscreenInfo_V2 { + qint32 id; + QString name; + QString deviceNode; + QString serialNumber; + QString UUID; + + bool operator ==(const TouchscreenInfo_V2& info); +}; + +typedef QList TouchscreenInfoList_V2; + +Q_DECLARE_METATYPE(TouchscreenInfo_V2) +Q_DECLARE_METATYPE(TouchscreenInfoList_V2) + +QDBusArgument &operator<<(QDBusArgument &arg, const TouchscreenInfo_V2 &info); +const QDBusArgument &operator>>(const QDBusArgument &arg, TouchscreenInfo_V2 &info); + +void registerTouchscreenInfoList_V2MetaType(); + +#endif // !TOUCHSCREENINFOLISTV2_H diff --git a/frame/dbusinterface/types/touchscreenmap.cpp b/frame/dbusinterface/types/touchscreenmap.cpp new file mode 100644 index 000000000..dacaa261e --- /dev/null +++ b/frame/dbusinterface/types/touchscreenmap.cpp @@ -0,0 +1,12 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "touchscreenmap.h" + +void registerTouchscreenMapMetaType() +{ + qRegisterMetaType("TouchscreenMap"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/touchscreenmap.h b/frame/dbusinterface/types/touchscreenmap.h new file mode 100644 index 000000000..a6a005e26 --- /dev/null +++ b/frame/dbusinterface/types/touchscreenmap.h @@ -0,0 +1,16 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TOUCHSCREENMAP_H +#define TOUCHSCREENMAP_H + +#include +#include + +typedef QMap TouchscreenMap; + +void registerTouchscreenMapMetaType(); + +#endif // TOUCHSCREENMAP_H diff --git a/frame/dbusinterface/types/zoneinfo.cpp b/frame/dbusinterface/types/zoneinfo.cpp new file mode 100644 index 000000000..12b1109dd --- /dev/null +++ b/frame/dbusinterface/types/zoneinfo.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "zoneinfo.h" + +ZoneInfo::ZoneInfo() +{ + +} + +bool ZoneInfo::operator ==(const ZoneInfo &what) const +{ + // TODO: 这里只判断这两个成员应该就可以了 + return m_zoneName == what.m_zoneName && + m_utcOffset == what.m_utcOffset; +} + +QDebug operator<<(QDebug argument, const ZoneInfo & info) +{ + argument << info.m_zoneName << ',' << info.m_zoneCity << ',' << info.m_utcOffset << ','; + argument << info.i2 << ',' << info.i3 << ',' << info.i4 << Qt::endl; + + return argument; +} + +QDBusArgument &operator<<(QDBusArgument & argument, const ZoneInfo & info) +{ + argument.beginStructure(); + argument << info.m_zoneName << info.m_zoneCity << info.m_utcOffset; + argument.beginStructure(); + argument << info.i2 << info.i3 << info.i4; + argument.endStructure(); + argument.endStructure(); + + return argument; +} + +QDataStream &operator<<(QDataStream & argument, const ZoneInfo & info) +{ + argument << info.m_zoneName << info.m_zoneCity << info.m_utcOffset; + argument << info.i2 << info.i3 << info.i4; + + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument & argument, ZoneInfo & info) +{ + argument.beginStructure(); + argument >> info.m_zoneName >> info.m_zoneCity >> info.m_utcOffset; + argument.beginStructure(); + argument >> info.i2 >> info.i3 >> info.i4; + argument.endStructure(); + argument.endStructure(); + + return argument; +} + +const QDataStream &operator>>(QDataStream & argument, ZoneInfo & info) +{ + argument >> info.m_zoneName >> info.m_zoneCity >> info.m_utcOffset; + argument >> info.i2 >> info.i3 >> info.i4; + + return argument; +} + +void registerZoneInfoMetaType() +{ + qRegisterMetaType("ZoneInfo"); + qDBusRegisterMetaType(); +} diff --git a/frame/dbusinterface/types/zoneinfo.h b/frame/dbusinterface/types/zoneinfo.h new file mode 100644 index 000000000..e9af23dcc --- /dev/null +++ b/frame/dbusinterface/types/zoneinfo.h @@ -0,0 +1,46 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef ZONEINFO_H +#define ZONEINFO_H + +#include +#include +#include +#include +#include + +class ZoneInfo +{ +public: + ZoneInfo(); + + friend QDebug operator<<(QDebug argument, const ZoneInfo &info); + friend QDBusArgument &operator<<(QDBusArgument &argument, const ZoneInfo &info); + friend QDataStream &operator<<(QDataStream &argument, const ZoneInfo &info); + friend const QDBusArgument &operator>>(const QDBusArgument &argument, ZoneInfo &info); + friend const QDataStream &operator>>(QDataStream &argument, ZoneInfo &info); + + bool operator==(const ZoneInfo &what) const; + +public: + inline QString getZoneName() const {return m_zoneName;} + inline QString getZoneCity() const {return m_zoneCity;} + inline int getUTCOffset() const {return m_utcOffset;} + +private: + QString m_zoneName; + QString m_zoneCity; + int m_utcOffset; + qint64 i2; + qint64 i3; + int i4; +}; + +Q_DECLARE_METATYPE(ZoneInfo) + +void registerZoneInfoMetaType(); + +#endif // ZONEINFO_H diff --git a/frame/dbusinterface/xml/org.deepin.dde.Appearance1.xml b/frame/dbusinterface/xml/org.deepin.dde.Appearance1.xml new file mode 100644 index 000000000..973b140ba --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.Appearance1.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.deepin.dde.Audio1.Sink.xml b/frame/dbusinterface/xml/org.deepin.dde.Audio1.Sink.xml new file mode 100644 index 000000000..72f6f68b0 --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.Audio1.Sink.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + \n + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frame/dbusinterface/xml/org.deepin.dde.Audio1.xml b/frame/dbusinterface/xml/org.deepin.dde.Audio1.xml new file mode 100644 index 000000000..7fbe4885f --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.Audio1.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.deepin.dde.Display1.xml b/frame/dbusinterface/xml/org.deepin.dde.Display1.xml new file mode 100644 index 000000000..c6e6235b8 --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.Display1.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.deepin.dde.Gesture1.xml b/frame/dbusinterface/xml/org.deepin.dde.Gesture1.xml new file mode 100644 index 000000000..de90b4a78 --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.Gesture1.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.deepin.dde.Launcher1.xml b/frame/dbusinterface/xml/org.deepin.dde.Launcher1.xml new file mode 100644 index 000000000..bea11ef51 --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.Launcher1.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.deepin.dde.Timedate1.xml b/frame/dbusinterface/xml/org.deepin.dde.Timedate1.xml new file mode 100644 index 000000000..f3a46e3bf --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.Timedate1.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.deepin.dde.XEventMonitor1.xml b/frame/dbusinterface/xml/org.deepin.dde.XEventMonitor1.xml new file mode 100644 index 000000000..633c6c1d6 --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.XEventMonitor1.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frame/dbusinterface/xml/org.deepin.dde.daemon.Dock1.xml b/frame/dbusinterface/xml/org.deepin.dde.daemon.Dock1.xml new file mode 100644 index 000000000..e41888c48 --- /dev/null +++ b/frame/dbusinterface/xml/org.deepin.dde.daemon.Dock1.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.freedesktop.FileManager.xml b/frame/dbusinterface/xml/org.freedesktop.FileManager.xml new file mode 100644 index 000000000..fb67a6c59 --- /dev/null +++ b/frame/dbusinterface/xml/org.freedesktop.FileManager.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/frame/dbusinterface/xml/org.kde.StatusNotifierItem.xml b/frame/dbusinterface/xml/org.kde.StatusNotifierItem.xml new file mode 100644 index 000000000..f1858b46e --- /dev/null +++ b/frame/dbusinterface/xml/org.kde.StatusNotifierItem.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frame/display/displaymanager.cpp b/frame/display/displaymanager.cpp index d0dfdcde3..6a364b1ec 100644 --- a/frame/display/displaymanager.cpp +++ b/frame/display/displaymanager.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -52,6 +53,17 @@ QScreen *DisplayManager::screen(const QString &screenName) const return nullptr; } +QScreen *DisplayManager::screenAt(const QPoint &pos) const +{ + for (QScreen *screen : m_screens) { + QRect screenGeometry = screen->geometry(); + if (screenGeometry.contains(pos)) + return screen; + } + + return nullptr; +} + /** * @brief DisplayManager::primary * @return 主屏幕名称 @@ -128,6 +140,8 @@ bool DisplayManager::isCopyMode() */ void DisplayManager::updateScreenDockInfo() { + // TODO 目前仅仅支持双屏,如果超过双屏,会出现异常,这里可以考虑做成通用的处理规则 + // 先清除原先的数据,然后再更新 m_screenPositionMap.clear(); @@ -163,7 +177,7 @@ void DisplayManager::updateScreenDockInfo() return; } - // 适配任意多个屏幕的情况 + // 适配多个屏幕的情况 for(auto s : m_screens) { QList otherScreens = m_screens; otherScreens.removeAll(s); @@ -264,7 +278,6 @@ void DisplayManager::screenCountChanged() for (auto s : to_remove_list) { disconnect(s); m_screens.removeOne(s); - Q_EMIT screenRemoved(s); } // 创建关联 @@ -287,7 +300,6 @@ void DisplayManager::screenCountChanged() connect(s, &QScreen::refreshRateChanged, this, &DisplayManager::dockInfoChanged); m_screens.append(s); - Q_EMIT screenAdded(s); } // 屏幕数量发生变化,应该刷新一下任务栏的显示 diff --git a/frame/display/displaymanager.h b/frame/display/displaymanager.h index 2f9547882..71c1c8b83 100644 --- a/frame/display/displaymanager.h +++ b/frame/display/displaymanager.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -9,20 +10,14 @@ #include "singleton.h" #include "constants.h" +#include "org_deepin_dde_display1.h" +using DisplayInter = org::deepin::dde::Display1; using namespace Dock; class QScreen; class QTimer; class QGSettings; -/** - * @brief The DisplayManager class - * @note 1、对QScreen信息的获取和监听进行了封装,不应该在此程序的其他处再出现类似的代码,而是从当前实例中进行提供 - * @note 2、对显示相关数据的读写尽可能通过Qt库进行,而不是通过一些DBus服务, - * @note 目的一是为了解耦 - * @note 二是DBus服务的稳定性较低,有部分问题存在 - * @note 三是DBus服务(特指Display相关)刚开始的目的是为了做一些架构和特殊机器的兼容适配工作,因为qt适配开展较慢,所以才有了DBus服务的存在,目前qt已足够稳定,我们不应该再大量使用后端提供的Display服务 - */ class DisplayManager: public QObject, public Singleton { Q_OBJECT @@ -33,6 +28,7 @@ public: QList screens() const; QScreen *screen(const QString &screenName) const; + QScreen *screenAt(const QPoint &pos) const; QString primary() const; int screenRawWidth() const; int screenRawHeight() const; @@ -48,10 +44,8 @@ private Q_SLOTS: void onGSettingsChanged(const QString &key); Q_SIGNALS: - void primaryScreenChanged(QScreen *s); + void primaryScreenChanged(); void screenInfoChanged(); // 屏幕信息发生变化,需要调整任务栏显示,只需要这一个信号,其他的都不要,简化流程 - void screenAdded(QScreen *s); - void screenRemoved(QScreen *s); private: QList m_screens; diff --git a/frame/drag/quickdragcore.cpp b/frame/drag/quickdragcore.cpp new file mode 100644 index 000000000..80353b3e8 --- /dev/null +++ b/frame/drag/quickdragcore.cpp @@ -0,0 +1,152 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "quickdragcore.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QuickPluginMimeData::QuickPluginMimeData(PluginsItemInterface *item, QDrag *drag) + : QMimeData() + , m_item(item) + , m_drag(drag) +{ +} + +QuickPluginMimeData::~QuickPluginMimeData() +{ +} + +PluginsItemInterface *QuickPluginMimeData::pluginItemInterface() const +{ + return m_item; +} + +QDrag *QuickPluginMimeData::drag() const +{ + return m_drag; +} + +/** + * @brief 拖动图标的窗口,可以根据实际情况设置动态图标 + * @param dragSource + */ +QuickIconDrag::QuickIconDrag(QObject *dragSource, const QPixmap &pixmap) + : QDrag(dragSource) + , m_imageWidget(new QWidget) + , m_timer(new QTimer(this)) + , m_sourcePixmap(pixmap) + , m_hotPoint(QPoint(0, 0)) +{ + m_timer->setInterval(10); + connect(m_timer, &QTimer::timeout, this, &QuickIconDrag::onDragMove); + m_timer->start(); + + m_imageWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowDoesNotAcceptFocus); + m_imageWidget->setAttribute(Qt::WA_TransparentForMouseEvents); + m_imageWidget->installEventFilter(this); + useSourcePixmap(); +} + +QuickIconDrag::~QuickIconDrag() +{ + m_imageWidget->deleteLater(); +} + +void QuickIconDrag::updatePixmap(QPixmap pixmap) +{ + if (m_sourcePixmap == pixmap) + return; + + m_pixmap = pixmap; + m_useSourcePixmap = false; + m_imageWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); + m_imageWidget->setFixedSize(pixmap.size()); + m_imageWidget->show(); + m_imageWidget->raise(); + m_imageWidget->update(); +} + +void QuickIconDrag::useSourcePixmap() +{ + m_useSourcePixmap = true; + m_imageWidget->setFixedSize(m_sourcePixmap.size() / qApp->devicePixelRatio()); + m_imageWidget->show(); + m_imageWidget->raise(); + m_imageWidget->update(); +} + +void QuickIconDrag::setDragHotPot(QPoint point) +{ + m_hotPoint = point; + m_imageWidget->update(); +} + +bool QuickIconDrag::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_imageWidget) { + switch (event->type()) { + case QEvent::Paint: { + QPixmap pixmap = m_useSourcePixmap ? m_sourcePixmap : m_pixmap; + QPainter painter(m_imageWidget); + painter.drawPixmap(QPoint(0, 0), pixmap); + + QPixmap pixmapMask(m_imageWidget->size()); + pixmapMask.fill(Qt::transparent); + QPainter painterMask(&pixmapMask); + QPainterPath path; + path.addRoundedRect(pixmapMask.rect(), 8, 8); + painterMask.fillPath(path, Qt::white); + painterMask.setRenderHint(QPainter::Antialiasing, true); + painterMask.setCompositionMode(QPainter::CompositionMode_Source); + painterMask.drawPixmap(0, 0, pixmap); + painterMask.setCompositionMode(QPainter::CompositionMode_DestinationIn); + QColor maskColor(Qt::black); + maskColor.setAlpha(150); + painterMask.fillRect(pixmapMask.rect(), maskColor); + painterMask.end(); + + // 绘制圆角 + QBitmap radiusMask(m_imageWidget->size()); + radiusMask.fill(); + QPainter radiusPainter(&radiusMask); + radiusPainter.setPen(Qt::NoPen); + radiusPainter.setBrush(Qt::black); + radiusPainter.setRenderHint(QPainter::Antialiasing); + radiusPainter.drawRoundedRect(radiusMask.rect(), 8, 8); + m_imageWidget->setMask(radiusMask); + + painter.end(); + break; + } + default: + break; + } + } + return QDrag::eventFilter(watched, event); +} + +QPoint QuickIconDrag::currentPoint() const +{ + QPoint mousePos = QCursor::pos(); + if (m_useSourcePixmap) + return mousePos - m_hotPoint; + + QSize pixmapSize = m_pixmap.size(); + return (mousePos - QPoint(pixmapSize.width() * (m_hotPoint.x() / m_sourcePixmap.width()) + , pixmapSize.height() * (m_hotPoint.y() / m_sourcePixmap.height()))); +} + +void QuickIconDrag::onDragMove() +{ + m_imageWidget->move(currentPoint()); +} diff --git a/frame/drag/quickdragcore.h b/frame/drag/quickdragcore.h new file mode 100644 index 000000000..996b80a70 --- /dev/null +++ b/frame/drag/quickdragcore.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef QUICKDRAGCORE_H +#define QUICKDRAGCORE_H + +#include +#include +#include + +class PluginsItemInterface; +class QTimer; + +class QuickPluginMimeData : public QMimeData +{ + Q_OBJECT + +public: + explicit QuickPluginMimeData(PluginsItemInterface *item, QDrag *drag); + ~QuickPluginMimeData(); + PluginsItemInterface *pluginItemInterface() const; + QDrag *drag() const; + +private: + PluginsItemInterface *m_item; + QDrag *m_drag; +}; + +class QuickIconDrag : public QDrag +{ + Q_OBJECT + +public: + explicit QuickIconDrag(QObject *dragSource, const QPixmap &pixmap); + ~QuickIconDrag(); + void updatePixmap(QPixmap pixmap); + void useSourcePixmap(); + void setDragHotPot(QPoint point); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + QPoint currentPoint() const; + +private Q_SLOTS: + void onDragMove(); + +private: + QWidget *m_imageWidget; + QTimer *m_timer; + QPixmap m_sourcePixmap; + QPixmap m_pixmap; + QPoint m_hotPoint; + bool m_useSourcePixmap; +}; + +#endif // QUICKDRAGCORE_H diff --git a/frame/item/appitem.cpp b/frame/item/appitem.cpp index 1b6f7b389..afa39a1f2 100644 --- a/frame/item/appitem.cpp +++ b/frame/item/appitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,6 +8,7 @@ #include "xcb_misc.h" #include "appswingeffectbuilder.h" #include "utils.h" +#include "screenspliter.h" #include #include @@ -31,18 +33,17 @@ DCORE_USE_NAMESPACE QPoint AppItem::MousePressPos; -AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent) +AppItem::AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent) : DockItem(parent) , m_appSettings(appSettings) , m_activeAppSettings(activeAppSettings) , m_dockedAppSettings(dockedAppSettings) , m_appPreviewTips(nullptr) - , m_itemEntryInter(new DockEntryInter("com.deepin.dde.daemon.Dock", entry.path(), QDBusConnection::sessionBus(), this)) + , m_itemEntryInter(new DockEntryInter(dockServiceName(), entry.path(), QDBusConnection::sessionBus(), this)) , m_swingEffectView(nullptr) , m_itemAnimation(nullptr) , m_wmHelper(DWindowManagerHelper::instance()) , m_drag(nullptr) - , m_dragging(false) , m_retryTimes(0) , m_iconValid(true) , m_lastclickTimes(0) @@ -51,6 +52,9 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti , m_retryObtainIconTimer(new QTimer(this)) , m_refershIconTimer(new QTimer(this)) , m_themeType(DGuiApplicationHelper::instance()->themeType()) + , m_createMSecs(QDateTime::currentMSecsSinceEpoch()) + , m_screenSpliter(ScreenSpliterFactory::createScreenSpliter(this, m_itemEntryInter)) + , m_dockInter(dockInter) { QHBoxLayout *centralLayout = new QHBoxLayout; centralLayout->setMargin(0); @@ -62,7 +66,6 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti m_id = m_itemEntryInter->id(); m_active = m_itemEntryInter->isActive(); - m_currentWindowId = m_itemEntryInter->currentWindow(); m_updateIconGeometryTimer->setInterval(500); m_updateIconGeometryTimer->setSingleShot(true); @@ -77,13 +80,13 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti connect(m_itemEntryInter, &DockEntryInter::IsActiveChanged, this, static_cast(&AppItem::update)); connect(m_itemEntryInter, &DockEntryInter::WindowInfosChanged, this, &AppItem::updateWindowInfos, Qt::QueuedConnection); connect(m_itemEntryInter, &DockEntryInter::IconChanged, this, &AppItem::refreshIcon); - - connect(m_retryObtainIconTimer, &QTimer::timeout, this, &AppItem::refreshIcon, Qt::QueuedConnection); + connect(m_itemEntryInter, &DockEntryInter::ModeChanged, this, &AppItem::modeChanged); connect(m_updateIconGeometryTimer, &QTimer::timeout, this, &AppItem::updateWindowIconGeometries, Qt::QueuedConnection); + connect(m_retryObtainIconTimer, &QTimer::timeout, this, &AppItem::refreshIcon, Qt::QueuedConnection); + connect(this, &AppItem::requestUpdateEntryGeometries, this, &AppItem::updateWindowIconGeometries); updateWindowInfos(m_itemEntryInter->windowInfos()); - refreshIcon(); if (m_appSettings) connect(m_appSettings, &QGSettings::changed, this, &AppItem::onGSettingsChanged); @@ -111,6 +114,11 @@ const QString AppItem::appId() const return m_id; } +QString AppItem::name() const +{ + return m_itemEntryInter->name(); +} + bool AppItem::isValid() const { return m_itemEntryInter->isValid() && !m_itemEntryInter->id().isEmpty(); @@ -121,14 +129,12 @@ bool AppItem::isValid() const // window behaviors like minimization. void AppItem::updateWindowIconGeometries() { + // wayland没做处理 + if (Utils::IS_WAYLAND_DISPLAY) + return; + const QRect r(mapToGlobal(QPoint(0, 0)), mapToGlobal(QPoint(width(), height()))); - - if (Utils::IS_WAYLAND_DISPLAY){ - Q_EMIT requestUpdateItemMinimizedGeometry(r); - return; - } - if (!QX11Info::connection()) { qWarning() << "QX11Info::connection() is 0x0"; return; @@ -164,11 +170,72 @@ void AppItem::setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry } } +void AppItem::setDraging(bool drag) +{ + if (drag == isDragging()) + return; + + DockItem::setDraging(drag); + if (!drag) + m_screenSpliter->releaseSplit(); +} + +void AppItem::startSplit(const QRect &rect) +{ + m_screenSpliter->startSplit(rect); +} + +bool AppItem::supportSplitWindow() +{ + return m_screenSpliter->suportSplitScreen(); +} + +bool AppItem::splitWindowOnScreen(ScreenSpliter::SplitDirection direction) +{ + return m_screenSpliter->split(direction); +} + +int AppItem::mode() const +{ + return m_itemEntryInter->mode(); +} + + +DockEntryInter *AppItem::itemEntryInter() const +{ + return m_itemEntryInter; +} + QString AppItem::accessibleName() { return m_itemEntryInter->name(); } +void AppItem::requestDock() +{ + m_itemEntryInter->RequestDock(); +} + +bool AppItem::isDocked() const +{ + return m_itemEntryInter->isDocked(); +} + +qint64 AppItem::appOpenMSecs() const +{ + return m_createMSecs; +} + +void AppItem::updateMSecs() +{ + m_createMSecs = QDateTime::currentMSecsSinceEpoch(); +} + +const WindowInfoMap &AppItem::windowsMap() const +{ + return m_windowInfos; +} + void AppItem::moveEvent(QMoveEvent *e) { DockItem::moveEvent(e); @@ -183,10 +250,8 @@ void AppItem::moveEvent(QMoveEvent *e) void AppItem::paintEvent(QPaintEvent *e) { DockItem::paintEvent(e); - if (m_draging) - return; - if (m_dragging || (m_swingEffectView != nullptr && DockDisplayMode != Fashion)) + if (isDragging() || (m_swingEffectView != nullptr && DockDisplayMode != Fashion)) return; QPainter painter(this); @@ -207,13 +272,21 @@ void AppItem::paintEvent(QPaintEvent *e) QPainterPath path; path.addRoundedRect(backgroundRect, 8, 8); - if (m_active) { - painter.fillPath(path, QColor(0, 0, 0, 255 * 0.8)); - } else if (!m_windowInfos.isEmpty()) { - if (hasAttention()) - painter.fillPath(path, QColor(241, 138, 46, 255 * .8)); - else - painter.fillPath(path, QColor(0, 0, 0, 255 * 0.3)); + // 在没有开启窗口多开的情况下,显示背景色 + if (!m_dockInter->showMultiWindow()) { + if (m_active) { + QColor color = Qt::black; + color.setAlpha(255 * 0.8); + painter.fillPath(path, color); + } else if (!m_windowInfos.isEmpty()) { + if (hasAttention()) { + painter.fillPath(path, QColor(241, 138, 46, 255 * .8)); + } else { + QColor color = Qt::black; + color.setAlpha(255 * 0.3); + painter.fillPath(path, color); + } + } } } else { if (!m_windowInfos.isEmpty()) { @@ -307,11 +380,16 @@ void AppItem::mouseReleaseEvent(QMouseEvent *e) qDebug() << "app item clicked, name:" << m_itemEntryInter->name() << "id:" << m_itemEntryInter->id() << "my-id:" << m_id << "icon:" << m_itemEntryInter->icon(); - m_itemEntryInter->Activate(QX11Info::getTimestamp()); - - // play launch effect - if (m_windowInfos.isEmpty() && DGuiApplicationHelper::isSpecialEffectsEnvironment()) - playSwingEffect(); + if (m_dockInter->showMultiWindow()) { + // 如果开启了多窗口显示,则直接新建一个窗口 + m_itemEntryInter->NewInstance(QX11Info::getTimestamp()); + } else { + // 如果没有开启新窗口显示,则 + m_itemEntryInter->Activate(QX11Info::getTimestamp()); + // play launch effect + if (m_windowInfos.isEmpty() && DGuiApplicationHelper::isSpecialEffectsEnvironment()) + playSwingEffect(); + } } } @@ -334,6 +412,10 @@ void AppItem::mouseMoveEvent(QMouseEvent *e) { e->accept(); + // handle preview + // if (e->buttons() == Qt::NoButton) + // return showPreview(); + // handle drag if (e->buttons() != Qt::LeftButton) return; @@ -341,6 +423,10 @@ void AppItem::mouseMoveEvent(QMouseEvent *e) const QPoint pos = e->pos(); if (!rect().contains(pos)) return; + + const QPoint distance = pos - MousePressPos; + if (distance.manhattanLength() > APP_DRAG_THRESHOLD) + return startDrag(); } void AppItem::wheelEvent(QWheelEvent *e) @@ -449,7 +535,7 @@ QWidget *AppItem::popupTips() if (checkGSettingsControl()) return nullptr; - if (m_dragging) + if (isDragging()) return nullptr; static TipsWidget appNameTips(topLevelWidget()); @@ -457,8 +543,9 @@ QWidget *AppItem::popupTips() appNameTips.setObjectName(m_itemEntryInter->name()); if (!m_windowInfos.isEmpty()) { - Q_ASSERT(m_windowInfos.contains(m_currentWindowId)); - appNameTips.setText(m_windowInfos[m_currentWindowId].title.simplified()); + const quint32 currentWindow = m_itemEntryInter->currentWindow(); + Q_ASSERT(m_windowInfos.contains(currentWindow)); + appNameTips.setText(m_windowInfos[currentWindow].title.simplified()); } else { appNameTips.setText(m_itemEntryInter->name().simplified()); } @@ -466,6 +553,57 @@ QWidget *AppItem::popupTips() return &appNameTips; } +void AppItem::startDrag() +{ + // 拖拽实现放到mainpanelcontrol + + /* + if (!acceptDrops()) + return; + + if (checkGSettingsControl()) { + return; + } + + m_dragging = true; + update(); + + const QPixmap &dragPix = m_appIcon; + + m_drag = new AppDrag(this); + m_drag->setMimeData(new QMimeData); + + // handle drag finished here + connect(m_drag->appDragWidget(), &AppDragWidget::destroyed, this, [ = ] { + m_dragging = false; + m_drag.clear(); + setVisible(true); + update(); + }); + + if (m_wmHelper->hasComposite()) { + m_drag->setPixmap(dragPix); + m_drag->appDragWidget()->setOriginPos(mapToGlobal(appIconPosition())); + emit dragStarted(); + m_drag->exec(Qt::MoveAction); + } else { + m_drag->QDrag::setPixmap(dragPix); + m_drag->setHotSpot(dragPix.rect().center() / dragPix.devicePixelRatioF()); + emit dragStarted(); + m_drag->QDrag::exec(Qt::MoveAction); + } + + // MainPanel will put this item to Item-Container when received this signal(MainPanel::itemDropped) + //emit itemDropped(m_drag->target()); + + if (!m_wmHelper->hasComposite()) { + if (!m_drag->target()) { + m_itemEntryInter->RequestUndock(); + } + } + */ +} + bool AppItem::hasAttention() const { auto it = std::find_if(m_windowInfos.constBegin(), m_windowInfos.constEnd(), [ = ] (const auto &info) { @@ -488,8 +626,11 @@ QPoint AppItem::appIconPosition() const void AppItem::updateWindowInfos(const WindowInfoMap &info) { + // 如果是打开第一个窗口,则更新窗口时间 + if (m_windowInfos.isEmpty() && !info.isEmpty()) + updateMSecs(); + m_windowInfos = info; - m_currentWindowId = info.firstKey(); if (m_appPreviewTips) m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value()); m_updateIconGeometryTimer->start(); @@ -503,6 +644,9 @@ void AppItem::updateWindowInfos(const WindowInfoMap &info) } update(); + + // 通知外面窗体数量发生变化,需要更新多开窗口的信息 + Q_EMIT windowCountChanged(); } void AppItem::refreshIcon() @@ -540,7 +684,9 @@ void AppItem::refreshIcon() update(); return; - } else if (m_retryTimes > 0) { + } + + if (m_retryTimes > 0) { // reset times m_retryTimes = 0; } @@ -578,7 +724,6 @@ void AppItem::showPreview() return; m_appPreviewTips = new PreviewContainer; - m_appPreviewTips->updateDockSize(DockSize); m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value()); m_appPreviewTips->updateLayoutDirection(DockPosition); @@ -593,19 +738,11 @@ void AppItem::showPreview() connect(m_appPreviewTips, &PreviewContainer::requestHidePopup, this, &AppItem::onResetPreview); // 预览标题显示方式的配置 - DConfig *config = DConfig::create("org.deepin.dde.dock", "org.deepin.dde.dock"); - if (config->isValid() && config->keyList().contains("showWindowName")) - m_appPreviewTips->setTitleDisplayMode(config->value("showWindowName").toInt()); - delete config; + DConfig config(QString("com.deepin.dde.dock.dconfig"), QString()); + if (config.isValid() && config.keyList().contains("Dock_Show_Window_name")) + m_appPreviewTips->setTitleDisplayMode(config.value("Dock_Show_Window_name").toInt()); - // 设置预览界面是否开启左右两边的圆角 - if (!PopupWindow.isNull() && m_wmHelper->hasComposite()) { - PopupWindow->setLeftRightRadius(true); - } else { - PopupWindow->setLeftRightRadius(false); - } - - showPopupWindow(m_appPreviewTips, true, 18); + showPopupWindow(m_appPreviewTips, true); } void AppItem::playSwingEffect() diff --git a/frame/item/appitem.h b/frame/item/appitem.h index fe2abb3c2..1a310895e 100644 --- a/frame/item/appitem.h +++ b/frame/item/appitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,47 +9,58 @@ #include "dockitem.h" #include "previewcontainer.h" #include "appdrag.h" -#include "dbusclientmanager.h" #include "../widgets/tipswidget.h" +#include "dbusutil.h" #include #include #include #include -#include - -using DockEntryInter = com::deepin::dde::daemon::dock::Entry; class QGSettings; +class ScreenSpliter; class AppItem : public DockItem { Q_OBJECT public: - explicit AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent = nullptr); + explicit AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent = nullptr); ~AppItem() override; void checkEntry() override; const QString appId() const; + QString name() const; bool isValid() const; void updateWindowIconGeometries(); void undock(); QWidget *appDragWidget(); void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry); + void setDraging(bool drag) override; + void startSplit(const QRect &rect); + bool supportSplitWindow(); + bool splitWindowOnScreen(ScreenSpliter::SplitDirection direction); + int mode() const; + DockEntryInter *itemEntryInter() const; inline ItemType itemType() const override { return App; } QPixmap appIcon(){ return m_appIcon; } virtual QString accessibleName() override; - inline quint32 getAppItemWindowId() const { return m_currentWindowId; } + void requestDock(); + bool isDocked() const; + qint64 appOpenMSecs() const; + void updateMSecs(); + const WindowInfoMap &windowsMap() const; signals: void requestActivateWindow(const WId wid) const; void requestPreviewWindow(const WId wid) const; void requestCancelPreview() const; void dragReady(QWidget *dragWidget); + void requestUpdateEntryGeometries() const; - void requestUpdateItemMinimizedGeometry(const QRect) const; + void windowCountChanged() const; + void modeChanged(int) const; private: void moveEvent(QMoveEvent *e) override; @@ -68,6 +80,7 @@ private: void invokedMenuItem(const QString &itemId, const bool checked) override; const QString contextMenu() const override; QWidget *popupTips() override; + void startDrag(); bool hasAttention() const; QPoint appIconPosition() const; @@ -102,11 +115,9 @@ private: QPointer m_drag; - bool m_dragging; bool m_active; int m_retryTimes; bool m_iconValid; - quint32 m_currentWindowId; quint64 m_lastclickTimes; WindowInfoMap m_windowInfos; @@ -124,8 +135,12 @@ private: QDate m_curDate; // 保存当前icon的日期来判断是否需要更新日历APP的ICON DGuiApplicationHelper::ColorType m_themeType; + qint64 m_createMSecs; static QPoint MousePressPos; + + ScreenSpliter *m_screenSpliter; + DockInter *m_dockInter; }; #endif // APPITEM_H diff --git a/frame/item/appmultiitem.cpp b/frame/item/appmultiitem.cpp new file mode 100644 index 000000000..f6b35bbc3 --- /dev/null +++ b/frame/item/appmultiitem.cpp @@ -0,0 +1,143 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "appitem.h" +#include "appmultiitem.h" +#include "imageutil.h" +#include "themeappicon.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +AppMultiItem::AppMultiItem(AppItem *appItem, WId winId, const WindowInfo &windowInfo, QWidget *parent) + : DockItem(parent) + , m_appItem(appItem) + , m_windowInfo(windowInfo) + , m_entryInter(appItem->itemEntryInter()) + , m_winId(winId) + , m_menu(new QMenu(this)) +{ + initMenu(); + initConnection(); +} + +AppMultiItem::~AppMultiItem() +{ +} + +QSize AppMultiItem::suitableSize(int size) const +{ + return QSize(size, size); +} + +AppItem *AppMultiItem::appItem() const +{ + return m_appItem; +} + +quint32 AppMultiItem::winId() const +{ + return m_winId; +} + +const WindowInfo &AppMultiItem::windowInfo() const +{ + return m_windowInfo; +} + +DockItem::ItemType AppMultiItem::itemType() const +{ + return DockItem::AppMultiWindow; +} + +void AppMultiItem::initMenu() +{ + QAction *actionOpen = new QAction(m_menu); + actionOpen->setText(tr("Open")); + connect(actionOpen, &QAction::triggered, this, &AppMultiItem::onOpen); + m_menu->addAction(actionOpen); +} + +void AppMultiItem::initConnection() +{ + connect(m_entryInter, &DockEntryInter::CurrentWindowChanged, this, &AppMultiItem::onCurrentWindowChanged); +} + +void AppMultiItem::onOpen() +{ + m_entryInter->ActiveWindow(m_winId); +} + +void AppMultiItem::onCurrentWindowChanged(uint32_t value) +{ + if (value != m_winId) + return; + + update(); +} + +void AppMultiItem::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); + + if (m_pixmap.isNull()) + m_pixmap = ImageUtil::loadWindowThumb(Utils::IS_WAYLAND_DISPLAY ? m_windowInfo.uuid : QString::number(m_winId)); + + DStyleHelper dstyle(style()); + const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius); + QRect itemRect = rect(); + itemRect.marginsRemoved(QMargins(6, 6, 6, 6)); + QPainterPath path; + path.addRoundedRect(rect(), radius, radius); + painter.fillPath(path, Qt::transparent); + + if (m_entryInter->currentWindow() == m_winId) { + QColor backColor = Qt::black; + backColor.setAlpha(255 * 0.8); + painter.fillPath(path, backColor); + } + + itemRect = m_pixmap.rect(); + int itemWidth = itemRect.width(); + int itemHeight = itemRect.height(); + int x = (rect().width() - itemWidth) / 2; + int y = (rect().height() - itemHeight) / 2; + painter.drawPixmap(QRect(x, y, itemWidth, itemHeight), m_pixmap); + + QPixmap pixmapAppIcon; + ThemeAppIcon::getIcon(pixmapAppIcon, m_entryInter->icon(), qMin(width(), height()) * 0.8); + if (!pixmapAppIcon.isNull()) { + // 绘制下方的图标,下方的小图标大约为应用图标的三分之一的大小 + //pixmap = pixmap.scaled(pixmap.width() * 0.3, pixmap.height() * 0.3); + QRect rectIcon = rect(); + int iconWidth = rectIcon.width() * 0.3; + int iconHeight = rectIcon.height() * 0.3; + rectIcon.setX((rect().width() - iconWidth) * 0.5); + rectIcon.setY(rect().height() - iconHeight); + rectIcon.setWidth(iconWidth); + rectIcon.setHeight(iconHeight); + painter.drawPixmap(rectIcon, pixmapAppIcon); + } +} + +void AppMultiItem::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + m_entryInter->ActiveWindow(m_winId); + } else { + QPoint currentPoint = QCursor::pos(); + m_menu->exec(currentPoint); + } +} diff --git a/frame/item/appmultiitem.h b/frame/item/appmultiitem.h new file mode 100644 index 000000000..00ad52470 --- /dev/null +++ b/frame/item/appmultiitem.h @@ -0,0 +1,52 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef APPMULTIITEM_H +#define APPMULTIITEM_H + +#include "dockitem.h" +#include "dbusutil.h" + +class AppItem; + +class AppMultiItem : public DockItem +{ + Q_OBJECT + + friend class AppItem; + +public: + AppMultiItem(AppItem *appItem, WId winId, const WindowInfo &windowInfo, QWidget *parent = Q_NULLPTR); + ~AppMultiItem() override; + + QSize suitableSize(int size) const; + AppItem *appItem() const; + quint32 winId() const; + const WindowInfo &windowInfo() const; + + ItemType itemType() const override; + +protected: + void paintEvent(QPaintEvent *) override; + void mouseReleaseEvent(QMouseEvent *event) override; + +private: + void initMenu(); + void initConnection(); + +private Q_SLOTS: + void onOpen(); + void onCurrentWindowChanged(uint32_t value); + +private: + AppItem *m_appItem; + WindowInfo m_windowInfo; + DockEntryInter *m_entryInter; + QPixmap m_pixmap; + WId m_winId; + QMenu *m_menu; +}; + +#endif // APPMULTIITEM_H diff --git a/frame/item/arrow-down.svg b/frame/item/arrow-down.svg new file mode 100644 index 000000000..f2a7454e6 --- /dev/null +++ b/frame/item/arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/arrow-left.svg b/frame/item/arrow-left.svg new file mode 100644 index 000000000..947aca4ee --- /dev/null +++ b/frame/item/arrow-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/arrow-right.svg b/frame/item/arrow-right.svg new file mode 100644 index 000000000..c4f4b01ad --- /dev/null +++ b/frame/item/arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/arrow-up.svg b/frame/item/arrow-up.svg new file mode 100644 index 000000000..dc7f8328b --- /dev/null +++ b/frame/item/arrow-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/components/appdrag.cpp b/frame/item/components/appdrag.cpp index 90b65fab7..771582784 100644 --- a/frame/item/components/appdrag.cpp +++ b/frame/item/components/appdrag.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -10,10 +11,13 @@ #include -AppDrag::AppDrag(QObject *dragSource) +AppDrag::AppDrag(QObject *dragSource, AppDragWidget *dragWidget) : QDrag(dragSource) - , m_appDragWidget(new AppDragWidget) + , m_appDragWidget(dragWidget) { + if (!m_appDragWidget) + m_appDragWidget = new AppDragWidget; + // delete by itself m_appDragWidget->setVisible(false); diff --git a/frame/item/components/appdrag.h b/frame/item/components/appdrag.h index fb63595b8..fa8dc172f 100644 --- a/frame/item/components/appdrag.h +++ b/frame/item/components/appdrag.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,7 +14,7 @@ class AppDrag : public QDrag { public: - explicit AppDrag(QObject *dragSource); + explicit AppDrag(QObject *dragSource, AppDragWidget *dragWidget = Q_NULLPTR); virtual ~AppDrag(); void setPixmap(const QPixmap &); diff --git a/frame/item/components/appdragwidget.cpp b/frame/item/components/appdragwidget.cpp index 99bb9e14a..5aa8a2c5b 100644 --- a/frame/item/components/appdragwidget.cpp +++ b/frame/item/components/appdragwidget.cpp @@ -1,10 +1,20 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "../appitem.h" #include "appdragwidget.h" #include "utils.h" +#include "displaymanager.h" + +#include "org_deepin_dde_xeventmonitor1.h" + +#define SPLIT_NONE 0 +#define SPLIT_LEFT 1 +#define SPLIT_RIGHT 2 + +using XEventMonitor = ::org::deepin::dde::XEventMonitor1; AppDragWidget::AppDragWidget(QWidget *parent) : QGraphicsView(parent) @@ -17,34 +27,29 @@ AppDragWidget::AppDragWidget(QWidget *parent) , m_animGroup(new QParallelAnimationGroup(this)) , m_goBackAnim(new QPropertyAnimation(this, "pos", this)) , m_dockPosition(Dock::Position::Bottom) - , m_removeTips(new TipsWidget(this)) , m_popupWindow(new DockPopupWindow(nullptr)) , m_distanceMultiple(Utils::SettingValue("com.deepin.dde.dock.distancemultiple", "/com/deepin/dde/dock/distancemultiple/", "distance-multiple", 1.5).toDouble()) , m_item(nullptr) - , m_cursorPosition(-1, -1) + , m_dockScreen(nullptr) { - m_removeTips->setText(tr("Remove")); - m_removeTips->setObjectName("AppRemoveTips"); - m_removeTips->setVisible(false); - m_removeTips->installEventFilter(this); - m_popupWindow->setShadowBlurRadius(20); m_popupWindow->setRadius(18); m_popupWindow->setShadowYOffset(2); m_popupWindow->setShadowXOffset(0); m_popupWindow->setArrowWidth(18); m_popupWindow->setArrowHeight(10); + m_popupWindow->setRadius(18); m_scene->addItem(m_object.get()); setScene(m_scene); - setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); setAttribute(Qt::WA_TranslucentBackground); if (Utils::IS_WAYLAND_DISPLAY) { - setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Window); + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Window | Qt::FramelessWindowHint); setAttribute(Qt::WA_NativeWindow); + initWaylandEnv(); } else { - setAcceptDrops(true); + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); } viewport()->setAutoFillBackground(false); setFrameShape(QFrame::NoFrame); @@ -52,12 +57,24 @@ AppDragWidget::AppDragWidget(QWidget *parent) setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setMouseTracking(true); + setAcceptDrops(true); + initAnimations(); - m_followMouseTimer->setInterval(16); - connect(m_followMouseTimer, &QTimer::timeout, this, &AppDragWidget::onFollowMouse); - m_followMouseTimer->start(); - QTimer::singleShot(0, this, &AppDragWidget::onFollowMouse); + if (!Utils::IS_WAYLAND_DISPLAY) { + m_followMouseTimer->setInterval(16); + connect(m_followMouseTimer, &QTimer::timeout, this, &AppDragWidget::onFollowMouse); + m_followMouseTimer->start(); + QTimer::singleShot(0, this, &AppDragWidget::onFollowMouse); + } +} + +void AppDragWidget::execFinished() +{ + if (!m_bDragDrop) + return; + + dropHandler(QCursor::pos()); } void AppDragWidget::mouseMoveEvent(QMouseEvent *event) @@ -72,24 +89,17 @@ void AppDragWidget::mouseMoveEvent(QMouseEvent *event) void AppDragWidget::dragEnterEvent(QDragEnterEvent *event) { - if (Utils::IS_WAYLAND_DISPLAY) { - QGraphicsView::dragEnterEvent(event); - } else { - event->accept(); - m_bDragDrop = true; - } + event->accept(); + m_bDragDrop = true; } void AppDragWidget::dragMoveEvent(QDragMoveEvent *event) { - if (Utils::IS_WAYLAND_DISPLAY) { - QGraphicsView::dragMoveEvent(event); - } else { - showRemoveTips(); - if (isRemoveItem() && m_bDragDrop) { - emit requestRemoveItem(); - } - } + if (Utils::IS_WAYLAND_DISPLAY) + return QGraphicsView::dragMoveEvent(event); + + if (m_bDragDrop) + moveHandler(QCursor::pos()); } /**获取应用的左上角坐标 @@ -129,7 +139,7 @@ const QPoint AppDragWidget::popupMarkPoint(Dock::Position pos) break; case Bottom: if (!DWindowManagerHelper::instance()->hasComposite()) { - p += QPoint(size().width() / 2 , -r.height() / 2); + p += QPoint(0 , -r.height() / 2); } else { p += QPoint(r.width() / 2, 0); } @@ -146,29 +156,11 @@ const QPoint AppDragWidget::popupMarkPoint(Dock::Position pos) void AppDragWidget::dropEvent(QDropEvent *event) { - if (Utils::IS_WAYLAND_DISPLAY) { - QGraphicsView::dropEvent(event); - } else { - m_followMouseTimer->stop(); - m_bDragDrop = false; + if (Utils::IS_WAYLAND_DISPLAY) + return dropEvent(event); - if (isRemoveAble(QCursor::pos())) { - if (DWindowManagerHelper::instance()->hasComposite()) { - showRemoveAnimation(); - } else { - hide(); - } - AppItem *appItem = static_cast((Utils::IS_WAYLAND_DISPLAY && m_item) ? m_item : event->source()); - appItem->undock(); - m_popupWindow->setVisible(false); - } else { - if (DWindowManagerHelper::instance()->hasComposite()) { - showGoBackAnimation(); - } else { - hide(); - } - } - } + m_followMouseTimer->stop(); + dropHandler(QCursor::pos()); } void AppDragWidget::hideEvent(QHideEvent *event) @@ -178,6 +170,49 @@ void AppDragWidget::hideEvent(QHideEvent *event) QGraphicsView::hideEvent(event); } +void AppDragWidget::dropHandler(const QPoint &pos) +{ + m_bDragDrop = false; + + if (canSplitWindow(pos)) { + if (DWindowManagerHelper::instance()->hasComposite()) { + showRemoveAnimation(); + } else { + hide(); + } + m_popupWindow->setVisible(false); + Q_EMIT requestSplitWindow(splitPosition()); + } else { + if (DWindowManagerHelper::instance()->hasComposite()) { + showGoBackAnimation(); + } else { + hide(); + } + } +} + +void AppDragWidget::moveHandler(const QPoint &pos) +{ + if (canSplitWindow(pos)) { + QRect screenGeometry = splitGeometry(pos); + if (screenGeometry.isValid() && screenGeometry != m_lastMouseGeometry) { + qDebug() << "change area:" << screenGeometry; + Q_EMIT requestChangedArea(screenGeometry); + m_lastMouseGeometry = screenGeometry; + } + } +} + +void AppDragWidget::moveCurrent(const QPoint &destPos) +{ + if (DWindowManagerHelper::instance()->hasComposite()) { + move(destPos.x() - width() / 2, destPos.y() - height() / 2); + } else { + // 窗口特效未开启时会隐藏m_object绘制的图标,移动的图标为QDrag绘制的图标 + move(destPos.x(), destPos.y()); + } +} + void AppDragWidget::setAppPixmap(const QPixmap &pix) { if (DWindowManagerHelper::instance()->hasComposite()) { @@ -205,7 +240,7 @@ void AppDragWidget::setOriginPos(const QPoint position) void AppDragWidget::setPixmapOpacity(qreal opacity) { - if (isRemoveAble(QCursor::pos())) { + if (canSplitWindow(QCursor::pos())) { m_object->setOpacity(opacity); m_animOpacity->setStartValue(opacity); } else { @@ -214,34 +249,6 @@ void AppDragWidget::setPixmapOpacity(qreal opacity) } } -bool AppDragWidget::isRemoveable(const Position &dockPos, const QRect &doctRect) -{ - const QPoint &p = QCursor::pos(); - switch (dockPos) { - case Dock::Position::Left: - if ((p.x() - doctRect.topRight().x()) > (doctRect.width() * 3)) { - return true; - } - break; - case Dock::Position::Top: - if ((p.y() - doctRect.bottomLeft().y()) > (doctRect.height() * 3)) { - return true; - } - break; - case Dock::Position::Right: - if ((doctRect.topLeft().x() - p.x()) > (doctRect.width() * 3)) { - return true; - } - break; - case Dock::Position::Bottom: - if ((doctRect.topLeft().y() - p.y()) > (doctRect.height() * 3)) { - return true; - } - break; - } - return false; -} - void AppDragWidget::initAnimations() { m_animScale->setDuration(300); @@ -297,12 +304,227 @@ void AppDragWidget::onRemoveAnimationStateChanged(QAbstractAnimation::State newS } } +/** 判断应用区域图标是否被拖出任务栏 + * @brief AppDragWidget::canSplitWindow + * @return 返回true应用移出任务栏,false应用在任务栏内 + */ +bool AppDragWidget::canSplitWindow(const QPoint &pos) const +{ + switch (m_dockPosition) { + case Dock::Position::Left: + if ((pos.x() > m_dockGeometry.topRight().x())) { + return true; + } + break; + case Dock::Position::Top: + if ((pos.y() > m_dockGeometry.bottomLeft().y())) { + return true; + } + break; + case Dock::Position::Right: + if ((m_dockGeometry.topLeft().x() > pos.x())) { + return true; + } + break; + case Dock::Position::Bottom: + if ((m_dockGeometry.topLeft().y() > pos.y())) { + return true; + } + break; + } + + return false; +} + +/** + * @brief AppDragWidget::splitPosition + * @return 1 左分屏;2 右分屏;5 左上;6 右上;9 左下;10 右下;15全屏。这些值是窗管给的 + */ +ScreenSpliter::SplitDirection AppDragWidget::splitPosition() const +{ + QPoint pos = QCursor::pos(); + QScreen *currentScreen = DisplayManager::instance()->screenAt(pos); + + if (!currentScreen) + return ScreenSpliter::None; + + int xCenter = currentScreen->geometry().x() + currentScreen->size().width() / 2; + // 1表示左分屏 + if (pos.x() < xCenter) + return ScreenSpliter::Left; + + // 2表示右分屏 + if (pos.x() > xCenter) + return ScreenSpliter::Right; + + return ScreenSpliter::None; +} + +void AppDragWidget::adjustDesktopGeometry(QRect &rect) const +{ + QRect rectGeometry = m_dockGeometry; + rectGeometry.setWidth(rectGeometry.width() * qApp->devicePixelRatio()); + rectGeometry.setHeight(rectGeometry.height() * qApp->devicePixelRatio()); + switch (m_dockPosition) { + case Dock::Position::Left: { + int leftX = (rectGeometry.x() + rectGeometry.width()) * qApp->devicePixelRatio(); + if (rect.x() < leftX) { + rect.setX(leftX); + rect.setWidth(rect.width() - (leftX - rect.x())); + } + break; + } + case Dock::Position::Top: { + int topY = (rectGeometry.y() + rectGeometry.height()) * qApp->devicePixelRatio(); + if (rect.y() < topY) { + rect.setY(topY); + rect.setHeight(rect.height() - (topY - rect.y())); + } + break; + } + case Dock::Position::Right: { + int rightX = rectGeometry.x() * qApp->devicePixelRatio(); + if (rightX < rect.x() + rect.width() * qApp->devicePixelRatio()) + rect.setWidth(rect.width() - (rect.x() + rect.width() - rightX)); + break; + } + case Dock::Position::Bottom: { + int bottomY = rectGeometry.y() * qApp->devicePixelRatio(); + if (bottomY < rect.y() + rect.height() * qApp->devicePixelRatio()) + rect.setHeight(rect.height() - (rect.y() + rect.height() - bottomY)); + break; + } + } +} + +QRect AppDragWidget::splitGeometry(const QPoint &pos) const +{ + QList screens = DisplayManager::instance()->screens(); + for (QScreen *screen : screens) { + QRect screenGeometry = screen->geometry(); + screenGeometry.setWidth(screenGeometry.width() * qApp->devicePixelRatio()); + screenGeometry.setHeight(screenGeometry.height() * qApp->devicePixelRatio()); + if (!screenGeometry.contains(pos)) + continue; + + // 左右分屏即可 + int centerX = screenGeometry.x() + screenGeometry.width() / 2; + if (pos.x() < centerX) { + // 左分屏 + QRect rectLeft = screenGeometry; + rectLeft.setWidth(screenGeometry.width() / 2); + adjustDesktopGeometry(rectLeft); + return rectLeft; + } + if (pos.x() > centerX) { + // 右分屏 + QRect rectRight = screenGeometry; + rectRight.setLeft(screenGeometry.x() + screenGeometry.width() / 2); + rectRight.setWidth(screenGeometry.width() / 2); + adjustDesktopGeometry(rectRight); + return rectRight; + } + break; + } + return QRect(); +} + +void AppDragWidget::initWaylandEnv() +{ + if (!Utils::IS_WAYLAND_DISPLAY) + return; + + // 由于在wayland环境下无法触发drop事件,导致鼠标无法释放,所以这里暂时用XEventMonitor的方式(具体原因待查) + XEventMonitor *extralEventInter = new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus()); + QString key = extralEventInter->RegisterFullScreen(); + connect(this, &AppDragWidget::destroyed, this, [ key, extralEventInter ] { + extralEventInter->UnregisterArea(key); + delete extralEventInter; + QDrag::cancel(); + }); + + connect(extralEventInter, &XEventMonitor::ButtonRelease, this, &AppDragWidget::onButtonRelease); + connect(extralEventInter, &XEventMonitor::CursorMove,this, &AppDragWidget::onCursorMove); +} + +void AppDragWidget::onButtonRelease(int, int x, int y, const QString &) +{ + if (!m_bDragDrop) + return; + + dropHandler(QPoint(x, y)); + + QDrag::cancel(); +} + +void AppDragWidget::onCursorMove(int x, int y, const QString &) +{ + QPoint pos = QPoint(x, y); + moveCurrent(pos); + moveHandler(pos); +} + +void AppDragWidget::onFollowMouse() +{ + moveCurrent(QCursor::pos()); +} + +void AppDragWidget::enterEvent(QEvent *event) +{ + Q_UNUSED(event); + + if (m_goBackAnim->state() != QPropertyAnimation::State::Running + && m_animGroup->state() != QParallelAnimationGroup::Running) { + hide(); + } +} + +QuickDragWidget::QuickDragWidget(QWidget *parent) + : AppDragWidget(parent) +{ + +} + +QuickDragWidget::~QuickDragWidget() +{ +} + +void QuickDragWidget::dropEvent(QDropEvent *event) +{ + Q_UNUSED(event); + + m_followMouseTimer->stop(); + m_bDragDrop = false; + + if (isRemoveAble(QCursor::pos())) { + if (DWindowManagerHelper::instance()->hasComposite()) + showRemoveAnimation(); + else + hide(); + + m_popupWindow->setVisible(false); + } else { + if (DWindowManagerHelper::instance()->hasComposite()) + showGoBackAnimation(); + else + hide(); + + Q_EMIT requestDropItem(event); + } +} + +void QuickDragWidget::dragMoveEvent(QDragMoveEvent *event) +{ + AppDragWidget::dragMoveEvent(event); + requestDragMove(event); +} + /**判断图标拖到一定高度(默认任务栏高度的1.5倍)后是否可以移除 * @brief AppDragWidget::isRemoveAble * @param curPos 当前鼠标所在位置 * @return 返回true可移除,false不可移除 */ -bool AppDragWidget::isRemoveAble(const QPoint &curPos) +bool QuickDragWidget::isRemoveAble(const QPoint &curPos) { const QPoint &p = curPos; switch (m_dockPosition) { @@ -329,109 +551,3 @@ bool AppDragWidget::isRemoveAble(const QPoint &curPos) } return false; } - -/**判断应用区域图标是否被拖出任务栏 - * @brief AppDragWidget::isRemoveItem - * @return 返回true应用移出任务栏,false应用在任务栏内 - */ -bool AppDragWidget::isRemoveItem() -{ - const QPoint &p = QCursor::pos(); - switch (m_dockPosition) { - case Dock::Position::Left: - if ((p.x() > m_dockGeometry.topRight().x())) { - return true; - } - break; - case Dock::Position::Top: - if ((p.y() > m_dockGeometry.bottomLeft().y())) { - return true; - } - break; - case Dock::Position::Right: - if ((m_dockGeometry.topLeft().x() > p.x())) { - return true; - } - break; - case Dock::Position::Bottom: - if ((m_dockGeometry.topLeft().y() > p.y())) { - return true; - } - break; - } - return false; -} - -void AppDragWidget::onFollowMouse() -{ - QPoint destPos = QCursor::pos(); - move(destPos.x() - width() / 2, destPos.y() - height() / 2); -} - -void AppDragWidget::enterEvent(QEvent *event) -{ - Q_UNUSED(event); - - if (m_goBackAnim->state() != QPropertyAnimation::State::Running - && m_animGroup->state() != QParallelAnimationGroup::Running) { - hide(); - } -} - -bool AppDragWidget::event(QEvent *event) -{ - if (Utils::IS_WAYLAND_DISPLAY && event->type() == QEvent::DeferredDelete) - requestRemoveSelf(isRemoveAble(m_cursorPosition)); - - return QGraphicsView::event(event); -} - -/**显示移除应用提示窗口 - * @brief AppDragWidget::showRemoveTips - */ -void AppDragWidget::showRemoveTips() -{ - Dock::Position pos = Dock::Position::Bottom; - - DockPopupWindow *popup = m_popupWindow.data(); - if (isRemoveAble(QCursor::pos())) { - QWidget *lastContent = popup->getContent(); - if (lastContent) - lastContent->setVisible(false); - - switch (pos) { - case Top: popup->setArrowDirection(DockPopupWindow::ArrowTop); break; - case Bottom: popup->setArrowDirection(DockPopupWindow::ArrowBottom); break; - case Left: popup->setArrowDirection(DockPopupWindow::ArrowLeft); break; - case Right: popup->setArrowDirection(DockPopupWindow::ArrowRight); break; - } - popup->resize(m_removeTips->sizeHint()); - popup->setContent(m_removeTips); - - const QPoint p = popupMarkPoint(pos); - if (!popup->isVisible()) - QMetaObject::invokeMethod(popup, "show", Qt::QueuedConnection, Q_ARG(QPoint, p), Q_ARG(bool, true)); - else - popup->show(p, true); - - m_object->setOpacity(0.5); - m_animOpacity->setStartValue(0.5); - } else { - m_object->setOpacity(1.0); - m_animOpacity->setStartValue(1.0); - if (popup->isVisible()) - popup->setVisible(false); - } -} - -void AppDragWidget::moveEvent(QMoveEvent *event) -{ - Q_UNUSED(event); - showRemoveTips(); - if (Utils::IS_WAYLAND_DISPLAY) { - m_cursorPosition = QCursor::pos(); - if (isRemoveItem()) { - emit requestRemoveItem(); - } - } -} diff --git a/frame/item/components/appdragwidget.h b/frame/item/components/appdragwidget.h index 09addad2a..503f6824c 100644 --- a/frame/item/components/appdragwidget.h +++ b/frame/item/components/appdragwidget.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,6 +7,8 @@ #define APPDRAGWIDGET_H #include "constants.h" +#include "screenspliter.h" +#include "utils.h" #include #include @@ -21,6 +24,9 @@ #include "dockpopupwindow.h" #include "dockitem.h" +class QDrag; +class DockScreen; + class AppGraphicsObject : public QGraphicsObject { public: @@ -68,19 +74,18 @@ class AppDragWidget : public QGraphicsView public: explicit AppDragWidget(QWidget *parent = Q_NULLPTR); + void execFinished(); void setAppPixmap(const QPixmap &pix); void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry); void setOriginPos(const QPoint position); void setPixmapOpacity(qreal opacity); - bool isRemoveAble(const QPoint &curPos); void setItem(DockItem *item) { m_item = item; } - static bool isRemoveable(const Dock::Position &dockPos, const QRect &doctRect); void showRemoveAnimation(); void showGoBackAnimation(); signals: - void requestRemoveItem(); - void requestRemoveSelf(bool); + void requestChangedArea(QRect); + void requestSplitWindow(ScreenSpliter::SplitDirection); protected: void mouseMoveEvent(QMouseEvent *event) override; @@ -88,9 +93,7 @@ protected: void dragMoveEvent(QDragMoveEvent *event) override; void dropEvent(QDropEvent *event) override; void hideEvent(QHideEvent *event) override; - void moveEvent(QMoveEvent *event) override; void enterEvent(QEvent *event) override; - bool event(QEvent *event) override; private: void initAnimations(); @@ -98,13 +101,22 @@ private: QAbstractAnimation::State oldState); const QPoint popupMarkPoint(Dock::Position pos); const QPoint topleftPoint() const; - void showRemoveTips(); - bool isRemoveItem(); + bool canSplitWindow(const QPoint &pos) const; + ScreenSpliter::SplitDirection splitPosition() const; + QRect splitGeometry(const QPoint &pos) const; + void initWaylandEnv(); + + void dropHandler(const QPoint &pos); + void moveHandler(const QPoint &pos); + void moveCurrent(const QPoint &destPos); + void adjustDesktopGeometry(QRect &rect) const; private Q_SLOTS: void onFollowMouse(); + void onButtonRelease(int, int x, int y, const QString &); + void onCursorMove(int x, int y, const QString &); -private: +protected: QScopedPointer m_object; QGraphicsScene *m_scene; QTimer *m_followMouseTimer; @@ -118,7 +130,6 @@ private: QRect m_dockGeometry; QPoint m_originPoint; QSize m_iconSize; - Dock::TipsWidget *m_removeTips; QScopedPointer m_popupWindow; /** * @brief m_distanceMultiple: 倍数 @@ -128,7 +139,28 @@ private: bool m_bDragDrop = false; // 图标是否被拖拽 DockItem *m_item; - QPoint m_cursorPosition; + QRect m_lastMouseGeometry; + DockScreen *m_dockScreen; +}; + +class QuickDragWidget : public AppDragWidget +{ + Q_OBJECT + +Q_SIGNALS: + void requestDropItem(QDropEvent *); + void requestDragMove(QDragMoveEvent *); + +public: + explicit QuickDragWidget(QWidget *parent = Q_NULLPTR); + ~QuickDragWidget() override; + +protected: + void dropEvent(QDropEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + +private: + bool isRemoveAble(const QPoint &curPos); }; #endif /* APPDRAGWIDGET_H */ diff --git a/frame/item/components/appsnapshot.cpp b/frame/item/components/appsnapshot.cpp index dea485d96..85d5faee1 100644 --- a/frame/item/components/appsnapshot.cpp +++ b/frame/item/components/appsnapshot.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,6 +7,7 @@ #include "previewcontainer.h" #include "../widgets/tipswidget.h" #include "utils.h" +#include "imageutil.h" #include @@ -20,6 +22,7 @@ #include #include #include +#include struct SHMInfo { long shmid; @@ -48,10 +51,8 @@ AppSnapshot::AppSnapshot(const WId wid, QWidget *parent) , m_waitLeaveTimer(new QTimer(this)) , m_closeBtn2D(new DIconButton(this)) , m_wmHelper(DWindowManagerHelper::instance()) - , m_dockDaemonInter(new DockDaemonInter("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) + , m_dockDaemonInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) { - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_closeBtn2D->setFixedSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH); m_closeBtn2D->setIconSize(QSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH)); m_closeBtn2D->setObjectName("closebutton-2d"); @@ -68,6 +69,7 @@ AppSnapshot::AppSnapshot(const WId wid, QWidget *parent) setLayout(centralLayout); setAcceptDrops(true); + resize(SNAP_WIDTH / 2, SNAP_HEIGHT / 2); connect(m_closeBtn2D, &DIconButton::clicked, this, &AppSnapshot::closeWindow, Qt::QueuedConnection); connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, this, &AppSnapshot::compositeChanged, Qt::QueuedConnection); @@ -100,7 +102,7 @@ void AppSnapshot::updateTitle() } QFontMetrics fm(m_3DtitleBtn->font()); - int textWidth = fm.width(title()) + 10 + BTN_TITLE_MARGIN; + int textWidth = fm.horizontalAdvance(title()) + 10 + BTN_TITLE_MARGIN; int titleWidth = SNAP_WIDTH - (TITLE_MARGIN * 2 + BORDER_MARGIN); if (textWidth < titleWidth) { @@ -166,18 +168,8 @@ void AppSnapshot::setWindowInfo(const WindowInfo &info) { m_windowInfo = info; QFontMetrics fm(m_title->font()); - QString strTtile = m_title->fontMetrics().elidedText(m_windowInfo.title, Qt::ElideRight, SNAP_WIDTH_WITHOUT_COMPOSITE - SNAP_CLOSE_BTN_WIDTH - 2 *SNAP_CLOSE_BTN_MARGIN); + QString strTtile = m_title->fontMetrics().elidedText(m_windowInfo.title, Qt::ElideRight, SNAP_WIDTH - SNAP_CLOSE_BTN_WIDTH - SNAP_CLOSE_BTN_MARGIN); m_title->setText(strTtile); - m_title->adjustSize(); - - // 设置单个预览界面大小 - if (m_wmHelper->hasComposite()) { - setMinimumSize(SNAP_WIDTH, SNAP_HEIGHT); - setFixedSize(SNAP_WIDTH, SNAP_HEIGHT); - } else { - setMinimumSize(m_title->width() + SNAP_CLOSE_BTN_WIDTH + 2 * SNAP_CLOSE_BTN_MARGIN, SNAP_HEIGHT_WITHOUT_COMPOSITE); - } - updateTitle(); // 只有在X11下,才能通过XGetWindowProperty获取窗口属性 @@ -199,93 +191,50 @@ void AppSnapshot::fetchSnapshot() if (!m_wmHelper->hasComposite()) return; - QImage qimage; SHMInfo *info = nullptr; uchar *image_data = nullptr; XImage *ximage = nullptr; - do { - // 优先使用窗管进行窗口截图 - if (isKWinAvailable()) { - QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot")); - qDebug() << "windowsID:"<< m_wid; - - QList args; - args << QVariant::fromValue(m_wid); - args << QVariant::fromValue(quint32(SNAP_WIDTH)); - args << QVariant::fromValue(quint32(SNAP_HEIGHT)); - - QDBusReply reply = interface.callWithArgumentList(QDBus::Block,QStringLiteral("screenshotForWindowExtend"), args); - if(reply.isValid()){ - const QString tmpFile = reply.value(); - if (QFile::exists(tmpFile)) { - m_snapshot.load(tmpFile); - m_snapshotSrcRect = m_snapshot.rect(); - qDebug() << "reply: " << tmpFile; - QFile::remove(tmpFile); + // 优先使用窗管进行窗口截图 + if (isKWinAvailable()) { + const QString windowInfoId = Utils::IS_WAYLAND_DISPLAY ? m_windowInfo.uuid : QString::number(m_wid); + m_pixmap = ImageUtil::loadWindowThumb(windowInfoId); + } else { + do { + // get window image from shm(only for deepin app) + QImage qimage; + info = getImageDSHM(); + if (info) { + qDebug() << "get Image from dxcbplugin SHM..."; + image_data = (uchar *)shmat(info->shmid, 0, 0); + if ((qint64)image_data != -1) { + qimage = QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format); break; - } else { - qDebug() << "get current workspace bckground error, file does not exist : " << tmpFile; } - } else { - qDebug() << "get current workspace bckground error: "<< reply.error().message(); + qDebug() << "invalid pointer of shm!"; + image_data = nullptr; } - } - // get window image from shm(only for deepin app) - info = getImageDSHM(); - if (info) { - qDebug() << "get Image from dxcbplugin SHM..."; - image_data = (uchar *)shmat(info->shmid, 0, 0); - if ((qint64)image_data != -1) { - m_snapshot = QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format); - m_snapshotSrcRect = QRect(info->rect.x, info->rect.y, info->rect.width, info->rect.height); - break; + if (!image_data || qimage.isNull()) { + // get window image from XGetImage(a little slow) + qDebug() << "get Image from dxcbplugin SHM failed!"; + qDebug() << "get Image from Xlib..."; + // guoyao note:这里会造成内存泄漏,而且是通过demo在X环境经过验证,改用xcb库同样会有内存泄漏,这里暂时未找到解决方案,所以优先使用kwin提供的接口 + ximage = getImageXlib(); + if (!ximage) { + qDebug() << "get Image from Xlib failed! giving up..."; + emit requestCheckWindow(); + return; + } + qimage = QImage((const uchar *)(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32); } - qDebug() << "invalid pointer of shm!"; - image_data = nullptr; - } - if (!Utils::IS_WAYLAND_DISPLAY && (!image_data || qimage.isNull())) { - // get window image from XGetImage(a little slow) - qDebug() << "get Image from dxcbplugin SHM failed!"; - qDebug() << "get Image from Xlib..."; - // guoyao note:这里会造成内存泄漏,而且是通过demo在X环境经过验证,改用xcb库同样会有内存泄漏,这里暂时未找到解决方案,所以优先使用kwin提供的接口 - ximage = getImageXlib(); - if (!ximage) { - qDebug() << "get Image from Xlib failed! giving up..."; - emit requestCheckWindow(); - return; - } - qimage = QImage((const uchar *)(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32); + Q_ASSERT(!qimage.isNull()); - if (!qimage.isNull()) { - m_snapshot = qimage; - // remove shadow frame - m_snapshotSrcRect = rectRemovedShadow(qimage, nullptr); - } else { - qDebug() << "can not get QImage! giving up..."; - } - } - } while(false); - - // 如果m_snapshot或m_snapshotSrcRect为空,说明三种方式均失败,返回不做处理 - if (m_snapshot.isNull() || m_snapshotSrcRect.isNull()) { - qWarning() << "can not get QImage or QRectF! giving up..."; - return; + m_pixmap = QPixmap::fromImage(qimage); + } while (false); } - QSizeF size(rect().marginsRemoved(QMargins(8, 8, 8, 8)).size()); - const auto ratio = devicePixelRatioF(); - size = m_snapshotSrcRect.size().scaled(size * ratio, Qt::KeepAspectRatio); - qreal scale = qreal(size.width()) / m_snapshotSrcRect.width(); - m_snapshot = m_snapshot.scaled(qRound(m_snapshot.width() * scale), qRound(m_snapshot.height() * scale), - Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - m_snapshotSrcRect.moveTop(m_snapshotSrcRect.top() * scale + 0.5); - m_snapshotSrcRect.moveLeft(m_snapshotSrcRect.left() * scale + 0.5); - m_snapshotSrcRect.setWidth(size.width() - 0.5); - m_snapshotSrcRect.setHeight(size.height() - 0.5); - if (image_data) shmdt(image_data); if (ximage) XDestroyImage(ximage); if (info) XFree(info); @@ -328,7 +277,7 @@ void AppSnapshot::paintEvent(QPaintEvent *e) return; } - if (m_snapshot.isNull()) + if (m_pixmap.isNull()) return; const auto ratio = devicePixelRatioF(); @@ -340,22 +289,16 @@ void AppSnapshot::paintEvent(QPaintEvent *e) painter.drawRoundedRect(rect(), 5, 5); } - // draw image - const QImage &im = m_snapshot; - - const qreal offset_x = width() / 2.0 - m_snapshotSrcRect.width() / ratio / 2 - m_snapshotSrcRect.left() / ratio; - const qreal offset_y = height() / 2.0 - m_snapshotSrcRect.height() / ratio / 2 - m_snapshotSrcRect.top() / ratio; - DStyleHelper dstyle(style()); const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius); - QBrush brush; - brush.setTextureImage(im); - painter.setBrush(brush); + painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + QRect imageRect(8, 8, width() - 16, height() - 16); painter.setPen(Qt::NoPen); - painter.scale(1 / ratio, 1 / ratio); - painter.translate(QPoint(offset_x * ratio, offset_y * ratio)); - painter.drawRoundedRect(m_snapshotSrcRect, radius * ratio, radius * ratio); + QPainterPath path; + path.addRoundedRect(imageRect, radius * ratio, radius * ratio); + painter.setClipPath(path); + painter.drawPixmap(imageRect, m_pixmap, m_pixmap.rect()); } void AppSnapshot::mousePressEvent(QMouseEvent *e) diff --git a/frame/item/components/appsnapshot.h b/frame/item/components/appsnapshot.h index 3b2aa8b7e..bccc9beb9 100644 --- a/frame/item/components/appsnapshot.h +++ b/frame/item/components/appsnapshot.h @@ -1,28 +1,26 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef APPSNAPSHOT_H #define APPSNAPSHOT_H -#include -#include -#include +#include "dbusutil.h" #include #include #include -#include -#include +#include +#include +#include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE #define SNAP_WIDTH 200 #define SNAP_HEIGHT 130 -#define SNAP_HEIGHT_WITHOUT_COMPOSITE 30 -#define SNAP_WIDTH_WITHOUT_COMPOSITE 300 #define SNAP_CLOSE_BTN_WIDTH (24) #define SNAP_CLOSE_BTN_MARGIN (5) @@ -39,8 +37,6 @@ struct SHMInfo; struct _XImage; typedef _XImage XImage; -using DockDaemonInter = com::deepin::dde::daemon::Dock; - namespace Dock { class TipsWidget; } @@ -50,14 +46,13 @@ class AppSnapshot : public QWidget Q_OBJECT public: - explicit AppSnapshot(const WId wid, QWidget *parent = 0); + explicit AppSnapshot(const WId wid, QWidget *parent = Q_NULLPTR); inline WId wid() const { return m_wid; } inline bool attentioned() const { return m_windowInfo.attention; } inline bool closeAble() const { return m_closeAble; } inline void setCloseAble(const bool value) { m_closeAble = value; } - inline const QImage snapshot() const { return m_snapshot; } - inline const QRectF snapshotGeometry() const { return m_snapshotSrcRect; } + inline const QPixmap snapshot() const { return m_pixmap; } inline const QString title() const { return m_windowInfo.title; } void setWindowState(); void setTitleVisible(bool bVisible); @@ -96,8 +91,7 @@ private: bool m_closeAble; bool m_isWidowHidden; - QImage m_snapshot; - QRectF m_snapshotSrcRect; + QPixmap m_pixmap; Dock::TipsWidget *m_title; DPushButton *m_3DtitleBtn; @@ -105,7 +99,7 @@ private: QTimer *m_waitLeaveTimer; DIconButton *m_closeBtn2D; DWindowManagerHelper *m_wmHelper; - DockDaemonInter *m_dockDaemonInter; + DockInter *m_dockDaemonInter; }; #endif // APPSNAPSHOT_H diff --git a/frame/item/components/appswingeffectbuilder.h b/frame/item/components/appswingeffectbuilder.h index f59315840..7d967997f 100644 --- a/frame/item/components/appswingeffectbuilder.h +++ b/frame/item/components/appswingeffectbuilder.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/item/components/floatingpreview.cpp b/frame/item/components/floatingpreview.cpp index c050722b3..1ef009f58 100644 --- a/frame/item/components/floatingpreview.cpp +++ b/frame/item/components/floatingpreview.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -14,13 +15,15 @@ FloatingPreview::FloatingPreview(QWidget *parent) : QWidget(parent) - , m_closeBtn3D(new DIconButton(DStyle::StandardPixmap::SP_CloseButton, this)) + , m_closeBtn3D(new DIconButton(this)) , m_titleBtn(new DPushButton(this)) { m_closeBtn3D->setObjectName("closebutton-3d"); m_closeBtn3D->setFixedSize(24, 24); m_closeBtn3D->setIconSize(QSize(24, 24)); + m_closeBtn3D->setIcon(QIcon(":/icons/resources/close_round_normal.svg")); m_closeBtn3D->setFlat(true); + m_closeBtn3D->installEventFilter(this); m_titleBtn->setBackgroundRole(QPalette::Base); m_titleBtn->setForegroundRole(QPalette::Text); @@ -75,6 +78,12 @@ void FloatingPreview::trackWindow(AppSnapshot *const snap) // 显示此标题的前提条件:配置了标题跟随鼠标显示 // 此对象是共用的,鼠标移动到哪个预览图,title就移动到哪里显示,所以他的text统一snap获取,不再重复计算显示长度 m_titleBtn->setText(snap->appTitle()); + + QTimer::singleShot(0, this, [ = ] { + // 此处获取的snap->geometry()有可能是错误的,所以做个判断并且在resizeEvent中也做处理 + if(snap->width() == SNAP_WIDTH) + setGeometry(snap->geometry()); + }); } void FloatingPreview::paintEvent(QPaintEvent *e) @@ -84,7 +93,7 @@ void FloatingPreview::paintEvent(QPaintEvent *e) if (m_tracked.isNull()) return; - const QImage &snapshot = m_tracked->snapshot(); + const QPixmap &snapshot = m_tracked->snapshot(); if (snapshot.isNull()) return; @@ -117,12 +126,27 @@ void FloatingPreview::mouseReleaseEvent(QMouseEvent *e) bool FloatingPreview::eventFilter(QObject *watched, QEvent *event) { + if(watched == m_closeBtn3D) { + if(watched == m_closeBtn3D && (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverMove)) { + m_closeBtn3D->setIcon(QIcon(":/icons/resources/close_round_hover.svg")); + } + else if (watched == m_closeBtn3D && event->type() == QEvent::HoverLeave) { + m_closeBtn3D->setIcon(QIcon(":/icons/resources/close_round_normal.svg")); + } + else if (watched == m_closeBtn3D && event->type() == QEvent::MouseButtonPress) { + m_closeBtn3D->setIcon(QIcon(":/icons/resources/close_round_press.svg")); + } + } + if (watched == m_tracked) { if (event->type() == QEvent::Destroy) { // 此处需要置空,否则当Destroy事件响应结束后,会在FloatingPreview::hideEvent使用m_tracked野指针 m_tracked = nullptr; hide(); } + + if (event->type() == QEvent::Resize && m_tracked->width() == SNAP_WIDTH) + setGeometry(m_tracked->geometry()); } return QWidget::eventFilter(watched, event); diff --git a/frame/item/components/floatingpreview.h b/frame/item/components/floatingpreview.h index 08010e13a..0136e62a4 100644 --- a/frame/item/components/floatingpreview.h +++ b/frame/item/components/floatingpreview.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/item/components/previewcontainer.cpp b/frame/item/components/previewcontainer.cpp index 74995efec..c4982919d 100644 --- a/frame/item/components/previewcontainer.cpp +++ b/frame/item/components/previewcontainer.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,66 +14,26 @@ #include #include #include -#include -#include #define SPACING 0 #define MARGIN 0 +#define SNAP_HEIGHT_WITHOUT_COMPOSITE 30 PreviewContainer::PreviewContainer(QWidget *parent) : QWidget(parent) , m_needActivate(false) - , m_canPreview(true) - , m_dockSize(40) , m_floatingPreview(new FloatingPreview(this)) - , m_preparePreviewTimer(new QTimer(this)) , m_mouseLeaveTimer(new QTimer(this)) , m_wmHelper(DWindowManagerHelper::instance()) , m_titleMode(HoverShow) { - m_windowListLayout = new QBoxLayout(QBoxLayout::LeftToRight); + m_windowListLayout = new QBoxLayout(QBoxLayout::LeftToRight, this); m_windowListLayout->setSpacing(SPACING); m_windowListLayout->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN); - m_windowListWidget = new QWidget(this); - m_windowListWidget->setAccessibleName("centralLayoutWidget"); - m_windowListWidget->setLayout(m_windowListLayout); - m_windowListWidget->setMinimumSize(SNAP_WIDTH, SNAP_HEIGHT); - m_windowListWidget->installEventFilter(this); - m_windowListWidget->setAttribute(Qt::WA_TranslucentBackground); - m_windowListWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - - m_scrollArea = new QScrollArea(this); - m_scrollArea->setAccessibleName("Preview_scrollArea"); - m_scrollArea->setWidgetResizable(false); - m_scrollArea->setFrameStyle(QFrame::NoFrame); - m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_scrollArea->setContentsMargins(0, 0, 0, 0); - m_scrollArea->setBackgroundRole(QPalette::Base); - m_scrollArea->setWidget(m_windowListWidget); - m_scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - - QVBoxLayout * mainLayout = new QVBoxLayout; - mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->setSpacing(0); - mainLayout->addWidget(m_scrollArea); - setLayout(mainLayout); - - // 设置触摸屏手势识别 - QScroller::grabGesture(m_scrollArea->viewport(), QScroller::LeftMouseButtonGesture); - QScroller *scroller = QScroller::scroller(m_scrollArea->viewport()); - m_sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootWhenScrollable); - m_sp.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootWhenScrollable); - scroller->setScrollerProperties(m_sp); - m_mouseLeaveTimer->setSingleShot(true); m_mouseLeaveTimer->setInterval(300); - m_preparePreviewTimer->setSingleShot(true); - m_preparePreviewTimer->setInterval(300); - - m_floatingPreview->installEventFilter(this); m_floatingPreview->setVisible(false); m_waitForShowPreviewTimer = new QTimer(this); @@ -84,38 +45,15 @@ PreviewContainer::PreviewContainer(QWidget *parent) connect(m_mouseLeaveTimer, &QTimer::timeout, this, &PreviewContainer::checkMouseLeave, Qt::QueuedConnection); connect(m_waitForShowPreviewTimer, &QTimer::timeout, this, &PreviewContainer::previewFloating); - - // 预览界面在滚动时,暂时不允许预览,避免在滚动时频繁切换预览造成闪屏 - connect(m_scrollArea->horizontalScrollBar(), &QScrollBar::valueChanged, this, [ = ]{ - m_floatingPreview->setVisible(false); - m_canPreview = false; - if (m_preparePreviewTimer->isActive()) { - m_preparePreviewTimer->stop(); - } - m_preparePreviewTimer->start(); - }); - connect(m_scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, this, [ = ]{ - m_floatingPreview->setVisible(false); - m_canPreview = false; - if (m_preparePreviewTimer->isActive()) { - m_preparePreviewTimer->stop(); - } - m_preparePreviewTimer->start(); - }); - - // 停止滚动后允许预览 - connect(m_preparePreviewTimer, &QTimer::timeout, this, [ = ]{ - m_canPreview = true; - if (m_wmHelper->hasComposite()) { - m_waitForShowPreviewTimer->start(); - } - }); } void PreviewContainer::setWindowInfos(const WindowInfoMap &infos, const WindowList &allowClose) { // check removed window for (auto it(m_snapshots.begin()); it != m_snapshots.end();) { + //初始化预览界面边距 + it.value()->setContentsMargins(0, 0, 0, 0); + if (!infos.contains(it.key())) { m_windowListLayout->removeWidget(it.value()); it.value()->deleteLater(); @@ -157,32 +95,14 @@ void PreviewContainer::setTitleDisplayMode(int mode) void PreviewContainer::updateLayoutDirection(const Dock::Position dockPos) { - m_dockPos = dockPos; - if (m_wmHelper->hasComposite() && (dockPos == Dock::Top || dockPos == Dock::Bottom)) { + if (m_wmHelper->hasComposite() && (dockPos == Dock::Top || dockPos == Dock::Bottom)) m_windowListLayout->setDirection(QBoxLayout::LeftToRight); - - m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - m_sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff); - m_sp.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootWhenScrollable); - } else { - m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + else m_windowListLayout->setDirection(QBoxLayout::TopToBottom); - m_sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootWhenScrollable); - m_sp.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff); - } - adjustSize(m_wmHelper->hasComposite()); } -void PreviewContainer::updateDockSize(const int size) -{ - m_dockSize = size; -} - void PreviewContainer::checkMouseLeave() { const bool hover = underMouse(); @@ -212,46 +132,64 @@ void PreviewContainer::prepareHide() void PreviewContainer::adjustSize(bool composite) { - const bool horizontal = m_windowListLayout->direction() == QBoxLayout::LeftToRight; - const int count = m_snapshots.size(); - + int count = m_snapshots.size(); const int screenWidth = QDesktopWidget().screenGeometry(this).width(); const int screenHeight = QDesktopWidget().screenGeometry(this).height(); //先根据屏幕宽高计算出能预览的最大数量,然后根据数量计算界面宽高 if (composite) { + // 3D + const int padding = 20; + const bool horizontal = m_windowListLayout->direction() == QBoxLayout::LeftToRight; if (horizontal) { + count = qMin(count, screenWidth * 2 / SNAP_WIDTH); + const int h = SNAP_HEIGHT + MARGIN * 2; const int w = SNAP_WIDTH * count + MARGIN * 2 + SPACING * (count - 1); - m_windowListWidget->setFixedSize(w, h); - setFixedSize(qMin(w, screenWidth), h); + setFixedHeight(h); + setFixedWidth(qMin(w, screenWidth - padding)); } else { - const int h = SNAP_HEIGHT * count + MARGIN * 2 + SPACING * (count - 1); - const int w = SNAP_WIDTH + MARGIN * 2; + count = qMin(count, screenWidth * 2 / SNAP_HEIGHT); - m_windowListWidget->setFixedSize(w, h); - setFixedSize(w, qMin(h, screenHeight)); + const int w = SNAP_WIDTH + MARGIN * 2; + const int h = SNAP_HEIGHT * count + MARGIN * 2 + SPACING * (count - 1); + + setFixedWidth(w); + setFixedHeight(qMin(h, screenHeight - padding)); } } else if (m_windowListLayout->count()) { // 2D + count = qMin(count, screenWidth / SNAP_HEIGHT_WITHOUT_COMPOSITE); const int h = SNAP_HEIGHT_WITHOUT_COMPOSITE * count + MARGIN * 2 + SPACING * (count - 1); - int titleWidth = 0; + auto appSnapshot = static_cast(m_windowListLayout->itemAt(0)->widget()); + auto font = appSnapshot->layout()->itemAt(0)->widget()->font(); + QFontMetrics fontMetrics(font); + + // 获取 appitem title 的最大宽度 + int titleWidth = fontMetrics.boundingRect(appSnapshot->title()).width(); for (int i = 0; i < m_windowListLayout->count(); i++) { - auto snapshotWidget = static_cast(m_windowListLayout->itemAt(i)->widget()); - titleWidth = qMax(titleWidth, snapshotWidget->minimumWidth()); + auto otherWidget = static_cast(m_windowListLayout->itemAt(i)->widget()); + titleWidth = qMax(titleWidth, fontMetrics.boundingRect(otherWidget->title()).width()); } - m_windowListWidget->setFixedSize(titleWidth, h); + // 关闭按键的宽度和边缘间距的和,调整标题居中 + const int closeBtnMargin = 2 * (SNAP_CLOSE_BTN_WIDTH + SNAP_CLOSE_BTN_MARGIN); + if (titleWidth < SNAP_WIDTH - closeBtnMargin) + setFixedSize(titleWidth + closeBtnMargin, h); + else + setFixedSize(SNAP_WIDTH, h); + } - if (m_dockPos == Dock::Top || m_dockPos == Dock::Bottom) { - // 滚动区域高度 = 屏幕高度 - 任务栏高度 - 箭头高度 - setFixedSize(titleWidth, qMin(h, screenHeight - m_dockSize - 20)); - } else { - // 滚动区域高度 = 屏幕高度 - setFixedSize(titleWidth, qMin(h, screenHeight)); + //根据计算的数量,将相应的预览界面添加到布局并显示,其他的暂时不添加,减少界面刷新次数 + int i = 0; + for (AppSnapshot *snap : m_snapshots) { + if (i < count && m_windowListLayout->indexOf(snap) < 0 ) { + m_windowListLayout->addWidget(snap); } + snap->setVisible(i < count); + i++; } } @@ -259,6 +197,7 @@ void PreviewContainer::appendSnapWidget(const WId wid) { //创建预览界面,默认不显示,等计算出显示数量后再加入布局并显示 AppSnapshot *snap = new AppSnapshot(wid); + snap->setVisible(false); connect(snap, &AppSnapshot::clicked, this, &PreviewContainer::onSnapshotClicked, Qt::QueuedConnection); connect(snap, &AppSnapshot::entered, this, &PreviewContainer::previewEntered, Qt::QueuedConnection); @@ -266,7 +205,6 @@ void PreviewContainer::appendSnapWidget(const WId wid) connect(snap, &AppSnapshot::requestCloseAppSnapshot, this, &PreviewContainer::onRequestCloseAppSnapshot); m_snapshots.insert(wid, snap); - m_windowListLayout->addWidget(snap); } void PreviewContainer::enterEvent(QEvent *e) @@ -312,72 +250,8 @@ void PreviewContainer::dragLeaveEvent(QDragLeaveEvent *e) m_mouseLeaveTimer->start(); } -bool PreviewContainer::eventFilter(QObject *watcher, QEvent *event) -{ - // 将鼠标滚轮事件转换成水平滚动 - if (watcher == m_windowListWidget && event->type() == QEvent::Wheel) { - QWheelEvent *wheelEvent = static_cast(event); - - if (m_windowListLayout->direction() == Qt::LeftToRight) { - const int delta = wheelEvent->delta(); - const int currValue = m_scrollArea->horizontalScrollBar()->value(); - - if (currValue - delta <= 0) { - m_scrollArea->horizontalScrollBar()->setValue(0); - } else if (currValue - delta >= m_scrollArea->horizontalScrollBar()->maximum()) { - m_scrollArea->horizontalScrollBar()->setValue(m_scrollArea->horizontalScrollBar()->maximum()); - } else { - m_scrollArea->horizontalScrollBar()->setValue(currValue - delta); - } - - return true; - } - } - - // 在m_floatingPreview界面显示时,需要响应滚轮事件 - if (watcher == m_floatingPreview && event->type() == QEvent::Wheel) { - QWheelEvent *wheelEvent = static_cast(event); - - if (m_windowListLayout->direction() == Qt::LeftToRight) { - const int delta = wheelEvent->delta(); - const int currValue = m_scrollArea->horizontalScrollBar()->value(); - - if (currValue - delta <= 0) { - m_scrollArea->horizontalScrollBar()->setValue(0); - } else if (currValue - delta >= m_scrollArea->horizontalScrollBar()->maximum()) { - m_scrollArea->horizontalScrollBar()->setValue(m_scrollArea->horizontalScrollBar()->maximum()); - } else { - m_scrollArea->horizontalScrollBar()->setValue(currValue - delta); - } - - return true; - } else { - const int delta = wheelEvent->delta(); - const int currValue = m_scrollArea->verticalScrollBar()->value(); - - if (currValue - delta <= 0) { - m_scrollArea->verticalScrollBar()->setValue(0); - } else if (currValue - delta >= m_scrollArea->verticalScrollBar()->maximum()) { - m_scrollArea->verticalScrollBar()->setValue(m_scrollArea->verticalScrollBar()->maximum()); - } else { - m_scrollArea->verticalScrollBar()->setValue(currValue - delta); - } - - return true; - } - } - - return QWidget::eventFilter(watcher, event); -} - void PreviewContainer::onSnapshotClicked(const WId wid) { - if (Utils::IS_WAYLAND_DISPLAY) { - /* BUGFIX-159303 本地发现该问题仅在wayland下出现,问题已与窗管对接沟通过,根据窗管建议,上层进 - 规避,避免因底层强行修改引入新的问题 */ - Q_EMIT requestCancelPreviewWindow(); - } - Q_EMIT requestActivateWindow(wid); m_needActivate = true; m_waitForShowPreviewTimer->stop(); @@ -393,13 +267,16 @@ void PreviewContainer::previewEntered(const WId wid) if (!snap) { return; } + snap->setContentsMargins(100, 0, 100, 0); AppSnapshot *preSnap = m_floatingPreview->trackedWindow(); if (preSnap && preSnap != snap) { + preSnap->setContentsMargins(0, 0, 0, 0); preSnap->setWindowState(); } m_currentWId = wid; + m_floatingPreview->trackWindow(snap); if (m_waitForShowPreviewTimer->isActive()) { @@ -411,15 +288,7 @@ void PreviewContainer::previewEntered(const WId wid) void PreviewContainer::previewFloating() { - if (!m_waitForShowPreviewTimer->isActive() && m_canPreview) { - // 将单个预览界面在滚动区域的坐标转换到当前界面坐标上 - if (m_floatingPreview->trackedWindow()) { - const QRect snapGeometry = m_floatingPreview->trackedWindow()->geometry(); - const QPoint topLeft = m_windowListWidget->mapTo(m_scrollArea, snapGeometry.topLeft()); - const QPoint bottomRight = m_windowListWidget->mapTo(m_scrollArea, snapGeometry.bottomRight()); - m_floatingPreview->setGeometry(QRect(topLeft, bottomRight)); - } - + if (!m_waitForShowPreviewTimer->isActive()) { m_floatingPreview->setVisible(true); m_floatingPreview->raise(); diff --git a/frame/item/components/previewcontainer.h b/frame/item/components/previewcontainer.h index dffad2aec..9194e8468 100644 --- a/frame/item/components/previewcontainer.h +++ b/frame/item/components/previewcontainer.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,15 +9,11 @@ #include #include #include -#include -#include #include "constants.h" #include "appsnapshot.h" #include "floatingpreview.h" -#include - #include DWIDGET_USE_NAMESPACE @@ -47,7 +44,6 @@ public: public slots: void updateLayoutDirection(const Dock::Position dockPos); - void updateDockSize(const int size); void checkMouseLeave(); void prepareHide(); @@ -55,11 +51,10 @@ private: void adjustSize(bool composite); void appendSnapWidget(const WId wid); - void enterEvent(QEvent *e) override; - void leaveEvent(QEvent *e) override; - void dragEnterEvent(QDragEnterEvent *e) override; - void dragLeaveEvent(QDragLeaveEvent *e) override; - bool eventFilter(QObject *watcher, QEvent *event) override; + void enterEvent(QEvent *e); + void leaveEvent(QEvent *e); + void dragEnterEvent(QDragEnterEvent *e); + void dragLeaveEvent(QDragLeaveEvent *e); private slots: void onSnapshotClicked(const WId wid); @@ -69,18 +64,11 @@ private slots: private: bool m_needActivate; - bool m_canPreview; - int m_dockSize; - Dock::Position m_dockPos; QMap m_snapshots; FloatingPreview *m_floatingPreview; - QScrollArea * m_scrollArea; - QWidget *m_windowListWidget; QBoxLayout *m_windowListLayout; - QScrollerProperties m_sp; - QTimer *m_preparePreviewTimer; QTimer *m_mouseLeaveTimer; DWindowManagerHelper *m_wmHelper; QTimer *m_waitForShowPreviewTimer; diff --git a/frame/item/dockitem.cpp b/frame/item/dockitem.cpp index bf245faab..b81911ec8 100644 --- a/frame/item/dockitem.cpp +++ b/frame/item/dockitem.cpp @@ -1,20 +1,22 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dockitem.h" #include "pluginsitem.h" +#include "utils.h" #include #include #include #include +#include #define PLUGIN_MARGIN 10 #define ITEM_MAXSIZE 100 Position DockItem::DockPosition = Position::Top; -int DockItem::DockSize = 40; DisplayMode DockItem::DockDisplayMode = DisplayMode::Efficient; QPointer DockItem::PopupWindow(nullptr); @@ -24,18 +26,23 @@ DockItem::DockItem(QWidget *parent) , m_popupShown(false) , m_tapAndHold(false) , m_draging(false) + , m_contextMenu(new QMenu(this)) , m_popupTipsDelayTimer(new QTimer(this)) , m_popupAdjustDelayTimer(new QTimer(this)) { if (PopupWindow.isNull()) { DockPopupWindow *arrowRectangle = new DockPopupWindow(nullptr); arrowRectangle->setShadowBlurRadius(20); - arrowRectangle->setRadius(6); + arrowRectangle->setRadius(18); arrowRectangle->setShadowYOffset(2); arrowRectangle->setShadowXOffset(0); arrowRectangle->setArrowWidth(18); arrowRectangle->setArrowHeight(10); arrowRectangle->setObjectName("apppopup"); + if (Utils::IS_WAYLAND_DISPLAY) { + Qt::WindowFlags flags = arrowRectangle->windowFlags() | Qt::FramelessWindowHint; + arrowRectangle->setWindowFlags(flags); + } PopupWindow = arrowRectangle; connect(qApp, &QApplication::aboutToQuit, PopupWindow, &DockPopupWindow::deleteLater); } @@ -48,7 +55,7 @@ DockItem::DockItem(QWidget *parent) connect(m_popupTipsDelayTimer, &QTimer::timeout, this, &DockItem::showHoverTips); connect(m_popupAdjustDelayTimer, &QTimer::timeout, this, &DockItem::updatePopupPosition, Qt::QueuedConnection); - connect(&m_contextMenu, &QMenu::triggered, this, &DockItem::menuActionClicked); + connect(m_contextMenu, &QMenu::triggered, this, &DockItem::menuActionClicked); grabGesture(Qt::TapAndHoldGesture); @@ -78,11 +85,6 @@ void DockItem::setDockPosition(const Position side) DockPosition = side; } -void DockItem::setDockSize(const int size) -{ - DockSize = size; -} - void DockItem::setDockDisplayMode(const DisplayMode mode) { DockDisplayMode = mode; @@ -222,7 +224,7 @@ void DockItem::showContextMenu() QJsonObject jsonMenu = jsonDocument.object(); - qDeleteAll(m_contextMenu.actions()); + qDeleteAll(m_contextMenu->actions()); QJsonArray jsonMenuItems = jsonMenu.value("items").toArray(); for (auto item : jsonMenuItems) { @@ -232,16 +234,13 @@ void DockItem::showContextMenu() action->setChecked(itemObj.value("checked").toBool()); action->setData(itemObj.value("itemId").toString()); action->setEnabled(itemObj.value("isActive").toBool()); - m_contextMenu.addAction(action); + m_contextMenu->addAction(action); } hidePopup(); emit requestWindowAutoHide(false); - if (!m_contextMenu.parentWidget()) - m_contextMenu.setParent(topLevelWidget(), Qt::Popup); - - m_contextMenu.exec(QCursor::pos()); + m_contextMenu->exec(QCursor::pos()); onContextMenuAccepted(); } @@ -270,9 +269,13 @@ void DockItem::showHoverTips() showPopupWindow(content); } -void DockItem::showPopupWindow(QWidget *const content, const bool model, const int radius) +void DockItem::showPopupWindow(QWidget *const content, const bool model) { - PopupWindow->setRadius(radius); + if(itemType() == App){ + PopupWindow->setRadius(18); + }else { + PopupWindow->setRadius(6); + } m_popupShown = true; m_lastPopupWidget = content; diff --git a/frame/item/dockitem.h b/frame/item/dockitem.h index 7d3cf36c4..aff21c656 100644 --- a/frame/item/dockitem.h +++ b/frame/item/dockitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -11,24 +12,28 @@ #include #include #include -#include #include using namespace Dock; +class QMenu; + class DockItem : public QWidget { Q_OBJECT public: enum ItemType { - Launcher, - App, - Plugins, - FixedPlugin, + Launcher, // 启动器 + App, // 任务栏区域的应用 + Plugins, // 插件区域图标 + FixedPlugin, // 固定区域图标,例如多任务试图 Placeholder, - TrayPlugin, + TrayPlugin, // 托盘插件 + QuickSettingPlugin, // 快捷设置区域插件 + StretchPlugin, // 时尚模式下的固定在最右侧的插件,例如开关机插件 + AppMultiWindow // APP的多开应用的窗口 }; public: @@ -36,10 +41,9 @@ public: ~DockItem() override; static void setDockPosition(const Position side); - static void setDockSize(const int size); static void setDockDisplayMode(const DisplayMode mode); - inline virtual ItemType itemType() const {return App;} + inline virtual ItemType itemType() const = 0; QSize sizeHint() const override; virtual QString accessibleName(); @@ -72,7 +76,7 @@ protected: void hideNonModel(); void popupWindowAccept(); - virtual void showPopupWindow(QWidget *const content, const bool model = false, const int radius = 6); + virtual void showPopupWindow(QWidget *const content, const bool model = false); virtual void showHoverTips(); virtual void invokedMenuItem(const QString &itemId, const bool checked); virtual const QString contextMenu() const; @@ -94,7 +98,7 @@ protected: bool m_popupShown; bool m_tapAndHold; bool m_draging; - QMenu m_contextMenu; + QMenu *m_contextMenu; QPointer m_lastPopupWidget; @@ -102,7 +106,6 @@ protected: QTimer *m_popupAdjustDelayTimer; static Position DockPosition; - static int DockSize; static DisplayMode DockDisplayMode; static QPointer PopupWindow; }; diff --git a/frame/item/item.qrc b/frame/item/item.qrc index 213d454ef..88004c5cb 100644 --- a/frame/item/item.qrc +++ b/frame/item/item.qrc @@ -13,6 +13,10 @@ resources/arrow-right.svg resources/arrow-left.svg resources/arrow-down.svg + resources/arrow-up-dark.svg + resources/arrow-right-dark.svg + resources/arrow-left-dark.svg + resources/arrow-down-dark.svg resources/application-x-desktop.svg resources/close_round_hover.svg resources/close_round_press.svg @@ -67,5 +71,17 @@ resources/week5.svg resources/week6.svg resources/week7.svg + resources/audio-volume-high-dark.svg + resources/audio-volume-high.svg + resources/audio-volume-low-dark.svg + resources/audio-volume-low.svg + resources/audio-volume-medium.svg + resources/audio-volume-muted-dark.svg + resources/audio-volume-muted.svg + resources/audio-volume-medium-dark.svg + resources/laptop.svg + resources/volume.svg + resources/dcc_dock_plug_in.svg + resources/broadcast.svg diff --git a/frame/item/launcheritem.cpp b/frame/item/launcheritem.cpp index ffe0eed06..497db223b 100644 --- a/frame/item/launcheritem.cpp +++ b/frame/item/launcheritem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,6 +7,7 @@ #include "themeappicon.h" #include "utils.h" #include "../widgets/tipswidget.h" +#include "dbusutil.h" #include #include @@ -84,13 +86,13 @@ void LauncherItem::mouseReleaseEvent(QMouseEvent *e) return; DDBusSender dbusSender = DDBusSender() - .service("com.deepin.dde.Launcher") - .path("/com/deepin/dde/Launcher") - .interface("com.deepin.dde.Launcher"); + .service(launcherService) + .path(launcherPath) + .interface(launcherInterface); QDBusPendingReply visibleReply = dbusSender.property("Visible").get(); if (!visibleReply.value()) - dbusSender.method("Show").call(); + dbusSender.method("Toggle").call(); } QWidget *LauncherItem::popupTips() diff --git a/frame/item/launcheritem.h b/frame/item/launcheritem.h index 2d9df29c2..ad60ce332 100644 --- a/frame/item/launcheritem.h +++ b/frame/item/launcheritem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/item/placeholderitem.cpp b/frame/item/placeholderitem.cpp index 0660753bc..4777ea617 100644 --- a/frame/item/placeholderitem.cpp +++ b/frame/item/placeholderitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/item/placeholderitem.h b/frame/item/placeholderitem.h index e9af54077..95546dc6c 100644 --- a/frame/item/placeholderitem.h +++ b/frame/item/placeholderitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/item/pluginsitem.cpp b/frame/item/pluginsitem.cpp index 304a28064..d6c1cf2fc 100644 --- a/frame/item/pluginsitem.cpp +++ b/frame/item/pluginsitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,6 +8,8 @@ #include "pluginsiteminterface.h" #include "utils.h" +#include + #include #include #include @@ -18,28 +21,30 @@ QPoint PluginsItem::MousePressPoint = QPoint(); -PluginsItem::PluginsItem(PluginsItemInterface *const pluginInter, const QString &itemKey, const QString &plginApi, QWidget *parent) +PluginsItem::PluginsItem(PluginsItemInterface *const pluginInter, const QString &itemKey, const QJsonObject &jsonData, QWidget *parent) : DockItem(parent) , m_pluginInter(pluginInter) , m_centralWidget(m_pluginInter->itemWidget(itemKey)) - , m_pluginApi(plginApi) + , m_jsonData(jsonData) , m_itemKey(itemKey) , m_dragging(false) , m_gsettings(Utils::ModuleSettingsPtr(pluginInter->pluginName(), QByteArray(), this)) { qDebug() << "load plugins item: " << pluginInter->pluginName() << itemKey << m_centralWidget; - m_centralWidget->setParent(this); - m_centralWidget->setVisible(true); - m_centralWidget->setObjectName(pluginInter->pluginName() + "-centralwidget"); - m_centralWidget->installEventFilter(this); + if (m_centralWidget) { + m_centralWidget->setParent(this); + m_centralWidget->setVisible(true); + m_centralWidget->setObjectName(pluginInter->pluginName() + "-centralwidget"); + m_centralWidget->installEventFilter(this); - QBoxLayout *hLayout = new QHBoxLayout; - hLayout->addWidget(m_centralWidget); - hLayout->setSpacing(0); - hLayout->setMargin(0); + QBoxLayout *hLayout = new QHBoxLayout; + hLayout->addWidget(m_centralWidget); + hLayout->setSpacing(0); + hLayout->setMargin(0); - setLayout(hLayout); + setLayout(hLayout); + } setAccessibleName(pluginInter->pluginName()); setAttribute(Qt::WA_TranslucentBackground); @@ -76,7 +81,7 @@ QString PluginsItem::pluginName() const PluginsItemInterface::PluginSizePolicy PluginsItem::pluginSizePolicy() const { // 插件版本大于 1.2.2 才能使用 PluginsItemInterface::pluginSizePolicy 函数 - if (Utils::comparePluginApi(m_pluginApi, "1.2.2") > 0) { + if (Utils::comparePluginApi(pluginApi(), "1.2.2") > 0) { return m_pluginInter->pluginSizePolicy(); } else { return PluginsItemInterface::System; @@ -139,7 +144,7 @@ void PluginsItem::mousePressEvent(QMouseEvent *e) if (e->button() == Qt::RightButton) { if (perfectIconRect().contains(e->pos())) { - return (m_gsettings && m_gsettings->keys().contains("menuEnable") && !m_gsettings->get("menuEnable").toBool()) ? void() : showContextMenu(); + return (m_gsettings && (!m_gsettings->keys().contains("menuEnable") || m_gsettings->get("menuEnable").toBool())) ? showContextMenu() : void(); } } @@ -242,9 +247,9 @@ void PluginsItem::invokedMenuItem(const QString &itemId, const bool checked) m_pluginInter->invokedMenuItem(m_itemKey, itemId, checked); } -void PluginsItem::showPopupWindow(QWidget *const content, const bool model, const int radius) +void PluginsItem::showPopupWindow(QWidget *const content, const bool model) { - DockItem::showPopupWindow(content, model, radius); + DockItem::showPopupWindow(content, model); } const QString PluginsItem::contextMenu() const @@ -289,6 +294,11 @@ bool PluginsItem::checkGSettingsControl() const return m_gsettings ? m_gsettings->keys().contains("control") && m_gsettings->get("control").toBool() : false; } +QString PluginsItem::pluginApi() const +{ + return m_jsonData.value("api").toString(); +} + void PluginsItem::resizeEvent(QResizeEvent *event) { setMaximumSize(m_centralWidget->maximumSize()); @@ -301,3 +311,8 @@ void PluginsItem::setDraging(bool bDrag) m_centralWidget->setVisible(!bDrag); } + +PluginsItemInterface *PluginsItem::pluginItem() const +{ + return m_pluginInter; +} diff --git a/frame/item/pluginsitem.h b/frame/item/pluginsitem.h index e79751c7d..0c09561d7 100644 --- a/frame/item/pluginsitem.h +++ b/frame/item/pluginsitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -9,12 +10,14 @@ #include "pluginsiteminterface.h" class QGSettings; + class PluginsItem : public DockItem { Q_OBJECT + friend class QuickSettingController; + public: - explicit PluginsItem(PluginsItemInterface *const pluginInter, const QString &itemKey, const QString &plginApi, QWidget *parent = nullptr); ~PluginsItem() override; int itemSortKey() const; @@ -34,9 +37,14 @@ public: virtual void setDraging(bool bDrag) override; + PluginsItemInterface *pluginItem() const; + public slots: void refreshIcon() override; +protected: + explicit PluginsItem(PluginsItemInterface *const pluginInter, const QString &itemKey, const QJsonObject &jsonData, QWidget *parent = nullptr); + private slots: void onGSettingsChanged(const QString &key); @@ -50,7 +58,7 @@ protected: void showEvent(QShowEvent *event) override; void invokedMenuItem(const QString &itemId, const bool checked) override; - void showPopupWindow(QWidget *const content, const bool model = false, const int radius = 6) override; + void showPopupWindow(QWidget *const content, const bool model = false) override; const QString contextMenu() const override; QWidget *popupTips() override; void resizeEvent(QResizeEvent *event) override; @@ -59,12 +67,13 @@ private: void startDrag(); void mouseClicked(); bool checkGSettingsControl() const; + QString pluginApi() const; private: PluginsItemInterface *const m_pluginInter; QWidget *m_centralWidget; - const QString m_pluginApi; + QJsonObject m_jsonData; const QString m_itemKey; bool m_dragging; diff --git a/frame/item/resources/arrow-down-dark.svg b/frame/item/resources/arrow-down-dark.svg new file mode 100644 index 000000000..6d5436cab --- /dev/null +++ b/frame/item/resources/arrow-down-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/arrow-left-dark.svg b/frame/item/resources/arrow-left-dark.svg new file mode 100644 index 000000000..1f32c3315 --- /dev/null +++ b/frame/item/resources/arrow-left-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/arrow-right-dark.svg b/frame/item/resources/arrow-right-dark.svg new file mode 100644 index 000000000..04d121e0b --- /dev/null +++ b/frame/item/resources/arrow-right-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/arrow-up-dark.svg b/frame/item/resources/arrow-up-dark.svg new file mode 100644 index 000000000..2a72912ff --- /dev/null +++ b/frame/item/resources/arrow-up-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-high-dark.svg b/frame/item/resources/audio-volume-high-dark.svg new file mode 100644 index 000000000..4d4091a65 --- /dev/null +++ b/frame/item/resources/audio-volume-high-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-high.svg b/frame/item/resources/audio-volume-high.svg new file mode 100644 index 000000000..81e42bb50 --- /dev/null +++ b/frame/item/resources/audio-volume-high.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-low-dark.svg b/frame/item/resources/audio-volume-low-dark.svg new file mode 100644 index 000000000..2a1451bd7 --- /dev/null +++ b/frame/item/resources/audio-volume-low-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-low.svg b/frame/item/resources/audio-volume-low.svg new file mode 100644 index 000000000..67caf09c3 --- /dev/null +++ b/frame/item/resources/audio-volume-low.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-medium-dark.svg b/frame/item/resources/audio-volume-medium-dark.svg new file mode 100644 index 000000000..aa30f960f --- /dev/null +++ b/frame/item/resources/audio-volume-medium-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-medium.svg b/frame/item/resources/audio-volume-medium.svg new file mode 100644 index 000000000..1558aff33 --- /dev/null +++ b/frame/item/resources/audio-volume-medium.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-muted-dark.svg b/frame/item/resources/audio-volume-muted-dark.svg new file mode 100644 index 000000000..1b62397ef --- /dev/null +++ b/frame/item/resources/audio-volume-muted-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/audio-volume-muted.svg b/frame/item/resources/audio-volume-muted.svg new file mode 100644 index 000000000..be87cfead --- /dev/null +++ b/frame/item/resources/audio-volume-muted.svg @@ -0,0 +1,3 @@ + + + diff --git a/frame/item/resources/broadcast.svg b/frame/item/resources/broadcast.svg new file mode 100644 index 000000000..f45b1ae57 --- /dev/null +++ b/frame/item/resources/broadcast.svg @@ -0,0 +1,15 @@ + + + ICON / MenuItem / Broadcast + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_plug_in_16px.svg b/frame/item/resources/dcc_dock_plug_in.svg similarity index 100% rename from plugins/dcc-dock-plugin/texts/dcc_dock_plug_in_16px.svg rename to frame/item/resources/dcc_dock_plug_in.svg diff --git a/frame/item/resources/laptop.svg b/frame/item/resources/laptop.svg new file mode 100644 index 000000000..90bf3ee48 --- /dev/null +++ b/frame/item/resources/laptop.svg @@ -0,0 +1,15 @@ + + + ICON / Device / Laptop + + + + + + + + + + + + \ No newline at end of file diff --git a/frame/item/resources/volume.svg b/frame/item/resources/volume.svg new file mode 100644 index 000000000..1655e82f1 --- /dev/null +++ b/frame/item/resources/volume.svg @@ -0,0 +1,15 @@ + + + ICON / MenuItem / Volume+ + + + + + + + + + + + + \ No newline at end of file diff --git a/frame/item/traypluginitem.cpp b/frame/item/traypluginitem.cpp index 4a01cc007..cdbc5e801 100644 --- a/frame/item/traypluginitem.cpp +++ b/frame/item/traypluginitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,8 +8,8 @@ #include -TrayPluginItem::TrayPluginItem(PluginsItemInterface * const pluginInter, const QString &itemKey, const QString &pluginApi, QWidget *parent) - : PluginsItem(pluginInter, itemKey, pluginApi, parent) +TrayPluginItem::TrayPluginItem(PluginsItemInterface * const pluginInter, const QString &itemKey, const QJsonObject &metaData, QWidget *parent) + : PluginsItem(pluginInter, itemKey, metaData, parent) { centralWidget()->installEventFilter(this); } diff --git a/frame/item/traypluginitem.h b/frame/item/traypluginitem.h index c150a3196..43e731d4f 100644 --- a/frame/item/traypluginitem.h +++ b/frame/item/traypluginitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -12,7 +13,7 @@ class TrayPluginItem : public PluginsItem Q_OBJECT public: - TrayPluginItem(PluginsItemInterface* const pluginInter, const QString &itemKey, const QString &pluginApi, QWidget *parent = nullptr); + TrayPluginItem(PluginsItemInterface* const pluginInter, const QString &itemKey, const QJsonObject &metaData, QWidget *parent = nullptr); inline ItemType itemType() const override {return ItemType::TrayPlugin;} diff --git a/frame/main.cpp b/frame/main.cpp index 532920ab1..5c79b0f09 100644 --- a/frame/main.cpp +++ b/frame/main.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -9,6 +10,8 @@ #include "themeappicon.h" #include "dockitemmanager.h" #include "dockapplication.h" +#include "traymainwindow.h" +#include "windowmanager.h" #include #include @@ -19,7 +22,6 @@ #include #include #include -#include #include #include @@ -173,16 +175,17 @@ int main(int argc, char *argv[]) app.setAttribute(Qt::AA_EnableHighDpiScaling, true); app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); - // 自动化标记 + // 自动化标记由此开始 QAccessible::installFactory(accessibleFactory); // 设置日志输出到控制台以及文件 + DLogManager::setLogFormat("%{time}{yyyyMMdd.HH:mm:ss.zzz}[%{type:1}][%{function:-35} %{line:-4}] %{message}\n"); DLogManager::registerConsoleAppender(); DLogManager::registerFileAppender(); // 启动入参 dde-dock --help可以看到一下内容, -x不加载插件 -r 一般用在startdde启动任务栏 QCommandLineOption disablePlugOption(QStringList() << "x" << "disable-plugins", "do not load plugins."); - QCommandLineOption runOption(QStringList() << "r" << "run-by-startdde", "run by startdde."); + QCommandLineOption runOption(QStringList() << "r" << "run-by-stardde", "run by startdde."); QCommandLineParser parser; parser.setApplicationDescription("DDE Dock"); parser.addHelpOption(); @@ -202,29 +205,40 @@ int main(int argc, char *argv[]) QDir::setCurrent(QApplication::applicationDirPath()); #endif + // 在qApp中记录当前是否为安全模式,如果为安全模式,则无需加载插件,在退出安全模式下,才正常加载插件 + // 此处设置这个属性必须在MainWindow创建之前,因为在mainWindow中会创建加载插件的代理,会在代理中根据这个属性来判断是否需要加载插件 + bool isSafeMode = IsSaveMode(); + bool disablePlugin = parser.isSet(disablePlugOption); + qApp->setProperty("safeMode", (isSafeMode || disablePlugin)); + + MultiScreenWorker multiScreenWorker; + + MainWindow mainWindow(&multiScreenWorker); + TrayMainWindow trayMainWindow(&multiScreenWorker); + + WindowManager windowManager(&multiScreenWorker); + + // 保证添加窗口的先后顺序,先添加的窗口显示在左边,后添加的窗口显示在右边 + windowManager.addWindow(&mainWindow); + windowManager.addWindow(&trayMainWindow); + // 注册任务栏的DBus服务 - MainWindow mw; - DBusDockAdaptors adaptor(&mw); + DBusDockAdaptors adaptor(&windowManager); - if(Utils::IS_WAYLAND_DISPLAY) { - mw.setAttribute(Qt::WA_NativeWindow); - mw.windowHandle()->setProperty("_d_dwayland_window-type", "dock"); - } - - QDBusConnection::sessionBus().registerService("com.deepin.dde.Dock"); - QDBusConnection::sessionBus().registerObject("/com/deepin/dde/Dock", "com.deepin.dde.Dock", &mw); + QDBusConnection::sessionBus().registerService("org.deepin.dde.Dock1"); + QDBusConnection::sessionBus().registerObject("/org/deepin/dde/Dock1", "org.deepin.dde.Dock1", &windowManager); // 当任务栏以-r参数启动时,设置CANSHOW未false,之后调用launch不显示任务栏 qApp->setProperty("CANSHOW", !parser.isSet(runOption)); - mw.launch(); + windowManager.launch(); + mainWindow.setVisible(true); // 判断是否进入安全模式,是否带有入参 -x - if (!IsSaveMode() && !parser.isSet(disablePlugOption)) { - DockItemManager::instance()->startLoadPlugins(); + if (!isSafeMode && !disablePlugin) { qApp->setProperty("PLUGINSLOADED", true); } else { - mw.sendNotifications(); + windowManager.sendNotifications(); } return app.exec(); diff --git a/frame/screenspliter/screenspliter.cpp b/frame/screenspliter/screenspliter.cpp new file mode 100644 index 000000000..c33635588 --- /dev/null +++ b/frame/screenspliter/screenspliter.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "screenspliter.h" +#include "appitem.h" +#include "utils.h" +#include "screenspliter_xcb.h" +#include "screenspliter_wayland.h" + +bool ScreenSpliter::releaseSplit() +{ + return true; +} + +ScreenSpliter::ScreenSpliter(AppItem *appItem, DockEntryInter *entryInter, QObject *parent) + : QObject(parent) + , m_appItem(appItem) + , m_entryInter(entryInter) +{ +} + +ScreenSpliter::~ScreenSpliter() +{ + m_appItem = nullptr; +} + +AppItem *ScreenSpliter::appItem() const +{ + return m_appItem; +} + +DockEntryInter *ScreenSpliter::entryInter() const +{ + return m_entryInter; +} + +ScreenSpliter *ScreenSpliterFactory::createScreenSpliter(AppItem *appItem, DockEntryInter *entryInter) +{ + if (Utils::IS_WAYLAND_DISPLAY) + return new ScreenSpliter_Wayland(appItem, entryInter, appItem); + + return new ScreenSpliter_Xcb(appItem, entryInter, appItem); +} diff --git a/frame/screenspliter/screenspliter.h b/frame/screenspliter/screenspliter.h new file mode 100644 index 000000000..20e015d85 --- /dev/null +++ b/frame/screenspliter/screenspliter.h @@ -0,0 +1,56 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SCREENSPLITER_H +#define SCREENSPLITER_H + +#include "dbusutil.h" + +#include + +class AppItem; + +class ScreenSpliter : public QObject +{ + Q_OBJECT + +public: + enum SplitDirection { + None, // 无操作 + Left, // 左分屏 + Right, // 右分屏 + Top, // 上分屏 + Bottom, // 下分屏 + LeftTop, // 左上 + RightTop, // 右上 + LeftBottom, // 左下 + RightBottom, // 右下 + Full // 全屏 + }; + +public: + virtual void startSplit(const QRect &) = 0; // 触发分屏提示效果 + virtual bool split(SplitDirection) = 0; // 开始触发分屏 + virtual bool suportSplitScreen() = 0; // 是否支持分屏 + virtual bool releaseSplit(); // 释放分屏 + +protected: + explicit ScreenSpliter(AppItem *appItem, DockEntryInter *entryInter, QObject *parent = nullptr); + virtual ~ScreenSpliter(); + AppItem *appItem() const; + DockEntryInter *entryInter() const; + +private: + AppItem *m_appItem; + DockEntryInter *m_entryInter; +}; + +class ScreenSpliterFactory +{ +public: + static ScreenSpliter *createScreenSpliter(AppItem *appItem, DockEntryInter *entryInter); +}; + +#endif // SCREENSPLITER_H diff --git a/frame/screenspliter/screenspliter_wayland.cpp b/frame/screenspliter/screenspliter_wayland.cpp new file mode 100644 index 000000000..851725f68 --- /dev/null +++ b/frame/screenspliter/screenspliter_wayland.cpp @@ -0,0 +1,171 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "screenspliter_wayland.h" +#include "appitem.h" + +#include +#include +#include +#include +#define private public +#include +#include +#include +#include +#undef private + +#include +#include +#include +#include +#include +#include +#include + +SplitWindowManager *ScreenSpliter_Wayland::m_splitManager = nullptr; + +/** wayland下的分屏功能 + * @brief ScreenSpliter_Wayland::ScreenSpliter_Wayland + * @param parent + */ +ScreenSpliter_Wayland::ScreenSpliter_Wayland(AppItem *appItem, DockEntryInter *entryInter, QObject *parent) + : ScreenSpliter(appItem, entryInter, parent) +{ + if (!m_splitManager) + m_splitManager = new SplitWindowManager; +} + +ScreenSpliter_Wayland::~ScreenSpliter_Wayland() +{ +} + +void ScreenSpliter_Wayland::startSplit(const QRect &rect) +{ + if (!suportSplitScreen()) + return; + + setMaskVisible(rect, true); +} + +void ScreenSpliter_Wayland::setMaskVisible(const QRect &rect, bool visible) +{ + static QWidget *desktopWidget = nullptr; + if (!desktopWidget) { + desktopWidget = new QWidget; + DPalette palette = DGuiApplicationHelper::instance()->applicationPalette(); + QColor backColor = palette.color(QPalette::Highlight); + backColor.setAlpha(255 * 0.3); + palette.setBrush(QPalette::ColorRole::Background, backColor); + desktopWidget->setPalette(palette); + desktopWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); + } + desktopWidget->setVisible(visible); + desktopWidget->setGeometry(rect); + desktopWidget->raise(); +} + +bool ScreenSpliter_Wayland::split(SplitDirection direction) +{ + setMaskVisible(QRect(), false); + // 如果当前不支持分屏,则返回false + if (!suportSplitScreen()) + return false; + + WindowInfoMap windowInfos = entryInter()->windowInfos(); + m_splitManager->requestSplitWindow(windowInfos.first().uuid.toStdString().c_str(), direction); + + return true; +} + +bool ScreenSpliter_Wayland::windowSupportSplit(const QString &uuid) const +{ + return m_splitManager->canSplit(uuid); +} + +bool ScreenSpliter_Wayland::suportSplitScreen() +{ + // 判断所有打开的窗口列表,只要有一个窗口支持分屏,就认为它支持分屏 + const WindowInfoMap &windowsInfo = entryInter()->windowInfos(); + for (const WindowInfo &windowInfo : windowsInfo) { + if (windowSupportSplit(windowInfo.uuid)) + return true; + } + + // 如果所有的窗口都不支持分屏,就认为它不支持分屏,包括没有打开窗口的情况 + return false; +} + +bool ScreenSpliter_Wayland::releaseSplit() +{ + setMaskVisible(QRect(), false); + return true; +} + +/** + * @brief SplitWindowManager::SplitWindowManager + * @param wayland下的分屏的管理 + */ +SplitWindowManager::SplitWindowManager(QObject *parent) + : QObject(parent) + , m_clientManagement(nullptr) + , m_connectionThread(new QThread(nullptr)) + , m_connectionThreadObject(new ConnectionThread) +{ + connect(m_connectionThreadObject, &ConnectionThread::connected, this, &SplitWindowManager::onConnectionFinished, Qt::QueuedConnection); + + m_connectionThreadObject->moveToThread(m_connectionThread); + m_connectionThread->start(); + m_connectionThreadObject->initConnection(); +} + +SplitWindowManager::~SplitWindowManager() +{ +} + +bool SplitWindowManager::canSplit(const QString &uuid) const +{ + const QVector &windowStates = m_clientManagement->getWindowStates(); + for (const ClientManagement::WindowState &winState : windowStates) + if (winState.uuid == uuid && winState.splitable > 0) + return true; + + return false; +} + +static ClientManagement::SplitType convertSplitType(ScreenSpliter::SplitDirection direction) +{ + static QMap direcionMapping = { + { ScreenSpliter::Left, ClientManagement::SplitType::Left }, + { ScreenSpliter::Right, ClientManagement::SplitType::Right}, + { ScreenSpliter::Top, ClientManagement::SplitType::Top }, + { ScreenSpliter::Bottom, ClientManagement::SplitType::Bottom }, + { ScreenSpliter::LeftTop, ClientManagement::SplitType::LeftTop }, + { ScreenSpliter::RightTop, ClientManagement::SplitType::RightTop }, + { ScreenSpliter::LeftBottom, ClientManagement::SplitType::LeftBottom }, + { ScreenSpliter::RightBottom, ClientManagement::SplitType::RightBottom } + }; + + return direcionMapping.value(direction, ClientManagement::SplitType::None); +} + +void SplitWindowManager::requestSplitWindow(const char *uuid, const ScreenSpliter::SplitDirection &direction) +{ + m_clientManagement->requestSplitWindow(uuid, convertSplitType(direction)); +} + +void SplitWindowManager::onConnectionFinished() +{ + EventQueue *eventQueue = new EventQueue(this); + eventQueue->setup(m_connectionThreadObject); + + Registry *registry = new Registry(this); + connect(registry, &Registry::clientManagementAnnounced, this, [ this, registry ](quint32 name, quint32 version) { + m_clientManagement = registry->createClientManagement(name, version, this); + }); + registry->setEventQueue(eventQueue); + registry->create(m_connectionThreadObject); + registry->setup(); +} diff --git a/frame/screenspliter/screenspliter_wayland.h b/frame/screenspliter/screenspliter_wayland.h new file mode 100644 index 000000000..fe98e48d2 --- /dev/null +++ b/frame/screenspliter/screenspliter_wayland.h @@ -0,0 +1,81 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SCREENSPLITER_WAYLAND_H +#define SCREENSPLITER_WAYLAND_H + +#include "screenspliter.h" + +#include + +namespace KWayland { +namespace Client { +class Registry; +class DDEShell; +class DDEShellSurface; +class EventQueue; +class Compositor; +class Surface; +class ClientManagement; +class ConnectionThread; +} +} + +class AppItem; +class QWindow; +class QThread; +class SplitWindowManager; + +class WindowInfo; +typedef QMap WindowInfoMap; + +using namespace KWayland::Client; + +class ScreenSpliter_Wayland : public ScreenSpliter +{ + Q_OBJECT + +public: + explicit ScreenSpliter_Wayland(AppItem *appItem, DockEntryInter *entryInter, QObject *parent); + ~ScreenSpliter_Wayland() override; + + void startSplit(const QRect &rect) override; + bool split(SplitDirection direction) override; + bool suportSplitScreen() override; + bool releaseSplit() override; + +private: + void setMaskVisible(const QRect &rect, bool visible); + bool windowSupportSplit(const QString &uuid) const; + +private: + static SplitWindowManager *m_splitManager; + QRect m_splitRect; +}; + +class SplitWindowManager : public QObject +{ + Q_OBJECT + + friend class ScreenSpliter_Wayland; + +protected: + explicit SplitWindowManager(QObject *parent = Q_NULLPTR); + ~SplitWindowManager() override; + + bool canSplit(const QString &uuid) const; + void requestSplitWindow(const char *uuid, const ScreenSpliter::SplitDirection &direction); + +private Q_SLOTS: + void onConnectionFinished(); + +private: + ClientManagement *m_clientManagement; + QThread *m_connectionThread; + ConnectionThread *m_connectionThreadObject; + QMap m_splitWindowState; +}; + +#endif // SCREENSPLITER_WAYLAND_H diff --git a/frame/screenspliter/screenspliter_xcb.cpp b/frame/screenspliter/screenspliter_xcb.cpp new file mode 100644 index 000000000..e403d8c4c --- /dev/null +++ b/frame/screenspliter/screenspliter_xcb.cpp @@ -0,0 +1,165 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "screenspliter_xcb.h" +#include "appitem.h" + +#include + +#include +#include +#include + +#define LEFT 1 +#define RIGHT 2 +#define TOP 3 +#define BOTTOM 4 +#define LEFTTOP 5 +#define RIGHTTOP 6 +#define LEFTBOTTOM 9 +#define RIGHTBOTTOM 10 +#define SPLITUNKNOW 0 + +static xcb_atom_t internAtom(const char *name, bool only_if_exist) +{ + if (!name || *name == 0) + return XCB_NONE; + + xcb_connection_t *connection = QX11Info::connection(); + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, only_if_exist, strlen(name), name); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookie, 0); + if (!reply) + return XCB_NONE; + + xcb_atom_t atom = reply->atom; + free(reply); + + return atom; +} + +static QByteArray windowProperty(quint32 WId, xcb_atom_t propAtom, xcb_atom_t typeAtom, quint32 len) +{ + xcb_connection_t *conn = QX11Info::connection(); + xcb_get_property_cookie_t cookie = xcb_get_property(conn, false, WId, propAtom, typeAtom, 0, len); + xcb_generic_error_t *err = nullptr; + xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, &err); + + QByteArray data; + if (reply != nullptr) { + int valueLen = xcb_get_property_value_length(reply); + const char *buf = static_cast(xcb_get_property_value(reply)); + data.append(buf, valueLen); + free(reply); + } + + if (err != nullptr) { + free(err); + } + + return data; +} + +ScreenSpliter_Xcb::ScreenSpliter_Xcb(AppItem *appItem, DockEntryInter *entryInter, QObject *parent) + : ScreenSpliter(appItem, entryInter, parent) +{ +} + +void ScreenSpliter_Xcb::startSplit(const QRect &rect) +{ + if (!suportSplitScreen()) + return; + + showSplitScreenEffect(rect, true); +} + +bool ScreenSpliter_Xcb::split(ScreenSpliter::SplitDirection direction) +{ + if (!suportSplitScreen()) + return false; + + quint32 WId = entryInter()->windowInfos().keys().first(); + xcb_client_message_event_t xev; + xev.response_type = XCB_CLIENT_MESSAGE; + xev.type = internAtom("_DEEPIN_SPLIT_WINDOW", false); + xev.window = WId; + xev.format = 32; + xev.data.data32[0] = direction_x11(direction); // 1: 左分屏 2: 右分屏 5 左上 6 右上 9 左下 10 右下 15: 全屏 + xev.data.data32[1] = 1; // 1 进入预览 0 不进入预览 + + xcb_send_event(QX11Info::connection(), false, QX11Info::appRootWindow(QX11Info::appScreen()), + SubstructureNotifyMask, (const char *)&xev); + xcb_flush(QX11Info::connection()); + + return true; +} + +uint32_t ScreenSpliter_Xcb::direction_x11(ScreenSpliter::SplitDirection direction) +{ + static QMap directionMapping = { + { ScreenSpliter::Left, LEFT }, + { ScreenSpliter::Right, RIGHT }, + { ScreenSpliter::Top, TOP }, + { ScreenSpliter::Bottom, TOP }, + { ScreenSpliter::LeftTop, LEFTTOP }, + { ScreenSpliter::RightTop, RIGHTTOP }, + { ScreenSpliter::LeftBottom, LEFTBOTTOM }, + { ScreenSpliter::RightBottom, RIGHTBOTTOM } + }; + + return directionMapping.value(direction, SPLITUNKNOW); +} + +void ScreenSpliter_Xcb::showSplitScreenEffect(const QRect &rect, bool visible) +{ + if (!suportSplitScreen()) + return; + + quint32 WId = entryInter()->windowInfos().keys().first(); + // 触发分屏的效果 + xcb_client_message_event_t xev; + xev.response_type = XCB_CLIENT_MESSAGE; + xev.type = internAtom("_DEEPIN_SPLIT_OUTLINE", false); + xev.window = WId; + xev.format = 32; + xev.data.data32[0] = visible ? 1 : 0; // 1: 显示 0: 取消 + xev.data.data32[1] = rect.x(); // X坐标 + xev.data.data32[2] = rect.y(); // Y坐标 + xev.data.data32[3] = rect.width(); // width + xev.data.data32[4] = rect.height(); // height + + xcb_send_event(QX11Info::connection(), false, QX11Info::appRootWindow(QX11Info::appScreen()), + SubstructureNotifyMask, (const char *)&xev); + xcb_flush(QX11Info::connection()); +} + +bool ScreenSpliter_Xcb::suportSplitScreen() +{ + // 判断所有的窗口,只要有一个窗口支持分屏,就认为它支持分屏 + QList winIds = entryInter()->windowInfos().keys(); + for (const quint32 &winId : winIds) { + if (windowSupportSplit(winId)) + return true; + } + + return false; +} + +bool ScreenSpliter_Xcb::releaseSplit() +{ + showSplitScreenEffect(QRect(), false); + return true; +} + +bool ScreenSpliter_Xcb::windowSupportSplit(quint32 winId) +{ + xcb_atom_t propAtom = internAtom("_DEEPIN_NET_SUPPORTED", true); + QByteArray data = windowProperty(winId, propAtom, XCB_ATOM_CARDINAL, 4); + + bool supported = false; + if (const char *cdata = data.constData()) + supported = *(reinterpret_cast(cdata)); + + return supported; +} diff --git a/frame/screenspliter/screenspliter_xcb.h b/frame/screenspliter/screenspliter_xcb.h new file mode 100644 index 000000000..67cda3a80 --- /dev/null +++ b/frame/screenspliter/screenspliter_xcb.h @@ -0,0 +1,32 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SCREENSPLITER_XCB_H +#define SCREENSPLITER_XCB_H + +#include "screenspliter.h" + +#include + +class WindowInfo; +typedef QMap WindowInfoMap; + +class ScreenSpliter_Xcb : public ScreenSpliter +{ +public: + explicit ScreenSpliter_Xcb(AppItem *appItem, DockEntryInter *entryInter, QObject *parent = nullptr); + + void startSplit(const QRect &rect) override; + bool split(ScreenSpliter::SplitDirection direction) override; + bool suportSplitScreen() override; + bool releaseSplit() override; + +private: + uint32_t direction_x11(ScreenSpliter::SplitDirection direction); + void showSplitScreenEffect(const QRect &rect, bool visible); + bool windowSupportSplit(quint32 winId); +}; + +#endif // SCREENSPLITER_XCB_H diff --git a/frame/util/abstractpluginscontroller.cpp b/frame/util/abstractpluginscontroller.cpp index 1aa5e09ff..86367dc6c 100644 --- a/frame/util/abstractpluginscontroller.cpp +++ b/frame/util/abstractpluginscontroller.cpp @@ -1,10 +1,13 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "abstractpluginscontroller.h" #include "pluginsiteminterface.h" #include "utils.h" +#include "settingconfig.h" +#include "pluginmanagerinterface.h" #include #include @@ -23,14 +26,9 @@ static const QStringList CompatiblePluginApiList { AbstractPluginsController::AbstractPluginsController(QObject *parent) : QObject(parent) - , m_dbusDaemonInterface(QDBusConnection::sessionBus().interface()) - , m_dockDaemonInter(new DockDaemonInter("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) + , m_pluginManager(nullptr) { qApp->installEventFilter(this); - - refreshPluginSettings(); - - connect(m_dockDaemonInter, &DockDaemonInter::PluginSettingsSynced, this, &AbstractPluginsController::refreshPluginSettings, Qt::QueuedConnection); } AbstractPluginsController::~AbstractPluginsController() @@ -44,109 +42,6 @@ AbstractPluginsController::~AbstractPluginsController() } } -void AbstractPluginsController::saveValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant &value) -{ - // is it necessary? - // refreshPluginSettings(); - - // save to local cache - QJsonObject localObject = m_pluginSettingsObject.value(itemInter->pluginName()).toObject(); - localObject.insert(key, QJsonValue::fromVariant(value)); //Note: QVariant::toJsonValue() not work in Qt 5.7 - - // save to daemon - QJsonObject remoteObject, remoteObjectInter; - remoteObjectInter.insert(key, QJsonValue::fromVariant(value)); //Note: QVariant::toJsonValue() not work in Qt 5.7 - remoteObject.insert(itemInter->pluginName(), remoteObjectInter); - - if (itemInter->type() == PluginsItemInterface::Fixed && key == "enable" && !value.toBool()) { - int fixedPluginCount = 0; - // 遍历FixPlugin插件个数 - for (auto it(m_pluginsMap.begin()); it != m_pluginsMap.end();) { - if (it.key()->type() == PluginsItemInterface::Fixed) { - fixedPluginCount++; - } - ++it; - } - // 修改插件的order值,位置为队尾 - QString name = localObject.keys().last(); - // 此次做一下判断,有可能初始数据不存在pos_*字段,会导致enable字段被修改。或者此处可以循环所有字段是否存在pos_开头的字段? - if (name != key) { - localObject.insert(name, QJsonValue::fromVariant(fixedPluginCount)); //Note: QVariant::toJsonValue() not work in Qt 5.7 - // daemon中同样修改 - remoteObjectInter.insert(name, QJsonValue::fromVariant(fixedPluginCount)); //Note: QVariant::toJsonValue() not work in Qt 5.7 - remoteObject.insert(itemInter->pluginName(), remoteObjectInter); - } - } - - m_pluginSettingsObject.insert(itemInter->pluginName(), localObject); - m_dockDaemonInter->MergePluginSettings(QJsonDocument(remoteObject).toJson(QJsonDocument::JsonFormat::Compact)); -} - -const QVariant AbstractPluginsController::getValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant &fallback) -{ - // load from local cache - QVariant v = m_pluginSettingsObject.value(itemInter->pluginName()).toObject().value(key).toVariant(); - if (v.isNull() || !v.isValid()) { - v = fallback; - } - - return v; -} - -void AbstractPluginsController::removeValue(PluginsItemInterface *const itemInter, const QStringList &keyList) -{ - if (keyList.isEmpty()) { - m_pluginSettingsObject.remove(itemInter->pluginName()); - } else { - QJsonObject localObject = m_pluginSettingsObject.value(itemInter->pluginName()).toObject(); - for (auto key : keyList) { - localObject.remove(key); - } - m_pluginSettingsObject.insert(itemInter->pluginName(), localObject); - } - - m_dockDaemonInter->RemovePluginSettings(itemInter->pluginName(), keyList); -} - -QMap > &AbstractPluginsController::pluginsMap() -{ - return m_pluginsMap; -} - -QObject *AbstractPluginsController::pluginItemAt(PluginsItemInterface *const itemInter, const QString &itemKey) const -{ - if (!m_pluginsMap.contains(itemInter)) - return nullptr; - - return m_pluginsMap[itemInter][itemKey]; -} - -PluginsItemInterface *AbstractPluginsController::pluginInterAt(const QString &itemKey) -{ - QMapIterator> it(m_pluginsMap); - while (it.hasNext()) { - it.next(); - if (it.value().keys().contains(itemKey)) { - return it.key(); - } - } - - return nullptr; -} - -PluginsItemInterface *AbstractPluginsController::pluginInterAt(QObject *destItem) -{ - QMapIterator> it(m_pluginsMap); - while (it.hasNext()) { - it.next(); - if (it.value().values().contains(destItem)) { - return it.key(); - } - } - - return nullptr; -} - void AbstractPluginsController::startLoader(PluginLoader *loader) { connect(loader, &PluginLoader::finished, loader, &PluginLoader::deleteLater, Qt::QueuedConnection); @@ -196,7 +91,6 @@ void AbstractPluginsController::loadPlugin(const QString &pluginFile) } PluginsItemInterface *interface = qobject_cast(pluginLoader->instance()); - if (!interface) { qDebug() << objectName() << "load plugin failed!!!" << pluginLoader->errorString() << pluginFile; @@ -217,15 +111,6 @@ void AbstractPluginsController::loadPlugin(const QString &pluginFile) return; } - if (interface->pluginName() == "multitasking" && Dtk::Core::DSysInfo::deepinType() == Dtk::Core::DSysInfo::DeepinServer) { - for (auto &pair : m_pluginLoadMap.keys()) { - if (pair.first == pluginFile) { - m_pluginLoadMap.remove(pair); - } - } - return; - } - QMapIterator, bool> it(m_pluginLoadMap); while (it.hasNext()) { it.next(); @@ -243,20 +128,11 @@ void AbstractPluginsController::loadPlugin(const QString &pluginFile) QMap interfaceData; interfaceData["pluginloader"] = pluginLoader; m_pluginsMap.insert(interface, interfaceData); - QString dbusService = meta.value("depends-daemon-dbus-service").toString(); - if (!dbusService.isEmpty() && !m_dbusDaemonInterface->isServiceRegistered(dbusService).value()) { - qDebug() << objectName() << dbusService << "daemon has not started, waiting for signal"; - connect(m_dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, - [ = ](const QString & name, const QString & oldOwner, const QString & newOwner) { - Q_UNUSED(oldOwner); - if (name == dbusService && !newOwner.isEmpty()) { - qDebug() << objectName() << dbusService << "daemon started, init plugin and disconnect"; - initPlugin(interface); - disconnect(m_dbusDaemonInterface); - } - } - ); - return; + + PluginManagerInterface * pluginManager = dynamic_cast(interface); + if (pluginManager) { + m_pluginManager = pluginManager; + connect(m_pluginManager, &PluginManagerInterface::pluginLoadFinished, this, &AbstractPluginsController::pluginLoaderFinished); } // NOTE(justforlxz): 插件的所有初始化工作都在init函数中进行, @@ -288,77 +164,15 @@ void AbstractPluginsController::initPlugin(PluginsItemInterface *interface) } } - //插件全部加载完成 - if (loaded) { - emit pluginLoaderFinished(); - } qDebug() << objectName() << "init plugin finished: " << interface->pluginName(); } -void AbstractPluginsController::refreshPluginSettings() +bool AbstractPluginsController::eventFilter(QObject *object, QEvent *event) { - const QString &pluginSettings = m_dockDaemonInter->GetPluginSettings().value(); - if (pluginSettings.isEmpty()) { - qDebug() << "Error! get plugin settings from dbus failed!"; - return; - } - - const QJsonObject &pluginSettingsObject = QJsonDocument::fromJson(pluginSettings.toLocal8Bit()).object(); - if (pluginSettingsObject.isEmpty()) { - return; - } - - // nothing changed - if (pluginSettingsObject == m_pluginSettingsObject) { - return; - } - - for (auto pluginsIt = pluginSettingsObject.constBegin(); pluginsIt != pluginSettingsObject.constEnd(); ++pluginsIt) { - const QString &pluginName = pluginsIt.key(); - const QJsonObject &settingsObject = pluginsIt.value().toObject(); - QJsonObject newSettingsObject = m_pluginSettingsObject.value(pluginName).toObject(); - for (auto settingsIt = settingsObject.constBegin(); settingsIt != settingsObject.constEnd(); ++settingsIt) { - newSettingsObject.insert(settingsIt.key(), settingsIt.value()); - } - // TODO: remove not exists key-values - m_pluginSettingsObject.insert(pluginName, newSettingsObject); - } - - // not notify plugins to refresh settings if this update is not emit by dock daemon - if (sender() != m_dockDaemonInter) { - return; - } - - // notify all plugins to reload plugin settings - for (PluginsItemInterface *pluginInter : m_pluginsMap.keys()) { - pluginInter->pluginSettingsChanged(); - } - - // reload all plugin items for sort order or container - QMap> pluginsMapTemp = m_pluginsMap; - for (auto it = pluginsMapTemp.constBegin(); it != pluginsMapTemp.constEnd(); ++it) { - const QList &itemKeyList = it.value().keys(); - for (auto key : itemKeyList) { - if (key != "pluginloader") { - itemRemoved(it.key(), key); - } - } - for (auto key : itemKeyList) { - if (key != "pluginloader") { - itemAdded(it.key(), key); - } - } - } -} - -bool AbstractPluginsController::eventFilter(QObject *o, QEvent *e) -{ - if (o != qApp) - return false; - if (e->type() != QEvent::DynamicPropertyChange) + if (object != qApp || event->type() != QEvent::DynamicPropertyChange) return false; - QDynamicPropertyChangeEvent *const dpce = static_cast(e); + QDynamicPropertyChangeEvent *const dpce = static_cast(event); const QString propertyName = dpce->propertyName(); if (propertyName == PROP_POSITION) @@ -368,3 +182,8 @@ bool AbstractPluginsController::eventFilter(QObject *o, QEvent *e) return false; } + +PluginManagerInterface *AbstractPluginsController::pluginManager() const +{ + return m_pluginManager; +} diff --git a/frame/util/abstractpluginscontroller.h b/frame/util/abstractpluginscontroller.h index f59caa685..87fa7ab42 100644 --- a/frame/util/abstractpluginscontroller.h +++ b/frame/util/abstractpluginscontroller.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,38 +8,42 @@ #include "pluginproxyinterface.h" #include "pluginloader.h" - -#include +#include "dbusutil.h" #include #include #include #include -using DockDaemonInter = com::deepin::dde::daemon::Dock; - class PluginsItemInterface; +class PluginAdapter; +class PluginManagerInterface; + class AbstractPluginsController : public QObject, PluginProxyInterface { Q_OBJECT public: - explicit AbstractPluginsController(QObject *parent = 0); + explicit AbstractPluginsController(QObject *parent = Q_NULLPTR); ~ AbstractPluginsController() override; - // implements PluginProxyInterface - void saveValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant &value) override; - const QVariant getValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant& fallback = QVariant()) override; - void removeValue(PluginsItemInterface * const itemInter, const QStringList &keyList) override; + void updateDockInfo(PluginsItemInterface *const, const DockPart &) override {} -signals: +Q_SIGNALS: void pluginLoaderFinished(); protected: - QMap> &pluginsMap(); - QObject *pluginItemAt(PluginsItemInterface * const itemInter, const QString &itemKey) const; - PluginsItemInterface *pluginInterAt(const QString &itemKey); - PluginsItemInterface *pluginInterAt(QObject *destItem); + bool eventFilter(QObject *object, QEvent *event) override; + + PluginManagerInterface *pluginManager() const; + +private: + // implements PluginProxyInterface + void requestWindowAutoHide(PluginsItemInterface * const itemInter, const QString &itemKey, const bool autoHide) override {} + void requestRefreshWindowVisible(PluginsItemInterface * const itemInter, const QString &itemKey) override {} + void saveValue(PluginsItemInterface * const itemInter, const QString &key, const QVariant &value) override {} + void removeValue(PluginsItemInterface *const itemInter, const QStringList &keyList) override {} + const QVariant getValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant& fallback = QVariant()) override { return QVariant(); } protected Q_SLOTS: void startLoader(PluginLoader *loader); @@ -48,22 +53,15 @@ private slots: void positionChanged(); void loadPlugin(const QString &pluginFile); void initPlugin(PluginsItemInterface *interface); - void refreshPluginSettings(); private: - bool eventFilter(QObject *o, QEvent *e) override; - -private: - QDBusConnectionInterface *m_dbusDaemonInterface; - DockDaemonInter *m_dockDaemonInter; - - // interface, "pluginloader", PluginLoader指针对象 QMap> m_pluginsMap; // filepath, interface, loaded QMap, bool> m_pluginLoadMap; QJsonObject m_pluginSettingsObject; + PluginManagerInterface *m_pluginManager; }; #endif // ABSTRACTPLUGINSCONTROLLER_H diff --git a/frame/util/customevent.cpp b/frame/util/customevent.cpp new file mode 100644 index 000000000..e687bd418 --- /dev/null +++ b/frame/util/customevent.cpp @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "customevent.h" + +// 注册事件类型 +static QEvent::Type pluginEventType = (QEvent::Type)QEvent::registerEventType(QEvent::User + 1001); + +// 事件处理,当收到该事件的时候,加载插件 +PluginLoadEvent::PluginLoadEvent() + : QEvent(pluginEventType) +{ +} + +PluginLoadEvent::~PluginLoadEvent() +{ +} + +QEvent::Type PluginLoadEvent::eventType() +{ + return pluginEventType; +} diff --git a/frame/util/customevent.h b/frame/util/customevent.h new file mode 100644 index 000000000..1465d5e50 --- /dev/null +++ b/frame/util/customevent.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef CUSTOMEVENT_H +#define CUSTOMEVENT_H + +#include + +// 该插件用于处理插件的延迟加载,当退出安全模式后,会收到该事件并加载插件 +class PluginLoadEvent : public QEvent +{ +public: + PluginLoadEvent(); + ~PluginLoadEvent() override; + + static Type eventType(); +}; + +#endif // CUSTOMEVENT_H diff --git a/frame/util/dbusutil.h b/frame/util/dbusutil.h new file mode 100644 index 000000000..27f611b9c --- /dev/null +++ b/frame/util/dbusutil.h @@ -0,0 +1,44 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DBUSUTIL_H +#define DBUSUTIL_H + +#include "dockinterface.h" +#include "entryinterface.h" + +using DockInter = org::deepin::dde::daemon::DdeDock; +using DockEntryInter = org::deepin::dde::daemon::dock::DockEntry; + +const QString xEventMonitorService = "org.deepin.dde.XEventMonitor1"; +const QString xEventMonitorPath = "/org/deepin/dde/XEventMonitor1"; + +const QString launcherService = "org.deepin.dde.Launcher1"; +const QString launcherPath = "/org/deepin/dde/Launcher1"; +const QString launcherInterface = "org.deepin.dde.Launcher1"; + +const QString controllCenterService = "org.deepin.dde.ControlCenter1"; +const QString controllCenterPath = "/org/deepin/dde/ControlCenter1"; +const QString controllCenterInterface = "org.deepin.dde.ControlCenter1"; + +const QString notificationService = "org.deepin.dde.Notification1"; +const QString notificationPath = "/org/deepin/dde/Notification1"; +const QString notificationInterface = "org.deepin.dde.Notification1"; + +const QString sessionManagerService = "org.deepin.dde.SessionManager1"; +const QString sessionManagerPath = "/org/deepin/dde/SessionManager1"; +const QString sessionManagerInterface = "org.deepin.dde.SessionManager1"; + +inline const QString dockServiceName() +{ + return QString("org.deepin.dde.daemon.Dock1"); +} + +inline const QString dockServicePath() +{ + return QString("/org/deepin/dde/daemon/Dock1"); +} + +#endif // DBUSUTIL_H diff --git a/frame/util/dockapplication.cpp b/frame/util/dockapplication.cpp index d5f8a71b3..b39133a9e 100644 --- a/frame/util/dockapplication.cpp +++ b/frame/util/dockapplication.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/dockapplication.h b/frame/util/dockapplication.h index 3fe654ad1..068167f89 100644 --- a/frame/util/dockapplication.h +++ b/frame/util/dockapplication.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/dockpopupwindow.cpp b/frame/util/dockpopupwindow.cpp index 8afb93a0d..3eeae2783 100644 --- a/frame/util/dockpopupwindow.cpp +++ b/frame/util/dockpopupwindow.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "dockpopupwindow.h" #include "imageutil.h" #include "utils.h" +#include "dbusutil.h" #include #include @@ -17,10 +19,11 @@ DWIDGET_USE_NAMESPACE DockPopupWindow::DockPopupWindow(QWidget *parent) - : DArrowRectangle(ArrowBottom, parent), - m_model(false), - m_regionInter(new DRegionMonitor(this)), - m_enableMouseRelease(true) + : DArrowRectangle(ArrowBottom, parent) + , m_model(false) + , m_eventMonitor(new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus(), this)) + , m_enableMouseRelease(true) + , m_extendWidget(nullptr) { setMargin(0); m_wmHelper = DWindowManagerHelper::instance(); @@ -30,14 +33,16 @@ DockPopupWindow::DockPopupWindow(QWidget *parent) setWindowFlags(Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus); if (Utils::IS_WAYLAND_DISPLAY) { setAttribute(Qt::WA_NativeWindow); - // 谨慎修改层级,特别要注意对锁屏的影响 - windowHandle()->setProperty("_d_dwayland_window-type", "dock"); + windowHandle()->setProperty("_d_dwayland_window-type", "override"); } else { setAttribute(Qt::WA_InputMethodEnabled, false); } connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, this, &DockPopupWindow::compositeChanged); - connect(m_regionInter, &DRegionMonitor::buttonRelease, this, &DockPopupWindow::onGlobMouseRelease); + connect(m_eventMonitor, &XEventMonitor::ButtonPress, this, &DockPopupWindow::onButtonPress); + + if (Utils::IS_WAYLAND_DISPLAY) + QDBusConnection::sessionBus().connect("com.deepin.dde.lockFront", "/com/deepin/dde/lockFront", "com.deepin.dde.lockFront", "Visible", "b", this, SLOT(hide())); } DockPopupWindow::~DockPopupWindow() @@ -65,6 +70,17 @@ void DockPopupWindow::setContent(QWidget *content) DArrowRectangle::setContent(content); } +void DockPopupWindow::setExtendWidget(QWidget *widget) +{ + m_extendWidget = widget; + connect(widget, &QWidget::destroyed, this, [ this ] { m_extendWidget = nullptr; }, Qt::UniqueConnection); +} + +QWidget *DockPopupWindow::extengWidget() const +{ + return m_extendWidget; +} + void DockPopupWindow::show(const QPoint &pos, const bool model) { m_model = model; @@ -72,13 +88,15 @@ void DockPopupWindow::show(const QPoint &pos, const bool model) show(pos.x(), pos.y()); - if (m_regionInter->registered()) { - m_regionInter->unregisterRegion(); + if (!m_eventKey.isEmpty()) { + m_eventMonitor->UnregisterArea(m_eventKey); + m_eventKey.clear(); } if (m_model) { - m_regionInter->registerRegion(); + m_eventKey = m_eventMonitor->RegisterFullScreen(); } + blockButtonRelease(); } @@ -101,8 +119,10 @@ void DockPopupWindow::blockButtonRelease() void DockPopupWindow::hide() { - if (m_regionInter->registered()) - m_regionInter->unregisterRegion(); + if (!m_eventKey.isEmpty()) { + m_eventMonitor->UnregisterArea(m_eventKey); + m_eventKey.clear(); + } DArrowRectangle::hide(); } @@ -117,6 +137,12 @@ void DockPopupWindow::showEvent(QShowEvent *e) QTimer::singleShot(1, this, &DockPopupWindow::ensureRaised); } +void DockPopupWindow::hideEvent(QHideEvent *event) +{ + m_extendWidget = nullptr; + Dtk::Widget::DArrowRectangle::hideEvent(event); +} + void DockPopupWindow::enterEvent(QEvent *e) { DArrowRectangle::enterEvent(e); @@ -133,8 +159,7 @@ bool DockPopupWindow::eventFilter(QObject *o, QEvent *e) return false; // FIXME: ensure position move after global mouse release event - if (isVisible()) - { + if (isVisible()) { QTimer::singleShot(10, this, [=] { // NOTE(sbw): double check is necessary, in this time, the popup maybe already hided. if (isVisible()) @@ -145,27 +170,6 @@ bool DockPopupWindow::eventFilter(QObject *o, QEvent *e) return false; } -void DockPopupWindow::onGlobMouseRelease(const QPoint &mousePos, const int flag) -{ - Q_ASSERT(m_model); - - if (!m_enableMouseRelease) - return; - - if (!((flag == DRegionMonitor::WatchedFlags::Button_Left) || - (flag == DRegionMonitor::WatchedFlags::Button_Right))) { - return; - } - - const QRect rect = QRect(pos(), size()); - if (rect.contains(mousePos)) - return; - - emit accept(); - - m_regionInter->unregisterRegion(); -} - void DockPopupWindow::compositeChanged() { if (m_wmHelper->hasComposite()) @@ -176,12 +180,65 @@ void DockPopupWindow::compositeChanged() void DockPopupWindow::ensureRaised() { - if (isVisible()) { - QWidget *content = getContent(); - if (!content || !content->isVisible()) { - this->setVisible(false); - } else { - raise(); - } - } + if (isVisible()) + raise(); +} + +void DockPopupWindow::onButtonPress(int type, int x, int y, const QString &key) +{ + if (!m_enableMouseRelease) + return; + + QRect popupRect(pos() * qApp->devicePixelRatio(), size() * qApp->devicePixelRatio()) ; + if (popupRect.contains(x, y)) + return; + + if (m_extendWidget) { + // 计算额外添加的区域,如果鼠标的点击点在额外的区域内,也无需隐藏 + QPoint extendPoint = m_extendWidget->mapToGlobal(QPoint(0, 0)); + QRect extendRect(extendPoint * qApp->devicePixelRatio(), m_extendWidget->size() * qApp->devicePixelRatio()); + if (extendRect.contains(QPoint(x, y))) + return; + } + + emit accept(); + hide(); +} + +PopupSwitchWidget::PopupSwitchWidget(QWidget *parent) + : QWidget(parent) + , m_containerLayout(new QVBoxLayout(this)) + , m_topWidget(nullptr) +{ + m_containerLayout->setContentsMargins(0, 0, 0, 0); + m_containerLayout->setSpacing(0); +} + +PopupSwitchWidget::~PopupSwitchWidget() +{ +} + +void PopupSwitchWidget::pushWidget(QWidget *widget) +{ + // 首先将界面其他的窗体移除 + for (int i = m_containerLayout->count() - 1; i >= 0; i--) { + QLayoutItem *item = m_containerLayout->itemAt(i); + item->widget()->removeEventFilter(this); + item->widget()->hide(); + m_containerLayout->removeItem(item); + } + m_topWidget = widget; + setFixedSize(widget->size()); + widget->installEventFilter(this); + m_containerLayout->addWidget(widget); + widget->show(); +} + +bool PopupSwitchWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_topWidget && event->type() == QEvent::Resize) { + setFixedSize(m_topWidget->size()); + } + + return QWidget::eventFilter(watched, event); } diff --git a/frame/util/dockpopupwindow.h b/frame/util/dockpopupwindow.h index cf178cbeb..b8c063a31 100644 --- a/frame/util/dockpopupwindow.h +++ b/frame/util/dockpopupwindow.h @@ -1,16 +1,22 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DOCKPOPUPWINDOW_H #define DOCKPOPUPWINDOW_H +#include "org_deepin_dde_xeventmonitor1.h" + #include -#include +#include #include +DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE +using XEventMonitor = org::deepin::dde::XEventMonitor1; + class DockPopupWindow : public Dtk::Widget::DArrowRectangle { Q_OBJECT @@ -22,6 +28,8 @@ public: bool model() const; void setContent(QWidget *content); + void setExtendWidget(QWidget *widget); + QWidget *extengWidget() const; public slots: void show(const QPoint &pos, const bool model = false); @@ -38,22 +46,43 @@ signals: protected: void showEvent(QShowEvent *e); + void hideEvent(QHideEvent *event); void enterEvent(QEvent *e); bool eventFilter(QObject *o, QEvent *e); void blockButtonRelease(); private slots: - void onGlobMouseRelease(const QPoint &mousePos, const int flag); void compositeChanged(); void ensureRaised(); + void onButtonPress(int type, int x, int y, const QString &key); private: bool m_model; QPoint m_lastPoint; - DRegionMonitor *m_regionInter; + XEventMonitor *m_eventMonitor; + QString m_eventKey; DWindowManagerHelper *m_wmHelper; bool m_enableMouseRelease; + QWidget *m_extendWidget; +}; + +class PopupSwitchWidget : public QWidget +{ + Q_OBJECT + +public: + explicit PopupSwitchWidget(QWidget *parent = nullptr); + ~PopupSwitchWidget(); + + void pushWidget(QWidget *widget); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + QVBoxLayout *m_containerLayout; + QWidget *m_topWidget; }; #endif // DOCKPOPUPWINDOW_H diff --git a/frame/util/dockscreen.cpp b/frame/util/dockscreen.cpp new file mode 100644 index 000000000..a4fa1a453 --- /dev/null +++ b/frame/util/dockscreen.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dockscreen.h" +#include "displaymanager.h" + +DockScreen::DockScreen() + : m_primary(DisplayManager::instance()->primary()) + , m_currentScreen(m_primary) + , m_lastScreen(m_primary) +{ +} + +DockScreen *DockScreen::instance() +{ + static DockScreen instance; + return &instance; +} + +const QString &DockScreen::current() const +{ + return m_currentScreen; +} + +const QString &DockScreen::last() const +{ + return m_lastScreen; +} + +const QString &DockScreen::primary() const +{ + return m_primary; +} + +void DockScreen::updateDockedScreen(const QString &screenName) +{ + m_lastScreen = m_currentScreen; + m_currentScreen = screenName; +} + +void DockScreen::updatePrimary(const QString &primary) +{ + m_primary = primary; + if (m_currentScreen.isEmpty()) { + updateDockedScreen(primary); + } +} diff --git a/frame/util/dockscreen.h b/frame/util/dockscreen.h new file mode 100644 index 000000000..6115527d3 --- /dev/null +++ b/frame/util/dockscreen.h @@ -0,0 +1,35 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DOCKSCREEN_H +#define DOCKSCREEN_H + +#include + +/** + * @brief The DockScreen class + * 保存任务栏的屏幕信息 + */ +class DockScreen +{ +public: + static DockScreen *instance(); + + const QString ¤t() const; + const QString &last() const; + const QString &primary() const; + void updateDockedScreen(const QString &screenName); + void updatePrimary(const QString &primary); + +private: + explicit DockScreen(); + +private: + QString m_primary; + QString m_currentScreen; + QString m_lastScreen; +}; + +#endif // DOCKSCREEN_H diff --git a/frame/util/horizontalseperator.cpp b/frame/util/horizontalseperator.cpp index 8bbe6780a..2db8c0329 100644 --- a/frame/util/horizontalseperator.cpp +++ b/frame/util/horizontalseperator.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/horizontalseperator.h b/frame/util/horizontalseperator.h index 300d20110..9deb340f2 100644 --- a/frame/util/horizontalseperator.h +++ b/frame/util/horizontalseperator.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/imageutil.cpp b/frame/util/imageutil.cpp index a6a21d241..f63beac93 100644 --- a/frame/util/imageutil.cpp +++ b/frame/util/imageutil.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,9 +9,21 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include + const QPixmap ImageUtil::loadSvg(const QString &iconName, const QString &localPath, const int size, const qreal ratio) { QIcon icon = QIcon::fromTheme(iconName); @@ -18,7 +31,9 @@ const QPixmap ImageUtil::loadSvg(const QString &iconName, const QString &localPa if (!icon.isNull()) { QPixmap pixmap = icon.pixmap(pixmapSize); pixmap.setDevicePixelRatio(ratio); - return pixmap; + if (ratio == 1) + return pixmap; + return pixmap.scaled(size * ratio, size * ratio); } QPixmap pixmap(pixmapSize, pixmapSize); @@ -32,15 +47,26 @@ const QPixmap ImageUtil::loadSvg(const QString &iconName, const QString &localPa painter.end(); pixmap.setDevicePixelRatio(ratio); - return pixmap; + if (ratio == 1) + return pixmap; + + return pixmap.scaled(size * ratio, size * ratio); } const QPixmap ImageUtil::loadSvg(const QString &iconName, const QSize size, const qreal ratio) { QIcon icon = QIcon::fromTheme(iconName); if (!icon.isNull()) { - QPixmap pixmap = icon.pixmap(size*ratio); + QPixmap pixmap = icon.pixmap(QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? size : QSize(size * ratio)); pixmap.setDevicePixelRatio(ratio); + if (ratio == 1) + return pixmap; + + if (pixmap.size().width() > size.width() * ratio) + pixmap = pixmap.scaledToWidth(size.width() * ratio); + if (pixmap.size().height() > size.height() * ratio) + pixmap = pixmap.scaledToHeight(size.height() * ratio); + return pixmap; } return QPixmap(); @@ -64,3 +90,67 @@ QCursor* ImageUtil::loadQCursorFromX11Cursor(const char* theme, const char* curs XcursorImagesDestroy(images); return cursor; } + +QPixmap ImageUtil::loadWindowThumb(const QString &winInfoId) +{ + // 在tmp下创建临时目录,用来存放缩略图 + QString thumbPath(imagePath()); + QDir dir(thumbPath); + if (!dir.exists()) + dir.mkpath(thumbPath); + + QString fileName = QString("%1/%2").arg(thumbPath).arg(winInfoId); + int fileId = open(fileName.toLocal8Bit().data(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR); + if (fileId < 0) { + //打开文件失败 + return QPixmap(); + } + + QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/ScreenShot2"), QStringLiteral("org.kde.KWin.ScreenShot2")); + // 第一个参数,winID或者UUID + QList args; + args << QVariant::fromValue(winInfoId); + // 第二个参数,需要截图的选项 + QVariantMap option; + option["include-decoration"] = true; + option["include-cursor"] = false; + option["native-resolution"] = true; + args << QVariant::fromValue(option); + // 第三个参数,文件描述符 + args << QVariant::fromValue(QDBusUnixFileDescriptor(fileId)); + + QDBusReply reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("CaptureWindow"), args); + if(!reply.isValid()) { + close(fileId); + qDebug() << "get current workspace background error: "<< reply.error().message(); + return QPixmap(); + } + + QVariantMap imageInfo = reply.value(); + int imageWidth = imageInfo.value("width").toUInt(); + int imageHeight = imageInfo.value("height").toUInt(); + int imageStride = imageInfo.value("stride").toUInt(); + int imageFormat = imageInfo.value("format").toUInt(); + + QFile file; + if (!file.open(fileId, QIODevice::ReadOnly)) { + close(fileId); + return QPixmap(); + } + + if (file.size() == 0) { + file.close(); + return QPixmap(); + } + + QByteArray fileContent = file.readAll(); + QImage image(reinterpret_cast(fileContent.data()), imageWidth, imageHeight, imageStride, static_cast(imageFormat)); + QPixmap pixmap = QPixmap::fromImage(image); + close(fileId); + return pixmap; +} + +QString ImageUtil::imagePath() +{ + return QString("%1/dde-dock/windowthumb").arg(QDir::tempPath()); +} diff --git a/frame/util/imageutil.h b/frame/util/imageutil.h index 86f9258a5..15a909357 100644 --- a/frame/util/imageutil.h +++ b/frame/util/imageutil.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -18,6 +19,11 @@ public: static const QPixmap loadSvg(const QString &iconName, const QString &localPath, const int size, const qreal ratio); static const QPixmap loadSvg(const QString &iconName, const QSize size, const qreal ratio = qApp->devicePixelRatio()); static QCursor* loadQCursorFromX11Cursor(const char* theme, const char* cursorName, int cursorSize); + // 加载窗口的预览图 + static QPixmap loadWindowThumb(const QString &winInfoId); // 加载图片,参数为windowId或者窗口的UUID + +private: + static QString imagePath(); }; #endif // IMAGEUTIL_H diff --git a/frame/util/menuworker.cpp b/frame/util/menuworker.cpp index 61094b676..732e0366c 100644 --- a/frame/util/menuworker.cpp +++ b/frame/util/menuworker.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -16,15 +17,13 @@ #define DIS_INS DisplayManager::instance() -MenuWorker::MenuWorker(DBusDock *dockInter,QWidget *parent) - : QObject (parent) +MenuWorker::MenuWorker(DockInter *dockInter, QObject *parent) + : QObject(parent) , m_dockInter(dockInter) - , m_autoHide(true) { - } -QMenu *MenuWorker::createMenu(QMenu *settingsMenu) +void MenuWorker::createMenu(QMenu *settingsMenu) { settingsMenu->setAccessibleName("settingsmenu"); settingsMenu->setTitle("Settings Menu"); @@ -137,51 +136,29 @@ QMenu *MenuWorker::createMenu(QMenu *settingsMenu) } delete menuSettings; - menuSettings = nullptr; - return settingsMenu; } void MenuWorker::onDockSettingsTriggered() { - DDBusSender().service("com.deepin.dde.ControlCenter") - .path("/com/deepin/dde/ControlCenter") - .interface("com.deepin.dde.ControlCenter") + DDBusSender().service(controllCenterService) + .path(controllCenterPath) + .interface(controllCenterInterface) .method("ShowPage") - .arg(QString("personalization")) - .arg(QString("Dock")) + .arg(QString("personalization/desktop/dock")) .call(); } -void MenuWorker::showDockSettingsMenu(QMenu *menu) +void MenuWorker::exec() { // 菜单功能被禁用 - static const QGSettings *setting = Utils::ModuleSettingsPtr("menu", QByteArray(), this); + static const QGSettings *setting = Utils::ModuleSettingsPtr("menu", QByteArray()); if (setting && setting->keys().contains("enable") && !setting->get("enable").toBool()) { return; } - // 菜单将要被打开 - setAutoHide(false); - - menu = createMenu(menu); - menu->exec(QCursor::pos()); - - // 菜单已经关闭 - setAutoHide(true); - delete menu; - menu = nullptr; -} - -void MenuWorker::setAutoHide(const bool autoHide) -{ - if (m_autoHide == autoHide) - return; - - m_autoHide = autoHide; - emit autoHideChanged(m_autoHide); -} - -void MenuWorker::onNotifyDaemonInterfaceUpdate(DBusDock *dockInter) -{ - m_dockInter = dockInter; + QMenu menu; + if (Utils::IS_WAYLAND_DISPLAY) + menu.setWindowFlag(Qt::FramelessWindowHint); + createMenu(&menu); + menu.exec(QCursor::pos()); } diff --git a/frame/util/menuworker.h b/frame/util/menuworker.h index 63a990011..44061972a 100644 --- a/frame/util/menuworker.h +++ b/frame/util/menuworker.h @@ -1,16 +1,16 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef MENUWORKER_H #define MENUWORKER_H -#include #include "constants.h" +#include "dbusutil.h" -#include +#include -using DBusDock = com::deepin::dde::daemon::Dock; class QMenu; class QGSettings; /** @@ -20,26 +20,18 @@ class MenuWorker : public QObject { Q_OBJECT public: - explicit MenuWorker(DBusDock *dockInter,QWidget *parent = nullptr); + explicit MenuWorker(DockInter *dockInter, QObject *parent = nullptr); - void showDockSettingsMenu(QMenu *menu); - -signals: - void autoHideChanged(const bool autoHide) const; - -public slots: - void setAutoHide(const bool autoHide); - void onNotifyDaemonInterfaceUpdate(DBusDock *dockInter); + void exec(); private: - QMenu *createMenu(QMenu *settingsMenu); + void createMenu(QMenu *settingsMenu); private slots: void onDockSettingsTriggered(); private: - DBusDock *m_dockInter; - bool m_autoHide; + DockInter *m_dockInter; }; #endif // MENUWORKER_H diff --git a/frame/util/multiscreenworker.cpp b/frame/util/multiscreenworker.cpp index a4f81ed52..bb3eec5ee 100644 --- a/frame/util/multiscreenworker.cpp +++ b/frame/util/multiscreenworker.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,8 +7,12 @@ #include "mainwindow.h" #include "utils.h" #include "displaymanager.h" - -#include +#include "traymainwindow.h" +#include "mainwindow.h" +#include "menuworker.h" +#include "windowmanager.h" +#include "dockitemmanager.h" +#include "dockscreen.h" #include #include @@ -18,6 +23,7 @@ #include #include #include +#include #include #include @@ -25,63 +31,45 @@ const QString MonitorsSwitchTime = "monitorsSwitchTime"; const QString OnlyShowPrimary = "onlyShowPrimary"; -#define WINDOW_MARGIN ((m_displayMode == Dock::Efficient) ? 0 : 10) #define DIS_INS DisplayManager::instance() +#define DOCK_SCREEN DockScreen::instance() // 保证以下数据更新顺序(大环节顺序不要变,内部还有一些小的调整,比如任务栏显示区域更新的时候,里面内容的布局方向可能也要更新...) // Monitor数据->屏幕是否可停靠更新->监视唤醒区域更新,任务栏显示区域更新->拖拽区域更新->通知后端接口,通知窗管 -MultiScreenWorker::MultiScreenWorker(QWidget *parent) +MultiScreenWorker::MultiScreenWorker(QObject *parent) : QObject(parent) - , m_parent(parent) - , m_eventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus(), this)) - , m_extralEventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus(), this)) - , m_touchEventInter(new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus(), this)) - , m_dockInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) - , m_launcherInter(new DBusLuncher("com.deepin.dde.Launcher", "/com/deepin/dde/Launcher", QDBusConnection::sessionBus(), this)) + , m_eventInter(new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus(), this)) + , m_extralEventInter(new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus(), this)) + , m_touchEventInter(new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus(), this)) + , m_dockInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) + , m_launcherInter(new DBusLuncher(launcherService, launcherPath, QDBusConnection::sessionBus(), this)) + , m_appearanceInter(new Appearance("org.deepin.dde.Appearance1", "/org/deepin/dde/Appearance1", QDBusConnection::sessionBus(), this)) , m_monitorUpdateTimer(new QTimer(this)) - , m_delayWakeOnScreenSwitchTimer(new QTimer(this)) - , m_delayWakeOnHideTimer(new QTimer(this)) - , m_ds(DIS_INS->primary()) - , m_screenMonitor(new ScreenChangeMonitor(&m_ds, this)) + , m_delayWakeTimer(new QTimer(this)) + , m_position(Dock::Position(-1)) + , m_hideMode(Dock::HideMode(-1)) + , m_hideState(Dock::HideState(-1)) + , m_displayMode(Dock::DisplayMode(-1)) , m_state(AutoHide) { - qInfo() << "init dock screen: " << m_ds.current(); - initConnection(); initMembers(); - initDBus(); - initDisplayData(); - initUI(); + initDockMode(); + QMetaObject::invokeMethod(this, &MultiScreenWorker::initDisplayData, Qt::QueuedConnection); } -void MultiScreenWorker::initShow() +MultiScreenWorker::~MultiScreenWorker() { - // 仅在初始化时调用一次 - static bool first = true; - if (!first) - return; - first = false; +} - // 这里是为了在调用时让MainWindow更新界面布局方向 - emit requestUpdateLayout(); - - if (m_hideMode == HideMode::KeepShowing) - displayAnimation(m_ds.current(), AniAction::Show); - else if (m_hideMode == HideMode::KeepHidden) { - QRect rect = getDockShowGeometry(m_ds.current(), m_position, m_displayMode); - parent()->panel()->setFixedSize(rect.size()); - parent()->panel()->move(0, 0); - - rect = getDockHideGeometry(m_ds.current(), m_position, m_displayMode); - parent()->setFixedSize(rect.size()); - parent()->setGeometry(rect); - } else if (m_hideMode == HideMode::SmartHide) { - if (m_hideState == HideState::Show) - displayAnimation(m_ds.current(), AniAction::Show); - else if (m_hideState == HideState::Hide) - displayAnimation(m_ds.current(), AniAction::Hide); - } +void MultiScreenWorker::updateDaemonDockSize(const int &dockSize) +{ + m_dockInter->setWindowSize(uint(dockSize)); + if (m_displayMode == Dock::DisplayMode::Fashion) + m_dockInter->setWindowSizeFashion(uint(dockSize)); + else + m_dockInter->setWindowSizeEfficient(uint(dockSize)); } /** @@ -99,49 +87,7 @@ void MultiScreenWorker::setStates(RunStates state, bool on) m_state &= ~(type); } -/** - * @brief dockRect - * @param screenName 屏幕名 - * @param pos 任务栏位置 - * @param hideMode 模式 - * @param displayMode 状态 - * @return 按照给定的数据计算出任务栏所在位置 - */ -QRect MultiScreenWorker::dockRect(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode) -{ - if (hideMode == HideMode::KeepShowing || (hideMode == HideMode::SmartHide && m_hideState == HideState::Show)) - return getDockShowGeometry(screenName, pos, displayMode); - else - return getDockHideGeometry(screenName, pos, displayMode); -} - -/** - * @brief dockRect - * @param screenName 屏幕名 - * @return 按照当前屏幕的当前属性给出任务栏所在区域 - */ -QRect MultiScreenWorker::dockRect(const QString &screenName) -{ - return dockRect(screenName, m_position, m_hideMode, m_displayMode); -} - -/** - * @brief realDockRect 给出不计算缩放情况的区域信息(和后端接口保持一致) - * @param screenName 屏幕名 - * @param pos 任务栏位置 - * @param hideMode 模式 - * @param displayMode 状态 - * @return - */ -QRect MultiScreenWorker::dockRectWithoutScale(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode) -{ - if (hideMode == HideMode::KeepShowing || m_currentHideState == HideState::Show) - return getDockShowGeometry(screenName, pos, displayMode, true); - else - return getDockHideGeometry(screenName, pos, displayMode, true); -} - -void MultiScreenWorker::onAutoHideChanged(bool autoHide) +void MultiScreenWorker::onAutoHideChanged(const bool autoHide) { if (testState(AutoHide) != autoHide) setStates(AutoHide, autoHide); @@ -151,44 +97,6 @@ void MultiScreenWorker::onAutoHideChanged(bool autoHide) } } -/** - * @brief updateDaemonDockSize - * @param dockSize 这里的高度是通过qt获取的,不能使用后端的接口数据 - */ -void MultiScreenWorker::updateDaemonDockSize(int dockSize) -{ - m_dockInter->setWindowSize(uint(dockSize)); - if (m_displayMode == DisplayMode::Fashion) - m_dockInter->setWindowSizeFashion(uint(dockSize)); - else - m_dockInter->setWindowSizeEfficient(uint(dockSize)); -} - -void MultiScreenWorker::handleDBusSignal(QDBusMessage msg) -{ - QList arguments = msg.arguments(); - // 参数固定长度 - if (3 != arguments.count()) - return; - // 返回的数据中,这一部分对应的是数据发送方的interfacename,可判断是否是自己需要的服务 - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName == "com.deepin.dde.daemon.Dock") { - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - QStringList keys = changedProps.keys(); - foreach (const QString &prop, keys) { - if (prop == "Position") { - onPositionChanged(static_cast(changedProps.value(prop).toInt())); - } else if (prop == "DisplayMode") { - onDisplayModeChanged(static_cast(changedProps.value(prop).toInt())); - } else if (prop == "HideMode") { - onHideModeChanged(static_cast(changedProps.value(prop).toInt())); - } else if (prop == "HideState") { - onHideStateChanged(static_cast(changedProps.value(prop).toInt())); - } - } - } -} - void MultiScreenWorker::onRegionMonitorChanged(int x, int y, const QString &key) { if (m_registerKey != key || testState(MousePress)) @@ -209,73 +117,37 @@ void MultiScreenWorker::onExtralRegionMonitorChanged(int x, int y, const QString return; // FIXME:每次都要重置一下,是因为qt中的QScreen类缺少nameChanged信号,后面会给上游提交patch修复 - m_ds.updateDockedScreen(getValidScreen(position())); + DOCK_SCREEN->updateDockedScreen(getValidScreen(position())); // 鼠标移动到任务栏界面之外,停止计时器(延时2秒改变任务栏所在屏幕) - m_delayWakeOnScreenSwitchTimer->stop(); + m_delayWakeTimer->stop(); if (m_hideMode == HideMode::KeepShowing || ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); } else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) { - displayAnimation(m_ds.current(), AniAction::Hide); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); } } -void MultiScreenWorker::showAniFinished() -{ - const QRect rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); - - parent()->setFixedSize(rect.size()); - parent()->setGeometry(rect); - - parent()->panel()->setFixedSize(rect.size()); - parent()->panel()->move(0, 0); - - emit requestUpdateFrontendGeometry(); - emit requestNotifyWindowManager(); -} - -void MultiScreenWorker::hideAniFinished() -{ - // 提前更新界面布局 - emit requestUpdateLayout(); - - const QRect rect = dockRect(m_ds.current(), m_position, HideMode::KeepHidden, m_displayMode); - parent()->setFixedSize(rect.size()); - parent()->setGeometry(rect); - parent()->panel()->setFixedSize(rect.size()); - parent()->panel()->move(0, 0); - - DockItem::setDockPosition(m_position); - qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); - - emit requestUpdateFrontendGeometry(); - emit requestNotifyWindowManager(); -} - void MultiScreenWorker::updateDisplay() { //1、屏幕停靠信息, //2、任务栏当前显示在哪个屏幕也需要更新 - //2、监视任务栏唤醒区域信息, //3、任务栏高度或宽度调整的拖拽区域, //4、通知窗管的任务栏显示区域信息, //5、通知后端的任务栏显示区域信息 - - // wayland环境下,QScreen销毁也就是拔掉显示器的时候,会隐藏当前窗口,这里手动显示一次 - parent()->setVisible(true); - if (DIS_INS->screens().size() == 0) { qWarning() << "No Screen Can Display."; return; } + // 更新所在屏幕 resetDockScreen(); // 通知后端 - onRequestUpdateFrontendGeometry(); + Q_EMIT requestUpdateFrontendGeometry(); // 通知窗管 - onRequestNotifyWindowManager(); + Q_EMIT requestNotifyWindowManager(); } void MultiScreenWorker::onWindowSizeChanged(uint value) @@ -285,12 +157,10 @@ void MultiScreenWorker::onWindowSizeChanged(uint value) m_monitorUpdateTimer->start(); } -void MultiScreenWorker::primaryScreenChanged(QScreen *screen) +void MultiScreenWorker::onPrimaryScreenChanged() { - Q_ASSERT(screen); - // 先更新主屏信息 - m_ds.updatePrimary(screen->name()); + DOCK_SCREEN->updatePrimary(DIS_INS->primary()); // 无效值 if (DIS_INS->screenRawHeight() == 0 || DIS_INS->screenRawWidth() == 0) { @@ -302,148 +172,92 @@ void MultiScreenWorker::primaryScreenChanged(QScreen *screen) m_monitorUpdateTimer->start(); } -void MultiScreenWorker::updateParentGeometry(const QVariant &value, const Position &pos) -{ - Q_ASSERT_X(value.type() == QVariant::Rect, "", "ERROR OCCURED!"); - - const QRect &rect = value.toRect(); - parent()->setFixedSize(rect.size()); - parent()->setGeometry(rect); - - const int panelSize = ((pos == Position::Top || pos == Position::Bottom) ? parent()->panel()->height() : parent()->panel()->width()); - - switch (pos) { - case Position::Top: { - parent()->panel()->move(0, rect.height() - panelSize); - } - break; - case Position::Left: { - parent()->panel()->move(rect.width() - panelSize, 0); - } - break; - case Position::Bottom: - case Position::Right: { - parent()->panel()->move(0, 0); - } - break; - } -} - -void MultiScreenWorker::updateParentGeometry(const QVariant &value) -{ - if (!testState(ShowAnimationStart) && !testState(HideAnimationStart)) - return; - - updateParentGeometry(value, m_position); -} - -void MultiScreenWorker::onPositionChanged(const Position &position) +void MultiScreenWorker::onPositionChanged(int position) { Position lastPos = m_position; if (lastPos == position) return; - - qInfo() << "position changed from: " << lastPos << " to: " << position; - m_position = position; - - // 更新鼠标拖拽样式,在类内部设置到qApp单例上去 - if ((Top == m_position) || (Bottom == m_position)) { - parent()->panel()->setCursor(Qt::SizeVerCursor); - } else { - parent()->panel()->setCursor(Qt::SizeHorCursor); - } +#ifdef QT_DEBUG + qDebug() << "position change from: " << lastPos << " to: " << position; +#endif + m_position = static_cast(position); if (m_hideMode == HideMode::KeepHidden || (m_hideMode == HideMode::SmartHide && m_hideState == HideState::Hide)) { // 这种情况切换位置,任务栏不需要显示 - displayAnimation(m_ds.current(), lastPos, AniAction::Hide); + // 参数说明 1 当前屏幕名称 2 改变位置之前的位置,因为需要从之前的位置完成隐藏的动画 + // 3 隐藏动画 4 无需考虑当前鼠标是否在任务栏上,这个参数是通过其他方式隐藏唤醒任务栏的时候考虑鼠标是否在任务栏的位置来决定是否做隐藏动画 + // 默认是false,也就是无需考虑 5 当前动画是否为执行位置改变的动画,如果该值为true,那么在动画执行完成后,WindowManager需要给其管理的 + // 子窗口来更新当前的位置的信息 + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), lastPos, Dock::AniAction::Hide, false, true); // 更新当前屏幕信息,下次显示从目标屏幕显示 - m_ds.updateDockedScreen(getValidScreen(m_position)); + DOCK_SCREEN->updateDockedScreen(getValidScreen(m_position)); // 需要更新frontendWindowRect接口数据,否则会造成HideState属性值不变 emit requestUpdateFrontendGeometry(); } else { // 一直显示的模式才需要显示 - emit requestUpdatePosition(lastPos, position); + emit requestUpdatePosition(lastPos, m_position); } } -void MultiScreenWorker::onDisplayModeChanged(const DisplayMode &displayMode) +void MultiScreenWorker::onDisplayModeChanged(int displayMode) { if (displayMode == m_displayMode) return; - qInfo() << "display mode changed:" << displayMode; + qInfo() << "display mode change:" << displayMode; - m_displayMode = displayMode; + m_displayMode = static_cast(displayMode); - DockItem::setDockDisplayMode(displayMode); - qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(displayMode)); - - QRect rect; - if (m_hideMode == HideMode::KeepShowing || (m_hideMode == HideMode::SmartHide && m_hideState == HideState::Show)) { - rect = dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode); - } else { - rect = dockRect(m_ds.current(), m_position, HideMode::KeepHidden, m_displayMode); - } - - parent()->setFixedSize(rect.size()); - parent()->move(rect.topLeft()); - - parent()->panel()->setFixedSize(rect.size()); - parent()->panel()->move(0, 0); - parent()->panel()->setDisplayMode(m_displayMode); - - emit displayModeChanegd(); + emit displayModeChanged(m_displayMode); emit requestUpdateFrontendGeometry(); emit requestNotifyWindowManager(); } -void MultiScreenWorker::onHideModeChanged(const HideMode &hideMode) +void MultiScreenWorker::onHideModeChanged(int hideMode) { if (m_hideMode == hideMode) return; - qInfo() << "hidemode changed:" << hideMode; + qInfo() << "hidemode change:" << hideMode; - m_hideMode = hideMode; + m_hideMode = static_cast(hideMode); if (m_hideMode == HideMode::KeepShowing || ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); } else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) { - displayAnimation(m_ds.current(), AniAction::Hide); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); } emit requestUpdateFrontendGeometry(); emit requestNotifyWindowManager(); } -void MultiScreenWorker::onHideStateChanged(const Dock::HideState &state) +void MultiScreenWorker::onHideStateChanged(int state) { - if (state == Dock::Unknown) + if (state == m_hideState) return; - m_hideState = state; + m_hideState = static_cast(state); // 检查当前屏幕的当前位置是否允许显示,不允许需要更新显示信息(这里应该在函数外部就处理好,不应该走到这里) //TODO 这里是否存在屏幕找不到的问题,m_ds的当前屏幕是否可以做成实时同步的,公用一个指针? //TODO 这里真的有必要加以下代码吗,只是隐藏模式的切换,理论上不需要检查屏幕是否允许任务栏停靠 - QScreen *curScreen = DIS_INS->screen(m_ds.current()); + const QString currentScreen = DOCK_SCREEN->current(); + QScreen *curScreen = DIS_INS->screen(currentScreen); if (!DIS_INS->canDock(curScreen, m_position)) { - m_ds.updateDockedScreen(getValidScreen(m_position)); + DOCK_SCREEN->updateDockedScreen(getValidScreen(m_position)); } - qInfo() << "hidestate changed:" << m_hideMode << m_hideState; + qInfo() << "hidestate change:" << m_hideMode << m_hideState; if (m_hideMode == HideMode::KeepShowing || ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Show)) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(currentScreen, m_position, Dock::AniAction::Show); } else if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) && m_hideState == HideState::Hide) { - // 如果鼠标正在任务栏要显示的区域,就可以不用隐藏(相当于智能隐藏被唤醒一样) - if (getDockShowGeometry(m_ds.current(), m_position, m_displayMode).contains(QCursor::pos())) - return; - - displayAnimation(m_ds.current(), AniAction::Hide); + // 最后一个参数,当任务栏的隐藏状态发生变化的时候(从一直显示变成一直隐藏或者智能隐藏),需要考虑鼠标是否在任务栏上,如果在任务栏上,此时无需执行隐藏动画 + Q_EMIT requestPlayAnimation(currentScreen, m_position, Dock::AniAction::Hide); } } @@ -595,7 +409,7 @@ void MultiScreenWorker::onRequestUpdateRegionMonitor() } // 触屏监控高度固定调整为最大任务栏高度100+任务栏与屏幕边缘间距 - const int monitHeight = 100 + WINDOW_MARGIN; + const int monitHeight = 100 + WINDOWMARGIN; // 任务栏触屏唤起区域 m_touchRectList.clear(); @@ -639,7 +453,6 @@ void MultiScreenWorker::onRequestUpdateRegionMonitor() break; } - if (!m_touchRectList.contains(monitorRect)) { m_touchRectList << monitorRect; } @@ -651,33 +464,6 @@ void MultiScreenWorker::onRequestUpdateRegionMonitor() m_touchRegisterKey = m_touchEventInter->RegisterAreas(m_touchRectList, flags); } -void MultiScreenWorker::onRequestUpdateFrontendGeometry() -{ - HideMode hideMode = HideMode::KeepShowing; - // 当设置为一直隐藏模式时,按照当前隐藏的状态去设置任务栏区域信息,否则,按照当前显示模式去设置 - if (m_hideMode == HideMode::KeepHidden) { - hideMode = m_hideMode; - } - - const QRect rect = dockRectWithoutScale(m_ds.current(), m_position, hideMode, m_displayMode); - -#ifdef QT_DEBUG - qDebug() << rect; -#endif - - m_dockInter->SetFrontendWindowRect(int(rect.x()), int(rect.y()), uint(rect.width()), uint(rect.height())); - emit requestUpdateDockEntry(); -} - -void MultiScreenWorker::onRequestUpdateLayout() -{ - parent()->panel()->setFixedSize(dockRect(m_ds.current(), position(), HideMode::KeepShowing, displayMode()).size()); - parent()->panel()->move(0, 0); - parent()->panel()->setDisplayMode(displayMode()); - parent()->panel()->setPositonValue(position()); - parent()->panel()->update(); -} - /** * @brief 判断屏幕是否为复制模式的依据,第一个屏幕的X和Y值是否和其他的屏幕的X和Y值相等 * 对于复制模式,这两个值肯定是相等的,如果不是复制模式,这两个值肯定不等,目前支持双屏 @@ -699,196 +485,22 @@ bool MultiScreenWorker::isCopyMode() return true; } -/** - * @brief MultiScreenWorker::getScreenRect - * @param s - * @param ratio - * @return 返回屏幕 \s 的原始尺寸,\ratio 为屏幕 \s 的当前缩放值 - */ -QRect MultiScreenWorker::getScreenRect(QScreen *s) -{ - if (!s) - return QRect(); - - auto geo = s->geometry(); - QRect screenRect; - screenRect.setX(geo.x()); - screenRect.setY(geo.y()); - screenRect.setWidth(static_cast(geo.width() * s->devicePixelRatio())); - screenRect.setHeight(static_cast(geo.height() * s->devicePixelRatio())); - - /* QScreen的handle会返回显示器缩放之前的分辨率 - * 比如1920*1080,调整缩放为1.25,那么QScreen::geometry返回的为QSize(1536, 864),QScreen::handle()->geometry()返回的为QSize(1920, 1080); - * - * @note 但在特殊情况下,比如频繁插拔显示器时,小概率出现handle返回的值并不等于缩放前的分辨率的情况,从而导致任务栏位置设置出错, - * 这里仍然直接使用geometry*ratio的方式,去获取缩放前的分辨率 - * 但考虑到缩放值类型为double,可能在高分屏下计算得到的尺寸和通过handle函数的原始尺寸有1像素的误差, - * 所以计算完毕后和handle比对一下,如果存在1像素的误差,则仍然使用handle函数,否则使用QScreen::geometry() * ratio - */ - auto size = s->handle()->geometry().size() - screenRect.size(); - if (Q_LIKELY(size.width() <= 1 && size.height() <= 1)) { - screenRect = s->handle()->geometry(); - } - - return screenRect; -} - -/** - * @brief 这里用到xcb去设置任务栏的高度,比较特殊,参考_NET_WM_STRUT_PARTIAL属性 - * 在屏幕旋转后,所有参数以控制中心自定义设置里主屏显示的图示为准(旋转不用特殊处理) - */ -void MultiScreenWorker::onRequestNotifyWindowManager() -{ - static QRect lastRect = QRect(); - static int lastScreenWidth = 0; - static int lastScreenHeight = 0; - - /* 在非主屏或非一直显示状态时,清除任务栏区域,不挤占应用 */ - if ((!DIS_INS->isCopyMode() && m_ds.current() != m_ds.primary()) || m_hideMode != HideMode::KeepShowing) { - lastRect = QRect(); - - qInfo() << "clear wm struct"; - - if (Utils::IS_WAYLAND_DISPLAY) { - QList varList; - varList.append(0);//dock位置 - varList.append(0);//dock高度/宽度 - varList.append(0);//start值 - varList.append(0);//end值 - if (parent()->windowHandle()->handle()) { - QGuiApplication::platformNativeInterface()->setWindowProperty(parent()->windowHandle()->handle(),"_d_dwayland_dockstrut", varList); - } - } else { - const auto display = QX11Info::display(); - if (!display) { - qWarning() << "QX11Info::display() is " << display; - return; - } - - XcbMisc::instance()->clear_strut_partial(xcb_window_t(parent()->winId())); - } - - return; - } - - QRect dockGeometry = getDockShowGeometry(m_ds.current(), m_position, m_displayMode, true); - if (lastRect == dockGeometry - && lastScreenWidth == DIS_INS->screenRawWidth() - && lastScreenHeight == DIS_INS->screenRawHeight()) { - return; - } - - lastRect = dockGeometry; - lastScreenWidth = DIS_INS->screenRawWidth(); - lastScreenHeight = DIS_INS->screenRawHeight(); - qDebug() << "dock real geometry:" << dockGeometry; - qDebug() << "screen width:" << DIS_INS->screenRawWidth() << ", height:" << DIS_INS->screenRawHeight(); - - const qreal &ratio = qApp->devicePixelRatio(); - if (Utils::IS_WAYLAND_DISPLAY) { - QList varList = {0, 0, 0, 0}; - switch (m_position) { - case Position::Top: - varList[0] = 1; - varList[1] = dockGeometry.height(); - varList[2] = dockGeometry.x(); - varList[3] = dockGeometry.x() + dockGeometry.width(); - break; - case Position::Bottom: - varList[0] = 3; - varList[1] = dockGeometry.height(); - varList[2] = dockGeometry.x(); - varList[3] = dockGeometry.x() + dockGeometry.width(); - break; - case Position::Left: - varList[0] = 0; - varList[1] = dockGeometry.width(); - varList[2] = dockGeometry.y(); - varList[3] = dockGeometry.y() + dockGeometry.height(); - break; - case Position::Right: - varList[0] = 2; - varList[1] = dockGeometry.width(); - varList[2] = dockGeometry.y(); - varList[3] = dockGeometry.y() + dockGeometry.height(); - break; - } - - // 加上边距(时尚模式为10+10, 高效模式为0) - varList[1] = varList[1].toDouble() + WINDOW_MARGIN * ratio * 2; - qDebug() << "Dock strut: " << varList; - - if (parent()->windowHandle()->handle()) { - QGuiApplication::platformNativeInterface()->setWindowProperty(parent()->windowHandle()->handle(),"_d_dwayland_dockstrut", varList); - } - } else { - XcbMisc::Orientation orientation = XcbMisc::OrientationTop; - double strut = 0; - double strutStart = 0; - double strutEnd = 0; - - switch (m_position) { - case Position::Top: - orientation = XcbMisc::OrientationTop; - strut = dockGeometry.y() + dockGeometry.height(); - strutStart = dockGeometry.x(); - strutEnd = qMin(dockGeometry.x() + dockGeometry.width(), dockGeometry.right()); - break; - case Position::Bottom: - orientation = XcbMisc::OrientationBottom; - strut = DIS_INS->screenRawHeight() - dockGeometry.y(); - strutStart = dockGeometry.x(); - strutEnd = qMin(dockGeometry.x() + dockGeometry.width(), dockGeometry.right()); - break; - case Position::Left: - orientation = XcbMisc::OrientationLeft; - strut = dockGeometry.x() + dockGeometry.width(); - strutStart = dockGeometry.y(); - strutEnd = qMin(dockGeometry.y() + dockGeometry.height(), dockGeometry.bottom()); - break; - case Position::Right: - orientation = XcbMisc::OrientationRight; - strut = DIS_INS->screenRawWidth() - dockGeometry.x(); - strutStart = dockGeometry.y(); - strutEnd = qMin(dockGeometry.y() + dockGeometry.height(), dockGeometry.bottom()); - break; - } - - qDebug() << "set reserved area to xcb:" << strut << strutStart << strutEnd; - - const auto display = QX11Info::display(); - if (!display) { - qWarning() << "QX11Info::display() is " << display; - return; - } - - XcbMisc::instance()->set_strut_partial(static_cast(parent()->winId()), orientation, - static_cast(strut + WINDOW_MARGIN * ratio), // 设置窗口与屏幕边缘距离,需要乘缩放 - static_cast(strutStart), // 设置任务栏起点坐标(上下为x,左右为y) - static_cast(strutEnd)); // 设置任务栏终点坐标(上下为x,左右为y) - } -} - void MultiScreenWorker::onRequestUpdatePosition(const Position &fromPos, const Position &toPos) { qInfo() << "request change pos from: " << fromPos << " to: " << toPos; // 更新要切换到的屏幕 - if (!DIS_INS->canDock(DIS_INS->screen(m_ds.current()), m_position)) - m_ds.updateDockedScreen(getValidScreen(m_position)); + if (!DIS_INS->canDock(DIS_INS->screen(DOCK_SCREEN->current()), m_position)) + DOCK_SCREEN->updateDockedScreen(getValidScreen(m_position)); - qInfo() << "update allow screen: " << m_ds.current(); + qInfo() << "update allow screen: " << DOCK_SCREEN->current(); // 无论什么模式,都先显示 - changeDockPosition(m_ds.last(), m_ds.current(), fromPos, toPos); + changeDockPosition(DOCK_SCREEN->last(), DOCK_SCREEN->current(), fromPos, toPos); } void MultiScreenWorker::onRequestUpdateMonitorInfo() { - // resetDockScreen 调用太频繁,未在合适的时机调用时出现 wayland set_position 数值异常 - // 推测是 qt 未能正确传递窗口位置到 waylandserver, 此处修改经过测试可以较好的规避此问题。 - // for test : DOCK_RESET_NOW=true dde-dock - if (qEnvironmentVariableIsSet("DOCK_RESET_NOW")) - resetDockScreen(); // m_monitorUpdateTimer timeout will call resetDockScreen + resetDockScreen(); // 只需要在屏幕信息变化的时候更新,其他时间不需要更新 onRequestUpdateRegionMonitor(); @@ -905,48 +517,30 @@ void MultiScreenWorker::onRequestDelayShowDock() // 复制模式.不需要响应切换屏幕 if (DIS_INS->screens().size() == 2 && DIS_INS->screens().first()->geometry() == DIS_INS->screens().last()->geometry()) { qInfo() << "copy mode or merge mode"; - parent()->setFixedSize(dockRect(m_ds.current()).size()); - parent()->setGeometry(dockRect(m_ds.current())); + Q_EMIT requestUpdateDockGeometry(m_hideMode); return; } - m_ds.updateDockedScreen(m_delayScreen); + DOCK_SCREEN->updateDockedScreen(m_delayScreen); // 检查当前屏幕的当前位置是否允许显示,不允许需要更新显示信息(这里应该在函数外部就处理好,不应该走到这里) // 检查边缘是否允许停靠 QScreen *curScreen = DIS_INS->screen(m_delayScreen); if (curScreen && DIS_INS->canDock(curScreen, m_position)) { if (m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) { - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); } else if (m_hideMode == HideMode::KeepShowing) { - changeDockPosition(m_ds.last(), m_ds.current(), m_position, m_position); + changeDockPosition(DOCK_SCREEN->last(), DOCK_SCREEN->current(), m_position, m_position); } } } -MainWindow *MultiScreenWorker::parent() -{ - return static_cast(m_parent); -} - void MultiScreenWorker::initMembers() { - if (Utils::IS_WAYLAND_DISPLAY) { - m_parent->createWinId(); - } m_monitorUpdateTimer->setInterval(100); m_monitorUpdateTimer->setSingleShot(true); - // 优化显示方式,隐藏后再显示会延迟一小段时间 - QScopedPointer config(DConfig::create("org.deepin.dde.dock", "org.deepin.dde.dock")); - if (config->isValid() && config->keyList().contains("delayIntervalOnHide")) { - m_delayWakeOnHideTimer->setInterval(config->value("delayIntervalOnHide").toInt()); - } else { - m_delayWakeOnHideTimer->setInterval(0); - } - m_delayWakeOnHideTimer->setSingleShot(true); - - m_delayWakeOnScreenSwitchTimer->setSingleShot(true); + m_delayWakeTimer->setSingleShot(true); setStates(LauncherDisplay, m_launcherInter->isValid() ? m_launcherInter->visible() : false); @@ -957,85 +551,28 @@ void MultiScreenWorker::initMembers() void MultiScreenWorker::initConnection() { - connect(DIS_INS, &DisplayManager::primaryScreenChanged, this, &MultiScreenWorker::primaryScreenChanged); + connect(DIS_INS, &DisplayManager::primaryScreenChanged, this, &MultiScreenWorker::onPrimaryScreenChanged); connect(DIS_INS, &DisplayManager::screenInfoChanged, this, &MultiScreenWorker::requestUpdateMonitorInfo); connect(m_launcherInter, static_cast(&DBusLuncher::VisibleChanged), this, [ = ](bool value) { setStates(LauncherDisplay, value); }); - /** FIXME - * 这里关联的信号有时候收不到是因为 qt-dbus-factory 中的 changed 的信号有时候会发不出来, - * qt-dbus-factory 中的 DBusExtendedAbstractInterface::internalPropGet 在同步调用情况下,会将缓存中的数据写入属性中, - * 导致后面 onPropertyChanged 中的判断认为属性值没变,就没有发出 changed 信号。 - * 建议:前端仅在初始化时主动获取一次 dbus 中的值存储在成员变量中,并建立 changed 信号连接,后面所有用到那个值的地方,均获取成员变量; - * 或去修改 qt-dbus-factory,取消 DBusExtendedAbstractInterface::internalPropGet 中将数据写入属性值, - * 但是 qt-dbus-factory 修改涉及面较广,需要大量测试确认没有问题,再合入。 - */ -#if 0 - // connect(m_dockInter, &DBusDock::PositionChanged, this, &MultiScreenWorker::onPositionChanged); - // connect(m_dockInter, &DBusDock::DisplayModeChanged, this, &MultiScreenWorker::onDisplayModeChanged); - // connect(m_dockInter, &DBusDock::HideModeChanged, this, &MultiScreenWorker::hideModeChanged); - // connect(m_dockInter, &DBusDock::HideStateChanged, this, &MultiScreenWorker::hideStateChanged); -#else - QDBusConnection::sessionBus().connect("com.deepin.dde.daemon.Dock", - "/com/deepin/dde/daemon/Dock", - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - "sa{sv}as", - this, SLOT(handleDBusSignal(QDBusMessage))); -#endif - - connect(this, &MultiScreenWorker::requestUpdateFrontendGeometry, this, &MultiScreenWorker::onRequestUpdateFrontendGeometry); connect(this, &MultiScreenWorker::requestUpdatePosition, this, &MultiScreenWorker::onRequestUpdatePosition); - connect(this, &MultiScreenWorker::requestNotifyWindowManager, this, &MultiScreenWorker::onRequestNotifyWindowManager); connect(this, &MultiScreenWorker::requestUpdateMonitorInfo, this, &MultiScreenWorker::onRequestUpdateMonitorInfo); - connect(m_delayWakeOnScreenSwitchTimer, &QTimer::timeout, this, &MultiScreenWorker::onRequestDelayShowDock); - connect(m_delayWakeOnHideTimer, &QTimer::timeout, this, [ = ] { - // 鼠标处于按下状态,不再显示 - if (testState(MousePress)) - return; - - const QRect boundRect = parent()->visibleRegion().boundingRect(); - qDebug() << "boundRect:" << boundRect; - if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide) - && (boundRect.size().isEmpty())) { - displayAnimation(m_ds.current(), AniAction::Show); - } - }); - - // 更新任务栏内容展示方式 - connect(this, &MultiScreenWorker::requestUpdateLayout, this, &MultiScreenWorker::onRequestUpdateLayout); + connect(m_delayWakeTimer, &QTimer::timeout, this, &MultiScreenWorker::onRequestDelayShowDock); // 刷新所有显示的内容,布局,方向,大小,位置等 connect(m_monitorUpdateTimer, &QTimer::timeout, this, &MultiScreenWorker::updateDisplay); } -void MultiScreenWorker::initUI() -{ - // 设置界面大小 - parent()->setFixedSize(dockRect(m_ds.current()).size()); - parent()->move(dockRect(m_ds.current()).topLeft()); - parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode).size()); - parent()->panel()->move(0, 0); - - onPositionChanged(static_cast(dockInter()->position())); - onDisplayModeChanged(static_cast(dockInter()->displayMode())); - onHideModeChanged(static_cast(dockInter()->hideMode())); - onHideStateChanged(static_cast(dockInter()->hideState())); - onOpacityChanged(m_dockInter->opacity()); - - // 初始化透明度 - QTimer::singleShot(0, this, [ = ] {onOpacityChanged(m_dockInter->opacity());}); -} - -void MultiScreenWorker::initDBus() +void MultiScreenWorker::initDockMode() { if (m_dockInter->isValid()) { - m_position = static_cast(m_dockInter->position()); - m_hideMode = static_cast(m_dockInter->hideMode()); - m_hideState = static_cast(m_dockInter->hideState()); - m_displayMode = static_cast(m_dockInter->displayMode()); - m_opacity = m_dockInter->opacity(); + onPositionChanged(dockInter()->position()); + onDisplayModeChanged(dockInter()->displayMode()); + onHideModeChanged(dockInter()->hideMode()); + onHideStateChanged(m_dockInter->hideState()); + onOpacityChanged(m_dockInter->opacity()); DockItem::setDockPosition(m_position); qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); @@ -1063,141 +600,10 @@ void MultiScreenWorker::initDisplayData() */ void MultiScreenWorker::reInitDisplayData() { - initDBus(); + initDockMode(); initDisplayData(); } -/** - * @brief MultiScreenWorker::displayAnimation - * 任务栏显示或隐藏过程的动画。 - * @param screen 任务栏要显示的屏幕 - * @param pos 任务栏显示的位置(上:0,右:1,下:2,左:3) - * @param act 显示(隐藏)任务栏 - * @return void - */ -void MultiScreenWorker::displayAnimation(const QString &screen, const Position &pos, AniAction act) -{ - if (!testState(AutoHide) || qApp->property("DRAG_STATE").toBool() - || testState(ChangePositionAnimationStart) - || testState(HideAnimationStart) - || testState(ShowAnimationStart)) - return; - - m_currentHideState = act ? HideState::Hide : HideState::Show; - QRect mainwindowRect = parent()->geometry(); - QRect dockShowRect = getDockShowGeometry(screen, pos, m_displayMode); - QRect dockHideRect = getDockHideGeometry(screen, pos, m_displayMode); - - /** FIXME - * 在高分屏2.75倍缩放的情况下,parent()->geometry()返回的任务栏高度有问题(实际是40,返回是39) - * 在这里增加判断,当返回值在范围(38,42)开区间内,均认为任务栏显示位置正确,直接返回,不执行动画 - * 也就是在实际值基础上下浮动1像素的误差范围 - * 正常屏幕情况下是没有这个问题的 - */ - switch (act) { - case AniAction::Show: - if (pos == Position::Top || pos == Position::Bottom) { - if (qAbs(dockShowRect.height() - mainwindowRect.height()) <= 1 - && mainwindowRect.contains(dockShowRect.center())) { - emit requestNotifyWindowManager(); - return; - } - } else if (pos == Position::Left || pos == Position::Right) { - if (qAbs(dockShowRect.width() - mainwindowRect.width()) <= 1 - && mainwindowRect.contains(dockShowRect.center())) { - emit requestNotifyWindowManager(); - return; - } - } - break; - case AniAction::Hide: - if (dockHideRect == mainwindowRect) { - emit requestNotifyWindowManager(); - return; - } - break; - } - - QVariantAnimation *ani = new QVariantAnimation(this); - ani->setEasingCurve(QEasingCurve::InOutCubic); - -#ifndef DISABLE_SHOW_ANIMATION - const bool composite = DWindowManagerHelper::instance()->hasComposite(); // 判断是否开启特效模式 - const int duration = composite ? ANIMATIONTIME : 0; -#else - const int duration = 0; -#endif - ani->setDuration(duration); - - ani->setStartValue(dockHideRect); - ani->setEndValue(dockShowRect); - - switch (act) { - case AniAction::Show: - ani->setDirection(QAbstractAnimation::Forward); - connect(ani, &QVariantAnimation::finished, this, &MultiScreenWorker::showAniFinished); - connect(this, &MultiScreenWorker::requestStopShowAni, ani, &QVariantAnimation::stop); - break; - - case AniAction::Hide: - ani->setDirection(QAbstractAnimation::Backward); // 隐藏时动画反向走 - connect(ani, &QVariantAnimation::finished, this, &MultiScreenWorker::hideAniFinished); - connect(this, &MultiScreenWorker::requestStopHideAni, ani, &QVariantAnimation::stop); - break; - } - - connect(ani, &QVariantAnimation::valueChanged, this, static_cast(&MultiScreenWorker::updateParentGeometry)); - - connect(ani, &QVariantAnimation::stateChanged, this, [ = ](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { - // 更新动画是否正在进行的信号值 - switch (act) { - case AniAction::Show: - if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { - if (m_hideMode == HideMode::KeepShowing || duration) - setStates(ShowAnimationStart); - else - setStates(DockIsShowing); - } - if (newState == QVariantAnimation::Stopped && oldState == QVariantAnimation::Running) { - if (m_hideMode == HideMode::KeepShowing || duration) - setStates(ShowAnimationStart, false); - else // 如果不是一直显示的状态,则让其延时修改状态,防止在resetDock的时候重复改变其高度引起任务栏闪烁导致无法唤醒 - QTimer::singleShot(ANIMATIONTIME, [ = ] { setStates(DockIsShowing, false); }); - } - break; - case AniAction::Hide: - if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { - setStates(HideAnimationStart); - } - if (newState == QVariantAnimation::Stopped && oldState == QVariantAnimation::Running) { - setStates(HideAnimationStart, false); - } - break; - } - }); - - parent()->panel()->setFixedSize(dockRect(m_ds.current(), m_position, HideMode::KeepShowing, m_displayMode).size()); - parent()->panel()->move(0, 0); - - emit requestStopShowAni(); - emit requestStopHideAni(); - emit requestUpdateLayout(); - - ani->start(QVariantAnimation::DeleteWhenStopped); -} - -/** - * @brief MultiScreenWorker::displayAnimation - * 任务栏显示或隐藏过程的动画。 - * @param screen 任务栏要显示的屏幕 - * @param act 显示(隐藏)任务栏 - * @return void - */ -void MultiScreenWorker::displayAnimation(const QString &screen, AniAction act) -{ - return displayAnimation(screen, m_position, act); -} - /** * @brief changeDockPosition 做一个动画操作 * @param fromScreen 上次任务栏所在的屏幕 @@ -1212,101 +618,13 @@ void MultiScreenWorker::changeDockPosition(QString fromScreen, QString toScreen, return; } + // 该动画放到WindowManager中来实现 // 更新屏幕信息 - m_ds.updateDockedScreen(toScreen); + DOCK_SCREEN->updateDockedScreen(toScreen); // TODO: 考虑切换过快的情况,这里需要停止上一次的动画,可增加信号控制,暂时无需要 qInfo() << "from: " << fromScreen << " to: " << toScreen; - - QSequentialAnimationGroup *group = new QSequentialAnimationGroup(this); - - QVariantAnimation *ani1 = new QVariantAnimation(group); - QVariantAnimation *ani2 = new QVariantAnimation(group); - - // 初始化动画信息 - ani1->setEasingCurve(QEasingCurve::InOutCubic); - ani2->setEasingCurve(QEasingCurve::InOutCubic); - - const bool composite = DWindowManagerHelper::instance()->hasComposite(); -#ifndef DISABLE_SHOW_ANIMATION - const int duration = composite ? ANIMATIONTIME : 0; -#else - const int duration = 0; -#endif - - ani1->setDuration(duration); - ani2->setDuration(duration); - - // 隐藏 - ani1->setStartValue(getDockShowGeometry(fromScreen, fromPos, m_displayMode)); - ani1->setEndValue(getDockHideGeometry(fromScreen, fromPos, m_displayMode)); - qDebug() << fromScreen << "hide from :" << getDockShowGeometry(fromScreen, fromPos, m_displayMode); - qDebug() << fromScreen << "hide to :" << getDockHideGeometry(fromScreen, fromPos, m_displayMode); - - // 显示 - ani2->setStartValue(getDockHideGeometry(toScreen, toPos, m_displayMode)); - ani2->setEndValue(getDockShowGeometry(toScreen, toPos, m_displayMode)); - qDebug() << toScreen << "show from :" << getDockHideGeometry(toScreen, toPos, m_displayMode); - qDebug() << toScreen << "show to :" << getDockShowGeometry(toScreen, toPos, m_displayMode); - - group->addAnimation(ani1); - group->addAnimation(ani2); - - // 隐藏时固定一下内容大小 - connect(ani1, &QVariantAnimation::stateChanged, this, [ = ](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { - if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { - parent()->panel()->setFixedSize(dockRect(fromScreen, fromPos, HideMode::KeepShowing, m_displayMode).size()); - parent()->panel()->move(0, 0); - } - }); - - connect(ani1, &QVariantAnimation::valueChanged, this, [ = ](const QVariant & value) { - updateParentGeometry(value, fromPos); - }); - - // 显示时固定一下内容大小 - connect(ani2, &QVariantAnimation::stateChanged, this, [ = ](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { - // 位置发生变化时需要更新位置属性,且要在隐藏动画之后,显示动画之前 - DockItem::setDockPosition(m_position); - qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); - - if (newState == QVariantAnimation::Running && oldState == QVariantAnimation::Stopped) { - parent()->panel()->setFixedSize(dockRect(toScreen, toPos, HideMode::KeepShowing, m_displayMode).size()); - parent()->panel()->move(0, 0); - } - }); - - connect(ani2, &QVariantAnimation::valueChanged, this, [ = ](const QVariant & value) { - updateParentGeometry(value, toPos); - }); - - // 如果更改了显示位置,在显示之前应该更新一下界面布局方向 - if (fromPos != toPos) - connect(ani1, &QVariantAnimation::finished, this, [ = ] { - const auto display = QX11Info::display(); - if (!display) { - qWarning() << "QX11Info::display() is " << display; - } else { - // 先清除原先的窗管任务栏区域 - //XcbMisc::instance()->clear_strut_partial(xcb_window_t(parent()->winId())); - } - - // 隐藏后需要通知界面更新布局方向 - emit requestUpdateLayout(); - }); - - connect(group, &QVariantAnimation::finished, this, [ = ] { - setStates(ChangePositionAnimationStart, false); - - // 结束之后需要根据确定需要再隐藏 - emit showAniFinished(); - emit requestUpdateFrontendGeometry(); - emit requestNotifyWindowManager(); - }); - - setStates(ChangePositionAnimationStart); - - group->start(QVariantAnimation::DeleteWhenStopped); + Q_EMIT requestChangeDockPosition(fromScreen, toScreen, fromPos, toPos); } /** @@ -1316,15 +634,12 @@ void MultiScreenWorker::changeDockPosition(QString fromScreen, QString toScreen, QString MultiScreenWorker::getValidScreen(const Position &pos) { //TODO 考虑在主屏幕名变化时自动更新,是不是就不需要手动处理了 - m_ds.updatePrimary(DIS_INS->primary()); + DOCK_SCREEN->updatePrimary(DIS_INS->primary()); - if (m_screenMonitor->needUsedLastScreen()) - return m_screenMonitor->lastScreen(); + if (DIS_INS->canDock(DIS_INS->screen(DOCK_SCREEN->current()), pos)) + return DOCK_SCREEN->current(); - if (DIS_INS->canDock(DIS_INS->screen(m_ds.current()), pos)) - return m_ds.current(); - - if (DIS_INS->canDock(qApp->primaryScreen(), pos)) + if (DIS_INS->canDock(DIS_INS->screen(DIS_INS->primary()), pos)) return DIS_INS->primary(); for (auto s : DIS_INS->screens()) { @@ -1343,63 +658,62 @@ void MultiScreenWorker::resetDockScreen() if (testState(ChangePositionAnimationStart) || testState(HideAnimationStart) || testState(ShowAnimationStart) - || testState(DockIsShowing)) + || Utils::isDraging()) return; - m_ds.updateDockedScreen(getValidScreen(position())); + DOCK_SCREEN->updateDockedScreen(getValidScreen(position())); // 更新任务栏自身信息 - /** - *注意这里要先对parent()进行setFixedSize,在分辨率切换过程中,setGeometry可能会导致其大小未改变 - */ - if (m_ds.current().isEmpty()) // wayland下当没有屏幕时连接时,qt会虚拟一个空的屏幕,空屏幕这里不处理,不然会导致崩溃 - return; - parent()->setFixedSize(dockRect(m_ds.current()).size()); - parent()->setGeometry(dockRect(m_ds.current())); - qDebug() << "update dock geometry: " << dockRect(m_ds.current()); - parent()->panel()->setFixedSize(dockRect(m_ds.current()).size()); - parent()->panel()->move(0, 0); + Q_EMIT requestUpdateDockGeometry(m_hideMode); } /** * @brief checkDaemonDockService - * 避免com.deepin.dde.daemon.Dock服务比dock晚启动,导致dock启动后的状态错误 + * org.deepin.dde.daemon.Dock1服务比dock晚启动,导致dock启动后的状态错误 */ void MultiScreenWorker::checkDaemonDockService() { - auto connectionInit = [ = ](DBusDock * dockInter) { - connect(dockInter, &DBusDock::ServiceRestarted, this, [ = ] { + auto connectionInit = [ = ](DockInter * dockInter) { + connect(dockInter, &DockInter::ServiceRestarted, this, [ = ] { resetDockScreen(); emit requestUpdateFrontendGeometry(); }); - connect(dockInter, &DBusDock::OpacityChanged, this, &MultiScreenWorker::onOpacityChanged); - connect(dockInter, &DBusDock::WindowSizeEfficientChanged, this, &MultiScreenWorker::onWindowSizeChanged); - connect(dockInter, &DBusDock::WindowSizeFashionChanged, this, &MultiScreenWorker::onWindowSizeChanged); + connect(m_appearanceInter, &Appearance::Changed, this, [ this ](const QString &ty, const QString &value) { + if (ty == "windowopacity") + onOpacityChanged(value.toDouble()); + }); + connect(dockInter, &DockInter::WindowSizeEfficientChanged, this, &MultiScreenWorker::onWindowSizeChanged); + connect(dockInter, &DockInter::WindowSizeFashionChanged, this, &MultiScreenWorker::onWindowSizeChanged); + connect(dockInter, &DockInter::PositionChanged, this, &MultiScreenWorker::onPositionChanged); + connect(dockInter, &DockInter::DisplayModeChanged, this, &MultiScreenWorker::onDisplayModeChanged); + connect(dockInter, &DockInter::HideModeChanged, this, &MultiScreenWorker::onHideModeChanged); + connect(dockInter, &DockInter::HideStateChanged, this, &MultiScreenWorker::onHideStateChanged); }; - const QString serverName = "com.deepin.dde.daemon.Dock"; QDBusConnectionInterface *ifc = QDBusConnection::sessionBus().interface(); - if (!ifc->isServiceRegistered(serverName)) { + if (!ifc->isServiceRegistered(dockServiceName())) { connect(ifc, &QDBusConnectionInterface::serviceOwnerChanged, this, [ = ](const QString & name, const QString & oldOwner, const QString & newOwner) { Q_UNUSED(oldOwner) - if (name == serverName && !newOwner.isEmpty()) { + if (name == dockServiceName() && !newOwner.isEmpty()) { FREE_POINT(m_dockInter); - m_dockInter = new DBusDock(serverName, "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this); - Q_EMIT notifyDaemonInterfaceUpdate(); + m_dockInter = new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this); // connect connectionInit(m_dockInter); + // 通知主窗体服务已经重启了,需要重新获取DockInter + emit serviceRestart(); + // reinit data reInitDisplayData(); // operation - onPositionChanged(static_cast(dockInter()->position())); - onDisplayModeChanged(static_cast(dockInter()->displayMode())); - onHideModeChanged(static_cast(dockInter()->hideMode())); - onHideStateChanged(static_cast(dockInter()->hideState())); - onOpacityChanged(m_dockInter->opacity()); + onPositionChanged(dockInter()->position()); + onDisplayModeChanged(dockInter()->displayMode()); + onHideModeChanged(dockInter()->hideMode()); + onHideStateChanged(dockInter()->hideState()); + onOpacityChanged(m_appearanceInter->opacity()); disconnect(ifc); } @@ -1458,35 +772,14 @@ bool MultiScreenWorker::isCursorOut(int x, int y) /** * @brief checkDaemonXEventMonitorService - * 避免com.deepin.api.XEventMonitor服务比dock晚启动,导致dock启动后的状态错误 + * org.deepin.dde.XEventMonitor1服务比dock晚启动,导致dock启动后的状态错误 */ void MultiScreenWorker::checkXEventMonitorService() { auto connectionInit = [ = ](XEventMonitor * eventInter, XEventMonitor * extralEventInter, XEventMonitor * touchEventInter) { connect(eventInter, &XEventMonitor::CursorMove, this, &MultiScreenWorker::onRegionMonitorChanged); - connect(eventInter, &XEventMonitor::CursorOut, this, [ = ] { m_delayWakeOnHideTimer->stop(); }); connect(eventInter, &XEventMonitor::ButtonPress, this, [ = ] { setStates(MousePress, true); }); - connect(eventInter, &XEventMonitor::ButtonRelease, this, [ = ](int i, int x, int y, const QString &key) { - Q_UNUSED(i); - Q_UNUSED(key); - setStates(MousePress, false); - - // 鼠标松开时,重新计时 - if (key == m_registerKey) { - m_delayWakeOnHideTimer->start(); - } - - // 在鼠标拖动任务栏在最大尺寸的时候,如果当前任务栏为隐藏模式(一直隐藏或智能隐藏),在松开鼠标的那一刻,判断当前 - // 鼠标位置是否在任务栏外面(isCursorOut(x,y)==true),此时需要触发onExtralRegionMonitorChanged函数, - // 目的是为了让其触发隐藏 - QTimer::singleShot(50, this, [ = ] { - if (isCursorOut(x, y) - && (m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide)) { - qApp->setProperty("DRAG_STATE", false); - onExtralRegionMonitorChanged(0, 0, m_extralRegisterKey); - } - }); - }); + connect(eventInter, &XEventMonitor::ButtonRelease, this, [ = ] { setStates(MousePress, false); }); connect(extralEventInter, &XEventMonitor::CursorOut, this, [ = ](int x, int y, const QString &key) { if (isCursorOut(x, y)) { @@ -1502,27 +795,24 @@ void MultiScreenWorker::checkXEventMonitorService() }); // 触屏时,后端只发送press、release消息,有move消息则为鼠标,press置false - connect(touchEventInter, &XEventMonitor::CursorMove, this, [ = ] { - setStates(Utils::IS_WAYLAND_DISPLAY? MousePress : TouchPress, false); - }); + connect(touchEventInter, &XEventMonitor::CursorMove, this, [ = ] { setStates(TouchPress, false); }); connect(touchEventInter, &XEventMonitor::ButtonPress, this, &MultiScreenWorker::onTouchPress); connect(touchEventInter, &XEventMonitor::ButtonRelease, this, &MultiScreenWorker::onTouchRelease); }; - const QString serverName = "com.deepin.api.XEventMonitor"; QDBusConnectionInterface *ifc = QDBusConnection::sessionBus().interface(); - if (!ifc->isServiceRegistered(serverName)) { + if (!ifc->isServiceRegistered(xEventMonitorService)) { connect(ifc, &QDBusConnectionInterface::serviceOwnerChanged, this, [ = ](const QString & name, const QString & oldOwner, const QString & newOwner) { Q_UNUSED(oldOwner) - if (name == serverName && !newOwner.isEmpty()) { + if (name == xEventMonitorService && !newOwner.isEmpty()) { FREE_POINT(m_eventInter); FREE_POINT(m_extralEventInter); FREE_POINT(m_touchEventInter); - m_eventInter = new XEventMonitor(serverName, "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus()); - m_extralEventInter = new XEventMonitor(serverName, "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus()); - m_touchEventInter = new XEventMonitor(serverName, "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus()); + m_eventInter = new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus()); + m_extralEventInter = new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus()); + m_touchEventInter = new XEventMonitor(xEventMonitorService, xEventMonitorPath, QDBusConnection::sessionBus()); // connect connectionInit(m_eventInter, m_extralEventInter, m_touchEventInter); @@ -1534,175 +824,9 @@ void MultiScreenWorker::checkXEventMonitorService() } } -/** - * @brief MultiScreenWorker::getDockShowMinGeometry - * @param screenName - * @return 如果dock在当前screenName对应的屏幕上显示,返回其在最小 高/宽 度(也就是40,最大值为100)的rect区域 - */ -QRect MultiScreenWorker::getDockShowMinGeometry(const QString &screenName) -{ - QRect rect; - const double ratio = qApp->devicePixelRatio(); - const int margin = static_cast((m_displayMode == DisplayMode::Fashion ? 10 : 0) * qApp->devicePixelRatio()); - const int dockSize = 40; - - for (auto s : DIS_INS->screens()) { - if (s->name() == screenName) { - const QRect screenRect = getScreenRect(s); - switch (m_position) { - case Position::Top: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(dockSize); - break; - case Position::Bottom: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + screenRect.height() / ratio - margin - dockSize)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(dockSize); - break; - case Position::Left: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(dockSize); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - case Position::Right: - rect.setX(static_cast(screenRect.x() + screenRect.width() / ratio - margin - dockSize)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(dockSize); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - } - } - } - return rect; -} - -bool MultiScreenWorker::launcherVisible() -{ - return m_launcherInter->isValid() ? m_launcherInter->visible() : false; -} - -void MultiScreenWorker::setLauncherVisble(bool isVisible) -{ - if (m_launcherInter->isValid()) { - isVisible ? m_launcherInter->Show() : m_launcherInter->Hide(); - } -} - -/** - * @brief 获取任务栏显示时的参数。目前多屏情况下缩放保持一致,如果后续缩放规则修改,这里需要重新调整 - * - * @param screenName 当前屏幕名字 - * @param pos 任务栏位置 - * @param displaymode 任务栏显示模式 - * @param withoutScale 是否考虑缩放(true:获取的是真实值; false:获取的是前端认为的值(默认)) - * @return QRect 任务栏参数 - */ -QRect MultiScreenWorker::getDockShowGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale) -{ - QRect rect; - const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); - const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); - const int dockSize = static_cast((displaymode == DisplayMode::Fashion ? m_dockInter->windowSizeFashion() : m_dockInter->windowSizeEfficient()) * (withoutScale ? qApp->devicePixelRatio() : 1)); - - for (auto s : DIS_INS->screens()) { - if (s->name() == screenName) { - const QRect screenRect = getScreenRect(s); - switch (pos) { - case Position::Top: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(dockSize); - break; - case Position::Bottom: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + screenRect.height() / ratio - margin - dockSize)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(dockSize); - break; - case Position::Left: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(dockSize); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - case Position::Right: - rect.setX(static_cast(screenRect.x() + screenRect.width() / ratio - margin - dockSize)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(dockSize); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - } - } - } - return rect; -} - -/** - * @brief 获取任务栏隐藏时的参数。目前多屏情况下缩放保持一致,如果后续缩放规则修改,这里需要重新调整 - * - * @param screenName 当前屏幕名字 - * @param pos 任务栏位置 - * @param displaymode 任务栏显示模式 - * @param withoutScale 是否考虑缩放(true:获取的是真实值; false:获取的是前端认为的值(默认)) - * @return QRect 任务栏参数 - */ -QRect MultiScreenWorker::getDockHideGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale) -{ - QRect rect; - const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); - const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); - - for (auto s : DIS_INS->screens()) { - if (s->name() == screenName) { - const QRect screenRect = getScreenRect(s); - switch (pos) { - case Position::Top: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(0); - break; - case Position::Bottom: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + screenRect.height() / ratio - margin)); - rect.setWidth(static_cast(screenRect.width() / ratio - 2 * margin)); - rect.setHeight(0); - break; - case Position::Left: - rect.setX(static_cast(screenRect.x() + margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(0); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - case Position::Right: - rect.setX(static_cast(screenRect.x() + screenRect.width() / ratio - margin)); - rect.setY(static_cast(screenRect.y() + margin)); - rect.setWidth(0); - rect.setHeight(static_cast(screenRect.height() / ratio - 2 * margin)); - break; - } - } - } - return rect; -} - -QScreen *MultiScreenWorker::screenByName(const QString &screenName) -{ - foreach (QScreen *screen, qApp->screens()) { - if (screen->name() == screenName) - return screen; - } - return nullptr; -} - bool MultiScreenWorker::onScreenEdge(const QString &screenName, const QPoint &point) { - QScreen *screen = screenByName(screenName); + QScreen *screen = DIS_INS->screen(screenName); if (screen) { const QRect r { screen->geometry() }; const QRect rect { r.topLeft(), r.size() *screen->devicePixelRatio() }; @@ -1788,27 +912,22 @@ void MultiScreenWorker::onTouchRelease(int type, int x, int y, const QString &ke void MultiScreenWorker::onDelayAutoHideChanged() { switch (m_hideMode) { - case HideMode::KeepHidden: - { - // 这时候鼠标如果在任务栏上,就不能隐藏 - if (!parent()->geometry().contains(QCursor::pos())) - displayAnimation(m_ds.current(), AniAction::Hide); - } + case HideMode::KeepHidden: { + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide, true); break; + } case HideMode::SmartHide: { if (m_hideState == HideState::Show) - { - displayAnimation(m_ds.current(), AniAction::Show); - } else if (m_hideState == HideState::Hide) { - displayAnimation(m_ds.current(), AniAction::Hide); - } - } - break; - case HideMode::KeepShowing: - displayAnimation(m_ds.current(), AniAction::Show); + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); + else if (m_hideState == HideState::Hide) + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Hide); break; } - + case HideMode::KeepShowing: { + Q_EMIT requestPlayAnimation(DOCK_SCREEN->current(), m_position, Dock::AniAction::Show); + break; + } + } } /** @@ -1837,8 +956,9 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) * 使用screenAtByScaled获取屏幕名时,实际上获取的不一定是当前屏幕 * 举例:点(100,100)不在(0,0,100,100)的屏幕上 */ - if (onScreenEdge(m_ds.current(), QPoint(eventX, eventY))) { - toScreen = m_ds.current(); + const QString ¤tScreen = DOCK_SCREEN->current(); + if (onScreenEdge(currentScreen, QPoint(eventX, eventY))) { + toScreen = currentScreen; } // 过滤重复坐标 @@ -1849,16 +969,15 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) lastPos = QPoint(eventX, eventY); // 任务栏显示状态,但需要切换屏幕 - if (toScreen != m_ds.current()) { - if (!m_delayWakeOnScreenSwitchTimer->isActive()) { + if (toScreen != currentScreen) { + if (!m_delayWakeTimer->isActive()) { m_delayScreen = toScreen; - m_delayWakeOnScreenSwitchTimer->start(Utils::SettingValue("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", MonitorsSwitchTime, 2000).toInt()); + m_delayWakeTimer->start(Utils::SettingValue("com.deepin.dde.dock.mainwindow", "/com/deepin/dde/dock/mainwindow/", MonitorsSwitchTime, 2000).toInt()); } } else { // 任务栏隐藏状态,但需要显示 if (hideMode() == HideMode::KeepShowing) { - parent()->setFixedSize(dockRect(m_ds.current()).size()); - parent()->setGeometry(dockRect(m_ds.current())); + Q_EMIT requestUpdateDockGeometry(m_hideMode); return; } @@ -1867,95 +986,8 @@ void MultiScreenWorker::tryToShowDock(int eventX, int eventY) return; } - m_delayWakeOnHideTimer->start(); + if ((m_hideMode == HideMode::KeepHidden || m_hideMode == HideMode::SmartHide)) { + Q_EMIT requestPlayAnimation(currentScreen, m_position, Dock::AniAction::Show); + } } } - -/** - * @brief 屏幕监视 - * @param ds - */ -#define TIMESPAN 1500 -ScreenChangeMonitor::ScreenChangeMonitor(DockScreen *ds, QObject *parent) - : QObject (parent) -{ - #define DATETOSTRING(date) date.toString("hh:mm:ss:zzz") - - connect(DIS_INS, &DisplayManager::primaryScreenChanged, this, [ this, ds ](QScreen *primaryScreen) { - Q_ASSERT(primaryScreen); - - // 在screenAdded之后,又会发送一次主屏幕的变更的信息 - qInfo() << "primary screen changed, primary Screen" << primaryScreen->name(); - if (changedInSeconds()) - return; - - m_lastScreenName = ds->current(); - m_changePrimaryName = primaryScreen->name(); - m_changeTime = QDateTime::currentDateTime(); - qInfo() << "primary changed from: " << m_lastScreenName << "to: " << DATETOSTRING(m_changeTime); - }); - connect(DIS_INS, &DisplayManager::screenAdded, this, [ this ](QScreen *newScreen) { - if (newScreen) { - m_newScreenName = newScreen->name(); - m_newTime = QDateTime::currentDateTime(); - qInfo() <<"screen added:" << m_newScreenName << ", time:" << DATETOSTRING(m_newTime); - } - }); - connect(DIS_INS, &DisplayManager::screenRemoved, this, [ this ](QScreen *rmScreen) { - if (rmScreen) { - m_removeScreenName = rmScreen->name(); - m_removeTime = QDateTime::currentDateTime(); - qInfo() <<"screen removed:" << m_removeScreenName << ", time:" << DATETOSTRING(m_removeTime); - } - }); -} - -ScreenChangeMonitor::~ScreenChangeMonitor() -{ -} - -bool ScreenChangeMonitor::changedInSeconds() -{ - // 如果上一次的主屏幕的名称为空,则认为未发送屏幕变化的信号 - if (m_changePrimaryName.isEmpty() || !m_changeTime.isValid()) - return false; - - qint64 nowMsec = QDateTime::currentDateTime().toMSecsSinceEpoch(); - qint64 preChangeMsec = m_changeTime.toMSecsSinceEpoch(); - return (nowMsec - preChangeMsec <= TIMESPAN); -} - -bool ScreenChangeMonitor::needUsedLastScreen() const -{ - if (m_lastScreenName.isEmpty()) - return false; - - // 判断是否在关闭显示器的时候由系统发出来的先禁用显示器再开启显示器 - if (!m_changeTime.isValid() || !m_removeTime.isValid() || !m_newTime.isValid()) - return false; - - // 如果禁用的掉的显示器和开启的显示器的名称不一样,则认为他们是正常的插拔操作 - if (m_removeScreenName != m_newScreenName) - return false; - - // 如果先插入显示器再拔掉显示器,则认为他们也是正常的插拔操作 - if (m_removeTime > m_newTime) - return false; - - // 只有在remove显示器在add显示器之前且时间小于1.5秒,才认为他们是由关闭显示器引起的 - qint64 changeMsec = m_changeTime.toMSecsSinceEpoch(); - - // 获取现在的时间,如果现在的时间大于这三个时间一定的值,则认为是手动操作 - qint64 nowMsec = QDateTime::currentDateTime().toMSecsSinceEpoch(); - if (nowMsec - changeMsec > TIMESPAN) - return false; - - qint64 addedMsec = m_newTime.toMSecsSinceEpoch(); - qint64 removeMsec = m_removeTime.toMSecsSinceEpoch(); - return ((addedMsec - removeMsec <= TIMESPAN) && qAbs(removeMsec - changeMsec) <= TIMESPAN); -} - -const QString ScreenChangeMonitor::lastScreen() -{ - return m_lastScreenName; -} diff --git a/frame/util/multiscreenworker.h b/frame/util/multiscreenworker.h index 07549abda..cb7e6797c 100644 --- a/frame/util/multiscreenworker.h +++ b/frame/util/multiscreenworker.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -9,15 +10,18 @@ #include "utils.h" #include "dockitem.h" #include "xcb_misc.h" +#include "dbusutil.h" -#include -#include -#include +#include "org_deepin_dde_xeventmonitor1.h" +#include "org_deepin_dde_launcher1.h" +#include "org_deepin_dde_appearance1.h" + +#include #include #include -#include +#define WINDOWMARGIN ((m_displayMode == Dock::Efficient) ? 0 : 10) #define ANIMATIONTIME 300 #define FREE_POINT(p) if (p) {\ delete p;\ @@ -30,9 +34,13 @@ DGUI_USE_NAMESPACE * 之前测试出的诸多问题都是在切换任务栏位置,切换屏幕,主屏更改,分辨率更改等情况发生后 * 任务栏的鼠标唤醒区域或任务栏的大小没更新或者更新时的大小还是按照原来的屏幕信息计算而来的, */ -using DBusDock = com::deepin::dde::daemon::Dock; -using XEventMonitor = ::com::deepin::api::XEventMonitor; -using DBusLuncher = ::com::deepin::dde::Launcher; + +#define DRAG_AREA_SIZE (5) +#define DOCKSPACE (WINDOWMARGIN * 2) + +using XEventMonitor = ::org::deepin::dde::XEventMonitor1; +using DBusLuncher = ::org::deepin::dde::Launcher1; +using Appearance = org::deepin::dde::Appearance1; using namespace Dock; class QVariantAnimation; @@ -40,48 +48,13 @@ class QWidget; class QTimer; class MainWindow; class QGSettings; -class ScreenChangeMonitor; - -/** - * @brief The DockScreen class - * 保存任务栏的屏幕信息 - */ -class DockScreen -{ -public: - explicit DockScreen(const QString &primary) - : m_currentScreen(primary) - , m_lastScreen(primary) - , m_primary(primary) - {} - inline const QString ¤t() const {return m_currentScreen;} - inline const QString &last() const {return m_lastScreen;} - inline const QString &primary() const {return m_primary;} - - void updateDockedScreen(const QString &screenName) - { - qInfo() << "update docked screen" << screenName; - m_lastScreen = m_currentScreen; - m_currentScreen = screenName; - } - - void updatePrimary(const QString &primary) - { - m_primary = primary; - if (m_currentScreen.isEmpty()) { - updateDockedScreen(primary); - } - } - -private: - QString m_currentScreen; - QString m_lastScreen; - QString m_primary; -}; +class TrayMainWindow; +class MenuWorker; class MultiScreenWorker : public QObject { Q_OBJECT + public: enum Flag { Motion = 1 << 0, @@ -89,11 +62,6 @@ public: Key = 1 << 2 }; - enum AniAction { - Show = 0, - Hide - }; - enum RunState { ShowAnimationStart = 0x1, // 单次显示动画正在运行状态 HideAnimationStart = 0x2, // 单次隐藏动画正在运行状态 @@ -102,7 +70,6 @@ public: MousePress = 0x10, // 当前鼠标是否被按下 TouchPress = 0x20, // 当前触摸屏下是否按下 LauncherDisplay = 0x40, // 启动器是否显示 - DockIsShowing = 0x80, // 任务栏正在显示 // 如果要添加新的状态,可以在上面添加 RunState_Mask = 0xffffffff, @@ -110,84 +77,63 @@ public: typedef QFlags RunStates; - MultiScreenWorker(QWidget *parent); + explicit MultiScreenWorker(QObject *parent = Q_NULLPTR); + ~MultiScreenWorker() override; - void initShow(); - - DBusDock *dockInter() { return m_dockInter; } + DockInter *dockInter() { return m_dockInter; } + void updateDaemonDockSize(const int &dockSize); inline bool testState(RunState state) { return (m_state & state); } void setStates(RunStates state, bool on = true); - inline const QString &lastScreen() { return m_ds.last(); } - inline const QString &deskScreen() { return m_ds.current(); } inline const Position &position() { return m_position; } inline const DisplayMode &displayMode() { return m_displayMode; } inline const HideMode &hideMode() { return m_hideMode; } inline const HideState &hideState() { return m_hideState; } inline quint8 opacity() { return m_opacity * 255; } - QRect dockRect(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode); - QRect dockRect(const QString &screenName); - QRect getDockShowMinGeometry(const QString &screenName); - - bool launcherVisible(); - void setLauncherVisble(bool isVisible); - signals: void opacityChanged(const quint8 value) const; - void displayModeChanegd(); + void displayModeChanged(const Dock::DisplayMode &); // 更新监视区域 void requestUpdateRegionMonitor(); // 更新监听区域 void requestUpdateFrontendGeometry(); //!!! 给后端的区域不能为是或宽度为0的区域,否则会带来HideState死循环切换的bug void requestNotifyWindowManager(); void requestUpdatePosition(const Position &fromPos, const Position &toPos); - void requestUpdateLayout(); // 界面需要根据任务栏更新布局的方向 - void requestUpdateDragArea(); // 更新拖拽区域 void requestUpdateMonitorInfo(); // 屏幕信息发生变化,需要更新任务栏大小,拖拽区域,所在屏幕,监控区域,通知窗管,通知后端, - void requestStopShowAni(); - void requestStopHideAni(); + // 用来通知WindowManager的信号 + void requestUpdateDockGeometry(const Dock::HideMode &hideMode); + void positionChanged(const Dock::Position &position); - void requestUpdateDockEntry(); - void notifyDaemonInterfaceUpdate(); + void requestPlayAnimation(const QString &screenName, const Position &position, const Dock::AniAction &animation, bool containMouse = false, bool updatePos = false); + void requestChangeDockPosition(const QString &fromScreen, const QString &toScreen, const Position &fromPos, const Position &toPos); + + // 服务重新启动的信号 + void serviceRestart(); public slots: - void onAutoHideChanged(bool autoHide); - void updateDaemonDockSize(int dockSize); + void onAutoHideChanged(const bool autoHide); void onRequestUpdateRegionMonitor(); private slots: - void handleDBusSignal(QDBusMessage); - // Region Monitor void onRegionMonitorChanged(int x, int y, const QString &key); void onExtralRegionMonitorChanged(int x, int y, const QString &key); - // Animation - void showAniFinished(); - void hideAniFinished(); - void updateDisplay(); void onWindowSizeChanged(uint value); - void primaryScreenChanged(QScreen *screen); - void updateParentGeometry(const QVariant &value, const Position &pos); - void updateParentGeometry(const QVariant &value); + void onPrimaryScreenChanged(); // 任务栏属性变化 - void onPositionChanged(const Position &position); - void onDisplayModeChanged(const DisplayMode &displayMode); - void onHideModeChanged(const HideMode &hideMode); - void onHideStateChanged(const Dock::HideState &state); + void onPositionChanged(int position); + void onDisplayModeChanged(int displayMode); + void onHideModeChanged(int hideMode); + void onHideStateChanged(int state); void onOpacityChanged(const double value); - // 通知后端任务栏所在位置 - void onRequestUpdateFrontendGeometry(); - - void onRequestUpdateLayout(); - void onRequestNotifyWindowManager(); void onRequestUpdatePosition(const Position &fromPos, const Position &toPos); void onRequestUpdateMonitorInfo(); void onRequestDelayShowDock(); @@ -199,66 +145,50 @@ private slots: void onDelayAutoHideChanged(); private: - MainWindow *parent(); - // 初始化数据信息 void initMembers(); - void initDBus(); + void initDockMode(); void initConnection(); - void initUI(); + void initDisplayData(); void reInitDisplayData(); - void displayAnimation(const QString &screen, const Position &pos, AniAction act); - void displayAnimation(const QString &screen, AniAction act); - void tryToShowDock(int eventX, int eventY); void changeDockPosition(QString fromScreen, QString toScreen, const Position &fromPos, const Position &toPos); - QString getValidScreen(const Position &pos); void resetDockScreen(); void checkDaemonDockService(); void checkXEventMonitorService(); - QRect dockRectWithoutScale(const QString &screenName, const Position &pos, const HideMode &hideMode, const DisplayMode &displayMode); + QString getValidScreen(const Position &pos); - QRect getDockShowGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale = false); - QRect getDockHideGeometry(const QString &screenName, const Position &pos, const DisplayMode &displaymode, bool withoutScale = false); bool isCursorOut(int x, int y); - QScreen *screenByName(const QString &screenName); bool onScreenEdge(const QString &screenName, const QPoint &point); const QPoint rawXPosition(const QPoint &scaledPos); static bool isCopyMode(); - QRect getScreenRect(QScreen *s); private: - QWidget *m_parent; - // monitor screen XEventMonitor *m_eventInter; XEventMonitor *m_extralEventInter; XEventMonitor *m_touchEventInter; // DBus interface - DBusDock *m_dockInter; + DockInter *m_dockInter; DBusLuncher *m_launcherInter; + Appearance *m_appearanceInter; // update monitor info QTimer *m_monitorUpdateTimer; - QTimer *m_delayWakeOnScreenSwitchTimer; // sp3需求,切换屏幕显示延时,默认2秒唤起任务栏 - QTimer *m_delayWakeOnHideTimer; // 任务栏在同一个屏幕隐藏后再唤出时,需要短暂延时 - - DockScreen m_ds; // 屏幕名称信息 - ScreenChangeMonitor *m_screenMonitor; // 用于监视屏幕是否为系统先拔再插 + QTimer *m_delayWakeTimer; // sp3需求,切换屏幕显示延时,默认2秒唤起任务栏 // 任务栏属性 double m_opacity; Position m_position; HideMode m_hideMode; HideState m_hideState; - HideState m_currentHideState; DisplayMode m_displayMode; /***************不和其他流程产生交互,尽量不要动这里的变量***************/ @@ -274,38 +204,4 @@ private: /*****************************************************************/ }; -/** - * 在控制中心设置了自动关闭显示器,等一段时间后,显示器会自动关闭。在多显示器的情况下,此时系统会自动禁用主屏 - * 马上又开启主屏(底层系统是这么设计的),唤醒后,在禁用主屏后,后端会改变主屏为另外一个显示器,再开启主屏, - * 后端又改变主屏为原来的主屏,这样就会导致的问题是:本来任务栏在主屏,由于瞬间触发了删除主屏幕的操作,引起了 - * 任务栏显示到副屏的问题,开启主屏后,由于任务栏已经在副屏了,就再也回不到主屏,因此,增加了这个类用于专门来 - * 处理这种异常情况 - */ -class ScreenChangeMonitor : public QObject -{ - Q_OBJECT - -public: - ScreenChangeMonitor(DockScreen *ds, QObject *parent); - ~ScreenChangeMonitor(); - - bool needUsedLastScreen() const; - const QString lastScreen(); - -private: - bool changedInSeconds(); - -private: - QString m_lastScreenName; - - QString m_changePrimaryName; - QDateTime m_changeTime; - - QString m_newScreenName; - QDateTime m_newTime; - - QString m_removeScreenName; - QDateTime m_removeTime; -}; - #endif // MULTISCREENWORKER_H diff --git a/frame/util/platformutils.cpp b/frame/util/platformutils.cpp new file mode 100644 index 000000000..72bf899e2 --- /dev/null +++ b/frame/util/platformutils.cpp @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "platformutils.h" +#include "utils.h" + +#include + +#include + +#define NORMAL_WINDOW_PROP_NAME "WM_CLASS" +#define WINE_WINDOW_PROP_NAME "__wine_prefix" +#define IS_WINE_WINDOW_BY_WM_CLASS "explorer.exe" + +QString PlatformUtils::getAppNameForWindow(quint32 winId) +{ + // is normal application + QString appName = getWindowProperty(winId, NORMAL_WINDOW_PROP_NAME); + if (!appName.isEmpty() && appName != IS_WINE_WINDOW_BY_WM_CLASS) + return appName; + + // is wine application + appName = getWindowProperty(winId, WINE_WINDOW_PROP_NAME).split("/").last(); + if (!appName.isEmpty()) + return appName; + + // fallback to window id + return QString::number(winId); +} + +QString PlatformUtils::getWindowProperty(quint32 winId, QString propName) +{ + const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display(); + if (!display) { + qWarning() << "QX11Info::display() is " << display; + return QString(); + } + + Atom atom_prop = XInternAtom(display, propName.toLocal8Bit(), true); + if (!atom_prop) { + qDebug() << "Error: get window property failed, invalid property atom"; + return QString(); + } + + Atom actual_type_return; + int actual_format_return; + unsigned long nitems_return; + unsigned long bytes_after_return; + unsigned char *prop_return; + + int r = XGetWindowProperty(display, winId, atom_prop, 0, 100, false, AnyPropertyType, + &actual_type_return, &actual_format_return, &nitems_return, + &bytes_after_return, &prop_return); + + Q_UNUSED(r); + if (Utils::IS_WAYLAND_DISPLAY) + XCloseDisplay(display); + + return QString::fromLocal8Bit((char*)prop_return); +} diff --git a/frame/util/platformutils.h b/frame/util/platformutils.h new file mode 100644 index 000000000..a4a107468 --- /dev/null +++ b/frame/util/platformutils.h @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef PLATFORMUTILS_H +#define PLATFORMUTILS_H + +#include + +class PlatformUtils +{ +public: + static QString getAppNameForWindow(quint32 winId); + +private: + static QString getWindowProperty(quint32 winId, QString propName); +}; + +#endif // PLATFORMUTILS_H diff --git a/frame/util/pluginloader.cpp b/frame/util/pluginloader.cpp index 434c1f234..bbdaa4d68 100644 --- a/frame/util/pluginloader.cpp +++ b/frame/util/pluginloader.cpp @@ -1,17 +1,14 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "pluginloader.h" -#include "utils.h" #include #include #include #include -#include -#include -#include #include @@ -38,12 +35,9 @@ void PluginLoader::run() const QStringList disable_plugins_list = getDisablePluginList(); - const QString dtkCoreName = dtkCoreFileName(); - QStringList plugins; // 查找可用插件 - QList filePaths; for (QString file : files) { if (!QLibrary::isLibrary(file)) continue; @@ -52,10 +46,6 @@ void PluginLoader::run() if (file.contains("libkeyboard-layout") && !DSysInfo::isCommunityEdition()) continue; - // 由于onboard不支持wayland下输入,因此屏蔽onboard插件加载 - if (file.contains("libonboard") && Utils::IS_WAYLAND_DISPLAY) - continue; - // TODO: old dock plugins is uncompatible if (file.startsWith("libdde-dock-")) continue; @@ -65,23 +55,7 @@ void PluginLoader::run() continue; } - filePaths.push_back(pluginsDir.absoluteFilePath(file)); - } - - // 由于使用ldd获取.so信息比较耗时,采用并行处理 - QFuture f = QtConcurrent::mapped(filePaths, &PluginLoader::libUsedDtkCoreFileName); - f.waitForFinished(); - const QStringList &results = f.results(); - if (results.size() == filePaths.size()) { - for (int i = 0; i < results.size(); ++i) { - const QString &libUsedDtkCore = results.at(i); - // 判断当前进程加载的dtkcore库是否和当前库加载的dtkcore的库为同一个,如果不同,则无需加载, - // 否则在加载dtkcore的时候会报错(dtkcore内部判断如果加载两次会抛出错误 - if (libUsedDtkCore.isEmpty() || libUsedDtkCore == dtkCoreName) - plugins << filePaths.at(i); - } - } else { - plugins.append(filePaths); + plugins << file; } for (auto plugin : plugins) { @@ -90,103 +64,3 @@ void PluginLoader::run() emit finished(); } - -/** - * @brief 获取当前进程使用的dtkcore库的文件名 - * @return 当前进程使用的dtkCore库的文件名 - */ -QString PluginLoader::dtkCoreFileName() -{ - QFile f("/proc/self/maps"); - if (!f.open(QIODevice::ReadOnly)) - return QString(); - - const QByteArray &data = f.readAll(); - QTextStream ts(data); - while (Q_UNLIKELY(!ts.atEnd())) { - const QString line = ts.readLine(); - const QStringList &maps = line.split(' ', QString::SplitBehavior::SkipEmptyParts); - if (Q_UNLIKELY(maps.size() < 6)) - continue; - - QFileInfo info(maps.value(5)); - QString infoAbPath = info.absoluteFilePath(); - if (info.fileName().contains("dtkcore")) { - infoAbPath = realFileName(infoAbPath); - if (infoAbPath.contains("/")) { - int pathIndex = infoAbPath.lastIndexOf("/"); - infoAbPath = infoAbPath.mid(pathIndex + 1).trimmed(); - } - - f.close(); - return infoAbPath; - } - } - - f.close(); - return QString(); -} - -/** - * @brief 返回某个so库使用的dtkcore库文件名 - * @param 用于获取dtkcore库的so库文件名 - * @return 返回使用的dtkcore库文件名 - */ -QString PluginLoader::libUsedDtkCoreFileName(const QString &fileName) -{ - QString lddCommand = QString("ldd -r %1").arg(fileName); - FILE *fp = popen(lddCommand.toLocal8Bit().data(), "r"); - if (fp) { - char buf[2000] = {0}; - while (fgets(buf, sizeof(buf), fp)) { - QString rowResult = buf; - rowResult = rowResult.trimmed(); - if (rowResult.contains("dtkcore")) { - QStringList coreSplits = rowResult.split("=>"); - if (coreSplits.size() < 2) - continue; - - pclose(fp); - QString dtkCorePath = coreSplits[1]; - - // 删除后面的括号的内容 - int addrIndex = dtkCorePath.indexOf("(0x"); - dtkCorePath = realFileName(dtkCorePath.left(addrIndex).trimmed()); - if (dtkCorePath.contains("/")) { - int pathIndex = dtkCorePath.lastIndexOf("/"); - dtkCorePath = dtkCorePath.mid(pathIndex + 1).trimmed(); - } - - return dtkCorePath; - } - } - pclose(fp); - } - return QString(); -} - -/** - * @brief 返回软连接对应的实际的文件名 - * @param 当前软连接的文件名 - * @return 软连接对应的库的实际的文件名 - */ -QString PluginLoader::realFileName(QString fileName) -{ - QString command = QString("ls %1 -al").arg(fileName); - FILE *fp = popen(command.toLocal8Bit().data(), "r"); - if (fp) { - char buf[2000] = {0}; - if (fgets(buf, sizeof(buf), fp)) { - QString rowInfo = buf; - if (rowInfo.contains("->")) { - pclose(fp); - QStringList fileInfos = rowInfo.split("->"); - QString srcFileName = fileInfos[1]; - srcFileName = srcFileName.trimmed(); - return srcFileName; - } - } - pclose(fp); - } - return fileName; -} diff --git a/frame/util/pluginloader.h b/frame/util/pluginloader.h index d4879ead7..7eda1bdcb 100644 --- a/frame/util/pluginloader.h +++ b/frame/util/pluginloader.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,13 +14,6 @@ class PluginLoader : public QThread public: explicit PluginLoader(const QString &pluginDirPath, QObject *parent); - static QString libUsedDtkCoreFileName(const QString &fileName); - /** - * @brief realFileName 获取软连接的真实文件的路径 - * @param fileName 文件地址 - * @return - */ - static QString realFileName(QString fileName); signals: void finished() const; @@ -28,8 +22,6 @@ signals: protected: void run(); - QString dtkCoreFileName(); - private: QString m_pluginDirPath; }; diff --git a/frame/util/settingconfig.cpp b/frame/util/settingconfig.cpp new file mode 100644 index 000000000..6e538af96 --- /dev/null +++ b/frame/util/settingconfig.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "settingconfig.h" + +#include + +DCORE_USE_NAMESPACE + +SettingConfig *SettingConfig::instance() +{ + static SettingConfig instance; + return &instance; +} + +void SettingConfig::setValue(const QString &key, const QVariant &value) +{ + if (m_config->isValid() && m_config->keyList().contains(key)) + m_config->setValue(key, value); +} + +QVariant SettingConfig::value(const QString &key) const +{ + if (m_config->isValid() && m_config->keyList().contains(key)) + return m_config->value(key); + + return QVariant(); +} + +SettingConfig::SettingConfig(QObject *parent) + : QObject(parent) + , m_config(new DConfig(QString("com.deepin.dde.dock.dconfig"), QString())) +{ + connect(m_config, &DConfig::valueChanged, this, &SettingConfig::onValueChanged); +} + +void SettingConfig::onValueChanged(const QString &key) +{ + Q_EMIT valueChanged(key, m_config->value(key)); +} diff --git a/frame/util/settingconfig.h b/frame/util/settingconfig.h new file mode 100644 index 000000000..f3ff31de2 --- /dev/null +++ b/frame/util/settingconfig.h @@ -0,0 +1,45 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SETTINGCONFIG_H +#define SETTINGCONFIG_H + +#include + +#include +#include + +DCORE_BEGIN_NAMESPACE +class DConfig; +DCORE_END_NAMESPACE + +DCORE_USE_NAMESPACE + +#define SETTINGCONFIG SettingConfig::instance() + +class SettingConfig : public QObject +{ + Q_OBJECT + +public: + static SettingConfig *instance(); + + void setValue(const QString &key, const QVariant &value); + QVariant value(const QString &key) const; + +Q_SIGNALS: + void valueChanged(const QString &key, const QVariant &value); + +protected: + explicit SettingConfig(QObject *parent = nullptr); + +private Q_SLOTS: + void onValueChanged(const QString &key); + +private: + DConfig *m_config; +}; + +#endif // SETTINGCONFIG_H diff --git a/frame/util/singleton.h b/frame/util/singleton.h index bd62d7e97..48b59800c 100644 --- a/frame/util/singleton.h +++ b/frame/util/singleton.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/statebutton.cpp b/frame/util/statebutton.cpp index 91226b843..b6c059a4d 100644 --- a/frame/util/statebutton.cpp +++ b/frame/util/statebutton.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/statebutton.h b/frame/util/statebutton.h index 342dc0d24..ba6c416d2 100644 --- a/frame/util/statebutton.h +++ b/frame/util/statebutton.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/themeappicon.cpp b/frame/util/themeappicon.cpp index 228e74ca9..3cb67ba3f 100644 --- a/frame/util/themeappicon.cpp +++ b/frame/util/themeappicon.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/themeappicon.h b/frame/util/themeappicon.h index bf6ac438a..4174a9cb7 100644 --- a/frame/util/themeappicon.h +++ b/frame/util/themeappicon.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/util/touchsignalmanager.cpp b/frame/util/touchsignalmanager.cpp index 12a7f8031..a022a9098 100644 --- a/frame/util/touchsignalmanager.cpp +++ b/frame/util/touchsignalmanager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -15,7 +15,7 @@ TouchSignalManager *TouchSignalManager::m_touchManager = nullptr; TouchSignalManager::TouchSignalManager(QObject *parent) : QObject(parent) - , m_gestureInter(new Gesture("com.deepin.daemon.Gesture", "/com/deepin/daemon/Gesture", QDBusConnection::systemBus(), this)) + , m_gestureInter(new Gesture("org.deepin.dde.Gesture1", "/org/deepin/dde/Gesture1", QDBusConnection::systemBus(), this)) , m_dragIconPressed(false) { // 处理后端触屏信号 diff --git a/frame/util/touchsignalmanager.h b/frame/util/touchsignalmanager.h index e5e9cceff..dd9ee764f 100644 --- a/frame/util/touchsignalmanager.h +++ b/frame/util/touchsignalmanager.h @@ -1,15 +1,16 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef TOUCHSIGNALMANAGER_H #define TOUCHSIGNALMANAGER_H +#include "org_deepin_dde_gesture1.h" + #include -#include - -using Gesture = com::deepin::daemon::Gesture; +using Gesture = org::deepin::dde::Gesture1; class TouchSignalManager : public QObject { diff --git a/frame/util/utils.h b/frame/util/utils.h index c5283feaa..86d7d927f 100644 --- a/frame/util/utils.h +++ b/frame/util/utils.h @@ -1,10 +1,10 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef UTILS #define UTILS - #include #include #include @@ -20,6 +20,19 @@ namespace Utils { const bool IS_WAYLAND_DISPLAY = !qgetenv("WAYLAND_DISPLAY").isEmpty(); +inline bool isDraging() +{ + if (!qApp->property("isDraging").isValid()) + return false; + + return qApp->property("isDraging").toBool(); +} + +inline void setIsDraging(bool isDraging) +{ + qApp->setProperty("isDraging", isDraging); +} + /** * @brief SettingsPtr 根据给定信息返回一个QGSettings指针 * @param schema_id The id of the schema @@ -41,7 +54,7 @@ inline QGSettings *SettingsPtr(const QString &schema_id, const QByteArray &path * @brief SettingsPtr 根据给定信息返回一个QGSettings指针 * @param module 传入QGSettings构造函数时,会添加"com.deepin.dde.dock.module."前缀 * @param path If non-empty, specifies the path for a relocatable schema - * @param parent 创建指针的父对象 + * @param parent 创建指针的付对象 * @return */ inline const QGSettings *ModuleSettingsPtr(const QString &module, const QByteArray &path = QByteArray(), QObject *parent = nullptr) @@ -174,8 +187,8 @@ inline int comparePluginApi(const QString &pluginApi1, const QString &pluginApi2 return 0; // 拆分版本号 - QStringList subPluginApis1 = pluginApi1.split(".", QString::SkipEmptyParts, Qt::CaseSensitive); - QStringList subPluginApis2 = pluginApi2.split(".", QString::SkipEmptyParts, Qt::CaseSensitive); + QStringList subPluginApis1 = pluginApi1.split(".", Qt::SkipEmptyParts, Qt::CaseSensitive); + QStringList subPluginApis2 = pluginApi2.split(".", Qt::SkipEmptyParts, Qt::CaseSensitive); for (int i = 0; i < subPluginApis1.size(); ++i) { auto subPluginApi1 = subPluginApis1[i]; if (subPluginApis2.size() > i) { diff --git a/frame/window/components/datetimedisplayer.cpp b/frame/window/components/datetimedisplayer.cpp new file mode 100644 index 000000000..9fd1d6495 --- /dev/null +++ b/frame/window/components/datetimedisplayer.cpp @@ -0,0 +1,425 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "datetimedisplayer.h" +#include "tipswidget.h" +#include "dockpopupwindow.h" +#include "utils.h" +#include "dbusutil.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +DWIDGET_USE_NAMESPACE +DGUI_USE_NAMESPACE + +#define DATETIMESIZE 40 +#define ITEMSPACE 8 + +static QMap dateFormat{{ 0,"yyyy/M/d" }, { 1,"yyyy-M-d" }, { 2,"yyyy.M.d" }, { 3,"yyyy/MM/dd" }, + { 4,"yyyy-MM-dd" }, { 5,"yyyy.MM.dd" }, { 6,"yy/M/d" }, { 7,"yy-M-d" }, { 8,"yy.M.d" }}; +static QMap timeFormat{{0, "h:mm"}, {1, "hh:mm"}}; + +DateTimeDisplayer::DateTimeDisplayer(bool showMultiRow, QWidget *parent) + : QWidget (parent) + , m_timedateInter(new Timedate("org.deepin.dde.Timedate1", "/org/deepin/dde/Timedate1", QDBusConnection::sessionBus(), this)) + , m_position(Dock::Position::Bottom) + , m_dateFont(DFontSizeManager::instance()->t10()) + , m_tipsWidget(new Dock::TipsWidget(this)) + , m_menu(new QMenu(this)) + , m_tipsTimer(new QTimer(this)) + , m_currentSize(0) + , m_oneRow(false) + , m_showMultiRow(showMultiRow) + , m_isEnter(false) +{ + m_tipPopupWindow.reset(new DockPopupWindow); + // 日期格式变化的时候,需要重绘 + connect(m_timedateInter, &Timedate::ShortDateFormatChanged, this, &DateTimeDisplayer::onDateTimeFormatChanged); + // 时间格式变化的时候,需要重绘 + connect(m_timedateInter, &Timedate::ShortTimeFormatChanged, this, &DateTimeDisplayer::onDateTimeFormatChanged); + // 是否使用24小时制发生变化的时候,也需要重绘 + connect(m_timedateInter, &Timedate::Use24HourFormatChanged, this, &DateTimeDisplayer::onDateTimeFormatChanged); + // 连接日期时间修改信号,更新日期时间插件的布局 + connect(m_timedateInter, &Timedate::TimeUpdate, this, static_cast(&DateTimeDisplayer::update)); + // 连接定时器和时间显示的tips信号,一秒钟触发一次,显示时间 + connect(m_tipsTimer, &QTimer::timeout, this, &DateTimeDisplayer::onTimeChanged); + m_tipsTimer->setInterval(1000); + m_tipsTimer->start(); + updatePolicy(); + createMenuItem(); + if (Utils::IS_WAYLAND_DISPLAY) + m_tipPopupWindow->setWindowFlags(m_tipPopupWindow->windowFlags() | Qt::FramelessWindowHint); + m_tipPopupWindow->hide(); +} + +DateTimeDisplayer::~DateTimeDisplayer() +{ +} + +void DateTimeDisplayer::setPositon(Dock::Position position) +{ + if (m_position == position) + return; + + m_position = position; + updatePolicy(); + update(); +} + +void DateTimeDisplayer::setOneRow(bool oneRow) +{ + m_oneRow = oneRow; + update(); +} + +void DateTimeDisplayer::updatePolicy() +{ + switch (m_position) { + case Dock::Position::Top: { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + m_tipPopupWindow->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowTop); + m_tipPopupWindow->setContent(m_tipsWidget); + break; + } + case Dock::Position::Bottom: { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + m_tipPopupWindow->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowBottom); + m_tipPopupWindow->setContent(m_tipsWidget); + break; + } + case Dock::Position::Left: { + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_tipPopupWindow->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowLeft); + m_tipPopupWindow->setContent(m_tipsWidget); + break; + } + case Dock::Position::Right: { + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_tipPopupWindow->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowRight); + m_tipPopupWindow->setContent(m_tipsWidget); + break; + } + } +} + +QSize DateTimeDisplayer::suitableSize() const +{ + return suitableSize(m_position); +} + +QSize DateTimeDisplayer::suitableSize(const Dock::Position &position) const +{ + DateTimeInfo info = dateTimeInfo(position); + if (position == Dock::Position::Left || position == Dock::Position::Right) + return QSize(width(), info.m_timeRect.height() + info.m_dateRect.height()); + + // 如果在上下显示 + if (m_showMultiRow) { + // 如果显示多行的情况,一般是在高效模式下显示,因此,返回最大的尺寸 + return QSize(qMax(info.m_timeRect.width(), info.m_dateRect.width()), height()); + } + + return QSize(info.m_timeRect.width() + info.m_dateRect.width() + 16, height()); +} + +void DateTimeDisplayer::mousePressEvent(QMouseEvent *event) +{ + if ((event->button() != Qt::RightButton)) + return QWidget::mousePressEvent(event); + + m_menu->exec(QCursor::pos()); +} + +void DateTimeDisplayer::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + + DDBusSender().service("org.deepin.dde.Widgets1") + .path("/org/deepin/dde/Widgets1") + .interface("org.deepin.dde.Widgets1") + .method("Toggle").call(); +} + +QString DateTimeDisplayer::getTimeString(const Dock::Position &position) const +{ + QString tFormat = QString("hh:mm"); + int type = m_timedateInter->shortTimeFormat(); + if (timeFormat.contains(type)) + tFormat = timeFormat[type]; + + if (!m_timedateInter->use24HourFormat()) { + if (position == Dock::Top || position == Dock::Bottom) + tFormat = tFormat.append(" AP"); + else + tFormat = tFormat.append("\nAP"); + } + + return QDateTime::currentDateTime().toString(tFormat); +} + +QString DateTimeDisplayer::getDateString() const +{ + return getDateString(m_position); +} + +QString DateTimeDisplayer::getDateString(const Dock::Position &position) const +{ + int type = m_timedateInter->shortDateFormat(); + QString shortDateFormat = "yyyy-MM-dd"; + if (dateFormat.contains(type)) + shortDateFormat = dateFormat.value(type); + // 如果是左右方向,则不显示年份 + if (position == Dock::Position::Left || position == Dock::Position::Right) { + static QStringList yearStrList{"yyyy/", "yyyy-", "yyyy.", "yy/", "yy-", "yy."}; + for (int i = 0; i < yearStrList.size() ; i++) { + const QString &yearStr = yearStrList[i]; + if (shortDateFormat.contains(yearStr)) { + shortDateFormat = shortDateFormat.remove(yearStr); + break; + } + } + } + + return QDateTime::currentDateTime().toString(shortDateFormat); +} + +DateTimeDisplayer::DateTimeInfo DateTimeDisplayer::dateTimeInfo(const Dock::Position &position) const +{ + DateTimeInfo info; + info.m_timeRect = rect(); + info.m_dateRect = rect(); + + info.m_time = getTimeString(position); + info.m_date = getDateString(position); + + // 如果是左右方向 + if (position == Dock::Position::Left || position == Dock::Position::Right) { + int textWidth = rect().width(); + info.m_timeRect = QRect(0, 0, textWidth, DATETIMESIZE / 2); + info.m_dateRect = QRect(0, DATETIMESIZE / 2 + 1, textWidth, DATETIMESIZE / 2); + return info; + } + int timeWidth = QFontMetrics(timeFont()).boundingRect(info.m_time).width(); + int dateWidth = QFontMetrics(m_dateFont).boundingRect(info.m_date).width(); + + // 如果是上下方向 + if (m_showMultiRow) { + // 日期时间多行显示(一般是高效模式下,向下和向上偏移2个像素) + info.m_timeRect = QRect(0, 2, timeWidth, height() / 2); + info.m_dateRect = QRect(0, height() / 2 -2, dateWidth, height() / 2); + } else { + // 3:时间和日期3部分间隔 + if (rect().width() > (ITEMSPACE * 3 + timeWidth + dateWidth)) { + info.m_timeRect = QRect(ITEMSPACE, 0, timeWidth, height()); + + int dateX = info.m_timeRect.right() + (rect().width() -(ITEMSPACE * 2 + timeWidth + dateWidth)); + info.m_dateRect = QRect(dateX, 0, dateWidth, height()); + } else { + // 宽度不满足间隔为ITEMSPACE的,需要自己计算间隔。 + int itemSpace = (rect().width() - timeWidth - dateWidth) / 3; + info.m_timeRect = QRect(itemSpace, 0, timeWidth, height()); + + int dateX = info.m_timeRect.right() + itemSpace; + info.m_dateRect = QRect(dateX, 0, dateWidth, height()); + } + } + + return info; +} + +void DateTimeDisplayer::onTimeChanged() +{ + const QDateTime currentDateTime = QDateTime::currentDateTime(); + + if (m_timedateInter->use24HourFormat()) + m_tipsWidget->setText(currentDateTime.date().toString(Qt::SystemLocaleLongDate) + currentDateTime.toString(" HH:mm:ss")); + else + m_tipsWidget->setText(currentDateTime.date().toString(Qt::SystemLocaleLongDate) + currentDateTime.toString(" hh:mm:ss AP")); + + // 如果时间和日期有一个不等,则实时刷新界面 + if (m_lastDateString != getDateString() || m_lastTimeString != getTimeString()) + update(); +} + +void DateTimeDisplayer::onDateTimeFormatChanged() +{ + int lastSize = m_currentSize; + // 此处需要强制重绘,因为在重绘过程中才会改变m_currentSize信息,方便在后面判断是否需要调整尺寸 + repaint(); + // 如果日期时间的格式发生了变化,需要通知外部来调整日期时间的尺寸 + if (lastSize != m_currentSize) + Q_EMIT requestUpdate(); +} + +void DateTimeDisplayer::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e); + + DateTimeInfo info = dateTimeInfo(m_position); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(QPen(palette().brightText(), 1)); + + // 绘制背景色 + if (m_isEnter) { + QColor backColor = DGuiApplicationHelper::ColorType::DarkType == DGuiApplicationHelper::instance()->themeType() ? QColor(20, 20, 20) : Qt::white; + backColor.setAlphaF(0.2); + // 鼠标进入的时候,绘制底色 + painter.fillRect(rect(), backColor); + } + + int timeAlignFlag = Qt::AlignCenter; + int dateAlignFlag = Qt::AlignCenter; + + QFont strTimeFont = timeFont(); + + if (m_showMultiRow) { + timeAlignFlag = Qt::AlignHCenter | Qt::AlignBottom; + dateAlignFlag = Qt::AlignHCenter | Qt::AlignTop; + } else { + if (strTimeFont.pixelSize() >= rect().height()) { + strTimeFont.setPixelSize(rect().height() - 2); + m_dateFont.setPixelSize(rect().height() - 2); + } + } + + painter.setFont(strTimeFont); + painter.drawText(textRect(info.m_timeRect), timeAlignFlag, info.m_time); + painter.setFont(m_dateFont); + painter.drawText(textRect(info.m_dateRect), dateAlignFlag, info.m_date); + + updateLastData(info); +} + +QPoint DateTimeDisplayer::tipsPoint() const +{ + QPoint pointInTopWidget = parentWidget()->mapTo(topLevelWidget(), pos()); + switch (m_position) { + case Dock::Position::Left: { + pointInTopWidget.setX(topLevelWidget()->x() + topLevelWidget()->width()); + pointInTopWidget.setY(pointInTopWidget.y() + height() / 2); + break; + } + case Dock::Position::Top: { + pointInTopWidget.setY(y() + topLevelWidget()->y() + topLevelWidget()->height()); + pointInTopWidget.setX(pointInTopWidget.x() + width() / 2); + break; + } + case Dock::Position::Right: { + pointInTopWidget.setY(pointInTopWidget.y() + height() / 2); + pointInTopWidget.setX(pointInTopWidget.x() - width() / 2); + break; + } + case Dock::Position::Bottom: { + pointInTopWidget.setY(0); + pointInTopWidget.setX(pointInTopWidget.x() + width() / 2); + break; + } + } + return topLevelWidget()->mapToGlobal(pointInTopWidget); +} + +QFont DateTimeDisplayer::timeFont() const +{ + if (m_position == Dock::Position::Left || m_position == Dock::Position::Right) + return DFontSizeManager::instance()->t6(); + +#define MINHEIGHT 40 + + // 如果是上下方向,且当前只有一行,则始终显示小号字体 + if (m_oneRow || rect().height() <= MINHEIGHT) + return DFontSizeManager::instance()->t10(); + + static QList dateFontSize = { DFontSizeManager::instance()->t10(), + DFontSizeManager::instance()->t9(), + DFontSizeManager::instance()->t8(), + DFontSizeManager::instance()->t7() }; + + int index = qMin(qMax(static_cast((rect().height() - MINHEIGHT) / 3), 0), dateFontSize.size() - 1); + return dateFontSize[index]; +} + +void DateTimeDisplayer::createMenuItem() +{ + QAction *timeFormatAction = new QAction(this); + if (m_timedateInter->use24HourFormat()) + timeFormatAction->setText(tr("12-hour time")); + else + timeFormatAction->setText(tr("24-hour time")); + + connect(timeFormatAction, &QAction::triggered, this, [ = ] { + m_timedateInter->setUse24HourFormat(!m_timedateInter->use24HourFormat()); + }); + m_menu->addAction(timeFormatAction); + + if (!QFile::exists(ICBC_CONF_FILE)) { + QAction *timeSettingAction = new QAction(tr("Time settings"), this); + connect(timeSettingAction, &QAction::triggered, this, [ = ] { + DDBusSender() + .service(controllCenterService) + .path(controllCenterPath) + .interface(controllCenterInterface) + .method(QString("ShowPage")) + .arg(QString("datetime")) + .call(); + }); + + m_menu->addAction(timeSettingAction); + } +} + +QRect DateTimeDisplayer::textRect(const QRect &sourceRect) const +{ + // 如果是上下,则不做任何变化 + if (!m_showMultiRow && (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom)) + return sourceRect; + + QRect resultRect = sourceRect; + QSize size = suitableSize(); + // 如果是左右或者上下多行显示,设置宽度 + resultRect.setWidth(size.width()); + return resultRect; +} + +void DateTimeDisplayer::enterEvent(QEvent *event) +{ + Q_UNUSED(event); + m_isEnter = true; + update(); + m_tipPopupWindow->show(tipsPoint()); +} + +void DateTimeDisplayer::leaveEvent(QEvent *event) +{ + Q_UNUSED(event); + m_isEnter = false; + update(); + m_tipPopupWindow->hide(); +} + +void DateTimeDisplayer::updateLastData(const DateTimeInfo &info) +{ + m_lastDateString = info.m_date; + m_lastTimeString = info.m_time; + QSize dateTimeSize = suitableSize(); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + m_currentSize = dateTimeSize.width(); + else + m_currentSize = dateTimeSize.height(); +} + +QString DateTimeDisplayer::getTimeString() const +{ + return getTimeString(m_position); +} diff --git a/frame/window/components/datetimedisplayer.h b/frame/window/components/datetimedisplayer.h new file mode 100644 index 000000000..421099422 --- /dev/null +++ b/frame/window/components/datetimedisplayer.h @@ -0,0 +1,89 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DATETIMEDISPLAYER_H +#define DATETIMEDISPLAYER_H + +#include "constants.h" + +#include "org_deepin_dde_timedate1.h" + +#include +#include + +namespace Dock { class TipsWidget; } + +class DockPopupWindow; +class QMenu; + +using Timedate = org::deepin::dde::Timedate1; + +class DateTimeDisplayer : public QWidget +{ + Q_OBJECT + +private: + struct DateTimeInfo { + QString m_time; + QString m_date; + QRect m_timeRect; + QRect m_dateRect; + }; + +public: + explicit DateTimeDisplayer(bool showMultiRow, QWidget *parent = nullptr); + ~DateTimeDisplayer() override; + void setPositon(Dock::Position position); + void setOneRow(bool oneRow); + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; + +Q_SIGNALS: + void requestUpdate(); // 当日期时间格式发生变化的时候,需要通知外面来更新窗口尺寸 + +protected: + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void paintEvent(QPaintEvent *e) override; + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + +private: + void updatePolicy(); + DateTimeInfo dateTimeInfo(const Dock::Position &position) const; + void updateLastData(const DateTimeInfo &info); + + QString getTimeString() const; + QString getTimeString(const Dock::Position &position) const; + QString getDateString() const; + QString getDateString(const Dock::Position &position) const; + + QPoint tipsPoint() const; + QFont timeFont() const; + + void createMenuItem(); + QRect textRect(const QRect &sourceRect) const; + +private Q_SLOTS: + void onTimeChanged(); + void onDateTimeFormatChanged(); + +private: + Timedate *m_timedateInter; + Dock::Position m_position; + QFont m_dateFont; + Dock::TipsWidget *m_tipsWidget; + QMenu *m_menu; + QSharedPointer m_tipPopupWindow; + QTimer *m_tipsTimer; + QString m_lastDateString; + QString m_lastTimeString; + int m_currentSize; + bool m_oneRow; + bool m_showMultiRow; + bool m_isEnter; +}; + +#endif // DATETIMEDISPLAYER_H diff --git a/frame/window/components/desktop_widget.cpp b/frame/window/components/desktop_widget.cpp index d41bac911..743cf5395 100644 --- a/frame/window/components/desktop_widget.cpp +++ b/frame/window/components/desktop_widget.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,12 +13,8 @@ DesktopWidget::DesktopWidget(QWidget *parent) : QWidget (parent) , m_isHover(false) , m_needRecoveryWin(false) - ,m_timer(new QTimer(this)) { setMouseTracking(true); - m_timer->setInterval(0); - m_timer->setSingleShot(true); - connect(m_timer, &QTimer::timeout, this, &DesktopWidget::toggleDesktop); } void DesktopWidget::paintEvent(QPaintEvent *event) @@ -45,9 +41,7 @@ void DesktopWidget::enterEvent(QEvent *event) { if (checkNeedShowDesktop()) { m_needRecoveryWin = true; -// QProcess::startDetached("/usr/lib/deepin-daemon/desktop-toggle"); - if (m_timer) - m_timer->start(); + QProcess::startDetached("/usr/lib/deepin-daemon/desktop-toggle", QStringList()); } m_isHover = true; @@ -60,10 +54,7 @@ void DesktopWidget::leaveEvent(QEvent *event) { // 鼠标移入时隐藏了窗口,移出时恢复 if (m_needRecoveryWin) { - if (m_timer->isActive()) - m_timer->stop(); - else - toggleDesktop(); + QProcess::startDetached("/usr/lib/deepin-daemon/desktop-toggle"); } m_isHover = false; @@ -80,25 +71,13 @@ void DesktopWidget::mousePressEvent(QMouseEvent *event) m_needRecoveryWin = false; } else { // 需求调整,鼠标移入,预览桌面时再点击显示桌面保持显示桌面状态,再点击才切换桌面显、隐状态 - toggleDesktop(); + QProcess::startDetached("/usr/lib/deepin-daemon/desktop-toggle"); } } QWidget::mousePressEvent(event); } -void DesktopWidget::toggleDesktop() -{ - QProcess::startDetached("/usr/lib/deepin-daemon/desktop-toggle"); -} - -void DesktopWidget::setToggleDesktopInterval(int ms) -{ - if (m_timer) { - m_timer->setInterval(ms); - } -} - /** * @brief ShowDesktopWidget::checkNeedShowDesktop 根据窗管提供接口(当前是否显示的桌面),提供鼠标 * 移入 显示桌面窗口 区域时,是否需要显示桌面判断依据 diff --git a/frame/window/components/desktop_widget.h b/frame/window/components/desktop_widget.h index e8e03c4e3..1263f68f5 100644 --- a/frame/window/components/desktop_widget.h +++ b/frame/window/components/desktop_widget.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,14 +8,12 @@ #include #include #include -#include class DesktopWidget : public QWidget { public: explicit DesktopWidget(QWidget *parent = nullptr); - void setToggleDesktopInterval(int ms); private: bool checkNeedShowDesktop(); @@ -24,12 +22,10 @@ protected: void enterEvent(QEvent *event) override; void leaveEvent(QEvent *event) override; void mousePressEvent(QMouseEvent *event) override; - void toggleDesktop(); private: bool m_isHover; // 判断鼠标是否移到desktop区域 bool m_needRecoveryWin; - QTimer *m_timer; }; #endif // DESKTOP_WIDGET_H diff --git a/frame/window/components/dragwidget.cpp b/frame/window/components/dragwidget.cpp new file mode 100644 index 000000000..769ce4fdb --- /dev/null +++ b/frame/window/components/dragwidget.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dragwidget.h" +#include "utils.h" +#include "constants.h" + +#include +#include + +DragWidget::DragWidget(QWidget *parent) + : QWidget(parent) + , m_dragStatus(false) +{ + setObjectName("DragWidget"); +} + +bool DragWidget::isDraging() const +{ + return m_dragStatus; +} + +void DragWidget::onTouchMove(double scaleX, double scaleY) +{ + Q_UNUSED(scaleX); + Q_UNUSED(scaleY); + + static QPoint lastPos; + QPoint curPos = QCursor::pos(); + if (lastPos == curPos) { + return; + } + lastPos = curPos; + qApp->postEvent(this, new QMouseEvent(QEvent::MouseMove, mapFromGlobal(curPos) + , QPoint(), curPos, Qt::LeftButton, Qt::LeftButton + , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication)); +} + +void DragWidget::mousePressEvent(QMouseEvent *event) +{ + // qt转发的触屏按下信号不进行响应 + if (event->source() == Qt::MouseEventSynthesizedByQt) + return; + + if (event->button() == Qt::LeftButton) { + m_resizePoint = event->globalPos(); + m_dragStatus = true; + this->grabMouse(); + } +} + +void DragWidget::mouseMoveEvent(QMouseEvent *) +{ + if (m_dragStatus) { + QPoint offset = QPoint(QCursor::pos() - m_resizePoint); + emit dragPointOffset(offset); + } +} + +void DragWidget::mouseReleaseEvent(QMouseEvent *) +{ + if (!m_dragStatus) + return; + + m_dragStatus = false; + releaseMouse(); + emit dragFinished(); +} + +void DragWidget::enterEvent(QEvent *) +{ + QApplication::setOverrideCursor(cursor()); +} + +void DragWidget::leaveEvent(QEvent *) +{ + QApplication::setOverrideCursor(Qt::ArrowCursor); +} + diff --git a/frame/window/components/dragwidget.h b/frame/window/components/dragwidget.h new file mode 100644 index 000000000..22c9bfa6b --- /dev/null +++ b/frame/window/components/dragwidget.h @@ -0,0 +1,39 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DRAGWIDGET_H +#define DRAGWIDGET_H + +#include + +class DragWidget : public QWidget +{ + Q_OBJECT + +public: + explicit DragWidget(QWidget *parent = nullptr); + + bool isDraging() const; + +public Q_SLOTS: + void onTouchMove(double scaleX, double scaleY); + +Q_SIGNALS: + void dragPointOffset(QPoint); + void dragFinished(); + +protected: + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void enterEvent(QEvent *) override; + void leaveEvent(QEvent *) override; + +private: + bool m_dragStatus; + QPoint m_resizePoint; +}; + +#endif // DRAGWIDGET_H diff --git a/frame/window/docktraywindow.cpp b/frame/window/docktraywindow.cpp new file mode 100644 index 000000000..402c11b25 --- /dev/null +++ b/frame/window/docktraywindow.cpp @@ -0,0 +1,439 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "docktraywindow.h" +#include "datetimedisplayer.h" +#include "systempluginwindow.h" +#include "quickpluginwindow.h" +#include "tray_gridview.h" +#include "tray_model.h" +#include "tray_delegate.h" +#include "quicksettingcontroller.h" +#include "pluginsitem.h" +#include "expandiconwidget.h" +#include "quickdragcore.h" +#include "desktop_widget.h" + +#include + +#include +#include + +#define FRONTSPACING 18 +#define SPLITERSIZE 2 +#define SPLITESPACE 5 + +DockTrayWindow::DockTrayWindow(DockInter *dockInter, QWidget *parent) + : QWidget(parent) + , m_dockInter(dockInter) + , m_position(Dock::Position::Bottom) + , m_displayMode(Dock::DisplayMode::Efficient) + , m_mainBoxLayout(new QBoxLayout(QBoxLayout::Direction::RightToLeft, this)) + , m_showDesktopWidget(new DesktopWidget(this)) + , m_toolWidget(new QWidget(this)) + , m_toolLayout(new QBoxLayout(QBoxLayout::RightToLeft, m_toolWidget)) + , m_toolLineLabel(new QLabel(this)) + , m_dateTimeWidget(new DateTimeDisplayer(true, this)) + , m_systemPuginWidget(new SystemPluginWindow(dockInter, this)) + , m_quickIconWidget(new QuickPluginWindow(Dock::DisplayMode::Efficient, this)) + , m_trayView(new TrayGridView(this)) + , m_model(TrayModel::getDockModel()) + , m_delegate(new TrayDelegate(m_trayView, this)) + , m_toolFrontSpaceWidget(new QWidget(this)) + , m_toolBackSpaceWidget(new QWidget(this)) + , m_dateTimeSpaceWidget(new QWidget(this)) +{ + initUi(); + initConnection(); + initAttribute(); +} + +void DockTrayWindow::setPositon(const Dock::Position &position) +{ + m_position = position; + m_dateTimeWidget->setPositon(position); + m_systemPuginWidget->setPositon(position); + m_quickIconWidget->setPositon(position); + m_trayView->setPosition(position); + m_delegate->setPositon(position); + // 改变位置的时候,需要切换编辑器,以适应正确的位置 + m_trayView->onUpdateEditorView(); + updateLayout(position); + onUpdateComponentSize(); +} + +void DockTrayWindow::setDisplayMode(const Dock::DisplayMode &displayMode) +{ + m_displayMode = displayMode; + moveToolPlugin(); + updateToolWidget(); + // 如果当前模式为高效模式,则设置当前的trayView为其计算位置的参照 + if (displayMode == Dock::DisplayMode::Efficient) + ExpandIconWidget::popupTrayView()->setReferGridView(m_trayView); +} + +QSize DockTrayWindow::suitableSize(const Dock::Position &position, const int &, const double &) const +{ + if (position == Dock::Position::Left || position == Dock::Position::Right) { + // 左右的尺寸 + int height = m_showDesktopWidget->height() + + m_toolFrontSpaceWidget->height() + + m_toolWidget->height() + + m_toolBackSpaceWidget->height() + + m_toolLineLabel->height() + + m_dateTimeSpaceWidget->height() + + m_dateTimeWidget->suitableSize(position).height() + + m_systemPuginWidget->suitableSize(position).height() + + m_quickIconWidget->suitableSize(position).height() + + m_trayView->suitableSize(position).height(); + + return QSize(-1, height); + } + // 上下的尺寸 + int width = m_showDesktopWidget->width() + + m_toolFrontSpaceWidget->width() + + m_toolWidget->width() + + m_toolBackSpaceWidget->width() + + m_toolLineLabel->width() + + m_dateTimeSpaceWidget->width() + + m_dateTimeWidget->width() + + m_systemPuginWidget->width() + + m_quickIconWidget->width() + + m_trayView->width(); + return QSize(width, -1); +} + +QSize DockTrayWindow::suitableSize() const +{ + return suitableSize(m_position, 0, 0); +} + +void DockTrayWindow::layoutWidget() +{ + resizeTool(); +} + +void DockTrayWindow::resizeEvent(QResizeEvent *event) +{ + // 当尺寸发生变化的时候,通知托盘区域刷新尺寸,让托盘图标始终保持居中显示 + Q_EMIT m_delegate->sizeHintChanged(m_model->index(0, 0)); + QWidget::resizeEvent(event); + onUpdateComponentSize(); +} + +void DockTrayWindow::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + if (!m_toolLineLabel->isVisible()) + return; + + QPainter painter(this); + QColor color; + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { + color = Qt::black; + painter.setOpacity(0.5); + } else { + color = Qt::white; + painter.setOpacity(0.1); + } + + painter.fillRect(m_toolLineLabel->geometry(), color); +} + +bool DockTrayWindow::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == this || watched == m_toolWidget || watched == m_dateTimeWidget + || watched == m_trayView) { + switch (event->type()) { + case QEvent::Drop: { + QDropEvent *dropEvent = static_cast(event); + onDropIcon(dropEvent); + break; + } + case QEvent::DragEnter: { + QDragEnterEvent *dragEnterEvent = static_cast(event); + dragEnterEvent->setDropAction(Qt::CopyAction); + dragEnterEvent->accept(); + return true; + } + case QEvent::DragMove: { + QDragMoveEvent *dragMoveEvent = static_cast(event); + dragMoveEvent->setDropAction(Qt::CopyAction); + dragMoveEvent->accept(); + return true; + } + case QEvent::DragLeave: { + QDragLeaveEvent *dragLeaveEvent = static_cast(event); + dragLeaveEvent->accept(); + break; + } + default: + break; + } + } + + return QWidget::eventFilter(watched, event); +} + +/** 根据任务栏的位置来更新布局的方向 + * @brief DockTrayWindow::updateLayout + * @param position + */ +void DockTrayWindow::updateLayout(const Dock::Position &position) +{ + switch (position) { + case Dock::Position::Left: + case Dock::Position::Right: { + m_mainBoxLayout->setDirection(QBoxLayout::BottomToTop); + m_toolLayout->setDirection(QBoxLayout::BottomToTop); + break; + } + case Dock::Position::Top: + case Dock::Position::Bottom: { + m_mainBoxLayout->setDirection(QBoxLayout::RightToLeft); + m_toolLayout->setDirection(QBoxLayout::RightToLeft); + break; + } + } +} + +void DockTrayWindow::resizeTool() const +{ + int toolSize = 0; + int size = 0; + if (m_position == Dock::Position::Left || m_position == Dock::Position::Right) + size = width(); + else + size = height(); + + for (int i = 0; i < m_toolLayout->count(); i++) { + QLayoutItem *layoutItem = m_toolLayout->itemAt(i); + if (!layoutItem) + continue; + + PluginsItem *toolWidget = qobject_cast(layoutItem->widget()); + if (!toolWidget) + continue; + + toolWidget->setFixedSize(size, size); + toolSize += size; + } + + if (m_position == Dock::Position::Left || m_position == Dock::Position::Right) + m_toolWidget->setFixedSize(QWIDGETSIZE_MAX, toolSize); + else + m_toolWidget->setFixedSize(toolSize, QWIDGETSIZE_MAX); +} + +bool DockTrayWindow::pluginExists(PluginsItemInterface *itemInter) const +{ + for (int i = 0; i < m_toolLayout->count(); i++) { + QLayoutItem *layoutItem = m_toolLayout->itemAt(i); + if (!layoutItem) + continue; + + PluginsItem *pluginItem = qobject_cast(layoutItem->widget()); + if (!pluginItem) + continue; + + if (pluginItem->pluginItem() == itemInter) + return true; + } + + return false; +} + +void DockTrayWindow::moveToolPlugin() +{ + for (int i = m_toolLayout->count() - 1; i >= 0; i--) { + QLayoutItem *layoutItem = m_toolLayout->itemAt(i); + if (!layoutItem) + continue; + + PluginsItem *pluginWidget = qobject_cast(layoutItem->widget()); + if (!pluginWidget) + continue; + + m_toolLayout->removeWidget(pluginWidget); + } + if (m_displayMode == Dock::DisplayMode::Efficient) { + // 如果当前是高效模式,则将所有的工具插件移动到当前的工具区域 + QuickSettingController *quickController = QuickSettingController::instance(); + QList plugins = quickController->pluginItems(QuickSettingController::PluginAttribute::Tool); + for (PluginsItemInterface *pluginInter : plugins) { + PluginsItem *pluginWidget = quickController->pluginItemWidget(pluginInter); + m_toolLayout->addWidget(pluginWidget); + } + } +} + +void DockTrayWindow::updateToolWidget() +{ + m_toolWidget->setVisible(m_toolLayout->count() > 0); + m_toolLineLabel->setVisible(m_toolLayout->count() > 0); + m_toolFrontSpaceWidget->setVisible(m_toolLayout->count() > 0); + m_toolBackSpaceWidget->setVisible(m_toolLayout->count() > 0); + m_dateTimeSpaceWidget->setVisible(m_toolLayout->count() > 0); +} + +void DockTrayWindow::initUi() +{ + m_toolLayout->setContentsMargins(0, 0, 0, 0); + m_toolLayout->setSpacing(0); + + m_systemPuginWidget->setDisplayMode(Dock::DisplayMode::Efficient); + m_mainBoxLayout->setContentsMargins(0, 0, 0, 0); + m_mainBoxLayout->setSpacing(0); + m_mainBoxLayout->addWidget(m_showDesktopWidget); + m_mainBoxLayout->addWidget(m_toolFrontSpaceWidget); + m_mainBoxLayout->addWidget(m_toolWidget); + m_mainBoxLayout->addWidget(m_toolBackSpaceWidget); + m_mainBoxLayout->addWidget(m_toolLineLabel); + m_mainBoxLayout->addWidget(m_dateTimeSpaceWidget); + m_mainBoxLayout->addWidget(m_dateTimeWidget); + m_mainBoxLayout->addWidget(m_systemPuginWidget); + m_mainBoxLayout->addWidget(m_quickIconWidget); + m_mainBoxLayout->addWidget(m_trayView); + m_mainBoxLayout->setAlignment(m_toolLineLabel, Qt::AlignCenter); + + m_toolLineLabel->setFixedSize(0, 0); + + m_mainBoxLayout->addStretch(); + updateToolWidget(); +} + +void DockTrayWindow::initConnection() +{ + connect(m_systemPuginWidget, &SystemPluginWindow::itemChanged, this, &DockTrayWindow::onUpdateComponentSize); + connect(m_dateTimeWidget, &DateTimeDisplayer::requestUpdate, this, &DockTrayWindow::onUpdateComponentSize); + connect(m_quickIconWidget, &QuickPluginWindow::itemCountChanged, this, &DockTrayWindow::onUpdateComponentSize); + connect(m_systemPuginWidget, &SystemPluginWindow::requestDrop, this, &DockTrayWindow::onDropIcon); + connect(m_model, &TrayModel::rowCountChanged, this, &DockTrayWindow::onUpdateComponentSize); + connect(m_model, &TrayModel::rowCountChanged, m_trayView, &TrayGridView::onUpdateEditorView); + connect(m_model, &TrayModel::requestRefreshEditor, m_trayView, &TrayGridView::onUpdateEditorView); + connect(m_trayView, &TrayGridView::dragFinished, this, [ this ] { + // 如果拖拽结束,则隐藏托盘 + Q_EMIT m_delegate->requestDrag(false); + }); + + connect(m_trayView, &TrayGridView::dragLeaved, m_delegate, [ this ] { + Q_EMIT m_delegate->requestDrag(true); + }); + connect(QuickSettingController::instance(), &QuickSettingController::pluginInserted, this, [ this ] (PluginsItemInterface *itemInter, const QuickSettingController::PluginAttribute pluginAttr) { + switch (pluginAttr) { + case QuickSettingController::PluginAttribute::Tool: + // 下方只处理回收站等插件 + onItemAdded(itemInter); + break; + default: + break; + } + }); + + connect(QuickSettingController::instance(), &QuickSettingController::pluginRemoved, this, &DockTrayWindow::onItemRemove); +} + +void DockTrayWindow::initAttribute() +{ + setAcceptDrops(true); + setMouseTracking(true); + + m_trayView->setModel(m_model); + m_trayView->setItemDelegate(m_delegate); + m_trayView->setDragDistance(2); + m_trayView->setDragEnabled(true); + + installEventFilter(this); + m_toolWidget->installEventFilter(this); + m_dateTimeWidget->installEventFilter(this); + m_systemPuginWidget->installEventFilter(this); + m_quickIconWidget->installEventFilter(this); + m_trayView->installEventFilter(this); +} + +void DockTrayWindow::onUpdateComponentSize() +{ + switch (m_position) { + case Dock::Position::Left: + case Dock::Position::Right: + m_toolLineLabel->setFixedSize(width() * 0.6, SPLITERSIZE); + m_showDesktopWidget->setFixedSize(QWIDGETSIZE_MAX, FRONTSPACING); + m_dateTimeWidget->setFixedSize(QWIDGETSIZE_MAX, m_dateTimeWidget->suitableSize().height()); + m_systemPuginWidget->setFixedSize(QWIDGETSIZE_MAX, m_systemPuginWidget->suitableSize().height()); + m_quickIconWidget->setFixedSize(QWIDGETSIZE_MAX, m_quickIconWidget->suitableSize().height()); + m_trayView->setFixedSize(QWIDGETSIZE_MAX, m_trayView->suitableSize().height()); + m_toolFrontSpaceWidget->setFixedSize(QWIDGETSIZE_MAX, SPLITESPACE); + m_toolBackSpaceWidget->setFixedSize(QWIDGETSIZE_MAX, SPLITESPACE); + m_dateTimeSpaceWidget->setFixedSize(QWIDGETSIZE_MAX, SPLITESPACE); + break; + case Dock::Position::Top: + case Dock::Position::Bottom: + m_toolLineLabel->setFixedSize(SPLITERSIZE, height() * 0.6); + m_showDesktopWidget->setFixedSize(FRONTSPACING, QWIDGETSIZE_MAX); + m_dateTimeWidget->setFixedSize(m_dateTimeWidget->suitableSize().width(), QWIDGETSIZE_MAX); + m_systemPuginWidget->setFixedSize(m_systemPuginWidget->suitableSize().width(), QWIDGETSIZE_MAX); + m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize().width(), QWIDGETSIZE_MAX); + m_trayView->setFixedSize(m_trayView->suitableSize().width(), QWIDGETSIZE_MAX); + m_toolFrontSpaceWidget->setFixedSize(SPLITESPACE, QWIDGETSIZE_MAX); + m_toolBackSpaceWidget->setFixedSize(SPLITESPACE, QWIDGETSIZE_MAX); + m_dateTimeSpaceWidget->setFixedSize(SPLITESPACE, QWIDGETSIZE_MAX); + break; + } + Q_EMIT requestUpdate(); +} + +void DockTrayWindow::onItemAdded(PluginsItemInterface *itemInter) +{ + if (m_displayMode != Dock::DisplayMode::Efficient || pluginExists(itemInter)) + return; + + QuickSettingController *quickController = QuickSettingController::instance(); + PluginsItem *pluginItem = quickController->pluginItemWidget(itemInter); + pluginItem->setVisible(true); + + m_toolLayout->addWidget(pluginItem); + updateToolWidget(); + + Q_EMIT requestUpdate(); +} + +void DockTrayWindow::onItemRemove(PluginsItemInterface *itemInter) +{ + for (int i = 0; i < m_toolLayout->count(); i++) { + QLayoutItem *layoutItem = m_toolLayout->itemAt(i); + if (!layoutItem) + continue; + + PluginsItem *pluginItem = qobject_cast(layoutItem->widget()); + if (!pluginItem || pluginItem->pluginItem() != itemInter) + continue; + + m_toolLayout->removeWidget(pluginItem); + updateToolWidget(); + + Q_EMIT requestUpdate(); + break; + } +} + +void DockTrayWindow::onDropIcon(QDropEvent *dropEvent) +{ + if (!dropEvent || !dropEvent->mimeData() || dropEvent->source() == this) + return; + + if (m_quickIconWidget->isQuickWindow(dropEvent->source())) { + const QuickPluginMimeData *mimeData = qobject_cast(dropEvent->mimeData()); + if (!mimeData) + return; + + PluginsItemInterface *pluginItem = static_cast(mimeData->pluginItemInterface()); + if (pluginItem) + m_quickIconWidget->dragPlugin(pluginItem); + } else if (qobject_cast(dropEvent->source())) { + // 将trayView中的dropEvent扩大到整个区域(this),这样便于随意拖动到这个区域都可以捕获。 + // m_trayView中有e->accept不会导致事件重复处理。 + m_trayView->handleDropEvent(dropEvent); + } +} diff --git a/frame/window/docktraywindow.h b/frame/window/docktraywindow.h new file mode 100644 index 000000000..686d01817 --- /dev/null +++ b/frame/window/docktraywindow.h @@ -0,0 +1,84 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DOCKTRAYWINDOW_H +#define DOCKTRAYWINDOW_H + +#include "constants.h" +#include "dbusutil.h" + +#include + +class QBoxLayout; +class SystemPluginWindow; +class DateTimeDisplayer; +class QuickPluginWindow; +class TrayGridView; +class TrayModel; +class TrayDelegate; +class PluginsItem; +class PluginsItemInterface; +class QLabel; + +class DockTrayWindow : public QWidget +{ + Q_OBJECT + +public: + explicit DockTrayWindow(DockInter *dockInter, QWidget *parent = nullptr); + + void setPositon(const Dock::Position &position); + void setDisplayMode(const Dock::DisplayMode &displayMode); + + QSize suitableSize(const Dock::Position &position, const int &, const double &) const; + QSize suitableSize() const; + + void layoutWidget(); + +Q_SIGNALS: + void requestUpdate(); + +protected: + void resizeEvent(QResizeEvent *event) override; + void paintEvent(QPaintEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + void initUi(); + void initConnection(); + void initAttribute(); + void updateLayout(const Dock::Position &position); + void resizeTool() const; + bool pluginExists(PluginsItemInterface *itemInter) const; + void moveToolPlugin(); + void updateToolWidget(); + +private Q_SLOTS: + void onUpdateComponentSize(); + void onItemAdded(PluginsItemInterface *itemInter); + void onItemRemove(PluginsItemInterface *itemInter); + void onDropIcon(QDropEvent *dropEvent); + +private: + DockInter *m_dockInter; + Dock::Position m_position; + Dock::DisplayMode m_displayMode; + QBoxLayout *m_mainBoxLayout; + QWidget *m_showDesktopWidget; + QWidget *m_toolWidget; + QBoxLayout *m_toolLayout; + QLabel *m_toolLineLabel; + DateTimeDisplayer *m_dateTimeWidget; // 日期时间 + SystemPluginWindow *m_systemPuginWidget; // 固定区域-一般是右侧的电源按钮 + QuickPluginWindow *m_quickIconWidget; // 插件区域-包括网络、蓝牙等 + TrayGridView *m_trayView; // 托盘区域视图 + TrayModel *m_model; // 托盘区域的model + TrayDelegate *m_delegate; // 托盘区域的视图代理 + QWidget *m_toolFrontSpaceWidget; // 用于显示桌面和回收站中间的间隔 + QWidget *m_toolBackSpaceWidget; // 用于回收站和时间日期分割线中间的间隔 + QWidget *m_dateTimeSpaceWidget; // 用于时间日期分割线和时间日期中间的间隔 +}; + +#endif // DOCKTRAYWINDOW_H diff --git a/frame/window/mainpanelcontrol.cpp b/frame/window/mainpanelcontrol.cpp old mode 100644 new mode 100755 index 92187c030..cff384ee5 --- a/frame/window/mainpanelcontrol.cpp +++ b/frame/window/mainpanelcontrol.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -14,6 +15,16 @@ #include "utils.h" #include "desktop_widget.h" #include "imageutil.h" +#include "multiscreenworker.h" +#include "displaymanager.h" +#include "recentapphelper.h" +#include "toolapphelper.h" +#include "multiwindowhelper.h" +#include "mainwindow.h" +#include "appmultiitem.h" +#include "dockscreen.h" +#include "docktraywindow.h" +#include "quicksettingcontroller.h" #include #include @@ -25,17 +36,16 @@ #include #include #include +#include + #include #include -#define protected public -#include -#undef protected -#include -#include #include #include +#include + #define SPLITER_SIZE 2 #define TRASH_MARGIN 20 #define PLUGIN_MAX_SIZE 40 @@ -44,7 +54,7 @@ DWIDGET_USE_NAMESPACE -MainPanelControl::MainPanelControl(QWidget *parent) +MainPanelControl::MainPanelControl(DockInter *dockInter, QWidget *parent) : QWidget(parent) , m_mainPanelLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) , m_fixedAreaWidget(new QWidget(this)) @@ -54,34 +64,42 @@ MainPanelControl::MainPanelControl(QWidget *parent) , m_appAreaSonWidget(new QWidget(this)) , m_appAreaSonLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) , m_appSpliter(new QLabel(this)) - , m_trayAreaWidget(new QWidget(this)) - , m_trayAreaLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) - , m_traySpliter(new QLabel(this)) - , m_pluginAreaWidget(new QWidget(this)) - , m_pluginLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) - , m_desktopWidget(new DesktopWidget(this)) + , m_recentAreaWidget(new QWidget(this)) + , m_recentLayout(new QBoxLayout(QBoxLayout::LeftToRight, this)) + , m_recentSpliter(new QLabel(this)) + , m_toolAreaWidget(new QWidget(this)) + , m_toolAreaLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_toolAreaWidget)) + , m_multiWindowWidget(new QWidget(m_toolAreaWidget)) + , m_multiWindowLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_multiWindowWidget)) + , m_toolSonAreaWidget(new QWidget(m_toolAreaWidget)) + , m_toolSonLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_toolSonAreaWidget)) , m_position(Position::Bottom) , m_placeholderItem(nullptr) , m_appDragWidget(nullptr) - , m_dislayMode(Efficient) - , m_tray(nullptr) - , m_trashItem(nullptr) + , m_displayMode(Efficient) + , m_tray(new DockTrayWindow(dockInter, this)) + , m_dockInter(dockInter) + , m_recentHelper(new RecentAppHelper(m_appAreaSonWidget, m_recentAreaWidget, m_dockInter, this)) + , m_toolHelper(new ToolAppHelper(m_toolSonAreaWidget, this)) + , m_multiHelper(new MultiWindowHelper(m_appAreaSonWidget, m_multiWindowWidget, this)) { initUI(); + initConnection(); updateMainPanelLayout(); + updateModeChange(); setAcceptDrops(true); setMouseTracking(true); m_appAreaWidget->installEventFilter(this); m_appAreaSonWidget->installEventFilter(this); - m_trayAreaWidget->installEventFilter(this); - m_pluginAreaWidget->installEventFilter(this); + m_fixedAreaWidget->installEventFilter(this); + m_tray->installEventFilter(this); - //在设置每条线大小前,应该设置fixedsize(0,0) - //应为paintEvent函数会先调用设置背景颜色,大小为随机值 - m_fixedSpliter->setFixedSize(0,0); - m_appSpliter ->setFixedSize(0,0); - m_traySpliter->setFixedSize(0,0); + // 在设置每条线大小前,应该设置fixedsize(0,0) + // 应为paintEvent函数会先调用设置背景颜色,大小为随机值 + m_fixedSpliter->setFixedSize(0, 0); + m_appSpliter ->setFixedSize(0, 0); + m_recentSpliter->setFixedSize(0, 0); } void MainPanelControl::initUI() @@ -107,32 +125,62 @@ void MainPanelControl::initUI() m_appSpliter->setObjectName("spliter_app"); m_mainPanelLayout->addWidget(m_appSpliter); - /* 托盘区域 */ - m_trayAreaWidget->setObjectName("trayarea"); - m_trayAreaWidget->setLayout(m_trayAreaLayout); - m_trayAreaLayout->setSpacing(0); - m_trayAreaLayout->setContentsMargins(0, 10, 0, 10); - m_mainPanelLayout->addWidget(m_trayAreaWidget); + /* 最近打开应用 */ + m_recentAreaWidget->setObjectName("recentarea"); + m_recentAreaWidget->setAccessibleName("recentarea"); + m_recentAreaWidget->setLayout(m_recentLayout); + m_recentLayout->setSpacing(0); + m_recentLayout->setContentsMargins(0, 0, 0, 0); + m_recentLayout->setAlignment(Qt::AlignCenter); + m_mainPanelLayout->addWidget(m_recentAreaWidget); - m_traySpliter->setObjectName("spliter_tray"); - m_mainPanelLayout->addWidget(m_traySpliter); + m_recentSpliter->setObjectName("spliter_recent"); + m_mainPanelLayout->addWidget(m_recentSpliter); - /* 插件区域 */ - m_pluginAreaWidget->setObjectName("pluginarea"); - m_pluginAreaWidget->setLayout(m_pluginLayout); - m_pluginLayout->setSpacing(10); - m_pluginLayout->setContentsMargins(0, 0, 0, 0); - m_mainPanelLayout->addWidget(m_pluginAreaWidget, 0, Qt::AlignCenter); + /* 工具应用 */ + // 包含窗口多开和工具组合 + m_toolAreaWidget->setObjectName("toolArea"); + m_toolAreaWidget->setAccessibleName("toolArea"); + m_toolAreaWidget->setLayout(m_toolAreaLayout); + m_toolAreaLayout->setContentsMargins(0, 0, 0, 0); + m_toolAreaLayout->setSpacing(0); + m_mainPanelLayout->addWidget(m_toolAreaWidget); + // 多开窗口区域 + m_multiWindowWidget->setObjectName("multiWindow"); + m_multiWindowWidget->setAccessibleName("multiWindow"); + m_multiWindowWidget->setLayout(m_multiWindowLayout); + m_multiWindowLayout->setContentsMargins(0, 2, 0, 2); + m_multiWindowLayout->setSpacing(0); + m_toolAreaLayout->addWidget(m_multiWindowWidget); + // 工具应用区域-包含打开窗口区域和回收站区域 + m_toolSonAreaWidget->setObjectName("toolsonarea"); + m_toolSonAreaWidget->setAccessibleName("toolsonarea"); + m_toolSonAreaWidget->setLayout(m_toolSonLayout); + m_toolSonLayout->setSpacing(0); + m_toolSonLayout->setContentsMargins(0, 0, 0, 0); + m_toolSonLayout->setAlignment(Qt::AlignCenter); + m_toolAreaLayout->addWidget(m_toolSonAreaWidget); - /* 桌面预览 */ - m_desktopWidget->setObjectName("showdesktoparea"); - m_mainPanelLayout->addWidget(m_desktopWidget); + // 添加托盘区域(包括托盘图标和插件)等 + m_tray->setObjectName("tray"); + m_mainPanelLayout->addWidget(m_tray); m_mainPanelLayout->setSpacing(0); m_mainPanelLayout->setContentsMargins(0, 0, 0, 0); m_mainPanelLayout->setAlignment(m_fixedSpliter, Qt::AlignCenter); m_mainPanelLayout->setAlignment(m_appSpliter, Qt::AlignCenter); - m_mainPanelLayout->setAlignment(m_traySpliter, Qt::AlignCenter); + m_mainPanelLayout->setAlignment(m_recentSpliter, Qt::AlignCenter); +} + +void MainPanelControl::initConnection() +{ + connect(m_recentHelper, &RecentAppHelper::requestUpdate, this, &MainPanelControl::requestUpdate); + connect(m_recentHelper, &RecentAppHelper::recentVisibleChanged, this, &MainPanelControl::onRecentVisibleChanged); + connect(m_recentHelper, &RecentAppHelper::dockAppVisibleChanged, this, &MainPanelControl::onDockAppVisibleChanged); + connect(m_toolHelper, &ToolAppHelper::requestUpdate, this, &MainPanelControl::requestUpdate); + connect(m_toolHelper, &ToolAppHelper::toolVisibleChanged, this, &MainPanelControl::onToolVisibleChanged); + connect(m_multiHelper, &MultiWindowHelper::requestUpdate, this, &MainPanelControl::requestUpdate); + connect(m_tray, &DockTrayWindow::requestUpdate, this, &MainPanelControl::onTrayRequestUpdate); } /** @@ -141,9 +189,11 @@ void MainPanelControl::initUI() */ void MainPanelControl::setDisplayMode(DisplayMode dislayMode) { - if (dislayMode == m_dislayMode) - return; - m_dislayMode = dislayMode; + m_displayMode = dislayMode; + m_recentHelper->setDisplayMode(dislayMode); + m_tray->setDisplayMode(dislayMode); + m_toolHelper->setDisplayMode(dislayMode); + m_multiHelper->setDisplayMode(dislayMode); updateDisplayMode(); } @@ -157,37 +207,35 @@ void MainPanelControl::updateMainPanelLayout() case Position::Bottom: m_fixedAreaWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); m_appAreaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_pluginAreaWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - m_trayAreaWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); m_mainPanelLayout->setDirection(QBoxLayout::LeftToRight); m_fixedAreaLayout->setDirection(QBoxLayout::LeftToRight); - m_pluginLayout->setDirection(QBoxLayout::LeftToRight); - m_trayAreaLayout->setDirection(QBoxLayout::LeftToRight); m_appAreaSonLayout->setDirection(QBoxLayout::LeftToRight); - m_trayAreaLayout->setContentsMargins(0, 10, 0, 10); - m_pluginLayout->setContentsMargins(10, 0, 10, 0); + m_recentLayout->setDirection(QBoxLayout::LeftToRight); + m_multiWindowLayout->setDirection(QBoxLayout::LeftToRight); + m_toolAreaLayout->setDirection(QBoxLayout::LeftToRight); + m_toolSonLayout->setDirection(QBoxLayout::LeftToRight); + m_multiWindowLayout->setContentsMargins(0, 2, 0, 2); break; case Position::Right: case Position::Left: m_fixedAreaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_appAreaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_pluginAreaWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - m_trayAreaWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_mainPanelLayout->setDirection(QBoxLayout::TopToBottom); m_fixedAreaLayout->setDirection(QBoxLayout::TopToBottom); - m_pluginLayout->setDirection(QBoxLayout::TopToBottom); - m_trayAreaLayout->setDirection(QBoxLayout::TopToBottom); m_appAreaSonLayout->setDirection(QBoxLayout::TopToBottom); - m_trayAreaLayout->setContentsMargins(10, 0, 10, 0); - m_pluginLayout->setContentsMargins(0, 10, 0, 10); + m_recentLayout->setDirection(QBoxLayout::TopToBottom); + m_multiWindowLayout->setDirection(QBoxLayout::TopToBottom); + m_toolAreaLayout->setDirection(QBoxLayout::TopToBottom); + m_toolSonLayout->setDirection(QBoxLayout::TopToBottom); + m_multiWindowLayout->setContentsMargins(2, 0, 2, 0); break; } - // 显示桌面的区域 - resizeDesktopWidget(); - // 设置任务栏各区域图标大小 resizeDockIcon(); + + // 调整托盘区域大小 + onTrayRequestUpdate(); } /**往固定区域添加应用 @@ -197,57 +245,13 @@ void MainPanelControl::updateMainPanelLayout() */ void MainPanelControl::addFixedAreaItem(int index, QWidget *wdg) { - if(m_position == Position::Top || m_position == Position::Bottom){ + if (m_position == Position::Top || m_position == Position::Bottom) { wdg->setMaximumSize(height(),height()); } else { wdg->setMaximumSize(width(),width()); } m_fixedAreaLayout->insertWidget(index, wdg); -} - -/**往应用区域添加应用 - * @brief MainPanelControl::addAppAreaItem - * @param index 位置索引,如果为负数则插入到最后,为正则插入到指定位置 - * @param wdg 应用指针对象 - */ -void MainPanelControl::addAppAreaItem(int index, QWidget *wdg) -{ - if(m_position == Position::Top || m_position == Position::Bottom){ - wdg->setMaximumSize(height(),height()); - } else { - wdg->setMaximumSize(width(),width()); - } - m_appAreaSonLayout->insertWidget(index, wdg); -} - -/**往托盘插件区域添加应用 - * @brief MainPanelControl::addTrayAreaItem - * @param index 位置索引,如果为负数则插入到最后,为正则插入到指定位置 - * @param wdg 应用指针对象 - */ -void MainPanelControl::addTrayAreaItem(int index, QWidget *wdg) -{ - m_tray = static_cast(wdg); - m_trayAreaLayout->insertWidget(index, wdg); -} - -/**往插件区域添加应用,保存回收站插件指针对象 - * @brief MainPanelControl::addPluginAreaItem - * @param index 位置索引,如果为负数则插入到最后,为正则插入到指定位置 - * @param wdg 应用指针对象 - */ -void MainPanelControl::addPluginAreaItem(int index, QWidget *wdg) -{ - //因为日期时间插件和其他插件的大小有异,为了方便设置边距,在插件区域布局再添加一层布局设置边距 - //因此在处理插件图标时,需要通过两层布局判断是否为需要的插件,例如拖动插件位置等判断 - QBoxLayout * boxLayout = new QBoxLayout(QBoxLayout::LeftToRight, this); - boxLayout->addWidget(wdg, 0, Qt::AlignCenter); - m_pluginLayout->insertLayout(index, boxLayout, 0); - - // 保存垃圾箱插件指针 - PluginsItem *pluginsItem = qobject_cast(wdg); - if (pluginsItem && pluginsItem->pluginName() == "trash") - m_trashItem = pluginsItem; + Q_EMIT requestUpdate(); } /**移除固定区域某一应用 @@ -257,6 +261,7 @@ void MainPanelControl::addPluginAreaItem(int index, QWidget *wdg) void MainPanelControl::removeFixedAreaItem(QWidget *wdg) { m_fixedAreaLayout->removeWidget(wdg); + Q_EMIT requestUpdate(); } /**移除应用区域某一应用 @@ -266,67 +271,69 @@ void MainPanelControl::removeFixedAreaItem(QWidget *wdg) void MainPanelControl::removeAppAreaItem(QWidget *wdg) { m_appAreaSonLayout->removeWidget(wdg); -} - -/**移除托盘插件区域某一应用 - * @brief MainPanelControl::removeTrayAreaItem - * @param wdg 应用指针对象 - */ -void MainPanelControl::removeTrayAreaItem(QWidget *wdg) -{ - m_trayAreaLayout->removeWidget(wdg); -} - -/**移除插件区域某一应用 - * @brief MainPanelControl::removePluginAreaItem - * @param wdg 应用指针对象 - */ -void MainPanelControl::removePluginAreaItem(QWidget *wdg) -{ - //因为日期时间插件大小和其他插件有异,为了方便设置边距,各插件中增加一层布局 - //因此remove插件图标时,需要从多的一层布局中取widget进行判断是否需要移除的插件 - // 清空保存的垃圾箱插件指针 - PluginsItem *pluginsItem = qobject_cast(wdg); - if (pluginsItem && pluginsItem->pluginName() == "trash") - m_trashItem = nullptr; - - for (int i = 0; i < m_pluginLayout->count(); ++i) { - QLayoutItem *layoutItem = m_pluginLayout->itemAt(i); - QLayout *boxLayout = layoutItem->layout(); - if (boxLayout && boxLayout->itemAt(0)->widget() == wdg) { - boxLayout->removeWidget(wdg); - m_pluginLayout->removeItem(layoutItem); - delete layoutItem; - layoutItem = nullptr; - } - } + Q_EMIT requestUpdate(); } void MainPanelControl::resizeEvent(QResizeEvent *event) { - //先通过消息循环让各部件调整好size后再计算图标大小 - //避免因为部件size没有调整完导致计算的图标大小不准确 - //然后重复触发m_pluginAreaWidget的reszie事件并重复计算,造成任务栏图标抖动问题 + // 先通过消息循环让各部件调整好size后再计算图标大小 + // 避免因为部件size没有调整完导致计算的图标大小不准确 + // 然后重复触发m_pluginAreaWidget的reszie事件并重复计算,造成任务栏图标抖动问题 QWidget::resizeEvent(event); - resizeDesktopWidget(); resizeDockIcon(); } +/** 当用户从最近使用区域拖动应用到左侧应用区域的时候,将该应用驻留 + * @brief MainPanelControl::dockRecentApp + * @param dockItem + */ +void MainPanelControl::dockRecentApp(DockItem *dockItem) +{ + // 如果不是插入或者当前不是特效模式,则无需做驻留操作 + if (m_dragIndex == -1 || m_displayMode != Dock::DisplayMode::Fashion) + return; + + AppItem *appItem = qobject_cast(dockItem); + if (!appItem) + return; + + // 如果控制中心设置不开启最近应用,则不让其驻留 + if (!m_dockInter->showRecent()) + return; + + // 如果控制中心开启了最近应用并且当前应用是未驻留应用,则可以驻留 + if (!appItem->isDocked()) + appItem->requestDock(); +} + +PluginsItem *MainPanelControl::trash() const +{ + QuickSettingController *quickController = QuickSettingController::instance(); + QList toolPlugins = quickController->pluginItems(QuickSettingController::PluginAttribute::Tool); + for (PluginsItemInterface *plugin : toolPlugins) { + if (plugin->pluginName() != "trash") + continue; + + return quickController->pluginItemWidget(plugin); + } + + return nullptr; +} + /**根据任务栏所在位置, 设置应用区域控件的大小 * @brief MainPanelControl::updateAppAreaSonWidgetSize */ void MainPanelControl::updateAppAreaSonWidgetSize() { if ((m_position == Position::Top) || (m_position == Position::Bottom)) { - m_appAreaSonWidget->setMaximumHeight(this->height()); + m_appAreaSonWidget->setMaximumHeight(height()); m_appAreaSonWidget->setMaximumWidth(m_appAreaWidget->width()); } else { - m_appAreaSonWidget->setMaximumWidth(this->width()); + m_appAreaSonWidget->setMaximumWidth(width()); m_appAreaSonWidget->setMaximumHeight(m_appAreaWidget->height()); } m_appAreaSonWidget->adjustSize(); - moveAppSonWidget(); } @@ -340,7 +347,10 @@ void MainPanelControl::setPositonValue(Dock::Position position) return; m_position = position; - QTimer::singleShot(0, this, &MainPanelControl::updateMainPanelLayout); + m_tray->setPositon(position); + m_toolHelper->setPosition(position); + + QMetaObject::invokeMethod(this, &MainPanelControl::updateMainPanelLayout, Qt::QueuedConnection); } /**向任务栏插入各类应用,并将属于同一个应用的窗口合并到同一个应用图标 @@ -364,13 +374,12 @@ void MainPanelControl::insertItem(int index, DockItem *item) break; case DockItem::App: case DockItem::Placeholder: - addAppAreaItem(index, item); + m_recentHelper->addAppItem(index, item); break; - case DockItem::TrayPlugin: // 此处只会有一个tray系统托盘插件,微信、声音、网络蓝牙等等,都在系统托盘插件中处理的 - addTrayAreaItem(index, item); + case DockItem::AppMultiWindow: + m_multiHelper->addMultiWindow(index, static_cast(item)); break; - case DockItem::Plugins: - addPluginAreaItem(index, item); + default: break; } @@ -379,7 +388,6 @@ void MainPanelControl::insertItem(int index, DockItem *item) resizeDockIcon(); item->checkEntry(); - QTimer::singleShot(0, this, &MainPanelControl::updatePluginsLayout); } /**从任务栏移除某一应用,并更新任务栏图标大小 @@ -395,13 +403,12 @@ void MainPanelControl::removeItem(DockItem *item) break; case DockItem::App: case DockItem::Placeholder: - removeAppAreaItem(item); + m_recentHelper->removeAppItem(item); break; - case DockItem::TrayPlugin: - removeTrayAreaItem(item); + case DockItem::AppMultiWindow: + m_multiHelper->removeMultiWindow(static_cast(item)); break; - case DockItem::Plugins: - removePluginAreaItem(item); + default: break; } @@ -423,8 +430,12 @@ void MainPanelControl::removeItem(DockItem *item) void MainPanelControl::moveItem(DockItem *sourceItem, DockItem *targetItem) { // get target index - int idx = getItemIndex(targetItem); - if (-1 == idx) + int idx = -1; + if (targetItem->itemType() == DockItem::App) + idx = m_appAreaSonLayout->indexOf(targetItem); + else if (targetItem->itemType() == DockItem::FixedPlugin) + idx = m_fixedAreaLayout->indexOf(targetItem); + else return; // remove old item @@ -437,31 +448,6 @@ void MainPanelControl::moveItem(DockItem *sourceItem, DockItem *targetItem) insertItem(idx, sourceItem); } -int MainPanelControl::getItemIndex(DockItem *targetItem) const -{ - if (!targetItem) - return -1; - - if (targetItem->itemType() == DockItem::App) - return m_appAreaSonLayout->indexOf(targetItem); - - if (targetItem->itemType() == DockItem::Plugins){ - //因为日期时间插件大小和其他插件大小有异,为了设置边距,在各插件中增加了一层布局 - //因此有拖动图标时,需要从多的一层布局中判断是否相同插件而获取插件位置顺序 - for (int i = 0; i < m_pluginLayout->count(); ++i) { - QLayout *layout = m_pluginLayout->itemAt(i)->layout(); - if (layout && layout->itemAt(0)->widget() == targetItem) { - return i; - } - } - } - - if (targetItem->itemType() == DockItem::FixedPlugin) - return m_fixedAreaLayout->indexOf(targetItem); - - return -1; -} - void MainPanelControl::dragEnterEvent(QDragEnterEvent *e) { //拖拽图标到任务栏时,如果拖拽到垃圾箱插件图标widget上,则默认不允许拖拽,其他位置默认为允许拖拽 @@ -489,6 +475,7 @@ void MainPanelControl::dragLeaveEvent(QDragLeaveEvent *e) removeAppAreaItem(m_placeholderItem); m_placeholderItem->deleteLater(); + m_placeholderItem = nullptr; } } @@ -620,6 +607,14 @@ void MainPanelControl::dragMoveEvent(QDragMoveEvent *e) bool MainPanelControl::eventFilter(QObject *watched, QEvent *event) { + // 在从时尚模式切换到高效模式的时候, + // m_tray子部件会调整高度,此时会触发m_tray调整尺寸 + // 但是子部件的模式变化函数在FashionTrayItem部件中的 + // NormalContainer部件尺寸变化完成之前就已经结束,导致 + // NormalContainer没有更新自己的尺寸,引起插件区域拥挤 + //if (m_tray && watched == m_tray && event->type() == QEvent::Resize) + //m_tray->pluginItem()->displayModeChanged(m_displayMode); + // 更新应用区域大小和任务栏图标大小 if (watched == m_appAreaSonWidget) { switch (event->type()) { @@ -637,7 +632,7 @@ bool MainPanelControl::eventFilter(QObject *watched, QEvent *event) } // fix:88133 在计算icon大小时m_pluginAreaWidget的数据错误 - if (watched == m_pluginAreaWidget) { + if (watched == m_tray || watched == m_fixedAreaWidget) { switch (event->type()) { case QEvent::Resize: resizeDockIcon(); @@ -733,44 +728,33 @@ void MainPanelControl::startDrag(DockItem *dockItem) m_appDragWidget = appDrag->appDragWidget(); - if (Utils::IS_WAYLAND_DISPLAY) { - m_dragIndex = getItemIndex(dockItem); - connect(m_appDragWidget, &AppDragWidget::requestRemoveSelf, this, [ = ](bool needDelete) { - m_appDragWidget = nullptr; - if (!item.isNull() && qobject_cast(item)->isValid()) { - if (m_dragIndex > -1 && !needDelete) { - insertItem(m_dragIndex, item); - m_dragIndex = -1; - } else { - if (-1 == m_appAreaSonLayout->indexOf(item) && m_dragIndex != -1) { - insertItem(m_dragIndex, item); - m_dragIndex = -1; - } - AppItem *app = static_cast(item.data()); - app->undock(); - } - item->setDraging(false); - item->update(); - } - }); - } else { - connect(m_appDragWidget, &AppDragWidget::destroyed, this, [ = ] { - m_appDragWidget = nullptr; - if (!item.isNull() && qobject_cast(item)->isValid()) { - if (-1 == m_appAreaSonLayout->indexOf(item) && m_dragIndex != -1) { - insertItem(m_dragIndex, item); - m_dragIndex = -1; - } - item->setDraging(false); - item->update(); - } - }); - } + connect(m_appDragWidget, &AppDragWidget::requestChangedArea, this, [ = ](QRect rect) { + // 在区域改变的时候,出现分屏提示效果 + AppItem *appItem = static_cast(dockItem); + if (appItem->supportSplitWindow()) + appItem->startSplit(rect); + }); - connect(m_appDragWidget, &AppDragWidget::requestRemoveItem, this, [ = ] { - if (-1 != m_appAreaSonLayout->indexOf(item)) { - m_dragIndex = m_appAreaSonLayout->indexOf(item); - removeItem(item); + connect(m_appDragWidget, &AppDragWidget::requestSplitWindow, this, [ = ](ScreenSpliter::SplitDirection dir) { + AppItem *appItem = static_cast(dockItem); + if (appItem->supportSplitWindow()) + appItem->splitWindowOnScreen(dir); + }); + + connect(m_appDragWidget, &AppDragWidget::destroyed, this, [ = ] { + m_appDragWidget = nullptr; + + if (!item.isNull() && qobject_cast(item)->isValid()) { + // 如果是从最近打开区域移动到应用区域的,则需要将其固定 + dockRecentApp(item); + if (-1 == m_appAreaSonLayout->indexOf(item) && m_dragIndex != -1) { + insertItem(m_dragIndex, item); + m_dragIndex = -1; + } + item->setDraging(false); + item->update(); + // 发送拖拽完成事件 + m_recentHelper->resetAppInfo(); } }); @@ -798,22 +782,45 @@ void MainPanelControl::startDrag(DockItem *dockItem) // isNeedBack 保存是否需要重置垃圾箱的AcceptDrops // 设置垃圾箱插件AcceptDrops false bool isNeedBack = false; - if (item->itemType() == DockItem::Plugins && m_trashItem && dockItem != m_trashItem) { - m_trashItem->centralWidget()->setAcceptDrops(false); + PluginsItem *trashItem = trash(); + if (item->itemType() == DockItem::Plugins && trashItem && dockItem != trashItem) { + trashItem->centralWidget()->setAcceptDrops(false); isNeedBack = true; } drag->setMimeData(new QMimeData); drag->exec(Qt::MoveAction); - if (item->itemType() != DockItem::App || m_dragIndex == -1) { + if (item->itemType() == DockItem::App && m_appDragWidget) { + // TODO AppDragWidget中偶尔会出现拖拽结束后没有触发dropEvent的情况,因此exec结束后处理dropEvent中未执行的操作(临时处理方式) + m_appDragWidget->execFinished(); + } + + if (item->itemType() == DockItem::App) { + // 判断是否在回收站区域, 如果在回收站区域,则移除驻留 + if (!trashItem) + return; + + QRect trashRect = trashItem->centralWidget()->geometry(); + QPoint pointMouse = trashItem->centralWidget()->mapFromGlobal(QCursor::pos()); + if (trashRect.contains(pointMouse)) { + AppItem *appItem = qobject_cast(dockItem); + if (!appItem) + return; + + // 先让其设置m_dragIndex==-1,避免在后续放到任务栏 + m_dragIndex = -1; + appItem->setDraging(false); + appItem->undock(); + } + } else if (m_dragIndex == -1) { m_appDragWidget = nullptr; item->setDraging(false); item->update(); // isNeedBack是否需要设置垃圾箱插件AcceptDrops true if (isNeedBack) - m_trashItem->centralWidget()->setAcceptDrops(true); + trashItem->centralWidget()->setAcceptDrops(true); } } @@ -826,9 +833,6 @@ DockItem *MainPanelControl::dropTargetItem(DockItem *sourceItem, QPoint point) case DockItem::App: parentWidget = m_appAreaSonWidget; break; - case DockItem::Plugins: - parentWidget = m_pluginAreaWidget; - break; case DockItem::FixedPlugin: parentWidget = m_fixedAreaWidget; break; @@ -848,15 +852,7 @@ DockItem *MainPanelControl::dropTargetItem(DockItem *sourceItem, QPoint point) for (int i = 0 ; i < parentLayout->count(); ++i) { QLayoutItem *layoutItem = parentLayout->itemAt(i); - DockItem *dockItem = nullptr; - if (parentWidget == m_pluginAreaWidget) { - QLayout *layout = layoutItem->layout(); - if (layout) { - dockItem = qobject_cast(layout->itemAt(0)->widget()); - } - } else{ - dockItem = qobject_cast(layoutItem->widget()); - } + DockItem *dockItem = qobject_cast(layoutItem->widget()); if (!dockItem) continue; @@ -876,11 +872,19 @@ DockItem *MainPanelControl::dropTargetItem(DockItem *sourceItem, QPoint point) return targetItem; } - void MainPanelControl::updateDisplayMode() { + updateModeChange(); moveAppSonWidget(); - resizeDesktopWidget(); +} + +void MainPanelControl::updateModeChange() +{ + m_toolAreaWidget->setVisible(m_displayMode == DisplayMode::Fashion); + onRecentVisibleChanged(m_recentHelper->recentIsVisible()); + onDockAppVisibleChanged(m_recentHelper->dockAppIsVisible()); + onToolVisibleChanged(m_toolHelper->toolIsVisible()); + m_tray->setVisible(m_displayMode == DisplayMode::Efficient); } /**把驻留应用和被打开的应用所在窗口移动到指定位置 @@ -889,21 +893,12 @@ void MainPanelControl::updateDisplayMode() void MainPanelControl::moveAppSonWidget() { QRect rect(QPoint(0, 0), m_appAreaSonWidget->size()); - if (DisplayMode::Efficient == m_dislayMode) { - switch (m_position) { - case Top: - case Bottom : - rect.moveTo(m_appAreaWidget->pos()); - break; - case Right: - case Left: - rect.moveTo(m_appAreaWidget->pos()); - break; - } + if (DisplayMode::Efficient == m_displayMode) { + rect.moveTo(m_appAreaWidget->pos()); } else { switch (m_position) { case Top: - case Bottom : + case Bottom: rect.moveCenter(this->rect().center()); if (rect.right() > m_appAreaWidget->geometry().right()) { rect.moveRight(m_appAreaWidget->geometry().right()); @@ -928,26 +923,107 @@ void MainPanelControl::moveAppSonWidget() m_appAreaSonWidget->move(rect.x(), rect.y()); } -/**通知布局器,控件已发生变化,需要重新设置几何位置 - * @brief MainPanelControl::updatePluginsLayout - */ -void MainPanelControl::updatePluginsLayout() +void MainPanelControl::updateDockInter(DockInter *dockInter) { - for (int i = 0; i < m_pluginLayout->count(); ++i) { - QLayout *layout = m_pluginLayout->itemAt(i)->layout(); - if (layout) { - PluginsItem *pItem = static_cast(layout->itemAt(0)->widget()); - if (pItem && pItem->sizeHint().width() != -1) { - pItem->updateGeometry(); - } - } - } + m_dockInter = dockInter; + m_recentHelper->updateDockInter(dockInter); } -void MainPanelControl::setToggleDesktopInterval(int ms) +QSize MainPanelControl::suitableSize(const Position &position, int screenSize, double deviceRatio) const { - if (m_desktopWidget) - m_desktopWidget->setToggleDesktopInterval(ms); + if (screenSize <= 0) + return QSize(-1, -1); + + double ratio = deviceRatio; + if (ratio <= 0) + ratio = qApp->devicePixelRatio(); + + // 如果当前任务栏正在调整大小,就以当前任务栏的实际尺寸作为它的尺寸,否则,就以后端存储的尺寸作为它计算宽度(上下)或高度(左右)的参考 + int dockSize = Utils::isDraging() ? ((position == Position::Top || position == Position::Bottom) ? height() : width()) + : (static_cast((m_displayMode == DisplayMode::Efficient ? m_dockInter->windowSizeEfficient() : m_dockInter->windowSizeFashion()))); + if (m_displayMode == DisplayMode::Efficient) { + // 如果是高效模式 + if (position == Position::Top || position == Position::Bottom) + return QSize(static_cast(screenSize / ratio), dockSize); + + return QSize(dockSize, static_cast(screenSize / ratio)); + } + + // 如果是特效模式 + int totalLength = getScreenSize(); + // 减去插件区域的尺寸 + totalLength -= trayAreaSize(ratio); + + if (m_fixedSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + if (m_appSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + if (m_recentSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + + // 需要参与计算的图标的总数 + int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count() + m_recentLayout->count() + m_toolSonLayout->count(); + int multiWindowCount = m_multiWindowLayout->count(); + if (iconCount <= 0 && multiWindowCount <= 0) { + if (position == Position::Top || position == Position::Bottom) + return QSize((static_cast(dockSize)), dockSize); + + return QSize(dockSize, static_cast(dockSize)); + } + + int redundantLength = (totalLength % iconCount); + // icon宽度 = (总宽度-余数)/icon个数 + int iconSize = qMin((static_cast((totalLength - redundantLength) / iconCount / ratio)), dockSize); + + if (position == Position::Top || position == Position::Bottom) { + int spliterWidth = m_fixedSpliter->isVisible() ? SPLITER_SIZE : 0; + if (m_appSpliter->isVisible()) + spliterWidth += SPLITER_SIZE; + + if (m_recentSpliter->isVisible()) + spliterWidth += SPLITER_SIZE; + + int multiSize = 0; + // 计算每个多开窗口的尺寸 + if (multiWindowCount > 0) { + for (int i = 0; i < multiWindowCount; i++) { + AppMultiItem *multiItem = qobject_cast(m_multiWindowLayout->itemAt(i)->widget()); + if (!multiItem) + continue; + + multiSize += multiItem->width(); + } + } + + int panelWidth = qMin(iconSize * iconCount + multiSize + static_cast(spliterWidth), + static_cast((screenSize - DOCKSPACE))); + + return QSize(panelWidth, static_cast(dockSize)); + } + + int spliterHeight = m_fixedSpliter->isVisible() ? SPLITER_SIZE : 0; + if (m_appSpliter->isVisible()) + spliterHeight += SPLITER_SIZE; + + if (m_recentSpliter->isVisible()) + spliterHeight += SPLITER_SIZE; + + int multiSize = 0; + // 计算每个多开窗口的尺寸 + if (multiWindowCount > 0) { + for (int i = 0; i < multiWindowCount; i++) { + AppMultiItem *multiItem = qobject_cast(m_multiWindowLayout->itemAt(i)->widget()); + if (!multiItem) + continue; + + multiSize += multiItem->height(); + } + } + + int panelHeight = qMin(iconSize * iconCount + multiSize + static_cast(spliterHeight), + static_cast((screenSize - DOCKSPACE))); + + return QSize(dockSize, panelHeight); } void MainPanelControl::itemUpdated(DockItem *item) @@ -970,9 +1046,52 @@ void MainPanelControl::paintEvent(QPaintEvent *event) painter.setOpacity(0.1); } - painter.fillRect(m_fixedSpliter->geometry(), color); - painter.fillRect(m_appSpliter->geometry(), color); - painter.fillRect(m_traySpliter->geometry(), color); + if (m_fixedSpliter->isVisible()) + painter.fillRect(m_fixedSpliter->geometry(), color); + + if (m_appSpliter->isVisible()) + painter.fillRect(m_appSpliter->geometry(), color); + + if (m_recentSpliter->isVisible()) + painter.fillRect(m_recentSpliter->geometry(), color); +} + +// 获取当前屏幕的高或者宽(任务栏上下的时候获取宽,左右获取高) +int MainPanelControl::getScreenSize() const +{ + DisplayManager *displayManager = DisplayManager::instance(); + QScreen *currentScreen = displayManager->screen(displayManager->primary()); + QScreen *screen = displayManager->screen(DockScreen::instance()->current()); + if (screen) + currentScreen = screen; + + QRect screenRect = currentScreen->handle()->geometry(); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + return screenRect.width(); + + return screenRect.height(); +} + +int MainPanelControl::trayAreaSize(qreal ratio) const +{ + if (m_displayMode == Dock::DisplayMode::Efficient) + return (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom ? m_tray->width() * ratio: m_tray->height() * ratio); + + int length = 0; + QWidgetList topLevelWidgets = qApp->topLevelWidgets(); + for (QWidget *widget : topLevelWidgets) { + MainWindowBase *topWindow = qobject_cast(widget); + if (!topWindow) + continue; + + if (topWindow->windowType() != MainWindowBase::DockWindowType::MainWindow) { + length += (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom ? topWindow->width() * ratio : topWindow->height() * ratio); + } + + length += topWindow->dockSpace() * ratio; + } + + return length; } /**重新计算任务栏上应用图标、插件图标的大小,并设置 @@ -980,160 +1099,168 @@ void MainPanelControl::paintEvent(QPaintEvent *event) */ void MainPanelControl::resizeDockIcon() { + int iconSize = 0; // 总宽度 - int totalLength = ((m_position == Position::Top) || (m_position == Position::Bottom)) ? width() : height(); + if (m_displayMode == DisplayMode::Fashion) { + // 时尚模式 + int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count(); + if (m_recentAreaWidget->isVisible()) + iconCount += m_recentLayout->count(); - // 减去托盘间隔区域 - if (m_tray) { - totalLength -= (m_tray->trayVisibleItemCount() + 1) * 10; - } + if (m_toolAreaWidget->isVisible()) + iconCount += m_toolSonLayout->count(); - // 减去3个分割线的宽度 - totalLength -= 3 * SPLITER_SIZE; + if (iconCount <= 0) + return; - // 减去显示桌面图标宽度 - totalLength -= ((m_position == Position::Top) || (m_position == Position::Bottom)) ? m_desktopWidget->width() : m_desktopWidget->height(); + int totalLength = getScreenSize() - trayAreaSize(qApp->devicePixelRatio()); - int pluginItemCount = 0; - int calcPluginItemCount = 0; + if (m_fixedSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + if (m_appSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + if (m_recentSpliter->isVisible()) + totalLength -= SPLITER_SIZE; - // 因为日期时间大小和其他插件大小有异,为了设置边距,在各插件中增加了一层布局 - // 因此需要通过多一层布局来获取各插件 - for (int i = 0; i < m_pluginLayout->count(); ++ i) { - QLayout *layout = m_pluginLayout->itemAt(i)->layout(); - if (layout) { - PluginsItem *w = static_cast(layout->itemAt(0)->widget()); - if (w) { - // 如果插件大小由自己决定,则不参与计算需要减去其宽度,其他插件则需要参与计算并计数 - if ((m_position == Position::Top || m_position == Position::Bottom) && (w->sizeHint().height() != -1)) { - totalLength -= w->width(); - } else if ((m_position == Position::Top || m_position == Position::Bottom) && (w->sizeHint().width() != -1)) { - totalLength -= w->height(); - } else { - calcPluginItemCount ++; - } - - // 所有插件个数,用于计算插件之间的间隔之和 - pluginItemCount ++; - } - } - } - - // 减去插件间隔大小, 只有一个插件或没有插件都是间隔20,2个或以上每多一个插件多间隔10 - if (pluginItemCount > 1) - totalLength -= (pluginItemCount + 1) * 10; - else - totalLength -= 20; - - if (totalLength < 0) - return; - - // 参与计算的插件的个数包含托盘和插件 - int pluginCount = m_tray ? m_tray->trayVisibleItemCount() + calcPluginItemCount : calcPluginItemCount; - - // 需要计算的图标总数 - int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count() + pluginCount; - if (iconCount <= 0) - return; - - // 余数 - int yu = (totalLength % iconCount); - // icon宽度 = (总宽度-余数)/icon个数 - int iconSize = (totalLength - yu) / iconCount; - - // 计算插件图标的最大或最小值 - int tray_item_size = qBound(20, iconSize, 40); - if ((m_position == Position::Top) || (m_position == Position::Bottom)) { - tray_item_size = qMin(tray_item_size,height()); - tray_item_size = std::min(tray_item_size, height() - 20); + // 余数 + int yu = (totalLength % iconCount); + // icon宽度 = (总宽度-余数)/icon个数 + iconSize = (totalLength - yu) / iconCount; } else { - tray_item_size = qMin(tray_item_size,width()); - tray_item_size = std::min(tray_item_size, width() - 20); + int totalLength = getScreenSize() - trayAreaSize(qApp->devicePixelRatio()); + // 减去3个分割线的宽度 + if (m_fixedSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + if (m_appSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + if (m_recentSpliter->isVisible()) + totalLength -= SPLITER_SIZE; + + // 减去插件间隔大小, 只有一个插件或没有插件都是间隔20,2个或以上每多一个插件多间隔10 + totalLength -= 20; + + if (totalLength < 0) + return; + + // 参与计算的插件的个数包含托盘和插件 + // 需要计算的图标总数 + int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count()/* + pluginCount*/; + if (iconCount <= 0) + return; + + // 余数 + int yu = (totalLength % iconCount); + // icon宽度 = (总宽度-余数)/icon个数 + iconSize = (totalLength - yu) / iconCount; + + // 余数 + yu = (totalLength % iconCount); + // icon宽度 = (总宽度-余数)/icon个数 + iconSize = (totalLength - yu) / iconCount; } - if (tray_item_size < 20) - tray_item_size = 20; - - // 减去插件图标的大小后重新计算固定图标和应用图标的平均大小 - totalLength -= tray_item_size * pluginCount; - iconCount -= pluginCount; - - // 余数 - yu = (totalLength % iconCount); - // icon宽度 = (总宽度-余数)/icon个数 - iconSize = (totalLength - yu) / iconCount; - + iconSize = iconSize / qApp->devicePixelRatio(); if ((m_position == Position::Top) || (m_position == Position::Bottom)) { if (iconSize >= height()) { - calcuDockIconSize(height(), height(), tray_item_size); + calcuDockIconSize(height(), height()); } else { - calcuDockIconSize(iconSize, height(), tray_item_size); + calcuDockIconSize(iconSize, height()); } } else { if (iconSize >= width()) { - calcuDockIconSize(width(), width(), tray_item_size); + calcuDockIconSize(width(), width()); } else { - calcuDockIconSize(width(), iconSize, tray_item_size); + calcuDockIconSize(width(), iconSize); } } } -void MainPanelControl::calcuDockIconSize(int w, int h, int traySize) +void MainPanelControl::calcuDockIconSize(int w, int h) { int appItemSize = qMin(w, h); - - for (int i = 0; i < m_fixedAreaLayout->count(); ++i) { + for (int i = 0; i < m_fixedAreaLayout->count(); ++i) m_fixedAreaLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize); - } if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { m_fixedSpliter->setFixedSize(SPLITER_SIZE, int(w * 0.6)); m_appSpliter->setFixedSize(SPLITER_SIZE, int(w * 0.6)); - m_traySpliter->setFixedSize(SPLITER_SIZE, int(w * 0.5)); + m_recentSpliter->setFixedSize(SPLITER_SIZE, int(w * 0.6)); } else { m_fixedSpliter->setFixedSize(int(h * 0.6), SPLITER_SIZE); m_appSpliter->setFixedSize(int(h * 0.6), SPLITER_SIZE); - m_traySpliter->setFixedSize(int(h * 0.5), SPLITER_SIZE); + m_recentSpliter->setFixedSize(int(h * 0.6), SPLITER_SIZE); } - for (int i = 0; i < m_appAreaSonLayout->count(); ++i) { - m_appAreaSonLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize); - } + // 时尚模式下判断是否需要显示最近打开的应用区域 + if (m_displayMode == Dock::DisplayMode::Fashion) { + for (int i = 0; i < m_appAreaSonLayout->count(); ++i) + m_appAreaSonLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize); - if (m_tray) { - m_tray->centralWidget()->setProperty("iconSize", traySize); - } + if (m_recentLayout->count() > 0) { + for (int i = 0; i < m_recentLayout->count(); ++i) + m_recentLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize); - //因为日期时间大小和其他插件大小有异,为了设置边距,在各插件中增加了一层布局 - //因此需要通过多一层布局来获取各插件 - if ((m_position == Position::Top) || (m_position == Position::Bottom)) { - // 三方插件 - for (int i = 0; i < m_pluginLayout->count(); ++ i) { - QLayout *layout = m_pluginLayout->itemAt(i)->layout(); - if (layout && layout->itemAt(0)) { - PluginsItem *pItem = static_cast(layout->itemAt(0)->widget()); - if (pItem) { - if (pItem->sizeHint().height() == -1) { - pItem->setFixedSize(traySize, traySize); - } else if (pItem->sizeHint().height() > height()) { - pItem->resize(pItem->width(), height()); - } - } + // 时尚模式下计算最近打开应用区域的尺寸 + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + m_recentAreaWidget->setFixedSize(appItemSize * m_recentLayout->count(), QWIDGETSIZE_MAX); + else + m_recentAreaWidget->setFixedSize(QWIDGETSIZE_MAX, appItemSize * m_recentLayout->count()); + } + + if (m_multiWindowLayout->count() > 0) { + QList multiSizes; + for (int i = 0; i < m_multiWindowLayout->count(); i++) { + // 因为多开窗口的长宽会不一样,因此,需要将当前的尺寸传入 + // 由它自己来计算自己的长宽尺寸 + AppMultiItem *appMultiItem = qobject_cast(m_multiWindowLayout->itemAt(i)->widget()); + if (!appMultiItem) + continue; + + QSize size = appMultiItem->suitableSize(appItemSize); + appMultiItem->setFixedSize(size); + multiSizes << size; + } + // 计算多开窗口的尺寸 + int totalSize = 0; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + for (QSize size : multiSizes) + totalSize += size.width(); + + m_multiWindowWidget->setFixedSize(totalSize, appItemSize); + } else { + for (QSize size : multiSizes) + totalSize += size.height(); + + m_multiWindowWidget->setFixedSize(appItemSize, totalSize); + } + } else { + m_multiWindowWidget->setFixedSize(0, 0); + } + if (m_toolSonLayout->count() > 0) { + for (int i = 0; i < m_toolSonLayout->count(); i++) + m_toolSonLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize); + + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + m_toolSonAreaWidget->setFixedSize(appItemSize * m_toolSonLayout->count(), QWIDGETSIZE_MAX); + } else { + m_toolSonAreaWidget->setFixedSize(QWIDGETSIZE_MAX, appItemSize * m_toolSonLayout->count()); } } + + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + m_toolAreaWidget->setFixedSize(m_multiWindowWidget->width() + m_toolSonAreaWidget->width(), QWIDGETSIZE_MAX); + else + m_toolAreaWidget->setFixedSize(QWIDGETSIZE_MAX, m_multiWindowWidget->height() + m_toolSonAreaWidget->height()); } else { - // 三方插件 - for (int i = 0; i < m_pluginLayout->count(); ++ i) { - QLayout *layout = m_pluginLayout->itemAt(i)->layout(); - if (layout) { - PluginsItem *pItem = static_cast(layout->itemAt(0)->widget()); - if (pItem) { - if (pItem->sizeHint().width() == -1) { - pItem->setFixedSize(traySize, traySize); - } else if (pItem->sizeHint().width() > width()) { - pItem->resize(width(), pItem->height()); - } - } + for (int i = 0; i < m_appAreaSonLayout->count(); ++i) { + DockItem *dockItem = qobject_cast(m_appAreaSonLayout->itemAt(i)->widget()); + if (!dockItem) + continue; + if (dockItem->itemType() == DockItem::ItemType::AppMultiWindow) { + AppMultiItem *appMultiItem = qobject_cast(dockItem); + dockItem->setFixedSize(appMultiItem->suitableSize(appItemSize)); + } else { + dockItem->setFixedSize(appItemSize, appItemSize); } } } @@ -1141,47 +1268,46 @@ void MainPanelControl::calcuDockIconSize(int w, int h, int traySize) int appTopAndBottomMargin = 0; int appLeftAndRightMargin = 0; - int trayTopAndBottomMargin = 0; - int trayLeftAndRightMargin = 0; - if ((m_position == Position::Top) || (m_position == Position::Bottom)) { appTopAndBottomMargin = (m_fixedAreaWidget->height() - appItemSize) / 2; - trayTopAndBottomMargin = (m_trayAreaWidget->height() - traySize) / 2; } else { appLeftAndRightMargin = (m_fixedAreaWidget->width() - appItemSize) / 2; - trayLeftAndRightMargin = (m_trayAreaWidget->width() - traySize) / 2; } m_fixedAreaLayout->setContentsMargins(appLeftAndRightMargin, appTopAndBottomMargin, appLeftAndRightMargin, appTopAndBottomMargin); m_appAreaSonLayout->setContentsMargins(appLeftAndRightMargin, appTopAndBottomMargin, appLeftAndRightMargin, appTopAndBottomMargin); - m_trayAreaLayout->setContentsMargins(trayLeftAndRightMargin, trayTopAndBottomMargin, trayLeftAndRightMargin, trayTopAndBottomMargin); - - //因为日期时间插件或第三方插件声明自定义大小 - //而不对自定义大小插件设置边距 - for (int i = 0; i < m_pluginLayout->count(); ++ i) { - QLayout *layout = m_pluginLayout->itemAt(i)->layout(); - if (layout && layout->itemAt(0)) { - PluginsItem *pItem = static_cast(layout->itemAt(0)->widget()); - - if (pItem && pItem->pluginSizePolicy() != PluginsItemInterface::Custom) { - layout->setContentsMargins(trayLeftAndRightMargin, trayTopAndBottomMargin, trayLeftAndRightMargin, trayTopAndBottomMargin); - } - } - } } -/**时尚模式没有‘显示桌面’区域 - * @brief MainPanelControl::resizeDesktopWidget - */ -void MainPanelControl::resizeDesktopWidget() +void MainPanelControl::onRecentVisibleChanged(bool visible) { - if (m_position == Position::Right || m_position == Position::Left) - m_desktopWidget->setFixedSize(width(), DESKTOP_SIZE); - else - m_desktopWidget->setFixedSize(DESKTOP_SIZE, height()); + m_appSpliter->setVisible(visible); +} - if (DisplayMode::Fashion == m_dislayMode) - m_desktopWidget->setFixedSize(0, 0); +void MainPanelControl::onDockAppVisibleChanged(bool visible) +{ + m_fixedSpliter->setVisible(visible); +} + +void MainPanelControl::onToolVisibleChanged(bool visible) +{ + m_recentSpliter->setVisible(visible); +} + +void MainPanelControl::onTrayRequestUpdate() +{ + m_tray->layoutWidget(); + switch (m_position) { + case Dock::Position::Left: + case Dock::Position::Right: { + m_tray->setFixedSize(QWIDGETSIZE_MAX, m_tray->suitableSize().height()); + break; + } + case Dock::Position::Top: + case Dock::Position::Bottom: { + m_tray->setFixedSize(m_tray->suitableSize().width(), QWIDGETSIZE_MAX); + break; + } + } } /** @@ -1211,31 +1337,3 @@ bool MainPanelControl::appIsOnDock(const QString &appDesktop) { return DockItemManager::instance()->appIsOnDock(appDesktop); } - -void MainPanelControl::setKwinAppItemMinimizedGeometry(DockItem *item, const QRect r) -{ - // 只处理wayland窗口 - if (!Utils::IS_WAYLAND_DISPLAY) { - return; - } - - // 对于wayland应用窗口,需要将窗口的位置传递给窗管,用于设置窗口最小化的位置 - auto w = static_cast(parent()); - const auto ratio = devicePixelRatioF(); - if (item->itemType() == DockItem::App && w->windowHandle() && w->windowHandle()->handle()) { - AppItem * appItem = dynamic_cast(item); - if (!appItem) { - qWarning() << "invalid item"; - return; - } - - QList varList = {0, 0, 0, 0, 0}; - varList[0] = appItem->getAppItemWindowId(); - // 此处传给窗管的坐标需要去掉缩放因子,防止最小化窗口位置错误 - varList[1] = (r.x() - w->geometry().x()) * ratio; - varList[2] = (r.y() - w->geometry().y()) * ratio; - varList[3] = r.width(); - varList[4] = r.height(); - QGuiApplication::platformNativeInterface()->setWindowProperty(w->windowHandle()->handle(), "_d_dwayland_dock-appitem-geometry", varList); - } -} diff --git a/frame/window/mainpanelcontrol.h b/frame/window/mainpanelcontrol.h old mode 100644 new mode 100755 index 85c7357ec..3df071748 --- a/frame/window/mainpanelcontrol.h +++ b/frame/window/mainpanelcontrol.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,70 +7,79 @@ #define MAINPANELCONTROL_H #include "constants.h" +#include "dbusutil.h" #include -#include - using namespace Dock; class QBoxLayout; class QLabel; -class TrayPluginItem; +class DockTrayWindow; class PluginsItem; class DockItem; class PlaceholderItem; class AppDragWidget; class DesktopWidget; +class RecentAppHelper; +class ToolAppHelper; +class MultiWindowHelper; + class MainPanelControl : public QWidget { Q_OBJECT + public: - explicit MainPanelControl(QWidget *parent = nullptr); + explicit MainPanelControl(DockInter *dockInter, QWidget *parent = nullptr); void setPositonValue(Position position); void setDisplayMode(DisplayMode dislayMode); void resizeDockIcon(); - void updatePluginsLayout(); - void setToggleDesktopInterval(int ms); + void updateDockInter(DockInter *dockInter); + + QSize suitableSize(const Position &position, int screenSize, double deviceRatio) const; public slots: void insertItem(const int index, DockItem *item); void removeItem(DockItem *item); void itemUpdated(DockItem *item); - void setKwinAppItemMinimizedGeometry(DockItem *item, const QRect); signals: void itemMoved(DockItem *sourceItem, DockItem *targetItem); void itemAdded(const QString &appDesktop, int idx); + void requestUpdate(); private: void initUI(); + void initConnection(); void updateAppAreaSonWidgetSize(); void updateMainPanelLayout(); void updateDisplayMode(); void moveAppSonWidget(); + void updateModeChange(); void addFixedAreaItem(int index, QWidget *wdg); void removeFixedAreaItem(QWidget *wdg); - void addAppAreaItem(int index, QWidget *wdg); void removeAppAreaItem(QWidget *wdg); - void addTrayAreaItem(int index, QWidget *wdg); - void removeTrayAreaItem(QWidget *wdg); - void addPluginAreaItem(int index, QWidget *wdg); - void removePluginAreaItem(QWidget *wdg); + int getScreenSize() const; + int trayAreaSize(qreal ratio) const; // 拖拽相关 void startDrag(DockItem *); DockItem *dropTargetItem(DockItem *sourceItem, QPoint point); void moveItem(DockItem *sourceItem, DockItem *targetItem); void handleDragMove(QDragMoveEvent *e, bool isFilter); - void calcuDockIconSize(int w, int h, int traySize); - void resizeDesktopWidget(); + void calcuDockIconSize(int w, int h); bool checkNeedShowDesktop(); bool appIsOnDock(const QString &appDesktop); + void dockRecentApp(DockItem *dockItem); + PluginsItem *trash() const; - int getItemIndex(DockItem *targetItem) const; +private Q_SLOTS: + void onRecentVisibleChanged(bool visible); + void onDockAppVisibleChanged(bool visible); + void onToolVisibleChanged(bool visible); + void onTrayRequestUpdate(); protected: void dragMoveEvent(QDragMoveEvent *e) override; @@ -86,29 +96,35 @@ private: QBoxLayout *m_mainPanelLayout; QWidget *m_fixedAreaWidget; // 固定区域 - QBoxLayout *m_fixedAreaLayout; // + QBoxLayout *m_fixedAreaLayout; // 固定区域布局 QLabel *m_fixedSpliter; // 固定区域与应用区域间的分割线 QWidget *m_appAreaWidget; // 应用区域 QWidget *m_appAreaSonWidget; // 子应用区域,所在位置根据显示模式手动指定 - QBoxLayout *m_appAreaSonLayout; // + QBoxLayout *m_appAreaSonLayout; // 子应用区域布局 QLabel *m_appSpliter; // 应用区域与托盘区域间的分割线 - QWidget *m_trayAreaWidget; // 托盘区域 - QBoxLayout *m_trayAreaLayout; // - QLabel *m_traySpliter; // 托盘区域与插件区域间的分割线 - QWidget *m_pluginAreaWidget; // 插件区域 - QBoxLayout *m_pluginLayout; // - DesktopWidget *m_desktopWidget; // 桌面预览区域 + QWidget *m_recentAreaWidget; // 最近打开应用 + QBoxLayout *m_recentLayout; + QLabel *m_recentSpliter; // 最近打开应用区域分割线 + QWidget *m_toolAreaWidget; // 工具区域,用来存放多开窗口和回收站等 + QBoxLayout *m_toolAreaLayout; // 工具区域的布局 + QWidget *m_multiWindowWidget; // 多开窗口区域,用来存放多开窗口 + QBoxLayout *m_multiWindowLayout;// 用来存放多开窗口的布局 + QWidget *m_toolSonAreaWidget; // 工具区域,用来存放回收站等工具 + QBoxLayout *m_toolSonLayout; // 工具区域布局 Position m_position; QPointer m_placeholderItem; QString m_draggingMimeKey; AppDragWidget *m_appDragWidget; - DisplayMode m_dislayMode; + DisplayMode m_displayMode; QPoint m_mousePressPos; - TrayPluginItem *m_tray; - int m_dragIndex = -1; // 记录应用区域被拖拽图标的位置 + DockTrayWindow *m_tray; + int m_dragIndex = -1; // 记录应用区域被拖拽图标的位置 - PluginsItem *m_trashItem; // 垃圾箱插件(需要特殊处理一下) + DockInter *m_dockInter; + RecentAppHelper *m_recentHelper; + ToolAppHelper *m_toolHelper; + MultiWindowHelper *m_multiHelper; }; #endif // MAINPANELCONTROL_H diff --git a/frame/window/mainwindow.cpp b/frame/window/mainwindow.cpp old mode 100644 new mode 100755 index a25ccbe3f..1a51058de --- a/frame/window/mainwindow.cpp +++ b/frame/window/mainwindow.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,6 +7,12 @@ #include "mainpanelcontrol.h" #include "dockitemmanager.h" #include "menuworker.h" +#include "windowmanager.h" +#include "dockscreen.h" +#include "dragwidget.h" +#include "multiscreenworker.h" +#include "constants.h" +#include "displaymanager.h" #include #include @@ -21,358 +28,39 @@ #include #include #include +#include +#include +#include #include #include -#include +#define DOCK_SCREEN DockScreen::instance() +#define DIS_INS DisplayManager::instance() -#define SNI_WATCHER_SERVICE "org.kde.StatusNotifierWatcher" -#define SNI_WATCHER_PATH "/StatusNotifierWatcher" - -#define MAINWINDOW_MAX_SIZE DOCK_MAX_SIZE -#define MAINWINDOW_MIN_SIZE (40) -#define DRAG_AREA_SIZE (5) - -#define DRAG_STATE_PROP "DRAG_STATE" - -using org::kde::StatusNotifierWatcher; - -// let startdde know that we've already started. -void MainWindow::RegisterDdeSession() +MainWindow::MainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent) + : MainWindowBase(multiScreenWorker, parent) + , m_mainPanel(new MainPanelControl(multiScreenWorker->dockInter(), this)) + , m_multiScreenWorker(multiScreenWorker) + , m_needUpdateUi(false) { - QString envName("DDE_SESSION_PROCESS_COOKIE_ID"); - - QByteArray cookie = qgetenv(envName.toUtf8().data()); - qunsetenv(envName.toUtf8().data()); - - if (!cookie.isEmpty()) { - QDBusPendingReply r = DDBusSender() - .interface("com.deepin.SessionManager") - .path("/com/deepin/SessionManager") - .service("com.deepin.SessionManager") - .method("Register") - .arg(QString(cookie)) - .call(); - - qDebug() << Q_FUNC_INFO << r.value(); - } -} - -MainWindow::MainWindow(QWidget *parent) - : DBlurEffectWidget(parent) - , m_mainPanel(new MainPanelControl(this)) - , m_platformWindowHandle(this) - , m_wmHelper(DWindowManagerHelper::instance()) - , m_multiScreenWorker(new MultiScreenWorker(this)) - , m_menuWorker(new MenuWorker(m_multiScreenWorker->dockInter(), this)) - , m_shadowMaskOptimizeTimer(new QTimer(this)) - , m_dbusDaemonInterface(QDBusConnection::sessionBus().interface()) - , m_sniWatcher(new StatusNotifierWatcher(SNI_WATCHER_SERVICE, SNI_WATCHER_PATH, QDBusConnection::sessionBus(), this)) - , m_dragWidget(new DragWidget(this)) - , m_launched(false) - , m_updateDragAreaTimer(new QTimer(this)) - , m_dconfig(DConfig::create("org.deepin.dde.dock", "org.deepin.dde.dock", QString(), this)) -{ - setAttribute(Qt::WA_TranslucentBackground); - setAttribute(Qt::WA_X11DoNotAcceptFocus); - - Qt::WindowFlags flags = Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Window; - //1 确保这两行代码的先后顺序,否则会导致任务栏界面不再置顶 - setWindowFlags(windowFlags() | flags | Qt::WindowDoesNotAcceptFocus); - - if (Utils::IS_WAYLAND_DISPLAY) - setWindowFlag(Qt::FramelessWindowHint, false); // 会导致设置圆角为0时无效 - - if (DGuiApplicationHelper::isXWindowPlatform()) { - const auto display = QX11Info::display(); - if (!display) { - qWarning() << "QX11Info::display() is " << display; - } else { - //2 确保这两行代码的先后顺序,否则会导致任务栏界面不再置顶 - XcbMisc::instance()->set_window_type(xcb_window_t(this->winId()), XcbMisc::Dock); - } - } - - setMouseTracking(true); - setAcceptDrops(true); - - DPlatformWindowHandle::enableDXcbForWindow(this, true); - m_platformWindowHandle.setEnableBlurWindow(true); - m_platformWindowHandle.setTranslucentBackground(true); - m_platformWindowHandle.setShadowOffset(QPoint(0, 5)); - m_platformWindowHandle.setShadowColor(QColor(0, 0, 0, 0.3 * 255)); - m_mainPanel->setDisplayMode(m_multiScreenWorker->displayMode()); - initMember(); - initSNIHost(); - initComponents(); initConnections(); - resetDragWindow(); - for (auto item : DockItemManager::instance()->itemList()) m_mainPanel->insertItem(-1, item); - - m_dragWidget->setMouseTracking(true); - m_dragWidget->setFocusPolicy(Qt::NoFocus); - - if (!Utils::IS_WAYLAND_DISPLAY) { - if ((Top == m_multiScreenWorker->position()) || (Bottom == m_multiScreenWorker->position())) { - m_dragWidget->setCursor(Qt::SizeVerCursor); - } else { - m_dragWidget->setCursor(Qt::SizeHorCursor); - } - } -} - -/** - * @brief MainWindow::launch - * 任务栏初次启动时调用此方法,里面是做了一些初始化操作 - */ -void MainWindow::launch() -{ - if (!qApp->property("CANSHOW").toBool()) - return; - - m_launched = true; - m_multiScreenWorker->initShow(); - m_shadowMaskOptimizeTimer->start(); - QTimer::singleShot(0, this, [ this ] { - bool showDock = true; - if (m_dconfig.data()->isValid()) { - showDock = !m_dconfig.data()->value("alwaysHideDock", false).toBool(); - const int ms = m_dconfig.data()->value("toggleDesktopInterval", 0).toInt(); - m_mainPanel->setToggleDesktopInterval(ms); - } - qApp->setProperty("ALWAYS_HIDE_DOCK", !showDock); - setVisible(showDock); - if (!showDock && m_multiScreenWorker->dockInter()) { - m_multiScreenWorker->dockInter()->setHideMode(KeepHidden); - } - }); -} - -/** - * @brief MainWindow::callShow - * 此方法是被外部进程通过DBus调用的。 - * @note 当任务栏以-r参数启动时,其不会显示界面,需要在外部通过DBus调用此接口之后才会显示界面, - * 这里是以前为了优化任务栏的启动速度做的处理,当任务栏启动时,此时窗管进程可能还未启动完全, - * 部分设置未初始化完等,导致任务栏显示的界面异常,所以留下此接口,被startdde延后调用 - */ -void MainWindow::callShow() -{ - static bool flag = false; - if (flag) { - return; - } - flag = true; - - qApp->setProperty("CANSHOW", true); - - launch(); - - // 预留200ms提供给窗口初始化再通知startdde,不影响启动速度 - QTimer::singleShot(200, this, &MainWindow::RegisterDdeSession); -} - -/** - * @brief MainWindow::relaodPlugins - * 需要重新加载插件时,此接口会被调用,目前是用于任务栏的安全模式退出时调用 - */ -void MainWindow::relaodPlugins() -{ - if (qApp->property("PLUGINSLOADED").toBool()) { - return; - } - - DockItemManager::instance()->startLoadPlugins(); - qApp->setProperty("PLUGINSLOADED", true); -} - -/** - * @brief MainWindow::mousePressEvent - * @param e - * @note 右键显示任务栏的菜单 - */ -void MainWindow::mousePressEvent(QMouseEvent *e) -{ - e->ignore(); - if (e->button() == Qt::RightButton) { - QTimer::singleShot(10, this, [this]{ - QMenu *menu = new QMenu(this); - m_menuWorker->showDockSettingsMenu(menu); - }); - return; - } - - if (Utils::IS_WAYLAND_DISPLAY && m_multiScreenWorker->launcherVisible()) { - m_multiScreenWorker->setLauncherVisble(false); - } -} - -void MainWindow::keyPressEvent(QKeyEvent *e) -{ - switch (e->key()) { -#ifdef QT_DEBUG - case Qt::Key_Escape: qApp->quit(); break; -#endif - default:; - } -} - -void MainWindow::enterEvent(QEvent *e) -{ - QWidget::enterEvent(e); - - if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != Qt::ArrowCursor) - QApplication::restoreOverrideCursor(); -} - -void MainWindow::mouseMoveEvent(QMouseEvent *e) -{ - Q_UNUSED(e); - //重写mouseMoveEvent 解决bug12866 leaveEvent事件失效 -} - -void MainWindow::moveEvent(QMoveEvent *event) -{ - Q_UNUSED(event); - - if (!qApp->property(DRAG_STATE_PROP).toBool()) - m_updateDragAreaTimer->start(); -} - -void MainWindow::resizeEvent(QResizeEvent *event) -{ - if (!qApp->property(DRAG_STATE_PROP).toBool()) - m_updateDragAreaTimer->start(); - - // 任务栏大小、位置、模式改变都会触发resize,发射大小改变信号,供依赖项目更新位置 - Q_EMIT panelGeometryChanged(); - - m_mainPanel->updatePluginsLayout(); - m_shadowMaskOptimizeTimer->start(); - - return DBlurEffectWidget::resizeEvent(event); -} - -void MainWindow::dragEnterEvent(QDragEnterEvent *e) -{ - QWidget::dragEnterEvent(e); -} - -void MainWindow::initMember() -{ - //INFO 这里要大于动画的300ms,否则可能动画过程中这个定时器就被触发了 - m_updateDragAreaTimer->setInterval(500); - m_updateDragAreaTimer->setSingleShot(true); -} - -/** - * @brief MainWindow::initSNIHost - * @note 将Dock注册到StatusNotifierWatcher服务上 - */ -void MainWindow::initSNIHost() -{ - // registor dock as SNI Host on dbus - QDBusConnection dbusConn = QDBusConnection::sessionBus(); - m_sniHostService = QString("org.kde.StatusNotifierHost-") + QString::number(qApp->applicationPid()); - dbusConn.registerService(m_sniHostService); - dbusConn.registerObject("/StatusNotifierHost", this); - - if (m_sniWatcher->isValid()) { - m_sniWatcher->RegisterStatusNotifierHost(m_sniHostService); - } else { - qDebug() << SNI_WATCHER_SERVICE << "SNI watcher daemon is not exist for now!"; - } -} - -void MainWindow::initComponents() -{ - m_shadowMaskOptimizeTimer->setSingleShot(true); - m_shadowMaskOptimizeTimer->setInterval(100); - - QTimer::singleShot(1, this, &MainWindow::compositeChanged); - - themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); - - if (m_dconfig.data()->isValid()) { - connect(m_dconfig.data(), &DConfig::valueChanged, this, [this] (const QString &key) { - if (key == "alwaysHideDock") { - const bool showDock = !m_dconfig.data()->value(key, false).toBool(); - qApp->setProperty("ALWAYS_HIDE_DOCK", !showDock); - setVisible(showDock); - if (!showDock && m_multiScreenWorker->dockInter()) { - m_multiScreenWorker->dockInter()->setHideMode(KeepHidden); - } - } else if ("toggleDesktopInterval") { - const int ms = m_dconfig.data()->value(key, 0).toInt(); - m_mainPanel->setToggleDesktopInterval(ms); - } - }); - } -} - -void MainWindow::compositeChanged() -{ - const bool composite = m_wmHelper->hasComposite(); - setComposite(composite); - - m_shadowMaskOptimizeTimer->start(); } void MainWindow::initConnections() { - connect(m_shadowMaskOptimizeTimer, &QTimer::timeout, this, &MainWindow::adjustShadowMask, Qt::QueuedConnection); - - connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); - connect(&m_platformWindowHandle, &DPlatformWindowHandle::frameMarginsChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); - connect(&m_platformWindowHandle, &DPlatformWindowHandle::windowRadiusChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); - - connect(m_dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, &MainWindow::onDbusNameOwnerChanged); - connect(DockItemManager::instance(), &DockItemManager::itemInserted, m_mainPanel, &MainPanelControl::insertItem, Qt::DirectConnection); connect(DockItemManager::instance(), &DockItemManager::itemRemoved, m_mainPanel, &MainPanelControl::removeItem, Qt::DirectConnection); connect(DockItemManager::instance(), &DockItemManager::itemUpdated, m_mainPanel, &MainPanelControl::itemUpdated, Qt::DirectConnection); - connect(DockItemManager::instance(), &DockItemManager::requestUpdateItemMinimizedGeometry, m_mainPanel, &MainPanelControl::setKwinAppItemMinimizedGeometry); connect(DockItemManager::instance(), &DockItemManager::trayVisableCountChanged, this, &MainWindow::resizeDockIcon, Qt::QueuedConnection); - connect(DockItemManager::instance(), &DockItemManager::requestWindowAutoHide, m_menuWorker, &MenuWorker::setAutoHide); connect(m_mainPanel, &MainPanelControl::itemMoved, DockItemManager::instance(), &DockItemManager::itemMoved, Qt::DirectConnection); connect(m_mainPanel, &MainPanelControl::itemAdded, DockItemManager::instance(), &DockItemManager::itemAdded, Qt::DirectConnection); - - // -拖拽任务栏改变高度或宽度------------------------------------------------------------------------------- - connect(m_updateDragAreaTimer, &QTimer::timeout, this, &MainWindow::resetDragWindow); - //TODO 后面考虑删除这块,目前还不能删除,调整任务栏高度的时候,任务栏外部区域有变化 - connect(m_updateDragAreaTimer, &QTimer::timeout, m_multiScreenWorker, &MultiScreenWorker::onRequestUpdateRegionMonitor); - - connect(m_dragWidget, &DragWidget::dragPointOffset, this, [ = ] { qApp->setProperty(DRAG_STATE_PROP, true); }); - connect(m_dragWidget, &DragWidget::dragFinished, this, [ = ] { - qApp->setProperty(DRAG_STATE_PROP, false); - m_updateDragAreaTimer->start(); - }); - - connect(m_dragWidget, &DragWidget::dragPointOffset, this, &MainWindow::onMainWindowSizeChanged); - connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindow::resetDragWindow); // 更新拖拽区域 - // ---------------------------------------------------------------------------------------------------- - - connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindow::themeTypeChanged); - - connect(m_menuWorker, &MenuWorker::autoHideChanged, m_multiScreenWorker, &MultiScreenWorker::onAutoHideChanged); - - connect(m_multiScreenWorker, &MultiScreenWorker::opacityChanged, this, &MainWindow::setMaskAlpha, Qt::QueuedConnection); - connect(m_multiScreenWorker, &MultiScreenWorker::displayModeChanegd, this, &MainWindow::adjustShadowMask, Qt::QueuedConnection); - - connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateDockEntry, DockItemManager::instance(), &DockItemManager::requestUpdateDockItem); - - // 响应后端触控屏拖拽任务栏高度长按信号 - connect(TouchSignalManager::instance(), &TouchSignalManager::middleTouchPress, this, &MainWindow::touchRequestResizeDock); - connect(TouchSignalManager::instance(), &TouchSignalManager::touchMove, m_dragWidget, &DragWidget::onTouchMove); - - connect(m_multiScreenWorker, &MultiScreenWorker::notifyDaemonInterfaceUpdate, m_menuWorker, [this]() { - m_menuWorker->onNotifyDaemonInterfaceUpdate(m_multiScreenWorker->dockInter()); - }); + connect(m_mainPanel, &MainPanelControl::requestUpdate, this, &MainWindow::requestUpdate); } /** @@ -384,317 +72,93 @@ void MainWindow::resizeDockIcon() m_mainPanel->resizeDockIcon(); } -/** - * @brief MainWindow::adjustShadowMask 更新任务栏的圆角大小(时尚模式下才有圆角效果) - */ -void MainWindow::adjustShadowMask() -{ - if (!m_launched || m_shadowMaskOptimizeTimer->isActive()) - return; - - DStyleHelper dstyle(style()); - int radius = 0; - if (m_wmHelper->hasComposite() && m_multiScreenWorker->displayMode() == DisplayMode::Fashion) { - if (Dtk::Core::DSysInfo::isCommunityEdition()) { // 社区版圆角与专业版不同 - DPlatformTheme *theme = DGuiApplicationHelper::instance()->systemTheme(); - radius = theme->windowRadius(radius); - } else { - radius = dstyle.pixelMetric(DStyle::PM_TopLevelWindowRadius); - } - } - - m_platformWindowHandle.setWindowRadius(radius); - m_mainPanel->updatePluginsLayout(); -} - -void MainWindow::onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) -{ - Q_UNUSED(oldOwner); - - if (name == SNI_WATCHER_SERVICE && !newOwner.isEmpty()) { - qDebug() << SNI_WATCHER_SERVICE << "SNI watcher daemon started, register dock to watcher as SNI Host"; - m_sniWatcher->RegisterStatusNotifierHost(m_sniHostService); - } -} - -/** - * @brief MainWindow::setEffectEnabled - * @param enabled 根据当前系统是否enabled特效来更新任务栏的外观样式 - */ -void MainWindow::setEffectEnabled(const bool enabled) -{ - setMaskColor(AutoColor); - - setMaskAlpha(m_multiScreenWorker->opacity()); - - m_platformWindowHandle.setBorderWidth(enabled ? 1 : 0); -} - -/** - * @brief MainWindow::setComposite - * @param hasComposite 系统是否支持混成(也就是特效) - */ -void MainWindow::setComposite(const bool hasComposite) -{ - setEffectEnabled(hasComposite); -} - -/** - * @brief MainWindow::resetDragWindow 更新任务栏的拖拽区域 - * @note 任务栏远离屏幕的一边是支持拖拽的,由一个不可见的widget提拽支持,当任务栏的geometry发生变化的时候,此拖拽区域也需要更新其自身的geometry - */ -void MainWindow::resetDragWindow() -{ - switch (m_multiScreenWorker->position()) { - case Dock::Top: - m_dragWidget->setGeometry(0, height() - DRAG_AREA_SIZE, width(), DRAG_AREA_SIZE); - break; - case Dock::Bottom: - m_dragWidget->setGeometry(0, 0, width(), DRAG_AREA_SIZE); - break; - case Dock::Left: - m_dragWidget->setGeometry(width() - DRAG_AREA_SIZE, 0, DRAG_AREA_SIZE, height()); - break; - case Dock::Right: - m_dragWidget->setGeometry(0, 0, DRAG_AREA_SIZE, height()); - break; - } - - QRect rect = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen() - , m_multiScreenWorker->position() - , HideMode::KeepShowing - , m_multiScreenWorker->displayMode()); - - // 这个时候屏幕有可能是隐藏的,不能直接使用this->width()这种去设置任务栏的高度,而应该保证原值 - int dockSize = 0; - if (m_multiScreenWorker->position() == Position::Left - || m_multiScreenWorker->position() == Position::Right) { - dockSize = this->width() == 0 ? rect.width() : this->width(); - } else { - dockSize = this->height() == 0 ? rect.height() : this->height(); - } - - /** FIX ME - * 作用:限制dockSize的值在40~100之间。 - * 问题1:如果dockSize为39,会导致dock的mainwindow高度变成99,显示的内容高度却是39。 - * 问题2:dockSize的值在这里不应该为39,但在高分屏上开启缩放后,拉高任务栏操作会概率出现。 - * 暂时未分析出原因,后面再修改。 - */ - dockSize = qBound(MAINWINDOW_MIN_SIZE, dockSize, MAINWINDOW_MAX_SIZE); - - // 通知窗管和后端更新数据 - m_multiScreenWorker->updateDaemonDockSize(dockSize); // 1.先更新任务栏高度 - m_multiScreenWorker->requestUpdateFrontendGeometry(); // 2.再更新任务栏位置,保证先1再2 - m_multiScreenWorker->requestNotifyWindowManager(); - m_multiScreenWorker->requestUpdateRegionMonitor(); // 界面发生变化,应更新监控区域 - DockItem::setDockSize(dockSize); // 更新预览界面2D模式时大小 - - if ((Top == m_multiScreenWorker->position()) || (Bottom == m_multiScreenWorker->position())) { - m_dragWidget->setCursor(Qt::SizeVerCursor); - } else { - m_dragWidget->setCursor(Qt::SizeHorCursor); - } -} - -void MainWindow::resizeDock(int offset, bool dragging) -{ - qApp->setProperty(DRAG_STATE_PROP, dragging); - - // 以任务栏的最小高度区域为参照,通过offset设置其高度或宽度 - const QRect &rect = m_multiScreenWorker->getDockShowMinGeometry(m_multiScreenWorker->deskScreen()); - QRect newRect; - switch (m_multiScreenWorker->position()) { - case Top: { - newRect.setX(rect.x()); - newRect.setY(rect.y()); - newRect.setWidth(rect.width()); - newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); - } - break; - case Bottom: { - newRect.setX(rect.x()); - newRect.setY(rect.y() + rect.height() - qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); - newRect.setWidth(rect.width()); - newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); - } - break; - case Left: { - newRect.setX(rect.x()); - newRect.setY(rect.y()); - newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); - newRect.setHeight(rect.height()); - } - break; - case Right: { - newRect.setX(rect.x() + rect.width() - qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); - newRect.setY(rect.y()); - newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, offset, MAINWINDOW_MAX_SIZE)); - newRect.setHeight(rect.height()); - } - break; - } - - // 更新界面大小 - m_mainPanel->setFixedSize(newRect.size()); - setFixedSize(newRect.size()); - move(newRect.topLeft()); - - if (!dragging) - resetDragWindow(); -} - -/** - * @brief MainWindow::onMainWindowSizeChanged 任务栏拖拽过程中会不听调用此方法更新自身大小 - * @param offset 拖拽时的坐标偏移量 - */ -void MainWindow::onMainWindowSizeChanged(QPoint offset) -{ - const QRect &rect = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen() - , m_multiScreenWorker->position() - , HideMode::KeepShowing, - m_multiScreenWorker->displayMode()); - QRect newRect; - switch (m_multiScreenWorker->position()) { - case Top: { - newRect.setX(rect.x()); - newRect.setY(rect.y()); - newRect.setWidth(rect.width()); - newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, rect.height() + offset.y(), MAINWINDOW_MAX_SIZE)); - } - break; - case Bottom: { - newRect.setX(rect.x()); - newRect.setY(rect.y() + rect.height() - qBound(MAINWINDOW_MIN_SIZE, rect.height() - offset.y(), MAINWINDOW_MAX_SIZE)); - newRect.setWidth(rect.width()); - newRect.setHeight(qBound(MAINWINDOW_MIN_SIZE, rect.height() - offset.y(), MAINWINDOW_MAX_SIZE)); - } - break; - case Left: { - newRect.setX(rect.x()); - newRect.setY(rect.y()); - newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, rect.width() + offset.x(), MAINWINDOW_MAX_SIZE)); - newRect.setHeight(rect.height()); - } - break; - case Right: { - newRect.setX(rect.x() + rect.width() - qBound(MAINWINDOW_MIN_SIZE, rect.width() - offset.x(), MAINWINDOW_MAX_SIZE)); - newRect.setY(rect.y()); - newRect.setWidth(qBound(MAINWINDOW_MIN_SIZE, rect.width() - offset.x(), MAINWINDOW_MAX_SIZE)); - newRect.setHeight(rect.height()); - } - break; - } - - // 更新界面大小 - m_mainPanel->setFixedSize(newRect.size()); - setFixedSize(newRect.size()); - move(newRect.topLeft()); -} - -/** - * @brief MainWindow::themeTypeChanged 系统主题发生变化时,此方法被调用 - * @param themeType 当前系统主题 - */ -void MainWindow::themeTypeChanged(DGuiApplicationHelper::ColorType themeType) -{ - if (m_wmHelper->hasComposite()) { - if (themeType == DGuiApplicationHelper::DarkType) - m_platformWindowHandle.setBorderColor(QColor(0, 0, 0, 255 * 0.3)); - else - m_platformWindowHandle.setBorderColor(QColor(QColor::Invalid)); - } -} - -/** - * @brief MainWindow::touchRequestResizeDock 触屏情况用手指调整任务栏高度或宽度 - */ -void MainWindow::touchRequestResizeDock() -{ - const QPoint touchPos(QCursor::pos()); - QRect dockRect = m_multiScreenWorker->dockRect(m_multiScreenWorker->deskScreen() - , m_multiScreenWorker->position() - , HideMode::KeepShowing - , m_multiScreenWorker->displayMode()); - - // 隐藏状态返回 - if (width() == 0 || height() == 0) { - return; - } - - int resizeHeight = Utils::SettingValue("com.deepin.dde.dock.touch", QByteArray(), "resizeHeight", 7).toInt(); - - QRect touchRect; - // 任务栏屏幕 内侧边线 内外resizeHeight距离矩形区域内长按可拖动任务栏高度 - switch (m_multiScreenWorker->position()) { - case Position::Top: - touchRect = QRect(dockRect.x(), dockRect.y() + dockRect.height() - resizeHeight, dockRect.width(), resizeHeight * 2); - break; - case Position::Bottom: - touchRect = QRect(dockRect.x(), dockRect.y() - resizeHeight, dockRect.width(), resizeHeight * 2); - break; - case Position::Left: - touchRect = QRect(dockRect.x() + dockRect.width() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height()); - break; - case Position::Right: - touchRect = QRect(dockRect.x() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height()); - break; - } - - if (!touchRect.contains(touchPos)) { - return; - } - qApp->postEvent(m_dragWidget, new QMouseEvent(QEvent::MouseButtonPress, m_dragWidget->mapFromGlobal(touchPos) - , QPoint(), touchPos, Qt::LeftButton, Qt::NoButton - , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication)); -} - /** * @brief MainWindow::setGeometry * @param rect 设置任务栏的位置和大小,重写此函数时为了及时发出panelGeometryChanged信号,最终供外部DBus调用方使用 */ void MainWindow::setGeometry(const QRect &rect) { - if (rect == this->geometry()) { + if (rect == this->geometry()) return; - } + DBlurEffectWidget::setGeometry(rect); - emit panelGeometryChanged(); } -/** - * @brief 当进入安全模式时,通过此方法发送通知告知用户 - */ -void MainWindow::sendNotifications() +MainWindowBase::DockWindowType MainWindow::windowType() const { - QStringList actionButton; - actionButton << "reload" << tr("Exit Safe Mode"); - QVariantMap hints; - hints["x-deepin-action-reload"] = QString("dbus-send,--session,--dest=com.deepin.dde.Dock,--print-reply,/com/deepin/dde/Dock,com.deepin.dde.Dock.ReloadPlugins"); - // 在进入安全模式时,执行此DBUS耗时25S左右,导致任务栏显示阻塞,所以使用线程调用 - QtConcurrent::run(QThreadPool::globalInstance(), [=] { - DDBusSender() - .service("com.deepin.dde.Notification") - .path("/com/deepin/dde/Notification") - .interface("com.deepin.dde.Notification") - .method(QString("Notify")) - .arg(QString("dde-control-center")) // appname - .arg(static_cast(0)) // id - .arg(QString("preferences-system")) // icon - .arg(QString(tr("Dock - Safe Mode"))) // summary - .arg(QString(tr("The Dock is in safe mode, please exit to show it properly"))) // content - .arg(actionButton) // actions - .arg(hints) // hints - .arg(15000) // timeout - .call(); - }); + return DockWindowType::MainWindow; } -void MainWindow::setVisible(bool visible) +void MainWindow::setPosition(const Position &position) { - // 设置了始终隐藏的情况下,任务栏将永远不显示 - if (visible && qApp->property("ALWAYS_HIDE_DOCK").toBool()) { - return; + MainWindowBase::setPosition(position); + m_mainPanel->setPositonValue(position); + + // 更新鼠标拖拽样式,在类内部设置到qApp单例上去 + if ((Top == position) || (Bottom == position)) + m_mainPanel->setCursor(Qt::SizeVerCursor); + else + m_mainPanel->setCursor(Qt::SizeHorCursor); +} + +void MainWindow::setDisplayMode(const Dock::DisplayMode &displayMode) +{ + m_mainPanel->setDisplayMode(displayMode); + MainWindowBase::setDisplayMode(displayMode); +} + +void MainWindow::updateParentGeometry(const Position &pos, const QRect &rect) +{ + setFixedSize(rect.size()); + setGeometry(rect); + + int panelSize = windowSize(); + QRect panelRect = rect; + switch (pos) { + case Position::Top: + m_mainPanel->move(0, rect.height() - panelSize); + panelRect.setHeight(panelSize); + break; + case Position::Left: + m_mainPanel->move(width() - panelSize, 0); + panelRect.setWidth(panelSize); + break; + case Position::Bottom: + m_mainPanel->move(0, 0); + panelRect.setHeight(panelSize); + break; + case Position::Right: + m_mainPanel->move(0, 0); + panelRect.setWidth(panelSize); + break; + } + m_mainPanel->setFixedSize(panelRect.size()); +} + +QSize MainWindow::suitableSize(const Position &pos, const int &screenSize, const double &deviceRatio) const +{ + return m_mainPanel->suitableSize(pos, screenSize, deviceRatio); +} + +void MainWindow::resetPanelGeometry() +{ + m_mainPanel->setFixedSize(size()); + m_mainPanel->move(0, 0); +} + +void MainWindow::serviceRestart() +{ + m_mainPanel->updateDockInter(m_multiScreenWorker->dockInter()); + // 在重启服务后,MultiScreenWorker会通知WindowManager类执行PositionChanged动画,在执行此动作过程中 + // 会执行动画,动画需要消耗时间,因此, 在重启服务后,需要标记更新UI,在稍后动画执行结束后,需要重新刷新界面的显示,否则任务栏显示错误 + m_needUpdateUi = true; +} + +void MainWindow::animationFinished(bool showOrHide) +{ + if (m_needUpdateUi) { + // 在动画执行结束后,如果收到需要更新UI的标记,那么则需要重新请求更新界面,在更新结束后,再将更新UI标记为false,那么在下次进来的时候,无需再次更新UI + Q_EMIT requestUpdate(); + m_needUpdateUi = false; } - - return DBlurEffectWidget::setVisible(visible); } diff --git a/frame/window/mainwindow.h b/frame/window/mainwindow.h index 3d399dce4..62692574d 100644 --- a/frame/window/mainwindow.h +++ b/frame/window/mainwindow.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,212 +7,58 @@ #define MAINWINDOW_H #include "xcb_misc.h" -#include "statusnotifierwatcher_interface.h" -#include "mainpanelcontrol.h" #include "multiscreenworker.h" #include "touchsignalmanager.h" #include "imageutil.h" #include "utils.h" +#include "mainwindowbase.h" #include -#include -#include -#include -#include #include DWIDGET_USE_NAMESPACE -DCORE_USE_NAMESPACE class MainPanelControl; class QTimer; class MenuWorker; -class DragWidget : public QWidget +class QScreen; + +class MainWindow : public MainWindowBase { Q_OBJECT -private: - bool m_dragStatus; - QPoint m_resizePoint; - public: - explicit DragWidget(QWidget *parent = nullptr) - : QWidget(parent) - { - setObjectName("DragWidget"); - m_dragStatus = false; - } + explicit MainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent = nullptr); + void setGeometry(const QRect &rect); -public slots: - void onTouchMove(double scaleX, double scaleY) - { - Q_UNUSED(scaleX); - Q_UNUSED(scaleY); - - static QPoint lastPos; - QPoint curPos = QCursor::pos(); - if (lastPos == curPos) { - return; - } - lastPos = curPos; - qApp->postEvent(this, new QMouseEvent(QEvent::MouseMove, mapFromGlobal(curPos) - , QPoint(), curPos, Qt::LeftButton, Qt::LeftButton - , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication)); - } - -signals: - void dragPointOffset(QPoint); - void dragFinished(); - -private: - void mousePressEvent(QMouseEvent *event) override - { - // qt转发的触屏按下信号不进行响应 - if (event->source() == Qt::MouseEventSynthesizedByQt) { - return; - } - if (event->button() == Qt::LeftButton) { - m_resizePoint = event->globalPos(); - m_dragStatus = true; - this->grabMouse(); - } - } - - void mouseMoveEvent(QMouseEvent *) override - { - if (m_dragStatus) { - QPoint offset = QPoint(QCursor::pos() - m_resizePoint); - emit dragPointOffset(offset); - } - } - - void mouseReleaseEvent(QMouseEvent *) override - { - if (!m_dragStatus) - return; - - m_dragStatus = false; - releaseMouse(); - emit dragFinished(); - } - - void enterEvent(QEvent *) override - { - if (Utils::IS_WAYLAND_DISPLAY) - updateCursor(); - - QApplication::setOverrideCursor(cursor()); - } - - void leaveEvent(QEvent *) override - { - QApplication::setOverrideCursor(Qt::ArrowCursor); - } - - void updateCursor() - { - QString theme = Utils::SettingValue("com.deepin.xsettings", "/com/deepin/xsettings/", "gtk-cursor-theme-name", "bloom").toString(); - int cursorSize = Utils::SettingValue("com.deepin.xsettings", "/com/deepin/xsettings/", "gtk-cursor-theme-size", 24).toInt(); - Position position = static_cast(qApp->property("position").toInt()); - - static QString lastTheme; - static int lastPosition = -1; - static int lastCursorSize = -1; - if (theme != lastTheme || position != lastPosition || cursorSize != lastCursorSize) { - lastTheme = theme; - lastPosition = position; - lastCursorSize = cursorSize; - const char* cursorName = (position == Bottom || position == Top) ? "v_double_arrow" : "h_double_arrow"; - QCursor *newCursor = ImageUtil::loadQCursorFromX11Cursor(theme.toStdString().c_str(), cursorName, cursorSize); - if (!newCursor) - return; - - setCursor(*newCursor); - static QCursor *lastCursor = nullptr; - if (lastCursor) - delete lastCursor; - - lastCursor = newCursor; - } - } -}; - -class MainWindow : public DBlurEffectWidget -{ - Q_OBJECT friend class MainPanelControl; -public: - explicit MainWindow(QWidget *parent = nullptr); - - void setEffectEnabled(const bool enabled); - void setComposite(const bool hasComposite); - void setGeometry(const QRect &rect); - void sendNotifications(); - - void setVisible(bool visible) override; - - MainPanelControl *panel() {return m_mainPanel;} - -public slots: - void launch(); - void callShow(); - void relaodPlugins(); + // 以下接口是实现基类的接口 + // 用来更新子区域的位置,一般用于在执行动画的过程中,根据当前的位置来更新里面panel的大小 + DockWindowType windowType() const override; + void setPosition(const Dock::Position &position) override; + void setDisplayMode(const Dock::DisplayMode &displayMode) override; + void updateParentGeometry(const Dock::Position &pos, const QRect &rect) override; + QSize suitableSize(const Dock::Position &pos, const int &screenSize, const double &deviceRatio) const override; + void resetPanelGeometry() override; + void serviceRestart() override; + void animationFinished(bool showOrHide) override; private: using QWidget::show; - void mousePressEvent(QMouseEvent *e) override; - void keyPressEvent(QKeyEvent *e) override; - void enterEvent(QEvent *e) override; - void dragEnterEvent(QDragEnterEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void moveEvent(QMoveEvent *event) override; - void resizeEvent(QResizeEvent *event) override; - - void initMember(); - void initSNIHost(); - void initComponents(); void initConnections(); - void resizeDockIcon(); -signals: - void panelGeometryChanged(); - -public slots: - void RegisterDdeSession(); - void resizeDock(int offset, bool dragging); - void resetDragWindow(); // 任务栏调整高度或宽度后需调用此函数 - -private slots: - void compositeChanged(); - void adjustShadowMask(); - - void onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); - void onMainWindowSizeChanged(QPoint offset); - void themeTypeChanged(DGuiApplicationHelper::ColorType themeType); - void touchRequestResizeDock(); - private: MainPanelControl *m_mainPanel; // 任务栏 - DPlatformWindowHandle m_platformWindowHandle; - DWindowManagerHelper *m_wmHelper; MultiScreenWorker *m_multiScreenWorker; // 多屏幕管理 - MenuWorker *m_menuWorker; - QTimer *m_shadowMaskOptimizeTimer; - QDBusConnectionInterface *m_dbusDaemonInterface; - org::kde::StatusNotifierWatcher *m_sniWatcher; // DBUS状态通知 - DragWidget *m_dragWidget; QString m_sniHostService; - bool m_launched; QString m_registerKey; QStringList m_registerKeys; - - QTimer *m_updateDragAreaTimer; - QSharedPointer m_dconfig; + bool m_needUpdateUi; }; #endif // MAINWINDOW_H diff --git a/frame/window/mainwindowbase.cpp b/frame/window/mainwindowbase.cpp new file mode 100644 index 000000000..050d1f7c0 --- /dev/null +++ b/frame/window/mainwindowbase.cpp @@ -0,0 +1,636 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "mainwindowbase.h" +#include "dragwidget.h" +#include "multiscreenworker.h" +#include "dockscreen.h" +#include "touchsignalmanager.h" +#include "displaymanager.h" +#include "menuworker.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DRAG_AREA_SIZE (5) + +// 任务栏圆角最小的时候,任务栏的高度值 +#define MIN_RADIUS_WINDOWSIZE 46 +// 任务栏圆角最小值和最大值的差值 +#define MAX_MIN_RADIUS_DIFFVALUE 6 +// 最小圆角值 +#define MIN_RADIUS 12 + +#define DOCK_SCREEN DockScreen::instance() +#define DIS_INS DisplayManager::instance() + +DGUI_USE_NAMESPACE + +MainWindowBase::MainWindowBase(MultiScreenWorker *multiScreenWorker, QWidget *parent) + : DBlurEffectWidget(parent) + , m_displayMode(Dock::DisplayMode::Efficient) + , m_position(Dock::Position::Bottom) + , m_dragWidget(new DragWidget(this)) + , m_multiScreenWorker(multiScreenWorker) + , m_updateDragAreaTimer(new QTimer(this)) + , m_platformWindowHandle(this) + , m_shadowMaskOptimizeTimer(new QTimer(this)) + , m_isShow(false) + , m_borderRadius(0) + , m_order(0) +{ + initUi(); + initAttribute(); + initConnection(); + initMember(); +} + +MainWindowBase::~MainWindowBase() +{ +} + +void MainWindowBase::setOrder(int order) +{ + m_order = order; +} + +int MainWindowBase::order() const +{ + return m_order; +} + +void MainWindowBase::initAttribute() +{ + setAttribute(Qt::WA_TranslucentBackground); + setAttribute(Qt::WA_X11DoNotAcceptFocus); + + Qt::WindowFlags flags = Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Window; + //1 确保这两行代码的先后顺序,否则会导致任务栏界面不再置顶 + setWindowFlags(windowFlags() | flags | Qt::WindowDoesNotAcceptFocus); + + if (Utils::IS_WAYLAND_DISPLAY) { + setWindowFlag(Qt::FramelessWindowHint, false); // 会导致设置圆角为0时无效 + setAttribute(Qt::WA_NativeWindow); + windowHandle()->setProperty("_d_dwayland_window-type", "dock"); + } + + if (DGuiApplicationHelper::isXWindowPlatform()) { + const auto display = QX11Info::display(); + if (!display) { + qWarning() << "QX11Info::display() is " << display; + } else { + //2 确保这两行代码的先后顺序,否则会导致任务栏界面不再置顶 + XcbMisc::instance()->set_window_type(xcb_window_t(this->winId()), XcbMisc::Dock); + } + } + + setMouseTracking(true); + setAcceptDrops(true); + + m_dragWidget->setMouseTracking(true); + m_dragWidget->setFocusPolicy(Qt::NoFocus); + + if ((Dock::Top == m_position) || (Dock::Bottom == m_position)) + m_dragWidget->setCursor(Qt::SizeVerCursor); + else + m_dragWidget->setCursor(Qt::SizeHorCursor); +} + +void MainWindowBase::initConnection() +{ + connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasCompositeChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); + connect(m_shadowMaskOptimizeTimer, &QTimer::timeout, this, &MainWindowBase::adjustShadowMask, Qt::QueuedConnection); + + connect(&m_platformWindowHandle, &DPlatformWindowHandle::frameMarginsChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); + connect(&m_platformWindowHandle, &DPlatformWindowHandle::windowRadiusChanged, m_shadowMaskOptimizeTimer, static_cast(&QTimer::start)); + + connect(m_dragWidget, &DragWidget::dragFinished, this, [ = ] { + Utils::setIsDraging(false); + }); + + // -拖拽任务栏改变高度或宽度------------------------------------------------------------------------------- + connect(m_updateDragAreaTimer, &QTimer::timeout, this, &MainWindowBase::resetDragWindow); + //TODO 后端考虑删除这块,目前还不能删除,调整任务栏高度的时候,任务栏外部区域有变化 + connect(m_updateDragAreaTimer, &QTimer::timeout, m_multiScreenWorker, &MultiScreenWorker::onRequestUpdateRegionMonitor); + + connect(m_dragWidget, &DragWidget::dragPointOffset, this, &MainWindowBase::onMainWindowSizeChanged); + connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindowBase::resetDragWindow); // 更新拖拽区域 + connect(TouchSignalManager::instance(), &TouchSignalManager::touchMove, m_dragWidget, &DragWidget::onTouchMove); + connect(TouchSignalManager::instance(), &TouchSignalManager::middleTouchPress, this, &MainWindowBase::touchRequestResizeDock); + + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindowBase::onThemeTypeChanged); + connect(m_multiScreenWorker, &MultiScreenWorker::opacityChanged, this, &MainWindowBase::setMaskAlpha, Qt::QueuedConnection); + + onThemeTypeChanged(DGuiApplicationHelper::instance()->themeType()); + QMetaObject::invokeMethod(this, &MainWindowBase::onCompositeChanged); +} + +void MainWindowBase::initMember() +{ + //INFO 这里要大于动画的300ms,否则可能动画过程中这个定时器就被触发了 + m_updateDragAreaTimer->setInterval(500); + m_updateDragAreaTimer->setSingleShot(true); + m_shadowMaskOptimizeTimer->setSingleShot(true); + m_shadowMaskOptimizeTimer->setInterval(100); +} + +int MainWindowBase::getBorderRadius() const +{ + if (!DWindowManagerHelper::instance()->hasComposite() || m_multiScreenWorker->displayMode() != DisplayMode::Fashion) + return 0; + + if (Dtk::Core::DSysInfo::isCommunityEdition()) { // 社区版圆角与专业版不同 + DPlatformTheme *theme = DGuiApplicationHelper::instance()->systemTheme(); + return theme->windowRadius(0); + } + + int size = ((m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) ? height() : width()); + return qMin(MAX_MIN_RADIUS_DIFFVALUE, qMax(size - MIN_RADIUS_WINDOWSIZE, 0)) + MIN_RADIUS; +} + +QRect MainWindowBase::getAnimationRect(const QRect &sourceRect, const Dock::Position &pos) const +{ + if (!Utils::IS_WAYLAND_DISPLAY + || m_multiScreenWorker->hideMode() == HideMode::KeepShowing + || m_multiScreenWorker->displayMode() == Dock::DisplayMode::Fashion) + return sourceRect; + + // 在wayland环境下,如果任务栏状态为智能隐藏或者一直隐藏,那么在高效模式下,任务栏距离边缘的距离如果为0 + // 会导致在WindowManager类中设置窗管的_d_dwayland_dockstrut属性失效,因此,此处将动画位置距离边缘设置为1 + // 此时就不会出现_d_dwayland_dockstrut属性失效的情况(1个像素并不影响动画效果) + // 在时尚模式下无需做这个设置,因为时尚模式下距离边缘的距离为10 + QRect animationRect = sourceRect; + switch (pos) { + case Dock::Position::Bottom: { + animationRect.setTop(animationRect.top() - 1); + animationRect.setHeight(sourceRect.height()); + break; + } + case Dock::Position::Left: { + animationRect.setLeft(1); + animationRect.setWidth(sourceRect.width()); + break; + } + case Dock::Position::Top: { + animationRect.setTop(1); + animationRect.setHeight(sourceRect.height()); + break; + } + case Dock::Position::Right: { + animationRect.setLeft(animationRect.left() - 1); + animationRect.setWidth(sourceRect.width()); + break; + } + } + return animationRect; +} + +/** + * @brief MainWindow::onMainWindowSizeChanged 任务栏拖拽过程中会不停调用此方法更新自身大小 + * @param offset 拖拽时的坐标偏移量 + */ +void MainWindowBase::onMainWindowSizeChanged(QPoint offset) +{ + QScreen *screen = DIS_INS->screen(DOCK_SCREEN->current()); + if (!screen) + return; + + const QRect rect = getDockGeometry(screen, position(), displayMode(), Dock::HideState::Show); + QRect newRect; + switch (m_multiScreenWorker->position()) { + case Top: { + newRect.setX(rect.x()); + newRect.setY(rect.y()); + newRect.setWidth(rect.width()); + newRect.setHeight(qBound(DOCK_MIN_SIZE, rect.height() + offset.y(), DOCK_MAX_SIZE)); + } + break; + case Bottom: { + newRect.setX(rect.x()); + newRect.setY(rect.y() + rect.height() - qBound(DOCK_MIN_SIZE, rect.height() - offset.y(), DOCK_MAX_SIZE)); + newRect.setWidth(rect.width()); + newRect.setHeight(qBound(DOCK_MIN_SIZE, rect.height() - offset.y(), DOCK_MAX_SIZE)); + } + break; + case Left: { + newRect.setX(rect.x()); + newRect.setY(rect.y()); + newRect.setWidth(qBound(DOCK_MIN_SIZE, rect.width() + offset.x(), DOCK_MAX_SIZE)); + newRect.setHeight(rect.height()); + } + break; + case Right: { + newRect.setX(rect.x() + rect.width() - qBound(DOCK_MIN_SIZE, rect.width() - offset.x(), DOCK_MAX_SIZE)); + newRect.setY(rect.y()); + newRect.setWidth(qBound(DOCK_MIN_SIZE, rect.width() - offset.x(), DOCK_MAX_SIZE)); + newRect.setHeight(rect.height()); + } + break; + } + + Utils::setIsDraging(true); + + setFixedSize(newRect.size()); + move(newRect.topLeft()); + resetPanelGeometry(); + + Q_EMIT requestUpdate(); +} + +void MainWindowBase::updateDragGeometry() +{ + switch (position()) { + case Dock::Top: + m_dragWidget->setGeometry(0, height() - DRAG_AREA_SIZE, width(), DRAG_AREA_SIZE); + break; + case Dock::Bottom: + m_dragWidget->setGeometry(0, 0, width(), DRAG_AREA_SIZE); + break; + case Dock::Left: + m_dragWidget->setGeometry(width() - DRAG_AREA_SIZE, 0, DRAG_AREA_SIZE, height()); + break; + case Dock::Right: + m_dragWidget->setGeometry(0, 0, DRAG_AREA_SIZE, height()); + break; + } + + m_dragWidget->raise(); + if ((Top == position()) || (Bottom == position())) { + m_dragWidget->setCursor(Qt::SizeVerCursor); + } else { + m_dragWidget->setCursor(Qt::SizeHorCursor); + } +} + +void MainWindowBase::resetDragWindow() +{ + updateDragGeometry(); + QScreen *screen = DIS_INS->screen(DOCK_SCREEN->current()); + if (!screen) + return; + + QRect currentRect = getDockGeometry(screen, position(), displayMode(), Dock::HideState::Show); + + // 这个时候屏幕有可能是隐藏的,不能直接使用this->width()这种去设置任务栏的高度,而应该保证原值 + int dockSize = 0; + if (m_multiScreenWorker->position() == Position::Left + || m_multiScreenWorker->position() == Position::Right) { + dockSize = this->width() == 0 ? currentRect.width() : this->width(); + } else { + dockSize = this->height() == 0 ? currentRect.height() : this->height(); + } + + /** FIX ME + * 作用:限制dockSize的值在40~100之间。 + * 问题1:如果dockSize为39,会导致dock的mainwindow高度变成99,显示的内容高度却是39。 + * 问题2:dockSize的值在这里不应该为39,但在高分屏上开启缩放后,拉高任务栏操作会概率出现。 + * 暂时未分析出原因,后面再修改。 + */ + dockSize = qBound(DOCK_MIN_SIZE, dockSize, DOCK_MAX_SIZE); + + // 通知窗管和后端更新数据 + m_multiScreenWorker->updateDaemonDockSize(dockSize); // 1.先更新任务栏高度 + m_multiScreenWorker->requestUpdateFrontendGeometry(); // 2.再更新任务栏位置,保证先1再2 + m_multiScreenWorker->requestNotifyWindowManager(); + m_multiScreenWorker->requestUpdateRegionMonitor(); // 界面发生变化,应更新监控区域 +} + +void MainWindowBase::touchRequestResizeDock() +{ + const QPoint touchPos(QCursor::pos()); + QRect dockRect = geometry(); + // 隐藏状态返回 + if (width() == 0 || height() == 0) + return; + + int resizeHeight = Utils::SettingValue("com.deepin.dde.dock.touch", QByteArray(), "resizeHeight", 7).toInt(); + + QRect touchRect; + // 任务栏屏幕 内侧边线 内外resizeHeight距离矩形区域内长按可拖动任务栏高度 + switch (position()) { + case Position::Top: + touchRect = QRect(dockRect.x(), dockRect.y() + dockRect.height() - resizeHeight, dockRect.width(), resizeHeight * 2); + break; + case Position::Bottom: + touchRect = QRect(dockRect.x(), dockRect.y() - resizeHeight, dockRect.width(), resizeHeight * 2); + break; + case Position::Left: + touchRect = QRect(dockRect.x() + dockRect.width() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height()); + break; + case Position::Right: + touchRect = QRect(dockRect.x() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height()); + break; + } + + if (!touchRect.contains(touchPos)) + return; + + qApp->postEvent(m_dragWidget, new QMouseEvent(QEvent::MouseButtonPress, m_dragWidget->mapFromGlobal(touchPos) + , QPoint(), touchPos, Qt::LeftButton, Qt::NoButton + , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication)); +} + +void MainWindowBase::adjustShadowMask() +{ + if (!m_isShow || m_shadowMaskOptimizeTimer->isActive()) + return; + + m_platformWindowHandle.setWindowRadius(m_borderRadius); +} + +void MainWindowBase::onCompositeChanged() +{ + setMaskColor(AutoColor); + + setMaskAlpha(m_multiScreenWorker->opacity()); + m_platformWindowHandle.setBorderWidth(0); + + m_shadowMaskOptimizeTimer->start(); +} + +void MainWindowBase::onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType) +{ + if (DWindowManagerHelper::instance()->hasComposite()) { + if (themeType == DGuiApplicationHelper::DarkType) { + QColor color = Qt::black; + color.setAlpha(255 * 0.3); + m_platformWindowHandle.setBorderColor(color); + } else { + m_platformWindowHandle.setBorderColor(QColor(QColor::Invalid)); + } + } +} + +void MainWindowBase::setDisplayMode(const Dock::DisplayMode &displayMode) +{ + m_displayMode = displayMode; + adjustShadowMask(); + m_platformWindowHandle.setShadowOffset(QPoint(0, (displayMode == Dock::DisplayMode::Fashion ? 5 : 0))); +} + +void MainWindowBase::setPosition(const Dock::Position &position) +{ + m_position = position; +} + +QRect MainWindowBase::getDockGeometry(QScreen *screen, const Dock::Position &pos, const Dock::DisplayMode &displaymode, const Dock::HideState &hideState, bool withoutScale) const +{ + QList topMainWindows; // 所有的顶层主窗口列表 + QList lessOrderMainWindows; // 所有在当前窗口之前的主窗口 + QWidgetList topWidgets = qApp->topLevelWidgets(); + for (QWidget *widget : topWidgets) { + MainWindowBase *currentWindow = qobject_cast(widget); + if (!currentWindow || !currentWindow->isVisible()) + continue; + + topMainWindows << currentWindow; + if (currentWindow->order() < order()) + lessOrderMainWindows << currentWindow; + } + + if (!topMainWindows.contains(this)) + return QRect(); + + // 对当前窗口前面的所有窗口按照order进行排序 + sort(lessOrderMainWindows.begin(), lessOrderMainWindows.end(), [](MainWindowBase const *window1, MainWindowBase const *window2) { + return window1->order() < window2->order(); + }); + QRect rect; + const double ratio = withoutScale ? 1 : qApp->devicePixelRatio(); + const int margin = static_cast((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1)); + int dockSize = 0; + if (hideState == Dock::HideState::Show) + dockSize = windowSize() * (withoutScale ? qApp->devicePixelRatio() : 1); + + // 拿到当前显示器缩放之前的分辨率 + QRect screenRect = screen->handle()->geometry(); + // 计算所有的窗口的总尺寸 + int totalSize = 0; + switch (pos) { + case Dock::Position::Top: + case Dock::Position::Bottom: { + // 计算任务栏的总的尺寸 + int width = 0; + for (MainWindowBase const *mainWindow : topMainWindows) { + QSize windowSize = mainWindow->suitableSize(pos, screenRect.width(), ratio); + totalSize += windowSize.width() + mainWindow->dockSpace(); + if (mainWindow == this) + width = windowSize.width(); + } + + // 计算第一个窗口的X坐标 + int x = screenRect.x() + (static_cast((screenRect.width() / ratio) - totalSize) / 2); + // 计算当前的X坐标 + for (MainWindowBase const *mainWindow : lessOrderMainWindows) { + x += mainWindow->suitableSize(pos, screenRect.width(), ratio).width() + mainWindow->dockSpace(); + } + int y = 0; + if (pos == Dock::Position::Top) + y = (screenRect.y() + static_cast(margin / ratio)); + else + y = (screenRect.y() + static_cast(screenRect.height() / ratio - margin / ratio)) - dockSize; + rect.setX(x); + rect.setY(y); + rect.setWidth(width); + rect.setHeight(dockSize); + break; + } + case Dock::Position::Left: + case Dock::Position::Right: { + int height = 0; + for (MainWindowBase const *mainWindow : topMainWindows) { + QSize windowSize = mainWindow->suitableSize(pos, screenRect.height(), ratio); + totalSize += windowSize.height() + mainWindow->dockSpace(); + if (mainWindow == this) + height = windowSize.height(); + } + int x = 0; + if (pos == Dock::Position::Left) + x = screenRect.x() + static_cast(margin / ratio); + else + x = screenRect.x() + static_cast(screenRect.width() /ratio - margin / ratio) - dockSize; + + int y = screenRect.y() + static_cast(((screenRect.height() / ratio) - totalSize) / 2); + // 计算y坐标 + for (MainWindowBase const *mainWindow : lessOrderMainWindows) + y += mainWindow->suitableSize(pos, screenRect.height(), ratio).height() + mainWindow->dockSpace(); + + rect.setX(x); + rect.setY(y); + rect.setWidth(dockSize); + rect.setHeight(height); + break; + } + } + return rect; +} + +QVariantAnimation *MainWindowBase::createAnimation(QScreen *screen, const Dock::Position &pos, const Dock::AniAction &act) +{ + /** FIXME + * 在高分屏2.75倍缩放的情况下,mainWindowGeometry返回的任务栏高度有问题(实际是40,返回是39) + * 在这里增加判断,当返回值在范围(38,42)开区间内,均认为任务栏显示位置正确,直接返回,不执行动画 + * 也就是在实际值基础上下浮动1像素的误差范围 + * 正常屏幕情况下是没有这个问题的 + */ + QRect mainwindowRect = geometry(); + const QRect dockShowRect = getAnimationRect(getDockGeometry(screen, pos, m_multiScreenWorker->displayMode(), Dock::HideState::Show), pos); + const QRect &dockHideRect = getAnimationRect(getDockGeometry(screen, pos, m_multiScreenWorker->displayMode(), Dock::HideState::Hide), pos); + if (act == Dock::AniAction::Show) { + if (pos == Position::Top || pos == Position::Bottom) { + if (qAbs(dockShowRect.height() - mainwindowRect.height()) <= 1 + && mainwindowRect.contains(dockShowRect.center())) + return nullptr; + } else if (pos == Position::Left || pos == Position::Right) { + if (qAbs(dockShowRect.width() - mainwindowRect.width()) <= 1 + && mainwindowRect.contains(dockShowRect.center())) + return nullptr; + } + } + if (act == Dock::AniAction::Hide && dockHideRect.size() == mainwindowRect.size()) + return nullptr; + + // 开始播放动画 + QVariantAnimation *ani = new QVariantAnimation(nullptr); + ani->setEasingCurve(QEasingCurve::InOutCubic); +#ifndef DISABLE_SHOW_ANIMATION + const bool composite = DWindowManagerHelper::instance()->hasComposite(); // 判断是否开启特效模式 + const int duration = composite ? ANIMATIONTIME : 0; +#else + const int duration = 0; +#endif + ani->setDuration(duration); + + connect(ani, &QVariantAnimation::valueChanged, this, [ = ](const QVariant &value) { + if ((!m_multiScreenWorker->testState(MultiScreenWorker::ShowAnimationStart) + && !m_multiScreenWorker->testState(MultiScreenWorker::HideAnimationStart) + && !m_multiScreenWorker->testState(MultiScreenWorker::ChangePositionAnimationStart)) + || ani->state() != QVariantAnimation::State::Running) + return; + + updateParentGeometry(pos, value.value()); + }); + + switch (act) { + case Dock::AniAction::Show: { + ani->setStartValue(dockHideRect); + ani->setEndValue(dockShowRect); + connect(ani, &QVariantAnimation::finished, this, [ = ]{ + updateParentGeometry(pos, dockShowRect); + }); + break; + } + case Dock::AniAction::Hide: { + ani->setStartValue(dockShowRect); + ani->setEndValue(dockHideRect); + connect(ani, &QVariantAnimation::finished, this, [ = ]{ + updateParentGeometry(pos, dockHideRect); + }); + break; + } + } + + return ani; +} + +Dock::DisplayMode MainWindowBase::displayMode() const +{ + return m_displayMode; +} + +Dock::Position MainWindowBase::position() const +{ + return m_position; +} + +int MainWindowBase::windowSize() const +{ + if (m_displayMode == Dock::DisplayMode::Efficient) + return m_multiScreenWorker->dockInter()->windowSizeEfficient(); + + return m_multiScreenWorker->dockInter()->windowSizeFashion(); +} + +bool MainWindowBase::isDraging() const +{ + return m_dragWidget->isDraging(); +} + +int MainWindowBase::dockSpace() const +{ + return DOCKSPACE; +} + +void MainWindowBase::initUi() +{ + DPlatformWindowHandle::enableDXcbForWindow(this, true); + m_platformWindowHandle.setEnableBlurWindow(true); + m_platformWindowHandle.setTranslucentBackground(true); + m_platformWindowHandle.setShadowOffset(QPoint(0, 0)); + QColor shadorColor = Qt::black; + shadorColor.setAlpha(static_cast(0.3 * 255)); + m_platformWindowHandle.setShadowColor(shadorColor); +} + +void MainWindowBase::resizeEvent(QResizeEvent *event) +{ + updateDragGeometry(); + + int borderRadius = getBorderRadius(); + if (borderRadius != m_borderRadius) { + m_borderRadius = borderRadius; + updateRadius(m_borderRadius); + } + + m_shadowMaskOptimizeTimer->start(); + + if (!isDraging()) + m_updateDragAreaTimer->start(); +} + +void MainWindowBase::moveEvent(QMoveEvent *) +{ + updateDragGeometry(); + + if (!isDraging()) + m_updateDragAreaTimer->start(); +} + +void MainWindowBase::enterEvent(QEvent *e) +{ + QWidget::enterEvent(e); + + if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != Qt::ArrowCursor) + QApplication::restoreOverrideCursor(); +} + +void MainWindowBase::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::RightButton && geometry().contains(QCursor::pos())) { + m_multiScreenWorker->onAutoHideChanged(false); + MenuWorker menuWorker(m_multiScreenWorker->dockInter()); + menuWorker.exec(); + m_multiScreenWorker->onAutoHideChanged(true); + } + + DBlurEffectWidget::mousePressEvent(event); +} + +void MainWindowBase::showEvent(QShowEvent *event) +{ + if (!m_isShow) { + m_isShow = true; + m_shadowMaskOptimizeTimer->start(); + } + + DBlurEffectWidget::showEvent(event); +} diff --git a/frame/window/mainwindowbase.h b/frame/window/mainwindowbase.h new file mode 100644 index 000000000..d587f6e2b --- /dev/null +++ b/frame/window/mainwindowbase.h @@ -0,0 +1,105 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef MAINWINDOWBASE_H +#define MAINWINDOWBASE_H + +#include "constants.h" +#include "dbusutil.h" + +#include +#include +#include + +#include +#include +#include + +class DragWidget; +class MultiScreenWorker; + +DWIDGET_USE_NAMESPACE + +class MainWindowBase : public DBlurEffectWidget +{ + Q_OBJECT + +public: + enum class DockWindowType { + MainWindow, // 主窗口 + TrayWindow // 主窗口之外的其他窗口 + }; + +public: + explicit MainWindowBase(MultiScreenWorker *multiScreenWorker, QWidget *parent = Q_NULLPTR); + virtual ~MainWindowBase(); + + void setOrder(int order); // 窗体展示的顺序,按照左到右和上到下 + int order() const; + + virtual DockWindowType windowType() const = 0; + virtual void setDisplayMode(const Dock::DisplayMode &displayMode); + virtual void setPosition(const Dock::Position &position); + // 用来更新子区域的位置,一般用于在执行动画的过程中,根据当前的位置来更新里面panel的大小 + virtual void updateParentGeometry(const Dock::Position &pos, const QRect &rect) = 0; + virtual QRect getDockGeometry(QScreen *screen, const Dock::Position &pos, const Dock::DisplayMode &displaymode, const Dock::HideState &hideState, bool withoutScale = false) const; + QVariantAnimation *createAnimation(QScreen *screen, const Dock::Position &pos, const Dock::AniAction &act); + virtual void resetPanelGeometry() {} // 重置内部区域,为了让内部区域和当前区域始终保持一致 + virtual int dockSpace() const; // 与后面窗体之间的间隔 + virtual void serviceRestart() {} // 服务重新启动后的操作 + virtual void animationFinished(bool showOrHide) {} + +Q_SIGNALS: + void requestUpdate(); + +protected: + void resizeEvent(QResizeEvent *event) override; + void moveEvent(QMoveEvent *) override; + void enterEvent(QEvent *e) override; + void mousePressEvent(QMouseEvent *event) override; + void showEvent(QShowEvent *event) override; + + Dock::DisplayMode displayMode() const; + Dock::Position position() const; + + int windowSize() const; + + bool isDraging() const; + + virtual void updateRadius(int borderRadius) {} + virtual QSize suitableSize(const Dock::Position &pos, const int &screenSize, const double &deviceRatio) const = 0; + +private: + void initUi(); + void initAttribute(); + void initConnection(); + void initMember(); + void updateDragGeometry(); + + int getBorderRadius() const; + QRect getAnimationRect(const QRect &sourceRect, const Dock::Position &pos) const; + +private Q_SLOTS: + void onMainWindowSizeChanged(QPoint offset); + void resetDragWindow(); + void touchRequestResizeDock(); + void adjustShadowMask(); + void onCompositeChanged(); + void onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType); + +private: + Dock::DisplayMode m_displayMode; + Dock::Position m_position; + DragWidget *m_dragWidget; + MultiScreenWorker *m_multiScreenWorker; + QTimer *m_updateDragAreaTimer; + DPlatformWindowHandle m_platformWindowHandle; + QTimer *m_shadowMaskOptimizeTimer; + bool m_isShow; + int m_borderRadius; + int m_order; +}; + +#endif // MAINWINDOWBASE_H diff --git a/frame/window/quickpluginmodel.cpp b/frame/window/quickpluginmodel.cpp new file mode 100644 index 000000000..3a87f828b --- /dev/null +++ b/frame/window/quickpluginmodel.cpp @@ -0,0 +1,240 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "quickpluginmodel.h" +#include "pluginsiteminterface.h" +#include "quicksettingcontroller.h" +#include "settingconfig.h" + +#include + +#define PLUGINNAMEKEY "Dock_Quick_Plugins" + +QuickPluginModel *QuickPluginModel::instance() +{ + static QuickPluginModel instance; + return &instance; +} + +void QuickPluginModel::addPlugin(PluginsItemInterface *itemInter, int index) +{ + // 这里只接受快捷面板的插件,因此,需要做一次判断 + if (QuickSettingController::instance()->pluginAttribute(itemInter) != QuickSettingController::PluginAttribute::Quick) + return; + + // 获取当前插件在插件区的位置索引(所有在任务栏上显示的插件) + int oldIndex = getCurrentIndex(itemInter); + // 计算插入之前的顺序 + if (oldIndex == index && m_dockedPluginsItems.contains(itemInter)) + return; + + // 根据插件区域的位置计算新的索引值 + int newIndex = generaIndex(index, oldIndex); + m_dockedPluginIndex[itemInter->pluginName()] = newIndex; + if (!m_dockedPluginsItems.contains(itemInter)) { + m_dockedPluginsItems << itemInter; + // 保存配置到dConfig中 + saveConfig(); + } + // 向外发送更新列表的信号 + Q_EMIT requestUpdate(); +} + +void QuickPluginModel::removePlugin(PluginsItemInterface *itemInter) +{ + if (!m_dockedPluginsItems.contains(itemInter) && !m_dockedPluginIndex.contains(itemInter->pluginName())) + return; + + if (m_dockedPluginIndex.contains(itemInter->pluginName())) { + m_dockedPluginIndex.remove(itemInter->pluginName()); + // 保存配置到DConfig中 + saveConfig(); + } + + if (m_dockedPluginsItems.contains(itemInter)) { + m_dockedPluginsItems.removeAll(itemInter); + Q_EMIT requestUpdate(); + } +} + +QList QuickPluginModel::dockedPluginItems() const +{ + // 先查找出固定插件,始终排列在最前面 + QList dockedItems; + QList activedItems; + for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { + if (isFixed(itemInter)) + dockedItems << itemInter; + else + activedItems << itemInter; + } + std::sort(dockedItems.begin(), dockedItems.end(), [ this ](PluginsItemInterface *item1, PluginsItemInterface *item2) { + return m_dockedPluginIndex.value(item1->pluginName()) < m_dockedPluginIndex.value(item2->pluginName()); + }); + std::sort(activedItems.begin(), activedItems.end(), [ this ](PluginsItemInterface *item1, PluginsItemInterface *item2) { + return m_dockedPluginIndex.value(item1->pluginName()) < m_dockedPluginIndex.value(item2->pluginName()); + }); + return (QList() << dockedItems << activedItems); +} + +bool QuickPluginModel::isDocked(PluginsItemInterface *itemInter) const +{ + return (m_dockedPluginsItems.contains(itemInter)); +} + +bool QuickPluginModel::isFixed(PluginsItemInterface *itemInter) const +{ + return !(itemInter->flags() & PluginFlag::Attribute_CanInsert); +} + +QuickPluginModel::QuickPluginModel(QObject *parent) + : QObject(parent) +{ + initConnection(); + initConfig(); +} + +void QuickPluginModel::onPluginRemoved(PluginsItemInterface *itemInter) +{ + // 如果插件移除,无需移除下方的排序设置,因为下次插件插入的时候还会插入到下方任务栏 + // 因此,此处只需要从列表中移除当前插件 + if (m_dockedPluginsItems.contains(itemInter)) + m_dockedPluginsItems.removeAll(itemInter); + // 向外发送更新列表的信号 + Q_EMIT requestUpdate(); +} + +void QuickPluginModel::initConnection() +{ + QuickSettingController *quickController = QuickSettingController::instance(); + connect(quickController, &QuickSettingController::pluginInserted, this, [ this, quickController ](PluginsItemInterface *itemInter, const QuickSettingController::PluginAttribute plugAttr) { + if (plugAttr != QuickSettingController::PluginAttribute::Quick) + return; + + QWidget *quickWidget = itemInter->itemWidget(QUICK_ITEM_KEY); + if (quickWidget && !quickWidget->parentWidget()) + quickWidget->setVisible(false); + + if (!m_dockedPluginIndex.contains(itemInter->pluginName())) { + QJsonObject json = quickController->metaData(itemInter); + if (json.contains("order")) + m_dockedPluginIndex[itemInter->pluginName()] = json.value("order").toInt(); + } + + m_dockedPluginsItems << itemInter; + + // 向外发送更新列表的信号 + Q_EMIT requestUpdate(); + }); + + connect(quickController, &QuickSettingController::pluginRemoved, this, &QuickPluginModel::onPluginRemoved); + connect(quickController, &QuickSettingController::pluginUpdated, this, &QuickPluginModel::requestUpdatePlugin); +} + +void QuickPluginModel::initConfig() +{ + // 此处用于读取dConfig配置,记录哪些插件是固定在任务栏上面的 + QStringList dockPluginsName = SETTINGCONFIG->value(PLUGINNAMEKEY).toStringList(); + for (int i = 0; i < dockPluginsName.size(); i++) + m_dockedPluginIndex[dockPluginsName[i]] = i; +} + +void QuickPluginModel::saveConfig() +{ + QStringList pluginNames; + for (PluginsItemInterface *item : m_dockedPluginsItems) { + pluginNames << item->pluginName(); + } + QStringList plugins; + for (auto it = m_dockedPluginIndex.begin(); it != m_dockedPluginIndex.end(); it++) { + if (pluginNames.contains(it.key())) + plugins << it.key(); + } + std::sort(plugins.begin(), plugins.end(), [ this ](const QString &p1, const QString &p2) { + return m_dockedPluginIndex.value(p1) < m_dockedPluginIndex.value(p2); + }); + SETTINGCONFIG->setValue(PLUGINNAMEKEY, plugins); +} + +int QuickPluginModel::getCurrentIndex(PluginsItemInterface *itemInter) +{ + QList dockedPluginsItems = m_dockedPluginsItems; + std::sort(dockedPluginsItems.begin(), dockedPluginsItems.end(), [ this ](PluginsItemInterface *plugin1, PluginsItemInterface *plugin2) { + return m_dockedPluginIndex.value(plugin1->pluginName()) < m_dockedPluginIndex.value(plugin2->pluginName()); + }); + return dockedPluginItems().indexOf(itemInter); +} + +int QuickPluginModel::generaIndex(int insertIndex, int oldIndex) +{ + int newIndex = insertIndex; + if (oldIndex < 0) { + newIndex = insertIndex + 1; + // 如果该插件在列表中存在,则需要将原来的索引值加一 + if (insertIndex < 0) { + // 如果新插入的索引值为-1,则表示需要插入到末尾的位置,此时需要从索引值中找到最大值 + int lastIndex = -1; + for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { + int index = m_dockedPluginIndex.value(itemInter->pluginName()); + if (lastIndex < index) + lastIndex = index; + } + newIndex = lastIndex + 1; + } + if (m_dockedPluginIndex.values().contains(newIndex)) { + // 遍历map列表,检查列表中是否存在等于新索引的插件,如果存在,将其后面的索引值向后加一 + for (auto it = m_dockedPluginIndex.begin(); it != m_dockedPluginIndex.end(); it++) { + if (it.value() < newIndex) + continue; + + m_dockedPluginIndex[it.key()] = it.value() + 1; + } + } + } else { + newIndex = insertIndex; + // 如果该插件已经存在于下面的列表中,则分两种情况 + if (insertIndex < 0) { + // 如果插入在末尾,则计算最大值 + if (m_dockedPluginIndex.size() > 0) { + int maxIndex = m_dockedPluginIndex.first(); + for (auto it = m_dockedPluginIndex.begin(); it != m_dockedPluginIndex.end(); it++) { + if (maxIndex < it.value()) + maxIndex = it.value(); + } + return maxIndex; + } + return 0; + } + if (insertIndex > oldIndex) { + int minIndex = NGROUPS_MAX; + // 新的位置的索引值大于原来位置的索引值,则认为插入在原来的任务栏的后面,将前面的插件的索引值减去1 + for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { + int pluginDockIndex = getCurrentIndex(itemInter); + if (pluginDockIndex > oldIndex) { + if (pluginDockIndex <= insertIndex) { + int tmpIndex = m_dockedPluginIndex[itemInter->pluginName()]; + if (tmpIndex < minIndex) + minIndex = tmpIndex; + } + m_dockedPluginIndex[itemInter->pluginName()]--; + } + qInfo() << itemInter->pluginDisplayName() << m_dockedPluginIndex[itemInter->pluginName()]; + } + + if (minIndex != NGROUPS_MAX) + newIndex = minIndex; + } else { + // 新的位置索引小于原来的索引值,则认为是插在任务栏的前面,将任务栏后面的插件的索引值加一 + for (PluginsItemInterface *itemInter : m_dockedPluginsItems) { + int pluginDockIndex = getCurrentIndex(itemInter); + if (pluginDockIndex >= insertIndex) { + m_dockedPluginIndex[itemInter->pluginName()]++; + } + } + } + } + + return newIndex; +} diff --git a/frame/window/quickpluginmodel.h b/frame/window/quickpluginmodel.h new file mode 100644 index 000000000..90b15c505 --- /dev/null +++ b/frame/window/quickpluginmodel.h @@ -0,0 +1,55 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef QUICKPLUGINMODEL_H +#define QUICKPLUGINMODEL_H + +#include +#include + +class PluginsItemInterface; +enum class DockPart; +/** + * 这是一个独立的Model,用来记录显示在任务栏下方的快捷插件 + * @brief The QuickPluginModel class + */ + +class QuickPluginModel : public QObject +{ + Q_OBJECT + +public: + static QuickPluginModel *instance(); + + void addPlugin(PluginsItemInterface *itemInter, int index = -1); + void removePlugin(PluginsItemInterface *itemInter); + + QList dockedPluginItems() const; + bool isDocked(PluginsItemInterface *itemInter) const; + bool isFixed(PluginsItemInterface *itemInter) const; + +Q_SIGNALS: + void requestUpdate(); + void requestUpdatePlugin(PluginsItemInterface *, const DockPart &); + +protected: + explicit QuickPluginModel(QObject *parent = nullptr); + +private Q_SLOTS: + void onPluginRemoved(PluginsItemInterface *itemInter); + +private: + void initConnection(); + void initConfig(); + void saveConfig(); + int getCurrentIndex(PluginsItemInterface *itemInter); + int generaIndex(int sourceIndex, int oldIndex); + +private: + QList m_dockedPluginsItems; + QMap m_dockedPluginIndex; +}; + +#endif // QUICKPLUGINMODEL_H diff --git a/frame/window/quickpluginwindow.cpp b/frame/window/quickpluginwindow.cpp new file mode 100644 index 000000000..60b0a949d --- /dev/null +++ b/frame/window/quickpluginwindow.cpp @@ -0,0 +1,1124 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "quickpluginwindow.h" +#include "quicksettingcontroller.h" +#include "pluginsiteminterface.h" +#include "appdrag.h" +#include "quickpluginmodel.h" +#include "quickdragcore.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ITEMSIZE 22 +#define STARTSPACE 6 +#define ITEMSPACE 0 +#define ICONWIDTH 18 +#define ICONHEIGHT 16 + +typedef struct DragInfo{ + QPoint dragPoint; + QuickDockItem *dockItem = nullptr; + + void reset() { + dockItem = nullptr; + dragPoint.setX(0); + dragPoint.setY(0); + } + + bool isNull() const { + return (!dockItem); + } + + bool canDrag(QPoint currentPoint) const { + if (dragPoint.isNull()) + return false; + + if (!dragPixmap()) + return false; + + return (qAbs(currentPoint.x() - dragPoint.x()) >= 1 || + qAbs(currentPoint.y() - dragPoint.y()) >= 1); + } + + QPixmap dragPixmap() const { + if (!dockItem) + return QPixmap(); + + QPixmap pixmap = dockItem->pluginItem()->icon(DockPart::QuickShow).pixmap(QSize(ITEMSIZE, ITEMSIZE)); + if (!pixmap.isNull()) + return pixmap; + + QString itemKey = QuickSettingController::instance()->itemKey(dockItem->pluginItem()); + QWidget *itemWidget = dockItem->pluginItem()->itemWidget(itemKey); + if (!itemWidget) + return QPixmap(); + + return itemWidget->grab(); + } +} DragInfo; + +QuickPluginWindow::QuickPluginWindow(Dock::DisplayMode displayMode, QWidget *parent) + : QWidget(parent) + , m_mainLayout(new QBoxLayout(QBoxLayout::RightToLeft, this)) + , m_position(Dock::Position::Bottom) + , m_dragInfo(new DragInfo) + , m_dragEnterMimeData(nullptr) + , m_displayMode(displayMode) +{ + initUi(); + initConnection(); + + topLevelWidget()->installEventFilter(this); + installEventFilter(this); + setAcceptDrops(true); + setMouseTracking(true); +} + +QuickPluginWindow::~QuickPluginWindow() +{ + delete m_dragInfo; +} + +void QuickPluginWindow::initUi() +{ + setAcceptDrops(true); + m_mainLayout->setAlignment(Qt::AlignCenter); + m_mainLayout->setDirection(QBoxLayout::RightToLeft); + m_mainLayout->setContentsMargins(0, 0, 0, 0); + m_mainLayout->setSpacing(ITEMSPACE); + // 时尚模式下的插件右侧的区域增加空白的间隔 + if (m_displayMode == Dock::DisplayMode::Fashion) + m_mainLayout->addSpacing(STARTSPACE); +} + +void QuickPluginWindow::setPositon(Position position) +{ + if (m_position == position) + return; + + m_position = position; + for (int i = 0; i < m_mainLayout->count(); i++) { + QuickDockItem *dockItemWidget = qobject_cast(m_mainLayout->itemAt(i)->widget()); + if (dockItemWidget) { + dockItemWidget->setPosition(position); + } + } + resizeDockItem(); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + m_mainLayout->setDirection(QBoxLayout::RightToLeft); + } else { + m_mainLayout->setDirection(QBoxLayout::BottomToTop); + } + switch(m_position) { + case Dock::Position::Top: + getPopWindow()->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowTop); + break; + case Dock::Position::Right: + getPopWindow()->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowRight); + break; + case Dock::Position::Bottom: + getPopWindow()->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowBottom); + break; + case Dock::Position::Left: + getPopWindow()->setArrowDirection(DArrowRectangle::ArrowDirection::ArrowLeft); + break; + } +} + +void QuickPluginWindow::dragPlugin(PluginsItemInterface *item) +{ + QuickPluginModel *quickModel = QuickPluginModel::instance(); + QPoint itemPoint = mapFromGlobal(QCursor::pos()); + // 查找移动后的位置,如果移动后的插件找不到,就直接放到最后 + int index = -1; + QuickDockItem *targetWidget = qobject_cast(childAt(itemPoint)); + if (targetWidget) { + // 如果是拖动到固定插件区域,也放到最后 + QList pluginItems = quickModel->dockedPluginItems(); + for (int i = 0; i < pluginItems.size(); i++) { + PluginsItemInterface *plugin = pluginItems[i]; + if (quickModel->isFixed(plugin)) + continue; + + if (targetWidget->pluginItem() == plugin) { + index = i; + break; + } + } + } + + quickModel->addPlugin(item, index); +} + +QSize QuickPluginWindow::suitableSize() const +{ + return suitableSize(m_position); +} + +QSize QuickPluginWindow::suitableSize(const Dock::Position &position) const +{ + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + int itemWidth = STARTSPACE; + for (int i = 0; i < m_mainLayout->count(); i++) { + QWidget *itemWidget = m_mainLayout->itemAt(i)->widget(); + if (itemWidget) + itemWidth += itemWidget->width() + ITEMSPACE; + } + itemWidth += ITEMSPACE; + + return QSize(itemWidth, QWIDGETSIZE_MAX); + } + + int itemHeight = STARTSPACE; + for (int i = 0; i < m_mainLayout->count(); i++) { + QWidget *itemWidget = m_mainLayout->itemAt(i)->widget(); + if (itemWidget) + itemHeight += itemWidget->height() + ITEMSPACE; + } + itemHeight += ITEMSPACE; + + return QSize(QWIDGETSIZE_MAX, itemHeight); +} + +bool QuickPluginWindow::isQuickWindow(QObject *object) const +{ + QList dockPlugins = QuickPluginModel::instance()->dockedPluginItems(); + for (PluginsItemInterface *plugin : dockPlugins) { + if (plugin->pluginName() == QString("pluginManager") && plugin->itemPopupApplet(QUICK_ITEM_KEY) == object) + return true; + } + + return false; +} + +PluginsItemInterface *QuickPluginWindow::findQuickSettingItem(const QPoint &mousePoint, const QList &settingItems) +{ + QuickDockItem *selectWidget = qobject_cast(childAt(mousePoint)); + if (!selectWidget) + return nullptr; + + for (int i = 0; i < settingItems.size(); i++) { + PluginsItemInterface *settingItem = settingItems[i]; + if (selectWidget->pluginItem() == settingItem) + return settingItem; + } + + return nullptr; +} + +bool QuickPluginWindow::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == topLevelWidget()) { + switch (event->type()) { + case QEvent::DragEnter: { + QDragEnterEvent *dragEvent = static_cast(event); + dragEnterEvent(dragEvent); + break; + } + case QEvent::DragLeave: { + QDragLeaveEvent *dragEvent = static_cast(event); + dragLeaveEvent(dragEvent); + break; + } + default: + break; + } + } + if (watched == getPopWindow()->getContent()) { +#define ITEMWIDTH 70 +#define QUICKITEMSPACE 10 + int maxWidth = ITEMWIDTH * 4 + (QUICKITEMSPACE * 5); + int contentWidget = getPopWindow()->getContent()->width(); + if (contentWidget > maxWidth || contentWidget <= 0) + getPopWindow()->getContent()->setFixedWidth(maxWidth); + } + switch (event->type()) { + case QEvent::MouseButtonPress: { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->button() != Qt::LeftButton) + break; + + QuickDockItem *dockItem = qobject_cast(watched); + if (!dockItem) + break; + + m_dragInfo->dockItem = dockItem; + m_dragInfo->dragPoint = mouseEvent->pos(); + break; + } + case QEvent::MouseButtonRelease: { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->button() != Qt::LeftButton) + break; + + if (m_dragInfo->isNull()) + break; + + do { + if (m_dragInfo->canDrag(mouseEvent->pos())) + break; + + showPopup(m_dragInfo->dockItem, m_dragInfo->dockItem->pluginItem(), m_dragInfo->dockItem->pluginItem()->itemPopupApplet(QUICK_ITEM_KEY), true); + } while (false); + m_dragInfo->reset(); + + break; + } + case QEvent::MouseMove: { + if (m_dragInfo->isNull()) + break; + + QMouseEvent *mouseEvent = static_cast(event); + if (m_dragInfo->canDrag(mouseEvent->pos()) && m_dragInfo->dockItem->canMove()) + startDrag(); + + m_dragInfo->reset(); + break; + } + case QEvent::Drop: { + m_dragEnterMimeData = nullptr; + QDropEvent *dropEvent = static_cast(event); + if (isQuickWindow(dropEvent->source())) { + QuickPluginMimeData *mimeData = static_cast(const_cast(dropEvent->mimeData())); + if (mimeData) + dragPlugin(mimeData->pluginItemInterface()); + } + break; + } + default: + break; + } + return QWidget::eventFilter(watched, event); +} + +void QuickPluginWindow::dragEnterEvent(QDragEnterEvent *event) +{ + // 由于QuickPluginMimeData和QuickIconDrag的来源是pluginManager插件,dock和插件中都使用了这两个类,但是这个两个类 + // 是各自编译的,相当于编译了两份,所以使用qobject_cast会导致转换失败,因此,此处使用dynamic_cast来保证转换成功 + m_dragEnterMimeData = dynamic_cast(const_cast(event->mimeData())); + if (m_dragEnterMimeData) { + PluginsItemInterface *plugin = m_dragEnterMimeData->pluginItemInterface(); + QIcon icon = plugin->icon(DockPart::QuickShow); + if (icon.isNull()) { + QWidget *widget = plugin->itemWidget(QuickSettingController::instance()->itemKey(plugin)); + if (widget) + icon = widget->grab(); + } + QuickIconDrag *drag = dynamic_cast(m_dragEnterMimeData->drag()); + if (drag && !icon.isNull()) { + QPixmap pixmap = icon.pixmap(QSize(16, 16)); + drag->updatePixmap(pixmap); + } + event->accept(); + } else { + event->ignore(); + } +} + +void QuickPluginWindow::dragLeaveEvent(QDragLeaveEvent *event) +{ + if (m_dragEnterMimeData) { + QPoint mousePos = topLevelWidget()->mapFromGlobal(QCursor::pos()); + QuickIconDrag *drag = qobject_cast(m_dragEnterMimeData->drag()); + if (!topLevelWidget()->rect().contains(mousePos) && drag) { + drag->useSourcePixmap(); + } + m_dragEnterMimeData = nullptr; + } + event->accept(); +} + +void QuickPluginWindow::onRequestUpdate() +{ + bool countChanged = false; + QuickPluginModel *model = QuickPluginModel::instance(); + QList plugins = model->dockedPluginItems(); + // 先删除所有的widget + QMap pluginItems; + for (int i = m_mainLayout->count() - 1; i >= 0; i--) { + QLayoutItem *layoutItem = m_mainLayout->itemAt(i); + if (!layoutItem) + continue; + + QuickDockItem *dockItem = qobject_cast(layoutItem->widget()); + if (!dockItem) + continue; + + dockItem->setParent(nullptr); + m_mainLayout->removeItem(layoutItem); + if (plugins.contains(dockItem->pluginItem())) { + // 如果该插件在任务栏上,则先将其添加到临时列表中 + pluginItems[dockItem->pluginItem()] = dockItem; + } else { + DockPopupWindow *popupWindow = getPopWindow(); + if (popupWindow->isVisible()) { + // 该插件被移除的情况下,判断弹出窗口是否在当前的插件中打开的,如果是,则隐藏该窗口 + if (popupWindow->extengWidget() == dockItem) + popupWindow->hide(); + } + // 如果该插件不在任务栏上,则先删除 + dockItem->deleteLater(); + countChanged = true; + } + } + + // 将列表中所有的控件按照顺序添加到布局上 + QuickSettingController *quickController = QuickSettingController::instance(); + for (PluginsItemInterface *item : plugins) { + QuickDockItem *itemWidget = nullptr; + if (pluginItems.contains(item)) { + itemWidget = pluginItems[item]; + } else { + itemWidget = new QuickDockItem(item, quickController->itemKey(item), this); + itemWidget->setPosition(m_position); + updateDockItemSize(itemWidget); + itemWidget->installEventFilter(this); + itemWidget->setMouseTracking(true); + countChanged = true; + } + itemWidget->setParent(this); + m_mainLayout->addWidget(itemWidget); + } + + if (countChanged) + Q_EMIT itemCountChanged(); +} + +QPoint QuickPluginWindow::popupPoint(QWidget *widget) const +{ + QWidget *itemWidget = widget; + if (!itemWidget && m_mainLayout->count() > 0) + itemWidget = m_mainLayout->itemAt(0)->widget(); + + if (!itemWidget) + return QPoint(); + + QPoint pointCurrent = itemWidget->mapToGlobal(QPoint(0, 0)); + switch (m_position) { + case Dock::Position::Bottom: { + // 在下方的时候,Y坐标设置在顶层窗口的y值,保证下方对齐 + pointCurrent.setX(pointCurrent.x() + itemWidget->width() / 2); + pointCurrent.setY(topLevelWidget()->y()); + break; + } + case Dock::Position::Top: { + // 在上面的时候,Y坐标设置为任务栏的下方,保证上方对齐 + pointCurrent.setX(pointCurrent.x() + itemWidget->width() / 2); + pointCurrent.setY(topLevelWidget()->y() + topLevelWidget()->height()); + break; + } + case Dock::Position::Left: { + // 在左边的时候,X坐标设置在顶层窗口的最右侧,保证左对齐 + pointCurrent.setX(topLevelWidget()->x() + topLevelWidget()->width()); + pointCurrent.setY(pointCurrent.y() + itemWidget->height() / 2); + break; + } + case Dock::Position::Right: { + // 在右边的时候,X坐标设置在顶层窗口的最左侧,保证右对齐 + pointCurrent.setX(topLevelWidget()->x()); + pointCurrent.setY(pointCurrent.y() + itemWidget->height() / 2); + } + } + return pointCurrent; +} + +void QuickPluginWindow::onUpdatePlugin(PluginsItemInterface *itemInter, const DockPart &dockPart) +{ + //update plugin status + if (dockPart != DockPart::QuickShow) + return; + + QuickDockItem *quickDockItem = getDockItemByPlugin(itemInter); + if (quickDockItem) { + updateDockItemSize(quickDockItem); + quickDockItem->update(); + } +} + +void QuickPluginWindow::onRequestAppletVisible(PluginsItemInterface *itemInter, const QString &itemKey, bool visible) +{ + if (visible) + showPopup(getDockItemByPlugin(itemInter), itemInter, itemInter->itemPopupApplet(itemKey), false); + else + getPopWindow()->hide(); +} + +void QuickPluginWindow::startDrag() +{ + if (!m_dragInfo->dockItem) + return; + + PluginsItemInterface *moveItem = m_dragInfo->dockItem->pluginItem(); + //AppDrag *drag = new AppDrag(this, new QuickDragWidget); + QDrag *drag = new QDrag(this); + QuickPluginMimeData *mimedata = new QuickPluginMimeData(moveItem, drag); + drag->setMimeData(mimedata); + QPixmap dragPixmap = m_dragInfo->dragPixmap(); + drag->setPixmap(dragPixmap); + + drag->setHotSpot(dragPixmap.rect().center()); + + drag->exec(Qt::CopyAction); + // 获取当前鼠标在任务栏快捷图标区域的位置 + QPoint currentPoint = mapFromGlobal(QCursor::pos()); + // 获取区域图标插入的位置 + QuickPluginModel::instance()->addPlugin(mimedata->pluginItemInterface(), getDropIndex(currentPoint)); +} + +QuickDockItem *QuickPluginWindow::getDockItemByPlugin(PluginsItemInterface *item) +{ + if (!item) + return nullptr; + + for (int i = 0; i < m_mainLayout->count(); i++) { + QLayoutItem *layoutItem = m_mainLayout->itemAt(i); + if (!layoutItem) + continue; + + QuickDockItem *dockItem = qobject_cast(layoutItem->widget()); + if (!dockItem) + continue; + + if (dockItem->pluginItem() == item) + return dockItem; + } + + return nullptr; +} + +QuickDockItem *QuickPluginWindow::getActiveDockItem(QPoint point) const +{ + QuickDockItem *selectWidget = qobject_cast(childAt(point)); + if (!selectWidget) + return nullptr; + + // 如果当前图标是固定插件,则不让插入 + if (QuickPluginModel::instance()->isFixed(selectWidget->pluginItem())) + return nullptr; + + return selectWidget; +} + +void QuickPluginWindow::showPopup(QuickDockItem *item, PluginsItemInterface *itemInter, QWidget *childPage, bool isClicked) +{ + if (!isVisible() || !item) + return; + + if (!childPage) { + const QString itemKey = QuickSettingController::instance()->itemKey(itemInter); + QStringList commandArgument = itemInter->itemCommand(itemKey).split(" "); + if (commandArgument.size() > 0) { + QString command = commandArgument.first(); + commandArgument.removeFirst(); + QProcess::startDetached(command, commandArgument); + } + return; + } + + DockPopupWindow *popWindow = getPopWindow(); + if (isClicked && popWindow->isVisible()) { + // 如果是点击插件,并且该插件曾经打开快捷面板且已经是显示状态,那么就直接隐藏快捷面板 + popWindow->hide(); + return; + } + + if (!popWindow->isVisible()) { + if (Utils::IS_WAYLAND_DISPLAY) { + // TODO: 临时解决方案,如果是wayland环境,toolTip没有消失,因此,此处直接调用接口来隐藏 + for (int i = m_mainLayout->count() - 1; i >= 0; i--) { + QLayoutItem *layoutItem = m_mainLayout->itemAt(i); + if (!layoutItem) + continue; + + QuickDockItem *dockItem = qobject_cast(layoutItem->widget()); + if (!dockItem) + continue; + + dockItem->hideToolTip(); + } + } + + PopupSwitchWidget *switchWidget = static_cast(popWindow->getContent()); + switchWidget->installEventFilter(this); + switchWidget->pushWidget(childPage); + popWindow->setExtendWidget(item); + popWindow->show(popupPoint(item), true); + } +} + +QList QuickPluginWindow::quickDockItems() +{ + QList dockItems; + for (int i = 0; i < m_mainLayout->count(); i++) { + QLayoutItem *layoutItem = m_mainLayout->itemAt(i); + if (!layoutItem) + continue; + + QuickDockItem *dockedItem = qobject_cast(layoutItem->widget()); + if (!dockedItem) + continue; + + dockItems << dockedItem; + } + + return dockItems; +} + +// 根据位置获取箭头的方向 +static DArrowRectangle::ArrowDirection getDirection(const Dock::Position &position) +{ + switch (position) { + case Dock::Position::Top: + return DArrowRectangle::ArrowDirection::ArrowTop; + case Dock::Position::Left: + return DArrowRectangle::ArrowDirection::ArrowLeft; + case Dock::Position::Right: + return DArrowRectangle::ArrowDirection::ArrowRight; + default: + return DArrowRectangle::ArrowDirection::ArrowBottom; + } + + return DArrowRectangle::ArrowDirection::ArrowBottom; +} + +DockPopupWindow *QuickPluginWindow::getPopWindow() const +{ + static DockPopupWindow *popWindow = nullptr; + if (popWindow) + return popWindow; + + popWindow = new DockPopupWindow; + popWindow->setShadowBlurRadius(20); + popWindow->setRadius(18); + popWindow->setShadowYOffset(2); + popWindow->setShadowXOffset(0); + popWindow->setArrowWidth(18); + popWindow->setArrowHeight(10); + popWindow->setArrowDirection(getDirection(m_position)); + popWindow->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); + PopupSwitchWidget *content = new PopupSwitchWidget(popWindow); + popWindow->setContent(content); + return popWindow; +} + +void QuickPluginWindow::updateDockItemSize(QuickDockItem *dockItem) +{ + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + dockItem->setFixedSize(dockItem->suitableSize().width(), height()); + } else { + dockItem->setFixedSize(width(), dockItem->suitableSize().height()); + } +} + +void QuickPluginWindow::resizeDockItem() +{ + for (int i = 0; i < m_mainLayout->count(); i++) { + QuickDockItem *dockItemWidget = qobject_cast(m_mainLayout->itemAt(i)->widget()); + if (dockItemWidget) { + updateDockItemSize(dockItemWidget); + } + } +} + +int QuickPluginWindow::getDropIndex(QPoint point) +{ + QList dockedItems = quickDockItems(); + QuickDockItem *targetItem = getActiveDockItem(point); + if (targetItem) { + for (int i = 0; i < dockedItems.count(); i++) { + if (dockedItems[i] == targetItem) + return i; + } + + return -1; + } + + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + // 上下方向从右向左排列 + for (int i = 0; i < dockedItems.count() - 1; i++) { + QuickDockItem *dockBeforeItem = dockedItems[i]; + QuickDockItem *dockItem = dockedItems[i + 1]; + if (!dockItem->canInsert()) + continue; + + if (dockBeforeItem->geometry().x() > point.x() && dockItem->geometry().right() < point.x()) + return i; + } + } else { + // 左右方向从下向上排列 + for (int i = 0; i < dockedItems.count() - 1; i++) { + QuickDockItem *dockBeforeItem = dockedItems[i]; + QuickDockItem *dockItem = dockedItems[i + 1]; + if (!dockItem->canInsert()) + continue; + + if (dockBeforeItem->geometry().bottom() > point.y() && dockItem->geometry().top() < point.y()) + return i; + } + } + // 如果都没有找到,直接插入到最后 + return -1; +} + +void QuickPluginWindow::dragMoveEvent(QDragMoveEvent *event) +{ + event->accept(); +} + +void QuickPluginWindow::resizeEvent(QResizeEvent *event) +{ + resizeDockItem(); + QWidget::resizeEvent(event); +} + +void QuickPluginWindow::initConnection() +{ + QuickPluginModel *model = QuickPluginModel::instance(); + connect(model, &QuickPluginModel::requestUpdate, this, &QuickPluginWindow::onRequestUpdate); + connect(model, &QuickPluginModel::requestUpdatePlugin, this, &QuickPluginWindow::onUpdatePlugin); + connect(QuickSettingController::instance(), &QuickSettingController::requestAppletVisible, this, &QuickPluginWindow::onRequestAppletVisible); +} + +/** + * @brief QuickDockItem::QuickDockItem + * @param pluginItem + * @param parent + */ + +QuickDockItem::QuickDockItem(PluginsItemInterface *pluginItem, const QString &itemKey, QWidget *parent) + : QWidget(parent) + , m_pluginItem(pluginItem) + , m_itemKey(itemKey) + , m_position(Dock::Position::Bottom) + , m_popupWindow(new DockPopupWindow) + , m_contextMenu(new QMenu(this)) + , m_tipParent(nullptr) + , m_mainWidget(nullptr) + , m_mainLayout(nullptr) + , m_dockItemParent(nullptr) + , m_isEnter(false) +{ + initUi(); + initConnection(); + initAttribute(); +} + +QuickDockItem::~QuickDockItem() +{ + QWidget *tipWidget = m_pluginItem->itemTipsWidget(m_itemKey); + if (tipWidget && (tipWidget->parentWidget() == m_popupWindow || tipWidget->parentWidget() == this)) + tipWidget->setParent(m_tipParent); + + QWidget *itemWidget = m_pluginItem->itemWidget(m_itemKey); + if (itemWidget) { + itemWidget->setParent(nullptr); + itemWidget->hide(); + } + m_popupWindow->deleteLater(); +} + +void QuickDockItem::setPosition(Dock::Position position) +{ + m_position = position; + updateWidgetSize(); + if (m_mainLayout) { + QWidget *itemWidget = m_pluginItem->itemWidget(m_itemKey); + if (itemWidget && m_mainLayout->indexOf(itemWidget) < 0) { + itemWidget->setFixedSize(suitableSize()); + } + } +} + +PluginsItemInterface *QuickDockItem::pluginItem() +{ + return m_pluginItem; +} + +bool QuickDockItem::canInsert() const +{ + return (m_pluginItem->flags() & PluginFlag::Attribute_CanInsert); +} + +bool QuickDockItem::canMove() const +{ + return (m_pluginItem->flags() & PluginFlag::Attribute_CanDrag); +} + +void QuickDockItem::hideToolTip() +{ + m_popupWindow->hide(); +} + +QSize QuickDockItem::suitableSize() const +{ + int widgetSize = (m_pluginItem->displayMode() == Dock::DisplayMode::Efficient) ? 24 : 30; + if (m_pluginItem->pluginSizePolicy() == PluginsItemInterface::PluginSizePolicy::Custom) { + QPixmap pixmap = iconPixmap(); + if (!pixmap.isNull()) { + QSize size = pixmap.size(); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + if (size.width() < widgetSize) { + size.setWidth(widgetSize); + } else { + int scaleWidth = size.width() / (size.height() / (widgetSize * 1.0f)); + size.setWidth(scaleWidth); + } + return size; + } + if (size.height() < widgetSize) { + size.setHeight(widgetSize); + } else { + int scaleHeight = size.height() / (size.width() / (widgetSize * 1.0f)); + size.setHeight(scaleHeight); + } + return size; + } + + QWidget *itemWidget = m_pluginItem->itemWidget(m_itemKey); + if (itemWidget) { + int itemWidth = widgetSize; + int itemHeight = ICONHEIGHT; + QSize itemSize = itemWidget->sizeHint(); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + if (itemSize.width() > widgetSize) + itemWidth = itemSize.width(); + if (itemSize.height() > 0 && itemSize.height() <= topLevelWidget()->height()) + itemHeight = itemSize.height(); + } else { + if (itemSize.width() > 0 && itemSize.width() < topLevelWidget()->width()) + itemWidth = itemSize.width(); + if (itemSize.height() > widgetSize && itemSize.height() < ICONHEIGHT) + itemHeight = itemSize.height(); + } + + return QSize(itemWidth, itemHeight); + } + } + + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + return QSize(widgetSize, ICONHEIGHT); + + return QSize(ICONWIDTH, widgetSize); +} + +void QuickDockItem::paintEvent(QPaintEvent *event) +{ + if (!m_pluginItem) + return QWidget::paintEvent(event); + + QPainter painter(this); + QColor backColor = DGuiApplicationHelper::ColorType::DarkType == DGuiApplicationHelper::instance()->themeType() ? QColor(20, 20, 20) : Qt::white; + backColor.setAlphaF(0.2); + if (m_isEnter) { + // 鼠标进入的时候,绘制底色 + QPainterPath path; + int borderRadius = shadowRadius(); + QRect rectBackground; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + int backHeight = qBound(20, height() - 4, 30); + rectBackground.setTop((height() - backHeight) / 2); + rectBackground.setHeight(backHeight); + rectBackground.setWidth(width()); + path.addRoundedRect(rectBackground, borderRadius, borderRadius); + } else { + int backWidth = qBound(20, width() - 4, 30); + rectBackground.setLeft((width() - backWidth) / 2); + rectBackground.setWidth(backWidth); + rectBackground.setHeight(height()); + path.addRoundedRect(rectBackground, borderRadius, borderRadius); + } + painter.fillPath(path, backColor); + } + + QPixmap pixmap = iconPixmap(); + if (pixmap.isNull()) + return QWidget::paintEvent(event); + + pixmap.setDevicePixelRatio(qApp->devicePixelRatio()); + + QSize size = QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? pixmap.size() / qApp->devicePixelRatio(): pixmap.size(); + QRect pixmapRect = QRect(QPoint((rect().width() - size.width()) / 2, (rect().height() - size.height()) / 2), size); + painter.drawPixmap(pixmapRect, pixmap); +} + +void QuickDockItem::mousePressEvent(QMouseEvent *event) +{ + if (event->button() != Qt::RightButton) + return QWidget::mousePressEvent(event); + + if (m_contextMenu->actions().isEmpty()) { + const QString menuJson = m_pluginItem->itemContextMenu(m_itemKey); + if (menuJson.isEmpty()) + return; + + QJsonDocument jsonDocument = QJsonDocument::fromJson(menuJson.toLocal8Bit().data()); + if (jsonDocument.isNull()) + return; + + QJsonObject jsonMenu = jsonDocument.object(); + + QJsonArray jsonMenuItems = jsonMenu.value("items").toArray(); + for (auto item : jsonMenuItems) { + QJsonObject itemObj = item.toObject(); + QAction *action = new QAction(itemObj.value("itemText").toString()); + action->setCheckable(itemObj.value("isCheckable").toBool()); + action->setChecked(itemObj.value("checked").toBool()); + action->setData(itemObj.value("itemId").toString()); + action->setEnabled(itemObj.value("isActive").toBool()); + m_contextMenu->addAction(action); + } + } + + m_contextMenu->exec(QCursor::pos()); +} + +void QuickDockItem::enterEvent(QEvent *event) +{ + m_isEnter = true; + update(); + QWidget::enterEvent(event); + + QWidget *tipWidget = m_pluginItem->itemTipsWidget(m_itemKey); + if (!tipWidget) + return; + + // 记录下toolTip的parent,因为在调用DockPopupWindow的时候会将DockPopupWindow设置为toolTip的parent, + // 在DockPopupWindow对象释放的时候, 会将toolTip也一起给释放 + if (tipWidget->parentWidget() != m_popupWindow) + m_tipParent = tipWidget->parentWidget(); + + switch (m_position) { + case Top: + m_popupWindow->setArrowDirection(DockPopupWindow::ArrowTop); + break; + case Bottom: + m_popupWindow->setArrowDirection(DockPopupWindow::ArrowBottom); + break; + case Left: + m_popupWindow->setArrowDirection(DockPopupWindow::ArrowLeft); + break; + case Right: + m_popupWindow->setArrowDirection(DockPopupWindow::ArrowRight); + break; + } + + m_popupWindow->resize(tipWidget->sizeHint()); + m_popupWindow->setContent(tipWidget); + + m_popupWindow->show(popupMarkPoint()); +} + +void QuickDockItem::leaveEvent(QEvent *event) +{ + m_isEnter = false; + update(); + + QWidget::leaveEvent(event); + m_popupWindow->hide(); +} + +void QuickDockItem::showEvent(QShowEvent *event) +{ + if (!m_mainLayout) + return QWidget::showEvent(event); + + QWidget *itemWidget = m_pluginItem->itemWidget(m_itemKey); + if (itemWidget && m_mainLayout->indexOf(itemWidget) < 0) { + itemWidget->show(); + itemWidget->setFixedSize(suitableSize()); + m_mainLayout->addWidget(itemWidget); + } +} + +void QuickDockItem::hideEvent(QHideEvent *event) +{ + if (!m_mainLayout) + return QWidget::hideEvent(event); + + QWidget *itemWidget = m_pluginItem->itemWidget(m_itemKey); + if (itemWidget && m_mainLayout->indexOf(itemWidget) >= 0) { + itemWidget->setParent(m_dockItemParent); + itemWidget->hide(); + m_mainLayout->removeWidget(itemWidget); + } +} + +bool QuickDockItem::eventFilter(QObject *watched, QEvent *event) +{ + // 让插件来处理当前插件的事件 + if (watched == this) + return m_pluginItem->eventHandler(event); + + return QWidget::eventFilter(watched, event); +} + +void QuickDockItem::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + updateWidgetSize(); +} + +QPixmap QuickDockItem::iconPixmap() const +{ + QIcon icon = m_pluginItem->icon(DockPart::QuickShow); + if (!icon.isNull()) { + if (icon.availableSizes().size() > 0) { + QSize size = icon.availableSizes().first(); + return icon.pixmap(size); + } + int pixmapWidth = static_cast(ICONWIDTH * (QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? 1 : qApp->devicePixelRatio())); + int pixmapHeight = static_cast(ICONHEIGHT * (QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? 1 : qApp->devicePixelRatio())); + return icon.pixmap(pixmapWidth, pixmapHeight); + } + + return QPixmap(); +} + +void QuickDockItem::initUi() +{ + QPixmap pixmap = iconPixmap(); + if (!pixmap.isNull()) + return; + + m_topLayout = new QHBoxLayout(this); + m_topLayout->setContentsMargins(0, 0, 0, 0); + m_topLayout->setAlignment(Qt::AlignCenter); + m_mainWidget = new QWidget(this); + m_topLayout->addWidget(m_mainWidget); + updateWidgetSize(); + + m_mainLayout = new QHBoxLayout(m_mainWidget); + m_mainLayout->setContentsMargins(0, 0, 0, 0); + QWidget *itemWidget = m_pluginItem->itemWidget(m_itemKey); + if (itemWidget) { + m_dockItemParent = itemWidget->parentWidget(); + itemWidget->installEventFilter(this); + } +} + +void QuickDockItem::initAttribute() +{ + m_popupWindow->setShadowBlurRadius(20); + m_popupWindow->setRadius(6); + m_popupWindow->setShadowYOffset(2); + m_popupWindow->setShadowXOffset(0); + m_popupWindow->setArrowWidth(18); + m_popupWindow->setArrowHeight(10); + m_popupWindow->setObjectName("quickitempopup"); + if (Utils::IS_WAYLAND_DISPLAY) { + Qt::WindowFlags flags = m_popupWindow->windowFlags() | Qt::FramelessWindowHint; + m_popupWindow->setWindowFlags(flags); + } + + this->installEventFilter(this); +} + +void QuickDockItem::initConnection() +{ + connect(m_contextMenu, &QMenu::triggered, this, &QuickDockItem::onMenuActionClicked); + connect(qApp, &QApplication::aboutToQuit, m_popupWindow, &DockPopupWindow::deleteLater); +} + +void QuickDockItem::updateWidgetSize() +{ + if (!m_mainWidget) + return; + + QSize size = suitableSize(); + int width = size.width(); + int height = size.height(); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + // 上下方向 + m_mainWidget->setFixedSize(QWIDGETSIZE_MAX, height); + } else { + // 左右方向 + m_mainWidget->setFixedSize(width, QWIDGETSIZE_MAX); + } +} + +int QuickDockItem::shadowRadius() const +{ +#define EFFECTRADIUS 8 +#define MARGIN 4 + // 高效模式下固定为8 + if (m_pluginItem->displayMode() == Dock::DisplayMode::Efficient) + return EFFECTRADIUS; + + return qApp->property("trayBorderRadius").toInt() - MARGIN; +} + +int QuickDockItem::iconSize() const +{ + if (m_pluginItem->displayMode() == Dock::DisplayMode::Efficient) + return 24; + return 30; +} + +QPoint QuickDockItem::topleftPoint() const +{ + QPoint p = this->pos(); + /* 由于点击范围的问题,在图标的外面加了一层布局,这个布局的边距需要考虑 */ + switch (m_position) { + case Top: + p.setY(p.y() * 2); + break; + case Bottom: + p.setY(0); + break; + case Left: + p.setX(p.x() * 2); + break; + case Right: + p.setX(0); + break; + } + + QWidget *w = qobject_cast(this->parent()); + while (w) { + p += w->pos(); + w = qobject_cast(w->parent()); + } + + return p; +} + +QPoint QuickDockItem::popupMarkPoint() const +{ + QPoint p(topleftPoint()); + const QRect r = rect(); + switch (m_position) { + case Top: + p += QPoint(r.width() / 2, r.height()); + break; + case Bottom: + p += QPoint(r.width() / 2, 0); + break; + case Left: + p += QPoint(r.width(), r.height() / 2); + break; + case Right: + p += QPoint(0, r.height() / 2); + break; + } + return p; +} + +void QuickDockItem::onMenuActionClicked(QAction *action) +{ + m_pluginItem->invokedMenuItem(m_itemKey, action->data().toString(), true); +} diff --git a/frame/window/quickpluginwindow.h b/frame/window/quickpluginwindow.h new file mode 100644 index 000000000..a910ca881 --- /dev/null +++ b/frame/window/quickpluginwindow.h @@ -0,0 +1,142 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef QUICKPLUGINWINDOW_H +#define QUICKPLUGINWINDOW_H + +#include "constants.h" + +#include + +class QuickSettingItem; +class PluginsItemInterface; +class QHBoxLayout; +class QStandardItemModel; +class QStandardItem; +class QMouseEvent; +class QBoxLayout; +class QuickDockItem; +class DockPopupWindow; +class QMenu; +class QuickPluginMimeData; +enum class DockPart; + +namespace Dtk { namespace Widget { class DListView; class DStandardItem; } } + +using namespace Dtk::Widget; + +class QuickPluginWindow : public QWidget +{ + Q_OBJECT + +public: + explicit QuickPluginWindow(Dock::DisplayMode displayMode, QWidget *parent = nullptr); + ~QuickPluginWindow() override; + + void setPositon(Dock::Position position); + void dragPlugin(PluginsItemInterface *item); + + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; + + bool isQuickWindow(QObject *object) const; + +Q_SIGNALS: + void itemCountChanged(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragLeaveEvent(QDragLeaveEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private Q_SLOTS: + void onRequestUpdate(); + void onUpdatePlugin(PluginsItemInterface *itemInter, const DockPart &dockPart); + void onRequestAppletVisible(PluginsItemInterface * itemInter, const QString &itemKey, bool visible); + +private: + void initUi(); + void initConnection(); + void startDrag(); + PluginsItemInterface *findQuickSettingItem(const QPoint &mousePoint, const QList &settingItems); + int getDropIndex(QPoint point); + QPoint popupPoint(QWidget *widget) const; + QuickDockItem *getDockItemByPlugin(PluginsItemInterface *item); + QuickDockItem *getActiveDockItem(QPoint point) const; + void showPopup(QuickDockItem *item, PluginsItemInterface *itemInter = nullptr, QWidget *childPage = nullptr, bool isClicked = true); + QList quickDockItems(); + DockPopupWindow *getPopWindow() const; + void updateDockItemSize(QuickDockItem *dockItem); + void resizeDockItem(); + +private: + QBoxLayout *m_mainLayout; + Dock::Position m_position; + struct DragInfo *m_dragInfo; + QuickPluginMimeData *m_dragEnterMimeData; + Dock::DisplayMode m_displayMode; +}; + +// 用于在任务栏上显示的插件 +class QuickDockItem : public QWidget +{ + Q_OBJECT + +public: + explicit QuickDockItem(PluginsItemInterface *pluginItem, const QString &itemKey, QWidget *parent = nullptr); + ~QuickDockItem(); + + void setPosition(Dock::Position position); + PluginsItemInterface *pluginItem(); + bool canInsert() const; + bool canMove() const; + void hideToolTip(); + + QSize suitableSize() const; + +protected: + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private: + QPoint topleftPoint() const; + QPoint popupMarkPoint() const; + + QPixmap iconPixmap() const; + + void initUi(); + void initAttribute(); + void initConnection(); + + void updateWidgetSize(); + int shadowRadius() const; + int iconSize() const; + +private Q_SLOTS: + void onMenuActionClicked(QAction *action); + +private: + PluginsItemInterface *m_pluginItem; + QString m_itemKey; + Dock::Position m_position; + DockPopupWindow *m_popupWindow; + QMenu *m_contextMenu; + QWidget *m_tipParent; + QHBoxLayout *m_topLayout; + QWidget *m_mainWidget; + QHBoxLayout *m_mainLayout; + QWidget *m_dockItemParent; + bool m_isEnter; +}; + +#endif // QUICKPLUGINWINDOW_H diff --git a/frame/window/systempluginwindow.cpp b/frame/window/systempluginwindow.cpp new file mode 100644 index 000000000..c7abc89b7 --- /dev/null +++ b/frame/window/systempluginwindow.cpp @@ -0,0 +1,421 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "systempluginwindow.h" +#include "systempluginitem.h" +#include "quicksettingcontroller.h" +#include "utils.h" + +#include +#include + +#include +#include +#include +#include + +#define MAXICONSIZE 48 +#define MINICONSIZE 24 +#define ICONMARGIN 8 + +SystemPluginWindow::SystemPluginWindow(DockInter *dockInter, QWidget *parent) + : QWidget(parent) + , m_listView(new DListView(this)) + , m_displayMode(Dock::DisplayMode::Efficient) + , m_position(Dock::Position::Bottom) + , m_mainLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this)) + , m_dockInter(dockInter) +{ + initUi(); + initConnection(); +} + +SystemPluginWindow::~SystemPluginWindow() +{ +} + +void SystemPluginWindow::setDisplayMode(const DisplayMode &displayMode) +{ + m_displayMode = displayMode; + QList items = stretchItems(); + switch (m_position) { + case Dock::Position::Top: + case Dock::Position::Bottom: { + for (StretchPluginsItem *item : items) + item->setDisplayMode(displayMode); + break; + } + case Dock::Position::Left: + case Dock::Position::Right: { + for (StretchPluginsItem *item : items) + item->setDisplayMode(displayMode); + break; + } + } +} + +void SystemPluginWindow::setPositon(Position position) +{ + if (m_position == position) + return; + + m_position = position; + + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); + else + m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); + + StretchPluginsItem::setPosition(position); + + QObjectList childObjects = children(); + for (QObject *childObject : childObjects) { + StretchPluginsItem *item = qobject_cast(childObject); + if (!item) + continue; + + item->update(); + } +} + +QSize SystemPluginWindow::suitableSize() const +{ + return suitableSize(m_position); +} + +QSize SystemPluginWindow::suitableSize(const Position &position) const +{ + QList items = stretchItems(); + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + int itemWidth = 0; + for (StretchPluginsItem *item : items) + itemWidth += item->suitableSize(position).width(); + + return QSize(itemWidth, QWIDGETSIZE_MAX); + } + + int itemHeight = 0; + for (StretchPluginsItem *item : items) + itemHeight += item->suitableSize(position).height(); + + return QSize(QWIDGETSIZE_MAX, itemHeight); +} + +bool SystemPluginWindow::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::Drop) + Q_EMIT requestDrop(static_cast(event)); + + return QWidget::eventFilter(watched, event); +} + +void SystemPluginWindow::initUi() +{ + m_mainLayout->setContentsMargins(0, 0, 0, 0); + m_mainLayout->setSpacing(0); + installEventFilter(this); +} + +void SystemPluginWindow::initConnection() +{ + QuickSettingController *quickController = QuickSettingController::instance(); + connect(quickController, &QuickSettingController::pluginInserted, this, [ = ](PluginsItemInterface *itemInter, const QuickSettingController::PluginAttribute pluginAttr) { + if (pluginAttr != QuickSettingController::PluginAttribute::System) + return; + + pluginAdded(itemInter); + }); + + connect(quickController, &QuickSettingController::pluginRemoved, this, &SystemPluginWindow::onPluginItemRemoved); + connect(quickController, &QuickSettingController::pluginUpdated, this, &SystemPluginWindow::onPluginItemUpdated); + + QList plugins = quickController->pluginItems(QuickSettingController::PluginAttribute::System); + for (int i = 0; i < plugins.size(); i++) + pluginAdded(plugins[i]); +} + +StretchPluginsItem *SystemPluginWindow::findPluginItemWidget(PluginsItemInterface *pluginItem) +{ + for (int i = 0; i < m_mainLayout->count(); i++) { + QLayoutItem *layoutItem = m_mainLayout->itemAt(i); + if (!layoutItem) + continue; + + StretchPluginsItem *itemWidget = qobject_cast(layoutItem->widget()); + if (itemWidget && itemWidget->pluginInter() == pluginItem) + return itemWidget; + } + + return nullptr; +} + +void SystemPluginWindow::pluginAdded(PluginsItemInterface *plugin) +{ + StretchPluginsItem *item = new StretchPluginsItem(m_dockInter, plugin, QuickSettingController::instance()->itemKey(plugin)); + item->setDisplayMode(m_displayMode); + item->setPosition(m_position); + item->installEventFilter(this); + item->setParent(this); + item->show(); + m_mainLayout->addWidget(item); + Q_EMIT itemChanged(); +} + +QList SystemPluginWindow::stretchItems() const +{ + QList items; + QObjectList childObjects = children(); + for (QObject *childObject : childObjects) { + StretchPluginsItem *item = qobject_cast(childObject); + if (!item) + continue; + + items << item; + } + return items; +} + +void SystemPluginWindow::onPluginItemRemoved(PluginsItemInterface *pluginItem) +{ + StretchPluginsItem *item = findPluginItemWidget(pluginItem); + if (item) { + item->setParent(nullptr); + item->hide(); + m_mainLayout->removeWidget(item); + Q_EMIT itemChanged(); + } +} + +void SystemPluginWindow::onPluginItemUpdated(PluginsItemInterface *pluginItem) +{ + StretchPluginsItem *item = findPluginItemWidget(pluginItem); + if (item) + item->update(); +} + +// 图标的尺寸 +#define ICONSIZE 20 +#define ICONTEXTSPACE 6 +#define PLUGIN_ITEM_DRAG_THRESHOLD 20 + +Dock::Position StretchPluginsItem::m_position = Dock::Position::Bottom; + +StretchPluginsItem::StretchPluginsItem(DockInter *dockInter, PluginsItemInterface * const pluginInter, const QString &itemKey, QWidget *parent) + : DockItem(parent) + , m_pluginInter(pluginInter) + , m_itemKey(itemKey) + , m_displayMode(Dock::DisplayMode::Efficient) + , m_dockInter(dockInter) + , m_isEnter(false) +{ +} + +StretchPluginsItem::~StretchPluginsItem() +{ +} + +void StretchPluginsItem::setDisplayMode(const DisplayMode &displayMode) +{ + m_displayMode = displayMode; +} + +void StretchPluginsItem::setPosition(Position position) +{ + m_position = position; +} + +QString StretchPluginsItem::itemKey() const +{ + return m_itemKey; +} + +QSize StretchPluginsItem::suitableSize() const +{ + return suitableSize(m_position); +} + +PluginsItemInterface *StretchPluginsItem::pluginInter() const +{ + return m_pluginInter; +} + +void StretchPluginsItem::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + QPainter painter(this); + QIcon icon = m_pluginInter->icon(DockPart::SystemPanel); + + QRect rctPixmap(rect()); + if (needShowText()) { + int textHeight = QFontMetrics(textFont()).height(); + // 文本与图标的间距为6 + int iconTop = (height() - textHeight - ICONSIZE - ICONTEXTSPACE) / 2; + rctPixmap.setX((width() - ICONSIZE) / 2); + rctPixmap.setY(iconTop); + rctPixmap.setWidth(ICONSIZE); + rctPixmap.setHeight(ICONSIZE); + // 先绘制下面的文本 + painter.setFont(textFont()); + painter.drawText(QRect(0, iconTop + ICONSIZE + ICONTEXTSPACE, width(), textHeight), Qt::AlignCenter, m_pluginInter->pluginDisplayName()); + } else { + rctPixmap.setX((width() - ICONSIZE) / 2); + rctPixmap.setY((height() - ICONSIZE) / 2); + rctPixmap.setWidth(ICONSIZE); + rctPixmap.setHeight(ICONSIZE); + } + + if (m_isEnter) { + QColor backColor = DGuiApplicationHelper::ColorType::DarkType == DGuiApplicationHelper::instance()->themeType() ? QColor(20, 20, 20) : Qt::white; + backColor.setAlphaF(0.2); + // 鼠标进入的时候,绘制底色 + painter.fillRect(rect(), backColor); + } + // 绘制图标 + int iconSize = static_cast(ICONSIZE * (QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? 1 : qApp->devicePixelRatio())); + painter.drawPixmap(rctPixmap, icon.pixmap(iconSize, iconSize)); +} + +QSize StretchPluginsItem::suitableSize(const Position &position) const +{ + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + int textWidth = 0; + if (needShowText()) + textWidth = QFontMetrics(textFont(position)).boundingRect(m_pluginInter->pluginDisplayName()).width(); + return QSize(qMax(textWidth, ICONSIZE) + (m_displayMode == Dock::DisplayMode::Efficient ? 5 : 10) * 2, -1); + } + + int height = 6; // 图标上边距6 + height += ICONSIZE; // 图标尺寸20 + if (m_displayMode == Dock::DisplayMode::Fashion) { + height += ICONTEXTSPACE; // 图标与文字间距6 + if (needShowText()) // 只有在显示文本的时候才计算文本的高度 + height += QFontMetrics(textFont(position)).height(); // 文本高度 + } + height += 4; // 下间距4 + return QSize(-1, height); +} + +QFont StretchPluginsItem::textFont() const +{ + return textFont(m_position); +} + +QFont StretchPluginsItem::textFont(const Position &position) const +{ + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + static QList fonts{ DFontSizeManager::instance()->t9(), + DFontSizeManager::instance()->t8(), + DFontSizeManager::instance()->t7(), + DFontSizeManager::instance()->t6() }; +#define MINHEIGHT 50 + // 如果当前的实际位置和请求的位置不一致,说明当前正在切换位置,此时将它的宽度作为它的高度(左到下切换的时候,左侧的宽度和下面的高度一致) + int size = (m_position == position ? height() : width()); + int index = qMin(qMax((size - MINHEIGHT) / 2, 0), fonts.size() - 1); + return fonts[index]; + } + + return DFontSizeManager::instance()->t10(); +} + +bool StretchPluginsItem::needShowText() const +{ + // 如果是高效模式,则不需要显示下面的文本 + if (m_displayMode == Dock::DisplayMode::Efficient) + return false; + + // 图标与文本,图标距离上方和文本距离下方的尺寸 +#define SPACEMARGIN 6 + // 文本的高度 +#define TEXTSIZE 14 + // 当前插件父窗口与顶层窗口的上下边距 +#define OUTMARGIN 7 + + // 任务栏在上方或者下方显示的时候,根据设计图,只有在当前区域高度大于50的时候才同时显示文本和图标 + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + return ((Utils::isDraging() ? topLevelWidget()->height() : m_dockInter->windowSizeFashion()) >= + (OUTMARGIN * 2 + SPACEMARGIN * 3 + ICONSIZE + TEXTSIZE)); + + return true; +} + +const QString StretchPluginsItem::contextMenu() const +{ + return m_pluginInter->itemContextMenu(m_itemKey); +} + +void StretchPluginsItem::invokedMenuItem(const QString &itemId, const bool checked) +{ + m_pluginInter->invokedMenuItem(m_itemKey, itemId, checked); +} + +QWidget *StretchPluginsItem::popupTips() +{ + return m_pluginInter->itemTipsWidget(m_itemKey); +} + +void StretchPluginsItem::mousePressEvent(QMouseEvent *e) +{ + m_hover = false; + update(); + + if (PopupWindow->isVisible()) + hideNonModel(); + + if (e->button() == Qt::LeftButton) + m_mousePressPoint = e->pos(); + + m_popupTipsDelayTimer->stop(); + hideNonModel(); + + if (e->button() == Qt::RightButton + && perfectIconRect().contains(e->pos())) + return showContextMenu(); + + DockItem::mousePressEvent(e); +} + +void StretchPluginsItem::mouseReleaseEvent(QMouseEvent *e) +{ + DockItem::mouseReleaseEvent(e); + + if (e->button() != Qt::LeftButton) + return; + + if (checkAndResetTapHoldGestureState() && e->source() == Qt::MouseEventSynthesizedByQt) + return; + + const QPoint distance = e->pos() - m_mousePressPoint; + if (distance.manhattanLength() < PLUGIN_ITEM_DRAG_THRESHOLD) + mouseClick(); +} + +void StretchPluginsItem::enterEvent(QEvent *event) +{ + m_isEnter = true; + update(); + DockItem::enterEvent(event); +} + +void StretchPluginsItem::leaveEvent(QEvent *event) +{ + m_isEnter = false; + update(); + DockItem::leaveEvent(event); +} + +void StretchPluginsItem::mouseClick() +{ + QStringList commandArgument = m_pluginInter->itemCommand(m_itemKey).split(" "); + if (commandArgument.size() > 0) { + QString command = commandArgument.first(); + commandArgument.removeFirst(); + QProcess::startDetached(command, commandArgument); + return; + } + + // request popup applet + if (QWidget *w = m_pluginInter->itemPopupApplet(m_itemKey)) + showPopupApplet(w); +} diff --git a/frame/window/systempluginwindow.h b/frame/window/systempluginwindow.h new file mode 100644 index 000000000..7da835d1b --- /dev/null +++ b/frame/window/systempluginwindow.h @@ -0,0 +1,105 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SYSTEMPLUGINWINDOW_H +#define SYSTEMPLUGINWINDOW_H + +#include "constants.h" +#include "dockitem.h" +#include "dbusutil.h" + +#include + +class StretchPluginsItem; +class QBoxLayout; +class PluginsItemInterface; + +namespace Dtk { namespace Widget { class DListView; } } + +DWIDGET_USE_NAMESPACE + +class SystemPluginWindow : public QWidget +{ + Q_OBJECT + +public: + explicit SystemPluginWindow(DockInter *dockInter, QWidget *parent = nullptr); + ~SystemPluginWindow() override; + void setDisplayMode(const Dock::DisplayMode &displayMode); + void setPositon(Dock::Position position); + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; + +Q_SIGNALS: + void itemChanged(); + void requestDrop(QDropEvent *dropEvent); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + void initUi(); + void initConnection(); + StretchPluginsItem *findPluginItemWidget(PluginsItemInterface *pluginItem); + void pluginAdded(PluginsItemInterface *plugin); + QList stretchItems() const; + +private Q_SLOTS: + void onPluginItemRemoved(PluginsItemInterface *pluginItem); + void onPluginItemUpdated(PluginsItemInterface *pluginItem); + +private: + DListView *m_listView; + Dock::DisplayMode m_displayMode; + Dock::Position m_position; + QBoxLayout *m_mainLayout; + DockInter *m_dockInter; +}; + +class StretchPluginsItem : public DockItem +{ + Q_OBJECT + +public: + StretchPluginsItem(DockInter *dockInter, PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent = nullptr); + ~StretchPluginsItem() override; + void setDisplayMode(const Dock::DisplayMode &displayMode); + static void setPosition(Dock::Position position); + PluginsItemInterface *pluginInter() const; + QString itemKey() const; + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; + + inline ItemType itemType() const override { return DockItem::StretchPlugin; } + +protected: + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + + const QString contextMenu() const override; + void invokedMenuItem(const QString &itemId, const bool checked) override; + + QWidget *popupTips() override; + +private: + void mouseClick(); + QFont textFont() const; + QFont textFont(const Dock::Position &position) const; + bool needShowText() const; + +private: + PluginsItemInterface *m_pluginInter; + QString m_itemKey; + Dock::DisplayMode m_displayMode; + static Dock::Position m_position; + QPoint m_mousePressPoint; + DockInter *m_dockInter; + bool m_isEnter; +}; + +#endif // SYSTEMPLUGINWINDOW_H diff --git a/frame/window/tray/dbustraymanager.cpp b/frame/window/tray/dbustraymanager.cpp new file mode 100644 index 000000000..16c4b54fb --- /dev/null +++ b/frame/window/tray/dbustraymanager.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dbustraymanager.h" + +/* + * Implementation of interface class DBusTrayManager + */ + +DBusTrayManager::DBusTrayManager(QObject *parent) + : QDBusAbstractInterface("org.deepin.dde.TrayManager1", "/org/deepin/dde/TrayManager1", staticInterfaceName(), QDBusConnection::sessionBus(), parent) +{ + qRegisterMetaType("TrayList"); + qDBusRegisterMetaType(); + + QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); +} + +DBusTrayManager::~DBusTrayManager() +{ + QDBusConnection::sessionBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); +} + diff --git a/frame/window/tray/dbustraymanager.h b/frame/window/tray/dbustraymanager.h new file mode 100644 index 000000000..d62fe9b76 --- /dev/null +++ b/frame/window/tray/dbustraymanager.h @@ -0,0 +1,108 @@ +// Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DBUSTRAYMANAGER_H_1467094672 +#define DBUSTRAYMANAGER_H_1467094672 + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef QList TrayList; + +/* + * Proxy class for interface org.deepin.dde.TrayManager1 + */ +class DBusTrayManager: public QDBusAbstractInterface +{ + Q_OBJECT + + Q_SLOT void __propertyChanged__(const QDBusMessage& msg) + { + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName !="org.deepin.dde.TrayManager1") + return; + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + foreach(const QString &prop, changedProps.keys()) { + const QMetaObject* self = metaObject(); + for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { + QMetaProperty p = self->property(i); + if (p.name() == prop) { + Q_EMIT p.notifySignal().invoke(this); + } + } + } + } +public: + static inline const char *staticInterfaceName() + { return "org.deepin.dde.TrayManager1"; } + +public: + explicit DBusTrayManager(QObject *parent = 0); + + ~DBusTrayManager(); + + Q_PROPERTY(TrayList TrayIcons READ trayIcons NOTIFY TrayIconsChanged) + inline TrayList trayIcons() const + { return qvariant_cast< TrayList >(property("TrayIcons")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> EnableNotification(uint in0, bool in1) + { + QList argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("EnableNotification"), argumentList); + } + + inline QDBusPendingReply GetName(uint in0) + { + QList argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("GetName"), argumentList); + } + + inline QDBusPendingReply Manage() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Manage"), argumentList); + } + + inline QDBusPendingReply<> RetryManager() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("RetryManager"), argumentList); + } + + inline QDBusPendingReply Unmanage() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Unmanage"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void Added(uint in0); + void Changed(uint in0); + void Inited(); + void Removed(uint in0); +// begin property changed signals +void TrayIconsChanged(); +}; + +namespace com { + namespace deepin { + namespace dde { + typedef ::DBusTrayManager TrayManager; + } + } +} +#endif diff --git a/frame/window/tray/tray_delegate.cpp b/frame/window/tray/tray_delegate.cpp new file mode 100644 index 000000000..0ef22c053 --- /dev/null +++ b/frame/window/tray/tray_delegate.cpp @@ -0,0 +1,279 @@ +// Copyright (C) 2018 ~ 2025 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "tray_delegate.h" +#include "tray_gridview.h" +#include "tray_model.h" +#include "widgets/xembedtrayitemwidget.h" +#include "widgets/indicatortrayitem.h" +#include "widgets/indicatorplugin.h" +#include "widgets/snitrayitemwidget.h" +#include "widgets/expandiconwidget.h" +#include "utils.h" +#include "constants.h" +#include "pluginsiteminterface.h" +#include "quicksettingcontroller.h" +#include "systempluginitem.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +TrayDelegate::TrayDelegate(QListView *view, QObject *parent) + : QStyledItemDelegate(parent) + , m_position(Dock::Position::Bottom) + , m_listView(view) +{ + connect(this, &TrayDelegate::requestDrag, this, &TrayDelegate::onUpdateExpand); +} + +void TrayDelegate::setPositon(Dock::Position position) +{ + m_position = position; + SNITrayItemWidget::setDockPostion(position); + SystemPluginItem::setDockPostion(m_position); +} + +QWidget *TrayDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option); + + TrayIconType type = index.data(TrayModel::TypeRole).value(); + QString key = index.data(TrayModel::KeyRole).value(); + QString servicePath = index.data(TrayModel::ServiceRole).value(); + quint32 winId = index.data(TrayModel::WinIdRole).value(); + + BaseTrayWidget *trayWidget = nullptr; + if(type == TrayIconType::XEmbed) { + if (Utils::IS_WAYLAND_DISPLAY) { + static Display *display = XOpenDisplay(nullptr); + static int screenp = 0; + static xcb_connection_t *xcb_connection = xcb_connect(qgetenv("DISPLAY"), &screenp); + trayWidget = new XEmbedTrayItemWidget(winId, xcb_connection, display, parent); + } else { + trayWidget = new XEmbedTrayItemWidget(winId, nullptr, nullptr, parent); + } + const TrayModel *model = qobject_cast(index.model()); + if (model) + connect(model, &TrayModel::requestUpdateIcon, trayWidget, &BaseTrayWidget::updateIcon); + } else if (type == TrayIconType::Sni) { + trayWidget = new SNITrayItemWidget(servicePath, parent); + } else if (type == TrayIconType::ExpandIcon) { + ExpandIconWidget *expandWidget = new ExpandIconWidget(parent); + expandWidget->setPositon(m_position); + bool openExpand = index.data(TrayModel::ExpandRole).toBool(); + if (openExpand) + expandWidget->setTrayPanelVisible(true); + + trayWidget = expandWidget; + } else if (type == TrayIconType::Incicator) { + QString indicateName = key; + int flagIndex = indicateName.indexOf("indicator:"); + if (flagIndex >= 0) + indicateName = indicateName.right(indicateName.length() - QString("indicator:").length()); + IndicatorTrayItem *indicatorWidget = new IndicatorTrayItem(indicateName, parent); + TrayModel *dataModel = qobject_cast(m_listView->model()); + if (IndicatorTrayItem *sourceIndicatorWidget = dataModel->indicatorWidget(key)) { + connect(indicatorWidget, &IndicatorTrayItem::clicked, sourceIndicatorWidget, &IndicatorTrayItem::clicked); + const QByteArray pixmapData = sourceIndicatorWidget->pixmapData(); + if (!pixmapData.isEmpty()) + indicatorWidget->setPixmapData(pixmapData); + const QString text = sourceIndicatorWidget->text(); + if (!text.isEmpty()) + indicatorWidget->setText(text); + } + trayWidget = indicatorWidget; + } else if (type == TrayIconType::SystemItem) { + PluginsItemInterface *pluginInter = (PluginsItemInterface *)(index.data(TrayModel::PluginInterfaceRole).toULongLong()); + if (pluginInter) { + const QString itemKey = QuickSettingController::instance()->itemKey(pluginInter); + SystemPluginItem *trayItem = new SystemPluginItem(pluginInter, itemKey, parent); + connect(trayItem, &SystemPluginItem::execActionFinished, this, &TrayDelegate::requestHide); + trayWidget = trayItem; + } + } + + if (trayWidget) + trayWidget->setFixedSize(16, 16); + + return trayWidget; +} + +void TrayDelegate::onUpdateExpand(bool on) +{ + ExpandIconWidget *expandwidget = expandWidget(); + + if (on) { + if (expandwidget) { + expandwidget->setTrayPanelVisible(true); + } else { + // 如果三角按钮不存在,那么就设置三角按钮可见,此时它会自动创建一个三角按钮 + TrayModel *model = qobject_cast(m_listView->model()); + if (model) + model->setExpandVisible(true, true); + } + } else { + // 获取托盘内图标的数量 + int trayIconCount = TrayModel::getIconModel()->rowCount(); + if (expandwidget) { + // 如果释放鼠标,则判断当前鼠标的位置是否在托盘内部,如果在,则无需隐藏 + QPoint currentPoint = QCursor::pos(); + TrayGridWidget *view = ExpandIconWidget::popupTrayView(); + expandwidget->setTrayPanelVisible(view->geometry().contains(currentPoint) && (trayIconCount > 0)); + } else if (trayIconCount == 0) { + ExpandIconWidget::popupTrayView()->hide(); + } + } +} + +void TrayDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + BaseTrayWidget *widget = static_cast(editor); + if (widget) { + widget->setNeedShow(!index.data(TrayModel::Blank).toBool()); + } +} + +QSize TrayDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option); + Q_UNUSED(index); + + // 如果是弹出托盘,则显示正常大小 + if (isPopupTray()) + return QSize(ITEM_SIZE, ITEM_SIZE); + + // 如果是任务栏的托盘,则高度显示为listView的高度或宽度 + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + return QSize(ITEM_SIZE, m_listView->height()); + + return QSize(m_listView->width(), ITEM_SIZE); +} + +void TrayDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(index); + QRect rect = option.rect; + // 让控件居中显示 + editor->setGeometry(rect.x() + (rect.width() - ICON_SIZE) / 2, + rect.y() + (rect.height() - ICON_SIZE) / 2, + ICON_SIZE, ICON_SIZE); +} + +void TrayDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(index); + + // 如果不是弹出菜单(在任务栏上显示的),在鼠标没有移入的时候无需绘制背景 + if (!isPopupTray() && !(option.state & QStyle::State_MouseOver)) + return QStyledItemDelegate::paint(painter, option, index); + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + if (isPopupTray()) { + QPainterPath path; + path.addRoundedRect(option.rect, 8, 8); + QColor borderColor; + QColor backColor; + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { + // 白色主题的情况下 + borderColor = Qt::black; + borderColor.setAlpha(static_cast(255 * 0.05)); + backColor = Qt::white; + if (option.state & QStyle::State_MouseOver) { + backColor.setAlphaF(0.4); + } else + backColor.setAlphaF(0.2); + } else { + borderColor = Qt::black; + borderColor.setAlpha(static_cast(255 * 0.2)); + backColor = Qt::black; + if (option.state & QStyle::State_MouseOver) + backColor.setAlphaF(0.4); + else + backColor.setAlphaF(0.2); + } + + painter->fillPath(path, backColor); + painter->setPen(borderColor); + painter->drawPath(path); + } else { + // 如果是任务栏上面的托盘图标,则绘制背景色 + int borderRadius = 8; + if (qApp->property(PROP_DISPLAY_MODE).value() == Dock::DisplayMode::Fashion) { + borderRadius = qApp->property("trayBorderRadius").toInt() - 4; + } + QRect rectBackground; + QPainterPath path; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + int backHeight = qBound(20, option.rect.height() - 4, 30); + rectBackground.setLeft(option.rect.left()); + rectBackground.setTop(option.rect.top() + (option.rect.height() - backHeight) / 2); + rectBackground.setHeight(backHeight); + rectBackground.setWidth(option.rect.width()); + path.addRoundedRect(rectBackground, borderRadius, borderRadius); + } else { + int backWidth = qBound(20, option.rect.width() - 4, 30); + rectBackground.setLeft(option.rect.left() + (option.rect.width() - backWidth) / 2); + rectBackground.setTop(option.rect.top()); + rectBackground.setWidth(backWidth); + rectBackground.setHeight(option.rect.height()); + path.addRoundedRect(rectBackground, borderRadius, borderRadius); + } + QColor backColor; + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { + // 白色主题的情况下 + backColor = Qt::white; + backColor.setAlphaF(0.2); + } else { + backColor = QColor(20, 20, 20); + backColor.setAlphaF(0.2); + } + + painter->fillPath(path, backColor); + } + + painter->restore(); +} + +ExpandIconWidget *TrayDelegate::expandWidget() +{ + if (!m_listView) + return nullptr; + + QAbstractItemModel *dataModel = m_listView->model(); + if (!dataModel) + return nullptr; + + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + ExpandIconWidget *widget = qobject_cast(m_listView->indexWidget(index)); + if (widget) + return widget; + } + + return nullptr; +} + +bool TrayDelegate::isPopupTray() const +{ + if (!m_listView) + return false; + + TrayModel *dataModel = qobject_cast(m_listView->model()); + if (!dataModel) + return false; + + return dataModel->isIconTray(); +} diff --git a/frame/window/tray/tray_delegate.h b/frame/window/tray/tray_delegate.h new file mode 100644 index 000000000..b9144c3a0 --- /dev/null +++ b/frame/window/tray/tray_delegate.h @@ -0,0 +1,54 @@ +// Copyright (C) 2018 ~ 2025 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TRAYDELEGATE_H +#define TRAYDELEGATE_H + +#include "constants.h" + +#include + +#define ITEM_SIZE 30 +// 托盘图标固定16个像素 +#define ICON_SIZE 16 +#define ITEM_SPACING 5 + +class ExpandIconWidget; +class QListView; +class PluginsItemInterface; + +class TrayDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit TrayDelegate(QListView *view, QObject *parent = nullptr); + void setPositon(Dock::Position position); + +Q_SIGNALS: + void removeRow(const QModelIndex &) const; + void requestDrag(bool) const; + void requestHide(); + +private Q_SLOTS: + void onUpdateExpand(bool on); + +protected: + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; + void setEditorData(QWidget *editor, const QModelIndex &index) const override ; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +private: + ExpandIconWidget *expandWidget(); + bool isPopupTray() const; + +private: + Dock::Position m_position; + QListView *m_listView; +}; + +#endif // TRAYDELEGATE_H diff --git a/frame/window/tray/tray_gridview.cpp b/frame/window/tray/tray_gridview.cpp new file mode 100644 index 000000000..cb7116fba --- /dev/null +++ b/frame/window/tray/tray_gridview.cpp @@ -0,0 +1,614 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "tray_gridview.h" +#include "settingconfig.h" +#include "expandiconwidget.h" +#include "tray_model.h" +#include "basetraywidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TrayGridView::TrayGridView(QWidget *parent) + : DListView(parent) + , m_aniCurveType(QEasingCurve::Linear) + , m_aniDuringTime(250) + , m_dragDistance(15) + , m_aniStartTime(new QTimer(this)) + , m_pressed(false) + , m_aniRunning(false) + , m_positon(Dock::Position::Bottom) +{ + initUi(); +} + +void TrayGridView::setPosition(Dock::Position position) +{ + m_positon = position; +} + +Dock::Position TrayGridView::position() const +{ + return m_positon; +} + +QSize TrayGridView::suitableSize() const +{ + return suitableSize(m_positon); +} + +QSize TrayGridView::suitableSize(const Dock::Position &position) const +{ + TrayModel *dataModel = qobject_cast(model()); + if (!dataModel) + return QSize(-1, -1); + + if (dataModel->isIconTray()) { + // 如果是托盘图标 + int width = 2; + int height = 0; + int count = dataModel->rowCount(); + if (count > 0) { + int columnCount = qMin(count, 3); + for (int i = 0; i < columnCount; i ++) { + QModelIndex index = dataModel->index(i, 0); + width += visualRect(index).width() + spacing() * 2; // 左右边距加上单元格宽度 + } + int rowCount = count / 3; + if (count % 3 > 0) + rowCount++; + for (int i = 0; i < rowCount; i++) { + QModelIndex index = dataModel->index(i * 3); + height += visualRect(index).height() + spacing() * 2; + } + } else { + width = spacing() * 2 + 30; + height = spacing() * 2 + 30; + } + return QSize(width, height); + } + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + int length = spacing() + 2; + if (m_positon == Dock::Position::Top || m_positon == Dock::Position::Bottom) { + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + length += indexRect.width() + spacing(); + } + } else { + // 如果是从左右切换过来的,此时还未进入上下位置,则将当前位置的高度作为计算左右位置的宽度 + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + length += indexRect.height() + spacing(); + } + } + + return QSize(length, -1); + } + int height = spacing() + 2; + if (m_positon == Dock::Position::Left || m_positon == Dock::Position::Right) { + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + height += indexRect.height() + spacing(); + } + } else { + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + QRect indexRect = visualRect(index); + height += indexRect.width() + spacing(); + } + } + + return QSize(-1, height); +} + +void TrayGridView::setDragDistance(int pixel) +{ + m_dragDistance = pixel; +} + +void TrayGridView::setAnimationProperty(const QEasingCurve::Type easing, const int duringTime) +{ + m_aniCurveType = easing; + m_aniDuringTime = duringTime; +} + +void TrayGridView::moveAnimation() +{ + if (m_aniRunning || m_aniStartTime->isActive()) + return; + + const QModelIndex dropModelIndex = indexAt(m_dropPos); + if (!dropModelIndex.isValid()) + return; + + const QModelIndex dragModelIndex = indexAt(m_dragPos); + if (dragModelIndex == dropModelIndex) + return; + + if (!dragModelIndex.isValid()) { + m_dragPos = indexRect(dropModelIndex).center(); + return; + } + + TrayModel *listModel = qobject_cast(model()); + if (!listModel) + return; + + listModel->clearDragDropIndex(); + listModel->setDragingIndex(dragModelIndex); + listModel->setDragDropIndex(dropModelIndex); + + const int startPos = dragModelIndex.row(); + const int endPos = dropModelIndex.row(); + + const bool next = startPos <= endPos; + const int start = next ? startPos : endPos; + const int end = !next ? startPos : endPos; + + for (int i = start + next; i <= (end - !next); i++) + createAnimation(i, next, (i == (end - !next))); + + m_dropPos = indexRect(dropModelIndex).center(); + m_dragPos = indexRect(dropModelIndex).center(); +} + +const QModelIndex TrayGridView::modelIndex(const int index) const +{ + return model()->index(index, 0, QModelIndex()); +} + +const QRect TrayGridView::indexRect(const QModelIndex &index) const +{ + return rectForIndex(index); +} + +void TrayGridView::dropSwap() +{ + qDebug() << "drop end"; + TrayModel *listModel = qobject_cast(model()); + if (!listModel) + return; + + QModelIndex index = indexAt(m_dropPos); + if (!index.isValid()) + return; + + listModel->dropSwap(index.row()); + clearDragModelIndex(); + m_aniRunning = false; + setState(NoState); +} + +void TrayGridView::clearDragModelIndex() +{ + TrayModel *listModel = static_cast(this->model()); + if (!listModel) + return; + + listModel->clearDragDropIndex(); +} + +void TrayGridView::createAnimation(const int pos, const bool moveNext, const bool isLastAni) +{ + qDebug() << "create moveAnimation"; + const QModelIndex index(modelIndex(pos)); + if (!index.isValid()) + return; + + QLabel *floatLabel = new QLabel(this); + QPropertyAnimation *ani = new QPropertyAnimation(floatLabel, "pos", floatLabel); + qreal ratio = qApp->devicePixelRatio(); + + BaseTrayWidget *widget = qobject_cast(indexWidget(index)); + if (!widget) + return; + + QPixmap pixmap = widget->icon(); + + QString text = index.data(Qt::DisplayRole).toString(); + + pixmap.scaled(pixmap.size() * ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation); + pixmap.setDevicePixelRatio(ratio); + + floatLabel->setFixedSize(indexRect(index).size()); + floatLabel->setPixmap(pixmap); + floatLabel->show(); + + ani->setStartValue(indexRect(index).center() - QPoint(0, floatLabel->height() /2)); + ani->setEndValue(indexRect(modelIndex(moveNext ? pos - 1 : pos + 1)).center() - QPoint(0, floatLabel->height() /2)); + ani->setEasingCurve(m_aniCurveType); + ani->setDuration(m_aniDuringTime); + + connect(ani, &QPropertyAnimation::finished, floatLabel, &QLabel::deleteLater); + if (isLastAni) { + m_aniRunning = true; + + TrayModel *model = qobject_cast(this->model()); + if (!model) + return; + + connect(ani, &QPropertyAnimation::finished, this, &TrayGridView::dropSwap); + connect(ani, &QPropertyAnimation::valueChanged, m_aniStartTime, &QTimer::stop); + } else { + } + + ani->start(QPropertyAnimation::DeleteWhenStopped); +} + +void TrayGridView::mousePressEvent(QMouseEvent *e) +{ + if (e->buttons() == Qt::LeftButton && !m_aniRunning) + m_dragPos = e->pos(); + + m_pressed = true; +} + +void TrayGridView::mouseMoveEvent(QMouseEvent *e) +{ + if (!m_pressed) + return DListView::mouseMoveEvent(e); + + setState(QAbstractItemView::NoState); + e->accept(); + + if (e->buttons() == Qt::RightButton) + return DListView::mouseMoveEvent(e); + + QModelIndex index = indexAt(e->pos()); + if (!index.isValid()) + return DListView::mouseMoveEvent(e); + + // 如果当前拖动的位置是托盘展开按钮,则不让其拖动 + TrayIconType iconType = index.data(TrayModel::Role::TypeRole).value(); + if (iconType == TrayIconType::ExpandIcon) + return DListView::mouseMoveEvent(e); + + if ((qAbs(e->pos().x() - m_dragPos.x()) > m_dragDistance || + qAbs(e->pos().y() - m_dragPos.y()) > m_dragDistance)) { + qDebug() << "start drag"; + if (!beginDrag(Qt::CopyAction | Qt::MoveAction)) + DListView::mouseMoveEvent(e); + } +} + +void TrayGridView::mouseReleaseEvent(QMouseEvent *e) +{ + Q_UNUSED(e); + m_pressed = false; +} + +void TrayGridView::dragEnterEvent(QDragEnterEvent *e) +{ + const QModelIndex index = indexAt(e->pos()); + + if (model()->canDropMimeData(e->mimeData(), e->dropAction(), index.row(), + index.column(), index)) + e->accept(); + else + e->ignore(); + + Q_EMIT dragEntered(); +} + +void TrayGridView::dragLeaveEvent(QDragLeaveEvent *e) +{ + m_aniStartTime->stop(); + e->accept(); + dragLeaved(); +} + +void TrayGridView::dragMoveEvent(QDragMoveEvent *e) +{ + m_aniStartTime->stop(); + if (m_aniRunning) + return; + + QModelIndex index = indexAt(e->pos()); + if (!model()->canDropMimeData(e->mimeData(), e->dropAction(), index.row(), + index.column(), index)) + return; + + setState(QAbstractItemView::DraggingState); + + if (index.isValid()) { + if (m_dropPos != indexRect(index).center()) { + qDebug() << "update drop position: " << index.row(); + m_dropPos = indexRect(index).center(); + } + } + + if (m_pressed) + m_aniStartTime->start(); +} + +const QModelIndex TrayGridView::getIndexFromPos(QPoint currentPoint) const +{ + QModelIndex index = indexAt(currentPoint); + if (index.isValid()) + return index; + + if (model()->rowCount() == 0) + return index; + + // 如果在第一个之前,则认为拖到了第一个的位置 + QRect indexRect0 = visualRect(model()->index(0, 0)); + if (currentPoint.x() < indexRect0.x() || currentPoint.y() < indexRect0.y()) + return model()->index(0, 0); + + // 如果从指定的位置没有找到索引,则依次从每个index中查找,先横向查找 + for (int i = 1; i < model()->rowCount(); i++) { + QModelIndex lastIndex = model()->index(i - 1, 0); + QModelIndex currentIndex = model()->index(i, 0); + QRect lastIndexRect = visualRect(lastIndex); + QRect indexRect = visualRect(currentIndex); + if (lastIndexRect.x() + lastIndexRect.width() <= currentPoint.x() + && indexRect.x() >= currentPoint.x()) + return currentIndex; + } + // 如果鼠标位置刚好在上下两个索引中间 + for (int i = 0; i < model()->rowCount(); i++) { + QModelIndex currentIndex = model()->index(i, 0); + QRect indexRect = visualRect(currentIndex); + + if (currentPoint.y() >= indexRect.y() - spacing() && currentPoint.y() < indexRect.y() + && currentPoint.x() >= indexRect.x() - spacing() && currentPoint.x() < indexRect.x()) + return currentIndex; + } + + return QModelIndex(); +} + +bool TrayGridView::mouseInDock() +{ + QPoint mousePosition = QCursor::pos(); + QRect dockRect(topLevelWidget()->pos(), topLevelWidget()->size()); + switch (m_positon) { + case Dock::Position::Bottom: { + return mousePosition.y() > dockRect.top(); + } + case Dock::Position::Left: { + return mousePosition.x() < dockRect.right(); + } + case Dock::Position::Top: { + return mousePosition.y() < dockRect.bottom(); + } + case Dock::Position::Right: { + return mousePosition.x() > dockRect.left(); + } + } + return false; +} + +void TrayGridView::handleDropEvent(QDropEvent *e) +{ + setState(DListView::NoState); + clearDragModelIndex(); + + if (m_aniStartTime->isActive()) + m_aniStartTime->stop(); + + if (e->mimeData()->formats().contains("type") && e->source() != this) { + e->setDropAction(Qt::CopyAction); + e->accept(); + + TrayModel *dataModel = qobject_cast(model()); + if (dataModel) { + WinInfo info; + info.type = static_cast(e->mimeData()->data("type").toInt()); + info.key = static_cast(e->mimeData()->data("key")); + info.winId = static_cast(e->mimeData()->data("winId").toInt()); + info.servicePath = static_cast(e->mimeData()->data("servicePath")); + info.itemKey = static_cast(e->mimeData()->data("itemKey")); + info.isTypeWriting = (static_cast(e->mimeData()->data("isTypeWritting")) == "1"); + info.expand = (static_cast(e->mimeData()->data("expand")) == "1"); + info.pluginInter = (PluginsItemInterface *)(e->mimeData()->imageData().value()); + QModelIndex targetIndex = getIndexFromPos(e->pos()); + int index = -1; + if (targetIndex.isValid() && targetIndex.row() < dataModel->rowCount()) { + // 如果拖动的位置是合法的位置,则让其插入到当前的位置 + index = targetIndex.row(); + dataModel->insertRow(index, info); + } else { + // 在其他的情况下,让其插入到最后 + dataModel->addRow(info); + } + + dataModel->saveConfig(index, info); + } + } else { + e->ignore(); + DListView::dropEvent(e); + } +} + +void TrayGridView::onUpdateEditorView() +{ + for (int i = 0; i < model()->rowCount(); i++) { + QModelIndex index = model()->index(i, 0); + closePersistentEditor(index); + } + // 在关闭QWidget后不要立即调用openPersistentEditor来打开 + // 因为closePersistentEditor后,异步删除QWidget,在关闭后,如果立即调用openPersistentEditor,在删除的时候,会把 + // 通过openPersistentEditor新建的QWidget给删除,引起bug,因此,在所有的都closePersistentEditor后,异步来调用 + // openPersistentEditor就不会出现这种问题 + QMetaObject::invokeMethod(this, [ = ] { + for (int i = 0; i < model()->rowCount(); i++) { + QModelIndex index = model()->index(i, 0); + openPersistentEditor(index); + } + }, Qt::QueuedConnection); +} + +bool TrayGridView::beginDrag(Qt::DropActions supportedActions) +{ + QModelIndex modelIndex = indexAt(m_dragPos); + TrayIconType trayType = modelIndex.data(TrayModel::Role::TypeRole).value(); + // 展开图标不能移动 + if (trayType == TrayIconType::ExpandIcon) + return false; + + m_dropPos = indexRect(modelIndex).center(); + + TrayModel *listModel = qobject_cast(model()); + if (!listModel) + return false; + + BaseTrayWidget *widget = qobject_cast(indexWidget(modelIndex)); + if (!widget) + return false; + + QMimeData *data = model()->mimeData(QModelIndexList() << modelIndex); + if (!data) + return false; + + auto pixmap = widget->icon(); + + qreal ratio = qApp->devicePixelRatio(); + // 创建拖拽释放时的应用图标 + QLabel *pixLabel = new QLabel(this); + pixLabel->setPixmap(pixmap); + pixLabel->setFixedSize(indexRect(modelIndex).size() / ratio); + + QDrag *drag = new QDrag(this); + pixmap.scaled(pixmap.size() * ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation); + pixmap.setDevicePixelRatio(ratio); + drag->setPixmap(pixmap); + drag->setHotSpot(pixmap.rect().center() / ratio); + + data->setImageData(pixmap); + drag->setMimeData(data); + + setState(DraggingState); + + listModel->setDragKey(modelIndex.data(TrayModel::Role::KeyRole).toString()); + listModel->setDragingIndex(modelIndex); + // 删除当前的图标 + WinInfo winInfo = listModel->getWinInfo(modelIndex); + + Qt::DropAction dropAct = drag->exec(supportedActions); + + // 拖拽完成结束动画 + m_aniStartTime->stop(); + m_pressed = false; + + if (dropAct == Qt::IgnoreAction) { + if (listModel->isIconTray()) { + // 如果当前是从托盘区域释放,按照原来的流程走 + QPropertyAnimation *posAni = new QPropertyAnimation(pixLabel, "pos", pixLabel); + connect(posAni, &QPropertyAnimation::finished, [ this, listModel, pixLabel, winInfo ] () { + pixLabel->hide(); + pixLabel->deleteLater(); + listModel->setDragKey(QString()); + clearDragModelIndex(); + QModelIndex dropIndex = indexAt(m_dropPos); + // 拖转完成后,将拖动的图标插入到新的位置 + //listModel->moveToIndex(winInfo, dropIndex.row()); + listModel->dropSwap(dropIndex.row()); + listModel->setExpandVisible(!TrayModel::getIconModel()->isEmpty()); + + m_dropPos = QPoint(); + m_dragPos = QPoint(); + + onUpdateEditorView(); + Q_EMIT dragFinished(); + }); + // 拖拽完成后,将当前拖拽的item从原来的列表中移除,后来会根据实际情况将item插入到特定的列表中 + posAni->setEasingCurve(QEasingCurve::Linear); + posAni->setDuration(m_aniDuringTime); + posAni->setStartValue((QCursor::pos() - QPoint(0, pixLabel->height() / 2))); + posAni->setEndValue(mapToGlobal(m_dropPos) - QPoint(0, pixLabel->height() / 2)); + pixLabel->show(); + posAni->start(QAbstractAnimation::DeleteWhenStopped); + + Q_EMIT dragFinished(); + } else { + listModel->setDragKey(QString()); + clearDragModelIndex(); + TrayModel *trayModel = TrayModel::getIconModel(); + if (!mouseInDock()) { + listModel->removeWinInfo(winInfo); + trayModel->addRow(winInfo); + trayModel->saveConfig(-1, winInfo); + } + // 如果是任务栏的的托盘区,则更新是否显示展开入口 + listModel->setExpandVisible(trayModel->rowCount() > 0, false); + + m_dragPos = QPoint(); + m_dropPos = QPoint(); + Q_EMIT dragFinished(); + } + } else { + // 拖拽完成后,将当前拖拽的item从原来的列表中移除,后来会根据实际情况将item插入到特定的列表中 + listModel->removeWinInfo(winInfo); + // 这里是将图标从一个区域移动到另外一个区域 + listModel->setDragKey(QString()); + clearDragModelIndex(); + if (listModel->isIconTray()) { + // 如果当前是从托盘移动到任务栏,则根据托盘内部是否有应用来决定是否显示展开图标 + bool hasIcon = (listModel->rowCount() > 0); + TrayModel::getDockModel()->setExpandVisible(hasIcon, hasIcon); + // 如果没有图标,则隐藏托盘图标 + if (!hasIcon) + ExpandIconWidget::popupTrayView()->hide(); + } + + m_dropPos = QPoint(); + m_dragPos = QPoint(); + Q_EMIT dragFinished(); + } + + return true; +} + +void TrayGridView::initUi() +{ + setAcceptDrops(true); + setDragEnabled(true); + setDragDropMode(QAbstractItemView::DragDrop); + setDropIndicatorShown(false); + + setMouseTracking(false); + setUniformItemSizes(true); + setFocusPolicy(Qt::NoFocus); + setMovement(DListView::Free); + setOrientation(QListView::LeftToRight, true); + setLayoutMode(DListView::Batched); + setResizeMode(DListView::Adjust); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setFrameStyle(QFrame::NoFrame); + setContentsMargins(0, 0, 0, 0); + setSpacing(0); + setItemSpacing(0); + setBackgroundType(DStyledItemDelegate::RoundedBackground); + setSelectionMode(QListView::SingleSelection); + setVerticalScrollMode(QListView::ScrollPerPixel); + + viewport()->setAcceptDrops(true); + viewport()->setAutoFillBackground(false); + + m_aniStartTime->setInterval(10); + m_aniStartTime->setSingleShot(true); + + connect(m_aniStartTime, &QTimer::timeout, this, &TrayGridView::moveAnimation); +} + +void TrayGridView::dropEvent(QDropEvent *e) +{ + handleDropEvent(e); +} diff --git a/frame/window/tray/tray_gridview.h b/frame/window/tray/tray_gridview.h new file mode 100644 index 000000000..1f14d270f --- /dev/null +++ b/frame/window/tray/tray_gridview.h @@ -0,0 +1,81 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TRAYGRIDVIEW_H +#define TRAYGRIDVIEW_H + +#include "constants.h" + +#include + +#include + +DWIDGET_USE_NAMESPACE + +class TrayGridView : public DListView +{ + Q_OBJECT + +public: + explicit TrayGridView(QWidget *parent = Q_NULLPTR); + + void setPosition(Dock::Position position); + Dock::Position position() const; + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; + void setDragDistance(int pixel); + void setAnimationProperty(const QEasingCurve::Type easing, const int duringTime = 250); + const QModelIndex modelIndex(const int index) const; + const QRect indexRect(const QModelIndex &index) const; + + void handleDropEvent(QDropEvent *e); + +public Q_SLOTS: + void onUpdateEditorView(); + +Q_SIGNALS: + void dragLeaved(); + void dragEntered(); + void dragFinished(); + void requestHide(); + +private Q_SLOTS: + void clearDragModelIndex(); + void dropSwap(); + void moveAnimation(); + +protected: + void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + + void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; + void dragLeaveEvent(QDragLeaveEvent *e) Q_DECL_OVERRIDE; + void dragMoveEvent(QDragMoveEvent *e) Q_DECL_OVERRIDE; + void dropEvent(QDropEvent *e) Q_DECL_OVERRIDE; + bool beginDrag(Qt::DropActions supportedActions); + +private: + void initUi(); + void createAnimation(const int pos, const bool moveNext, const bool isLastAni); + const QModelIndex getIndexFromPos(QPoint currentPoint) const; + bool mouseInDock(); + +private: + QEasingCurve::Type m_aniCurveType; + int m_aniDuringTime; + + QPoint m_dragPos; + QPoint m_dropPos; + + int m_dragDistance; + + QTimer *m_aniStartTime; + bool m_pressed; + bool m_aniRunning; + Dock::Position m_positon; +}; + +#endif // GRIDVIEW_H diff --git a/frame/window/tray/tray_model.cpp b/frame/window/tray/tray_model.cpp new file mode 100644 index 000000000..c5672e9e7 --- /dev/null +++ b/frame/window/tray/tray_model.cpp @@ -0,0 +1,801 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "tray_model.h" +#include "tray_monitor.h" + +#include "indicatortrayitem.h" +#include "indicatorplugin.h" +#include "quicksettingcontroller.h" +#include "pluginsiteminterface.h" +#include "settingconfig.h" +#include "platformutils.h" + +#include +#include +#include +#include +#include + +#define TRAY_DRAG_FALG "tray_drag" +#define DOCKQUICKTRAYNAME "Dock_Quick_Tray_Name" + +TrayModel *TrayModel::getDockModel() +{ + static TrayModel *model = nullptr; + if (!model) { + model = new TrayModel(false); + TrayModel *iconModel = getIconModel(); + connect(iconModel, &TrayModel::rowsRemoved, model, [ = ] { + model->setExpandVisible(iconModel->rowCount() > 0); + }); + connect(iconModel, &TrayModel::rowsInserted, model, [ = ] { + model->setExpandVisible(iconModel->rowCount() > 0); + }); + connect(iconModel, &TrayModel::rowCountChanged, model, [ = ] { + model->setExpandVisible(iconModel->rowCount() > 0); + }); + } + + return model; +} + +TrayModel *TrayModel::getIconModel() +{ + static TrayModel model(true); + return &model; +} + +TrayModel::TrayModel(bool isIconTray, QObject *parent) + : QAbstractListModel(parent) + , m_dragModelIndex(QModelIndex()) + , m_dropModelIndex(QModelIndex()) + , m_monitor(new TrayMonitor(this)) + , m_isTrayIcon(isIconTray) +{ + connect(m_monitor, &TrayMonitor::xEmbedTrayAdded, this, &TrayModel::onXEmbedTrayAdded); + connect(m_monitor, &TrayMonitor::xEmbedTrayRemoved, this, &TrayModel::onXEmbedTrayRemoved); + + connect(m_monitor, &TrayMonitor::sniTrayAdded, this, &TrayModel::onSniTrayAdded); + connect(m_monitor, &TrayMonitor::sniTrayRemoved, this, &TrayModel::onSniTrayRemoved); + + connect(m_monitor, &TrayMonitor::indicatorFounded, this, &TrayModel::onIndicatorFounded); + + connect(m_monitor, &TrayMonitor::systemTrayAdded, this, &TrayModel::onSystemTrayAdded); + connect(m_monitor, &TrayMonitor::systemTrayRemoved, this, &TrayModel::onSystemTrayRemoved); + + connect(m_monitor, &TrayMonitor::requestUpdateIcon, this, &TrayModel::requestUpdateIcon); + connect(SETTINGCONFIG, &SettingConfig::valueChanged, this, &TrayModel::onSettingChanged); + + m_fixedTrayNames = SETTINGCONFIG->value(DOCKQUICKTRAYNAME).toStringList(); + m_fixedTrayNames.removeDuplicates(); +} + +void TrayModel::dropSwap(int newPos) +{ + if (!m_dragModelIndex.isValid()) + return; + + int row = m_dragModelIndex.row(); + + if (row < m_winInfos.size()) + m_dragInfo = m_winInfos.takeAt(row); + + WinInfo name = m_dragInfo; + m_winInfos.insert(newPos, name); + + emit QAbstractItemModel::dataChanged(m_dragModelIndex, m_dropModelIndex); + requestRefreshEditor(); +} + +void TrayModel::clearDragDropIndex() +{ + const QModelIndex startIndex = m_dragModelIndex; + const QModelIndex endIndex = m_dropModelIndex; + + m_dragModelIndex = m_dropModelIndex = QModelIndex(); + + emit QAbstractItemModel::dataChanged(startIndex, endIndex); + emit QAbstractItemModel::dataChanged(endIndex, startIndex); +} + +void TrayModel::setDragingIndex(const QModelIndex index) +{ + m_dragModelIndex = index; + m_dropModelIndex = index; + + emit QAbstractListModel::dataChanged(index, index); +} + +void TrayModel::setDragDropIndex(const QModelIndex index) +{ + if (m_dragModelIndex == index) + return; + + m_dropModelIndex = index; + + emit QAbstractListModel::dataChanged(m_dragModelIndex, index); + emit QAbstractListModel::dataChanged(index, m_dragModelIndex); +} + +void TrayModel::setExpandVisible(bool visible, bool openExpand) +{ + // 如果是托盘,不支持展开图标 + if (m_isTrayIcon) + return; + + if (visible) { + // 如果展开图标已经存在,则不添加, + for (WinInfo &winInfo : m_winInfos) { + if (winInfo.type == TrayIconType::ExpandIcon) { + winInfo.expand = openExpand; + return; + } + } + // 如果是任务栏图标,则添加托盘展开图标 + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + WinInfo info; + info.type = TrayIconType::ExpandIcon; + info.expand = openExpand; + m_winInfos.insert(0, info); // 展开图标始终显示在第一个 + endInsertRows(); + + Q_EMIT requestRefreshEditor(); + Q_EMIT rowCountChanged(); + } else { + // 如果隐藏,则直接从列表中移除 + bool rowChanged = false; + beginResetModel(); + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.type == TrayIconType::ExpandIcon) { + m_winInfos.removeOne(winInfo); + rowChanged = true; + } + } + endResetModel(); + if (rowChanged) + Q_EMIT rowCountChanged(); + } +} + +void TrayModel::updateOpenExpand(bool openExpand) +{ + for (WinInfo &winInfo : m_winInfos) { + if (winInfo.type == TrayIconType::ExpandIcon) + winInfo.expand = openExpand; + } +} + +void TrayModel::setDragKey(const QString &key) +{ + m_dragKey = key; +} + +bool TrayModel::indexDragging(const QModelIndex &index) const +{ + if (index.isValid() && index.data(Role::KeyRole).toString() == m_dragKey) + return true; + + if (!m_dragModelIndex.isValid() || !m_dropModelIndex.isValid()) + return false; + + const int start = m_dragModelIndex.row(); + const int end = m_dropModelIndex.row(); + const int current = index.row(); + + return (start <= end && current >= start && current <= end) + || (start >= end && current <= start && current >= end); +} + +IndicatorTrayItem *TrayModel::indicatorWidget(const QString &indicatorName) const +{ + QString indicatorKey = indicatorName; + indicatorKey = indicatorKey.remove(0, QString("indicator:").length()); + if (m_indicatorMap.contains(indicatorKey)) + return m_indicatorMap.value(indicatorKey)->widget(); + + return nullptr; +} + +QMimeData *TrayModel::mimeData(const QModelIndexList &indexes) const +{ + Q_ASSERT(indexes.size() == 1); + + QMimeData *mime = new QMimeData; + mime->setData(TRAY_DRAG_FALG, QByteArray()); + for (auto index : indexes) { + if (!index.isValid()) + continue; + + int itemIndex = index.row(); + auto info = m_winInfos.at(itemIndex); + mime->setData("type", QByteArray::number(static_cast(info.type))); + mime->setData("key", info.key.toLatin1()); + mime->setData("itemKey", info.itemKey.toLatin1()); + mime->setData("winId", QByteArray::number(info.winId)); + mime->setData("servicePath", info.servicePath.toLatin1()); + mime->setData("isTypeWritting", info.isTypeWriting ? "1" : "0"); + mime->setData("expand", info.expand ? "1" : "0"); + mime->setImageData(QVariant::fromValue((qulonglong)(info.pluginInter))); + + //TODO 支持多个index的数据,待支持 + } + return mime; +} + +QVariant TrayModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int itemIndex = index.row(); + const WinInfo &info = m_winInfos[itemIndex]; + + switch (role) { + case Role::TypeRole: + return info.type; + case Role::KeyRole: + return info.key; + case Role::WinIdRole: + return info.winId; + case Role::ServiceRole: + return info.servicePath; + case Role::PluginInterfaceRole: + return (qulonglong)(info.pluginInter); + case Role::ExpandRole: + return info.expand; + case Role::ItemKeyRole: + return info.itemKey; + case Role::Blank: + return indexDragging(index); + default: + return QVariant(); + } +} + +bool TrayModel::removeRows(int row, int count, const QModelIndex &parent) +{ + Q_UNUSED(count); + + if (m_winInfos.size() - 1 < row) + return false; + + beginRemoveRows(parent, row, row); + m_dragInfo = m_winInfos.takeAt(row); + endRemoveRows(); + + Q_EMIT rowCountChanged(); + + return true; +} + +bool TrayModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(action) + Q_UNUSED(row) + Q_UNUSED(column) + + TrayIconType iconType = parent.data(TrayModel::Role::TypeRole).value(); + if (iconType == TrayIconType::ExpandIcon) + return false; + + return data->formats().contains(TRAY_DRAG_FALG); +} + +Qt::ItemFlags TrayModel::flags(const QModelIndex &index) const +{ + const Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); + Q_EMIT requestOpenEditor(index); + + return defaultFlags | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; +} + +int TrayModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return m_winInfos.size(); +} + +bool TrayModel::isIconTray() +{ + return m_isTrayIcon; +} + +bool TrayModel::hasExpand() const +{ + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.type == TrayIconType::ExpandIcon) + return true; + } + + return false; +} + +bool TrayModel::isEmpty() const +{ + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.type != TrayIconType::ExpandIcon) + return false; + } + + return true; +} + +void TrayModel::clear() +{ + beginResetModel(); + m_winInfos.clear(); + endResetModel(); + + Q_EMIT rowCountChanged(); +} + +WinInfo TrayModel::getWinInfo(const QModelIndex &index) +{ + int row = index.row(); + if (row < 0 || row >= m_winInfos.size()) + return WinInfo(); + + return m_winInfos[row]; +} + +void TrayModel::onXEmbedTrayAdded(quint32 winId) +{ + if (!xembedCanExport(winId)) + return; + + for (const WinInfo &info : m_winInfos) { + if (info.winId == winId) + return; + } + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + WinInfo info; + info.type = XEmbed; + info.key = "wininfo:" + QString::number(winId); + info.itemKey = xembedItemKey(winId); + info.winId = winId; + m_winInfos.append(info); + sortItems(); + endInsertRows(); + + Q_EMIT rowCountChanged(); +} + +void TrayModel::onXEmbedTrayRemoved(quint32 winId) +{ + for (auto info : m_winInfos) { + if (info.winId == winId) { + int index = m_winInfos.indexOf(info); + beginRemoveRows(QModelIndex(), index, index); + m_winInfos.removeOne(info); + endRemoveRows(); + + Q_EMIT rowCountChanged(); + return; + } + } +} + +QString TrayModel::fileNameByServiceName(const QString &serviceName) const +{ + QStringList serviceInfo = serviceName.split("/"); + if (serviceInfo.size() <= 0) + return QString(); + + QDBusInterface dbsInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", + "org.freedesktop.DBus", QDBusConnection::sessionBus()); + QDBusMessage msg = dbsInterface.call("GetConnectionUnixProcessID", serviceInfo[0] ); + QList arguments = msg.arguments(); + if (arguments.size() == 0) + return QString(); + + QVariant v = arguments.at(0); + uint pid = v.toUInt(); + QString path = QString("/proc/%1/cmdline").arg(pid); + QFile file(path); + if (file.open(QIODevice::ReadOnly)) { + const QString fileName = file.readAll(); + file.close(); + return fileName; + } + + return QString(); +} + +bool TrayModel::isTypeWriting(const QString &servicePath) const +{ + const QString appFilePath = fileNameByServiceName(servicePath); + return (appFilePath.startsWith("/usr/bin/fcitx") || appFilePath.endsWith("chinime-qim")); +} + +void TrayModel::saveConfig(int index, const WinInfo &winInfo) +{ + if (m_isTrayIcon) { + // 如果是从任务栏将图标移动到托盘,就从配置中移除 + if (!m_fixedTrayNames.contains(winInfo.itemKey)) + return; + + m_fixedTrayNames.removeOne(winInfo.itemKey); + } else { + // 如果是将图标从托盘移到任务栏上面,就增加到配置中 + if (m_fixedTrayNames.contains(winInfo.itemKey)) + return; + + if (index >= 0 && index < m_fixedTrayNames.size()) { + m_fixedTrayNames.insert(index, winInfo.itemKey); + } else { + m_fixedTrayNames << winInfo.itemKey; + } + } + + SETTINGCONFIG->setValue(DOCKQUICKTRAYNAME, m_fixedTrayNames); +} + +void TrayModel::removeWinInfo(WinInfo winInfo) +{ + for (const WinInfo &info : m_winInfos) { + if (winInfo == info) { + int index = m_winInfos.indexOf(info); + beginRemoveRows(QModelIndex(), index, index); + m_winInfos.removeOne(info); + endRemoveRows(); + + Q_EMIT rowCountChanged(); + break; + } + } +} + +bool TrayModel::inTrayConfig(const QString itemKey) const +{ + if (m_isTrayIcon) { + // 如果是托盘区域,显示所有不在配置中的应用 + return !m_fixedTrayNames.contains(itemKey); + } + // 如果是任务栏区域,显示所有在配置中的应用 + return m_fixedTrayNames.contains(itemKey); +} + +QString TrayModel::xembedItemKey(quint32 winId) const +{ + return QString("embed:%1").arg(PlatformUtils::getAppNameForWindow(winId)); +} + +bool TrayModel::xembedCanExport(quint32 winId) const +{ + return inTrayConfig(xembedItemKey(winId)); +} + +QString TrayModel::sniItemKey(const QString &servicePath) const +{ + if (isTypeWriting(servicePath)) + return "fcitx"; + + QString fileName = fileNameByServiceName(servicePath); + return QString("sni:%1").arg(fileName.mid(fileName.lastIndexOf("/") + 1)); +} + +bool TrayModel::sniCanExport(const QString &servicePath) const +{ + return inTrayConfig(sniItemKey(servicePath)); +} + +bool TrayModel::indicatorCanExport(const QString &indicatorName) const +{ + return inTrayConfig(IndicatorTrayItem::toIndicatorKey(indicatorName)); +} + +QString TrayModel::systemItemKey(const QString &pluginName) const +{ + return QString("systemItem:%1").arg(pluginName); +} + +bool TrayModel::systemItemCanExport(const QString &pluginName) const +{ + return inTrayConfig(systemItemKey(pluginName)); +} + +void TrayModel::sortItems() +{ + // 如果当前是展开托盘的内容,则无需排序 + if (m_isTrayIcon) + return; + + // 数据排列,展开按钮始终排在最前面,输入法始终排在最后面 + WinInfos expandWin; + WinInfos inputMethodWin; + // 从列表中获取输入法和展开按钮 + for (const WinInfo &winInfo : m_winInfos) { + switch (winInfo.type) { + case TrayIconType::ExpandIcon: { + expandWin << winInfo; + break; + } + case TrayIconType::Sni: { + if (winInfo.isTypeWriting) + inputMethodWin << winInfo; + break; + } + default: + break; + } + } + // 从列表中移除展开按钮 + for (const WinInfo &winInfo : expandWin) + m_winInfos.removeOne(winInfo); + + // 从列表中移除输入法 + for (const WinInfo &winInfo : inputMethodWin) + m_winInfos.removeOne(winInfo); + + // 将展开按钮添加到列表的最前面 + for (int i = expandWin.size() - 1; i >= 0; i--) + m_winInfos.push_front(expandWin[i]); + + // 将输入法添加到列表的最后面 + for (int i = 0; i < inputMethodWin.size(); i++) + m_winInfos.push_back(inputMethodWin[i]); +} + +void TrayModel::onSniTrayAdded(const QString &servicePath) +{ + if (!sniCanExport(servicePath)) + return; + + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.servicePath == servicePath) + return; + } + + bool typeWriting = isTypeWriting(servicePath); + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + WinInfo info; + info.type = Sni; + info.key = "sni:" + servicePath; + info.itemKey = sniItemKey(servicePath); + info.servicePath = servicePath; + info.isTypeWriting = typeWriting; // 是否为输入法 + m_winInfos.append(info); + + sortItems(); + endInsertRows(); + + Q_EMIT rowCountChanged(); +} + +void TrayModel::onSniTrayRemoved(const QString &servicePath) +{ + for (const WinInfo &info : m_winInfos) { + if (info.servicePath == servicePath) { + int index = m_winInfos.indexOf(info); + + // 如果为输入法,则无需立刻删除,等100毫秒后再观察是否会删除输入法(因为在100毫秒内如果是切换输入法,就会很快发送add信号) + if (info.isTypeWriting) { + QTimer::singleShot(100, this, [ servicePath, this ] { + for (WinInfo info : m_winInfos) { + if (info.servicePath == servicePath) { + int index = m_winInfos.indexOf(info); + beginRemoveRows(QModelIndex(), index, index); + m_winInfos.removeOne(info); + endRemoveRows(); + } + } + }); + } else { + beginRemoveRows(QModelIndex(), index, index); + m_winInfos.removeOne(info); + endRemoveRows(); + + Q_EMIT rowCountChanged(); + } + break; + } + } +} + +void TrayModel::onIndicatorFounded(const QString &indicatorName) +{ + const QString &itemKey = IndicatorTrayItem::toIndicatorKey(indicatorName); + if (exist(itemKey) || !IndicatorTrayItem::isIndicatorKey(itemKey)) + return; + + IndicatorPlugin *indicatorTray = nullptr; + if (!m_indicatorMap.keys().contains(indicatorName)) { + indicatorTray = new IndicatorPlugin(indicatorName, this); + m_indicatorMap[indicatorName] = indicatorTray; + } else { + indicatorTray = m_indicatorMap[itemKey]; + } + + connect(indicatorTray, &IndicatorPlugin::delayLoaded, indicatorTray, [ = ] { + onIndicatorAdded(indicatorName); + }, Qt::UniqueConnection); + + connect(indicatorTray, &IndicatorPlugin::removed, this, [ = ] { + onIndicatorRemoved(indicatorName); + }, Qt::UniqueConnection); +} + +void TrayModel::onIndicatorAdded(const QString &indicatorName) +{ + if (!indicatorCanExport(indicatorName)) + return; + + const QString &itemKey = IndicatorTrayItem::toIndicatorKey(indicatorName); + for (const WinInfo &info : m_winInfos) { + if (info.itemKey == itemKey) + return; + } + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + WinInfo info; + info.type = Incicator; + info.key = itemKey; + info.itemKey = itemKey; + m_winInfos.append(info); + + sortItems(); + endInsertRows(); + + Q_EMIT rowCountChanged(); +} + +void TrayModel::onIndicatorRemoved(const QString &indicatorName) +{ + const QString &itemKey = IndicatorTrayItem::toIndicatorKey(indicatorName); + removeRow(itemKey); +} + +void TrayModel::onSystemTrayAdded(PluginsItemInterface *itemInter) +{ + if (!systemItemCanExport(itemInter->pluginName())) + return; + + for (const WinInfo &info : m_winInfos) { + if (info.pluginInter == itemInter) + return; + } + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + + WinInfo info; + info.type = SystemItem; + info.pluginInter = itemInter; + info.itemKey = systemItemKey(itemInter->pluginName()); + m_winInfos.append(info); + + sortItems(); + endInsertRows(); + + Q_EMIT rowCountChanged(); +} + +void TrayModel::onSystemTrayRemoved(PluginsItemInterface *itemInter) +{ + for (const WinInfo &info : m_winInfos) { + if (info.pluginInter != itemInter) + continue; + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_winInfos.removeOne(info); + endInsertRows(); + + Q_EMIT rowCountChanged(); + break; + } +} + +void TrayModel::onSettingChanged(const QString &key, const QVariant &value) +{ + if (key != DOCKQUICKTRAYNAME) + return; + + // 先将其转换为任务栏上的图标列表 + m_fixedTrayNames = value.toStringList(); + // 依次获取所有的图盘图标,判断当前图标是否可以保持在当前的view中, + // 如果可以保留,则添加到view上显示,否则,移除显示 + QList trayWinIds = m_monitor->trayWinIds(); + for (quint32 trayId : trayWinIds) { + if (xembedCanExport(trayId)) + onXEmbedTrayAdded(trayId); + else + onXEmbedTrayRemoved(trayId); + } + + QStringList sniServices = m_monitor->sniServices(); + for (const QString &sniService : sniServices) { + if (sniCanExport(sniService)) + onSniTrayAdded(sniService); + else + onSniTrayRemoved(sniService); + } + + QStringList indicators = m_monitor->indicatorNames(); + for (const QString &indicatorName : indicators) { + if (!m_indicatorMap.contains(indicatorName)) + continue; + + IndicatorPlugin *plugin = m_indicatorMap[indicatorName]; + if (!plugin->isLoaded()) + continue; + + if (indicatorCanExport(indicatorName)) + onIndicatorAdded(indicatorName); + else + onIndicatorRemoved(indicatorName); + } + + QList pluginItems = m_monitor->systemTrays(); + for (PluginsItemInterface *plugin : pluginItems) { + if (systemItemCanExport(plugin->pluginName())) + onSystemTrayAdded(plugin); + else + onSystemTrayRemoved(plugin); + } +} + +void TrayModel::removeRow(const QString &itemKey) +{ + for (const WinInfo &info : m_winInfos) { + if (info.itemKey == itemKey) { + int index = m_winInfos.indexOf(info); + beginRemoveRows(QModelIndex(), index, index); + m_winInfos.removeOne(info); + endRemoveRows(); + + Q_EMIT rowCountChanged(); + break; + } + } +} + +void TrayModel::addRow(WinInfo info) +{ + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.key == info.key) + return; + } + + beginResetModel(); + m_winInfos.append(info); + sortItems(); + endResetModel(); + + Q_EMIT requestRefreshEditor(); + Q_EMIT rowCountChanged(); +} + +void TrayModel::insertRow(int index, WinInfo info) +{ + for (int i = 0; i < m_winInfos.size(); i++) { + const WinInfo &wininfo = m_winInfos[i]; + if (wininfo.key == info.key) { + beginResetModel(); + m_winInfos.swapItemsAt(index, i); + endResetModel(); + return; + } + } + beginInsertRows(QModelIndex(), index, index); + m_winInfos.insert(index, info); + sortItems(); + + endInsertRows(); + + Q_EMIT requestRefreshEditor(); + Q_EMIT rowCountChanged(); +} + +bool TrayModel::exist(const QString &itemKey) +{ + for (const WinInfo &winInfo : m_winInfos) { + if (winInfo.key == itemKey) + return true; + } + + return false; +} diff --git a/frame/window/tray/tray_model.h b/frame/window/tray/tray_model.h new file mode 100644 index 000000000..fd74121c0 --- /dev/null +++ b/frame/window/tray/tray_model.h @@ -0,0 +1,171 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TRAYMODEL_H +#define TRAYMODEL_H + +#include +#include +#include + +class TrayMonitor; +class IndicatorPlugin; +class IndicatorTrayItem; +class PluginsItemInterface; + +enum TrayIconType { + UnKnow, + XEmbed, + Sni, + Incicator, + ExpandIcon, + SystemItem +}; + +struct WinInfo { + TrayIconType type; + QString key; + QString itemKey; + quint32 winId; + QString servicePath; + bool isTypeWriting; + bool expand; + PluginsItemInterface *pluginInter; + + WinInfo() : type(UnKnow) + , key(QString()) + , itemKey(QString()) + , winId(0) + , servicePath(QString()) + , isTypeWriting(false) + , expand(false) + , pluginInter(nullptr) {} + + bool operator==(const WinInfo &other) { + return this->type == other.type + && this->key == other.key + && this->winId == other.winId + && this->servicePath == other.servicePath + && this->itemKey == other.itemKey + && this->isTypeWriting == other.isTypeWriting + && this->pluginInter == other.pluginInter; + } +}; + +class TrayModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Role { + TypeRole = Qt::UserRole + 1, + KeyRole, + WinIdRole, + ServiceRole, + PluginInterfaceRole, + ExpandRole, + ItemKeyRole, + Blank + }; + + typedef QList WinInfos; + + static TrayModel *getDockModel(); + static TrayModel *getIconModel(); + + void dropSwap(int newPos); + + void clearDragDropIndex(); + void setDragingIndex(const QModelIndex index); + void setDragDropIndex(const QModelIndex index); + void setExpandVisible(bool visible, bool openExpand = false); + void updateOpenExpand(bool openExpand); + + void setDragKey(const QString &key); + + bool indexDragging(const QModelIndex &index) const; + + IndicatorTrayItem *indicatorWidget(const QString &indicatorName) const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + bool isIconTray(); + bool hasExpand() const; + bool isEmpty() const; + + void clear(); + WinInfo getWinInfo(const QModelIndex &index); + void saveConfig(int index, const WinInfo &winInfo); + void removeWinInfo(WinInfo winInfo); + +Q_SIGNALS: + void requestUpdateIcon(quint32); + void requestOpenEditor(const QModelIndex &index, bool isOpen = true) const; + void rowCountChanged(); + void requestRefreshEditor(); + +public Q_SLOTS: + void addRow(WinInfo info); + void insertRow(int index, WinInfo info); + +protected: + TrayModel(bool isIconTray, QObject *parent = Q_NULLPTR); + +private Q_SLOTS: + void onXEmbedTrayAdded(quint32 winId); + void onXEmbedTrayRemoved(quint32 winId); + void onSniTrayAdded(const QString &servicePath); + void onSniTrayRemoved(const QString &servicePath); + + void onIndicatorFounded(const QString &indicatorName); + void onIndicatorAdded(const QString &indicatorName); + void onIndicatorRemoved(const QString &indicatorName); + + void onSystemTrayAdded(PluginsItemInterface *itemInter); + void onSystemTrayRemoved(PluginsItemInterface *itemInter); + + void onSettingChanged(const QString &key, const QVariant &value); + +protected: + QMimeData *mimeData(const QModelIndexList &indexes) const Q_DECL_OVERRIDE; + QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; + bool removeRows(int row, int count, const QModelIndex &parent) Q_DECL_OVERRIDE; + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE; + Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; + +private: + void removeRow(const QString &itemKey); + bool exist(const QString &itemKey); + QString fileNameByServiceName(const QString &serviceName) const; + bool isTypeWriting(const QString &servicePath) const; + + bool inTrayConfig(const QString itemKey) const; + QString xembedItemKey(quint32 winId) const; + bool xembedCanExport(quint32 winId) const; + QString sniItemKey(const QString &servicePath) const; + bool sniCanExport(const QString &servicePath) const; + bool indicatorCanExport(const QString &indicatorName) const; + QString systemItemKey(const QString &pluginName) const; + bool systemItemCanExport(const QString &pluginName) const; + void sortItems(); + +private: + WinInfos m_winInfos; + + QModelIndex m_dragModelIndex; + QModelIndex m_dropModelIndex; + WinInfo m_dragInfo; + TrayMonitor *m_monitor; + + QString m_dragKey; + + QMap m_indicatorMap; + QStringList m_fixedTrayNames; + bool m_isTrayIcon; +}; + +Q_DECLARE_METATYPE(TrayIconType); + +#endif // TRAYMODEL_H diff --git a/frame/window/tray/tray_monitor.cpp b/frame/window/tray/tray_monitor.cpp new file mode 100644 index 000000000..970e4ef81 --- /dev/null +++ b/frame/window/tray/tray_monitor.cpp @@ -0,0 +1,135 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "tray_monitor.h" +#include "quicksettingcontroller.h" +#include "pluginsiteminterface.h" + +TrayMonitor::TrayMonitor(QObject *parent) + : QObject(parent) + , m_trayInter(new DBusTrayManager(this)) + , m_sniWatcher(new StatusNotifierWatcher("org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher", QDBusConnection::sessionBus(), this)) +{ + //-------------------------------Tray Embed---------------------------------------------// + connect(m_trayInter, &DBusTrayManager::TrayIconsChanged, this, &TrayMonitor::onTrayIconsChanged, Qt::QueuedConnection); + connect(m_trayInter, &DBusTrayManager::Changed, this, &TrayMonitor::requestUpdateIcon, Qt::QueuedConnection); + m_trayInter->Manage(); + QMetaObject::invokeMethod(this, "onTrayIconsChanged", Qt::QueuedConnection); + + //-------------------------------Tray SNI---------------------------------------------// + connect(m_sniWatcher, &StatusNotifierWatcher::StatusNotifierItemRegistered, this, &TrayMonitor::onSniItemsChanged, Qt::QueuedConnection); + connect(m_sniWatcher, &StatusNotifierWatcher::StatusNotifierItemUnregistered, this, &TrayMonitor::onSniItemsChanged, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "onSniItemsChanged", Qt::QueuedConnection); + + //-------------------------------System Tray------------------------------------------// + QuickSettingController *quickController = QuickSettingController::instance(); + connect(quickController, &QuickSettingController::pluginInserted, this, [ = ](PluginsItemInterface *itemInter, const QuickSettingController::PluginAttribute pluginAttr) { + if (pluginAttr != QuickSettingController::PluginAttribute::Tray) + return; + + m_systemTrays << itemInter; + Q_EMIT systemTrayAdded(itemInter); + }); + + connect(quickController, &QuickSettingController::pluginRemoved, this, [ = ](PluginsItemInterface *itemInter) { + if (!m_systemTrays.contains(itemInter)) + return; + + m_systemTrays.removeOne(itemInter); + Q_EMIT systemTrayRemoved(itemInter); + }); + + //-------------------------------Tray Indicator---------------------------------------------// + // Indicators服务是集成在插件中的,因此需要在所有的插件加载完成后再加载Indicators服务 + connect(quickController, &QuickSettingController::pluginLoaderFinished, this, [ this ] { + startLoadIndicators(); + }); + + QMetaObject::invokeMethod(this, [ = ] { + QList trayPlugins = quickController->pluginItems(QuickSettingController::PluginAttribute::Tray); + for (PluginsItemInterface *plugin : trayPlugins) { + m_systemTrays << plugin; + Q_EMIT systemTrayAdded(plugin); + } + }, Qt::QueuedConnection); +} + +QList TrayMonitor::trayWinIds() const +{ + return m_trayWids; +} + +QStringList TrayMonitor::sniServices() const +{ + return m_sniServices; +} + +QStringList TrayMonitor::indicatorNames() const +{ + return m_indicatorNames; +} + +QList TrayMonitor::systemTrays() const +{ + return m_systemTrays; +} + +void TrayMonitor::onTrayIconsChanged() +{ + QList wids = m_trayInter->trayIcons(); + if (m_trayWids == wids) + return; + + for (auto wid : wids) { + if (!m_trayWids.contains(wid)) { + Q_EMIT xEmbedTrayAdded(wid); + } + } + + for (auto wid : m_trayWids) { + if (!wids.contains(wid)) { + Q_EMIT xEmbedTrayRemoved(wid); + } + } + + m_trayWids = wids; +} + +void TrayMonitor::onSniItemsChanged() +{ + //TODO 防止同一个进程注册多个sni服务 + const QStringList &sniServices = m_sniWatcher->registeredStatusNotifierItems(); + if (m_sniServices == sniServices) + return; + + for (auto s : sniServices) { + if (!m_sniServices.contains(s)) { + if (s.startsWith("/") || !s.contains("/")) { + qWarning() << __FUNCTION__ << "invalid sni service" << s; + continue; + } + Q_EMIT sniTrayAdded(s); + } + } + + for (auto s : m_sniServices) { + if (!sniServices.contains(s)) { + Q_EMIT sniTrayRemoved(s); + } + } + + m_sniServices = sniServices; +} + +void TrayMonitor::startLoadIndicators() +{ + QDir indicatorConfDir("/etc/dde-dock/indicator"); + + for (const QFileInfo &fileInfo : indicatorConfDir.entryInfoList({"*.json"}, QDir::Files | QDir::NoDotAndDotDot)) { + const QString &indicatorName = fileInfo.baseName(); + m_indicatorNames << indicatorName; + Q_EMIT indicatorFounded(indicatorName); + } +} diff --git a/frame/window/tray/tray_monitor.h b/frame/window/tray/tray_monitor.h new file mode 100644 index 000000000..30e11e2b3 --- /dev/null +++ b/frame/window/tray/tray_monitor.h @@ -0,0 +1,59 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TRAYMONITOR_H +#define TRAYMONITOR_H + +#include + +#include "dbustraymanager.h" +#include "statusnotifierwatcher_interface.h" + +class PluginsItemInterface; + +using namespace org::kde; + +class TrayMonitor : public QObject +{ + Q_OBJECT + +public: + explicit TrayMonitor(QObject *parent = nullptr); + + QList trayWinIds() const; + QStringList sniServices() const; + QStringList indicatorNames() const; + QList systemTrays() const; + +Q_SIGNALS: + void requestUpdateIcon(quint32); + void xEmbedTrayAdded(quint32); + void xEmbedTrayRemoved(quint32); + + void sniTrayAdded(const QString &); + void sniTrayRemoved(const QString &); + + void systemTrayAdded(PluginsItemInterface *); + void systemTrayRemoved(PluginsItemInterface *); + + void indicatorFounded(const QString &); + +public Q_SLOTS: + void onTrayIconsChanged(); + void onSniItemsChanged(); + + void startLoadIndicators(); + +private: + DBusTrayManager *m_trayInter; + StatusNotifierWatcher *m_sniWatcher; + + QList m_trayWids; + QStringList m_sniServices; + QStringList m_indicatorNames; + QList m_systemTrays; +}; + +#endif // TRAYMONITOR_H diff --git a/frame/window/tray/widgets/basetraywidget.cpp b/frame/window/tray/widgets/basetraywidget.cpp new file mode 100644 index 000000000..ebca9e9fa --- /dev/null +++ b/frame/window/tray/widgets/basetraywidget.cpp @@ -0,0 +1,146 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "constants.h" +#include "basetraywidget.h" + +#include +#include +#include + +BaseTrayWidget::BaseTrayWidget(QWidget *parent, Qt::WindowFlags f) + : QWidget(parent, f) + , m_handleMouseReleaseTimer(new QTimer(this)) + , m_ownerPID(0) + , m_needShow(true) +{ + m_handleMouseReleaseTimer->setSingleShot(true); + m_handleMouseReleaseTimer->setInterval(10); + + connect(m_handleMouseReleaseTimer, &QTimer::timeout, this, &BaseTrayWidget::handleMouseRelease); +} + +BaseTrayWidget::~BaseTrayWidget() +{ +} + +void BaseTrayWidget::mousePressEvent(QMouseEvent *event) +{ + // call QWidget::mousePressEvent means to show dock-context-menu + // when right button of mouse is pressed immediately in fashion mode + + // here we hide the right button press event when it is click in the special area + if (event->button() == Qt::RightButton && perfectIconRect().contains(event->pos(), true)) { + event->accept(); + return; + } + + QWidget::mousePressEvent(event); +} + +void BaseTrayWidget::mouseReleaseEvent(QMouseEvent *e) +{ + //e->accept(); + // 由于 XWindowTrayWidget 中对 发送鼠标事件到X窗口的函数, 如 sendClick/sendHoverEvent 中 + // 使用了 setX11PassMouseEvent, 而每次调用 setX11PassMouseEvent 时都会导致产生 mousePress 和 mouseRelease 事件 + // 因此如果直接在这里处理事件会导致一些问题, 所以使用 Timer 来延迟处理 100 毫秒内的最后一个事件 + m_lastMouseReleaseData.first = e->pos(); + m_lastMouseReleaseData.second = e->button(); + + m_handleMouseReleaseTimer->start(); + + QWidget::mouseReleaseEvent(e); +} + +void BaseTrayWidget::handleMouseRelease() +{ + Q_ASSERT(sender() == m_handleMouseReleaseTimer); + + // do not dealwith all mouse event of SystemTray, class SystemTrayItem will handle it + if (trayType() == SystemTray) + return; + + const QPoint point(m_lastMouseReleaseData.first - rect().center()); + if (point.manhattanLength() > 24) + return; + + QPoint globalPos = QCursor::pos(); + uint8_t buttonIndex = XCB_BUTTON_INDEX_1; + + switch (m_lastMouseReleaseData.second) { + case Qt:: MiddleButton: + buttonIndex = XCB_BUTTON_INDEX_2; + break; + case Qt::RightButton: + buttonIndex = XCB_BUTTON_INDEX_3; + break; + default: + break; + } + + sendClick(buttonIndex, globalPos.x(), globalPos.y()); + + // left mouse button clicked + if (buttonIndex == XCB_BUTTON_INDEX_1) { + Q_EMIT clicked(); + } +} + +const QRect BaseTrayWidget::perfectIconRect() const +{ + const QRect itemRect = rect(); + const int iconSize = std::min(itemRect.width(), itemRect.height()); + + QRect iconRect; + iconRect.setWidth(iconSize); + iconRect.setHeight(iconSize); + iconRect.moveTopLeft(itemRect.center() - iconRect.center()); + + return iconRect; +} + +void BaseTrayWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + + const Dock::Position position = qApp->property(PROP_POSITION).value(); + // 保持横纵比 + if (position == Dock::Bottom || position == Dock::Top) { + setMaximumWidth(height()); + setMaximumHeight(QWIDGETSIZE_MAX); + } else { + setMaximumHeight(width()); + setMaximumWidth(QWIDGETSIZE_MAX); + } +} + +uint BaseTrayWidget::getOwnerPID() +{ + return this->m_ownerPID; +} + +bool BaseTrayWidget::needShow() +{ + return m_needShow; +} + +void BaseTrayWidget::setNeedShow(bool needShow) +{ +#ifdef QT_DEBUG + if (m_needShow == needShow) + return; + + m_needShow = needShow; +#else + m_needShow = true; +#endif + + update(); +} + +void BaseTrayWidget::setOwnerPID(uint PID) +{ + this->m_ownerPID = PID; +} diff --git a/frame/window/tray/widgets/basetraywidget.h b/frame/window/tray/widgets/basetraywidget.h new file mode 100644 index 000000000..b68064959 --- /dev/null +++ b/frame/window/tray/widgets/basetraywidget.h @@ -0,0 +1,60 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include +#include +#include + +class QDBusMessage; +class BaseTrayWidget : public QWidget +{ + Q_OBJECT + +public: + enum TrayType { + ApplicationTray, + SystemTray, + }; + + explicit BaseTrayWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + virtual ~BaseTrayWidget() override; + + virtual QString itemKeyForConfig() = 0; + virtual void updateIcon() = 0; + virtual void sendClick(uint8_t mouseButton, int x, int y) = 0; + virtual inline TrayType trayType() const { return TrayType::ApplicationTray; } // default is ApplicationTray + virtual bool isValid() {return true;} + uint getOwnerPID(); + virtual bool needShow(); + virtual void setNeedShow(bool needShow); + virtual QPixmap icon() = 0; + +Q_SIGNALS: + void iconChanged(); + void clicked(); + void needAttention(); + void requestWindowAutoHide(const bool autoHide); + void requestRefershWindowVisible(); + +protected: + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *e) override; + + void handleMouseRelease(); + const QRect perfectIconRect() const; + void resizeEvent(QResizeEvent *event) override; + void setOwnerPID(uint PID); + +private: + QTimer *m_handleMouseReleaseTimer; + + QPair m_lastMouseReleaseData; + + uint m_ownerPID; + bool m_needShow; +}; + diff --git a/frame/window/tray/widgets/expandiconwidget.cpp b/frame/window/tray/widgets/expandiconwidget.cpp new file mode 100644 index 000000000..1cd9d70aa --- /dev/null +++ b/frame/window/tray/widgets/expandiconwidget.cpp @@ -0,0 +1,345 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "expandiconwidget.h" +#include "tray_gridview.h" +#include "tray_model.h" +#include "tray_delegate.h" +#include "dockpopupwindow.h" +#include "imageutil.h" +#include "systempluginitem.h" + +#include +#include +#include +#include +#include + +#include + +DGUI_USE_NAMESPACE + +using RegionMonitor = Dtk::Gui::DRegionMonitor; + +ExpandIconWidget::ExpandIconWidget(QWidget *parent, Qt::WindowFlags f) + : BaseTrayWidget(parent, f) + , m_position(Dock::Position::Bottom) +{ +} + +ExpandIconWidget::~ExpandIconWidget() +{ +} + +void ExpandIconWidget::setPositon(Dock::Position position) +{ + if (m_position != position) + m_position = position; + + TrayGridWidget::setPosition(position); +} + +void ExpandIconWidget::sendClick(uint8_t mouseButton, int x, int y) +{ + Q_UNUSED(x); + Q_UNUSED(y); + + if (mouseButton != XCB_BUTTON_INDEX_1) + return; + + QWidget *gridParentView = popupTrayView(); + setTrayPanelVisible(!gridParentView->isVisible()); +} + +void ExpandIconWidget::setTrayPanelVisible(bool visible) +{ + TrayGridWidget *gridParentView = popupTrayView(); + if (visible) { + gridParentView->resetPosition(); + gridParentView->show(); + } else { + gridParentView->hide(); + } +} + +QPixmap ExpandIconWidget::icon() +{ + return QPixmap(dropIconFile()); +} + +void ExpandIconWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + QPixmap pixmap = ImageUtil::loadSvg(dropIconFile(), QSize(ICON_SIZE, ICON_SIZE)); + QRect rectOfPixmap(rect().x() + (rect().width() - ICON_SIZE) / 2, + rect().y() + (rect().height() - ICON_SIZE) / 2, + ICON_SIZE, ICON_SIZE); + + painter.drawPixmap(rectOfPixmap, pixmap); +} + +void ExpandIconWidget::moveEvent(QMoveEvent *event) +{ + BaseTrayWidget::moveEvent(event); + // 当前展开按钮位置发生变化的时候,需要同时改变托盘的位置 + QMetaObject::invokeMethod(this, [] { + TrayGridWidget *gridView = popupTrayView(); + if (gridView->isVisible()) + gridView->resetPosition(); + }, Qt::QueuedConnection); +} + +const QString ExpandIconWidget::dropIconFile() const +{ + QString arrow; + switch (m_position) { + case Dock::Position::Bottom: { + arrow = "up"; + break; + } + case Dock::Position::Top: { + arrow = "down"; + break; + } + case Dock::Position::Left: { + arrow = "right"; + break; + } + case Dock::Position::Right: { + arrow = "left"; + break; + } + } + + QString iconFile = QString(":/icons/resources/arrow-%1").arg(arrow); + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) + iconFile += QString("-dark"); + + return iconFile + ".svg"; +} + +TrayGridWidget *ExpandIconWidget::popupTrayView() +{ + static TrayGridWidget *gridParentView = nullptr; + if (gridParentView) + return gridParentView; + + gridParentView = new TrayGridWidget(nullptr); + TrayGridView *trayView = new TrayGridView(gridParentView); + TrayDelegate *trayDelegate = new TrayDelegate(trayView, trayView); + TrayModel *trayModel = TrayModel::getIconModel(); + gridParentView->setTrayGridView(trayView); + + gridParentView->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); + trayView->setModel(trayModel); + trayView->setItemDelegate(trayDelegate); + trayView->setSpacing(ITEM_SPACING); + trayView->setDragDistance(2); + + QVBoxLayout *layout = new QVBoxLayout(gridParentView); + layout->setContentsMargins(ITEM_SPACING, ITEM_SPACING, ITEM_SPACING, ITEM_SPACING); + layout->setSpacing(0); + layout->addWidget(trayView); + + auto rowCountChanged = [ = ] { + if (gridParentView->isVisible()) { + int count = trayModel->rowCount(); + if (count > 0) + gridParentView->resetPosition(); + else + gridParentView->hide(); + } + }; + + connect(trayModel, &TrayModel::rowCountChanged, gridParentView, rowCountChanged); + connect(trayModel, &TrayModel::requestRefreshEditor, trayView, &TrayGridView::onUpdateEditorView); + + connect(trayDelegate, &TrayDelegate::requestHide, trayView, &TrayGridView::requestHide); + connect(trayDelegate, &TrayDelegate::removeRow, trayView, [ = ](const QModelIndex &index) { + trayView->model()->removeRow(index.row(),index.parent()); + }); + connect(trayModel, &TrayModel::requestOpenEditor, trayView, [ trayView ](const QModelIndex &index) { + trayView->openPersistentEditor(index); + }); + + QMetaObject::invokeMethod(gridParentView, rowCountChanged, Qt::QueuedConnection); + + return gridParentView; +} + +/** + * @brief 圆角窗体的绘制 + * @param parent + */ + +Dock::Position TrayGridWidget::m_position = Dock::Position::Bottom; + +TrayGridWidget::TrayGridWidget(QWidget *parent) + : QWidget (parent) + , m_dockInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) + , m_trayGridView(nullptr) + , m_referGridView(nullptr) + , m_regionInter(new RegionMonitor(this)) +{ + initMember(); + setAttribute(Qt::WA_TranslucentBackground); +} + +void TrayGridWidget::setPosition(const Dock::Position &position) +{ + m_position = position; +} + +void TrayGridWidget::setTrayGridView(TrayGridView *trayView) +{ + m_trayGridView = trayView; + connect(m_trayGridView, &TrayGridView::requestHide, this, &TrayGridWidget::hide); +} + +void TrayGridWidget::setReferGridView(TrayGridView *trayView) +{ + m_referGridView = trayView; +} + +TrayGridView *TrayGridWidget::trayView() const +{ + return m_trayGridView; +} + +void TrayGridWidget::resetPosition() +{ + // 如果没有设置所属窗体,则无法计算位置 + ExpandIconWidget *expWidget = expandWidget(); + if (!expWidget) + return; + + m_trayGridView->setFixedSize(m_trayGridView->suitableSize()); + setFixedSize(m_trayGridView->size() + QSize(ITEM_SPACING * 2, ITEM_SPACING * 2)); + + QWidget *topWidget = expWidget->topLevelWidget(); + QPoint ptPos = expWidget->mapToGlobal(QPoint(0, 0)); + switch (m_position) { + case Dock::Position::Bottom: { + ptPos.setY(topWidget->y() - height()); + break; + } + case Dock::Position::Top: { + ptPos.setY(topWidget->y() + topWidget->height()); + break; + } + case Dock::Position::Left: { + ptPos.setX(topWidget->x() + topWidget->width()); + break; + } + case Dock::Position::Right: { + ptPos.setX(topWidget->x() - width()); + break; + } + } + move(ptPos); +} + +void TrayGridWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + QPainterPath path; + path.addRoundedRect(rect(), 18, 18); + painter.setCompositionMode(QPainter::CompositionMode_Xor); + painter.setClipPath(path); + + painter.fillPath(path, maskColor()); +} + +void TrayGridWidget::showEvent(QShowEvent *event) +{ + m_regionInter->registerRegion(); + QWidget::showEvent(event); +} + +void TrayGridWidget::hideEvent(QHideEvent *event) +{ + m_regionInter->unregisterRegion(); + // 在当前托盘区域隐藏后,需要设置任务栏区域的展开按钮的托盘为隐藏状态 + TrayModel::getDockModel()->updateOpenExpand(false); + QWidget::hideEvent(event); +} + +void TrayGridWidget::initMember() +{ + connect(m_regionInter, &RegionMonitor::buttonPress, this, [ = ](const QPoint &mousePos, const int flag) { + // 如果当前是隐藏,那么在点击任何地方都隐藏 + if (!isVisible()) { + hide(); + return; + } + + if ((flag != RegionMonitor::WatchedFlags::Button_Left) && (flag != RegionMonitor::WatchedFlags::Button_Right)) + return; + + QPoint ptPos = parentWidget()->mapToGlobal(this->pos()); + const QRect rect = QRect(ptPos, size()); + if (rect.contains(mousePos)) + return; + // 如果点击的是展开区域,则不做任何处理,因为点击展开区域自己会处理 + if (m_referGridView) { + QAbstractItemModel *model = m_referGridView->model(); + for (int i = 0; i < model->rowCount(); i++) { + ExpandIconWidget *widget = qobject_cast(m_referGridView->indexWidget(model->index(i, 0))); + if (!widget) + continue; + + QRect rectExpandWidget(widget->mapToGlobal(QPoint(0, 0)), widget->size()); + if (rectExpandWidget.contains(mousePos)) + return; + } + } + + const QRect rctView(pos(), size()); + if (rctView.contains(mousePos)) + return; + + // 查看是否存在SystemPluginItem插件,在此处判断的原因是因为当弹出右键菜单的时候,如果鼠标在菜单上点击 + // 刚好把托盘区域给隐藏了,导致菜单也跟着隐藏,导致点击菜单的时候不生效 + QAbstractItemModel *dataModel = m_trayGridView->model(); + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + SystemPluginItem *widget = qobject_cast(m_trayGridView->indexWidget(index)); + if (widget && widget->containsPoint(mousePos)) + return; + } + + hide(); + }); +} + +QColor TrayGridWidget::maskColor() const +{ + QColor color = DGuiApplicationHelper::standardPalette(DGuiApplicationHelper::instance()->themeType()).window().color(); + int maskAlpha(static_cast(255 * m_dockInter->opacity())); + color.setAlpha(maskAlpha); + return color; +} + +ExpandIconWidget *TrayGridWidget::expandWidget() const +{ + if (!m_referGridView) + return nullptr; + + QAbstractItemModel *dataModel = m_referGridView->model(); + if (!dataModel) + return nullptr; + + for (int i = 0; i < dataModel->rowCount(); i++) { + QModelIndex index = dataModel->index(i, 0); + ExpandIconWidget *widget = qobject_cast(m_referGridView->indexWidget(index)); + if (widget) + return widget; + } + + return nullptr; +} diff --git a/frame/window/tray/widgets/expandiconwidget.h b/frame/window/tray/widgets/expandiconwidget.h new file mode 100644 index 000000000..8fca811b9 --- /dev/null +++ b/frame/window/tray/widgets/expandiconwidget.h @@ -0,0 +1,77 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef EXPANDICONWIDGET_H +#define EXPANDICONWIDGET_H + +#include "constants.h" +#include "basetraywidget.h" +#include "dbusutil.h" + +class TrayGridView; +class TrayModel; +class TrayDelegate; +class TrayGridWidget; + +namespace Dtk { namespace Gui { class DRegionMonitor; } } + +class ExpandIconWidget : public BaseTrayWidget +{ + Q_OBJECT + +public: + explicit ExpandIconWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + ~ExpandIconWidget() override; + void setPositon(Dock::Position position); + + void sendClick(uint8_t mouseButton, int x, int y) override; + void setTrayPanelVisible(bool visible); + QString itemKeyForConfig() override { return "Expand"; } + void updateIcon() override {} + QPixmap icon() override; + static TrayGridWidget *popupTrayView(); + +protected: + void paintEvent(QPaintEvent *event) override; + void moveEvent(QMoveEvent *event) override; + const QString dropIconFile() const; + +private: + Dock::Position m_position; +}; + +// 绘制圆角窗体 +class TrayGridWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TrayGridWidget(QWidget *parent); + + static void setPosition(const Dock::Position &position); + void setTrayGridView(TrayGridView *trayView); + void setReferGridView(TrayGridView *trayView); + TrayGridView *trayView() const; + void resetPosition(); + +protected: + void paintEvent(QPaintEvent *event) override; + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + +private: + void initMember(); + QColor maskColor() const; + ExpandIconWidget *expandWidget() const; + +private: + DockInter *m_dockInter; + TrayGridView *m_trayGridView; + TrayGridView *m_referGridView; + Dtk::Gui::DRegionMonitor *m_regionInter; + static Dock::Position m_position; +}; + +#endif // EXPANDICONWIDGET_H diff --git a/frame/window/tray/widgets/indicatorplugin.cpp b/frame/window/tray/widgets/indicatorplugin.cpp new file mode 100644 index 000000000..5d0856622 --- /dev/null +++ b/frame/window/tray/widgets/indicatorplugin.cpp @@ -0,0 +1,280 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "indicatorplugin.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class IndicatorPluginPrivate +{ +public: + explicit IndicatorPluginPrivate(IndicatorPlugin *parent) : q_ptr(parent) {} + + void init(); + + void updateContent(); + + void initDBus(const QString &indicatorName); + + template + void featData(const QString &key, + const QJsonObject &data, + const char *propertyChangedSlot, + Func const &callback) + { + Q_Q(IndicatorPlugin); + auto dataConfig = data.value(key).toObject(); + auto dbusService = dataConfig.value("dbus_service").toString(); + auto dbusPath = dataConfig.value("dbus_path").toString(); + auto dbusInterface = dataConfig.value("dbus_interface").toString(); + auto isSystemBus = dataConfig.value("system_dbus").toBool(false); + auto bus = isSystemBus ? QDBusConnection::systemBus() : QDBusConnection::sessionBus(); + + QDBusInterface interface(dbusService, dbusPath, dbusInterface, bus, q); + + if (dataConfig.contains("dbus_method")) { + QString methodName = dataConfig.value("dbus_method").toString(); + auto ratio = qApp->devicePixelRatio(); + QDBusReply reply = interface.call(methodName.toStdString().c_str(), ratio); + callback(reply.value()); + } + + if (dataConfig.contains("dbus_properties")) { + auto propertyName = dataConfig.value("dbus_properties").toString(); + auto propertyNameCStr = propertyName.toStdString(); + propertyInterfaceNames.insert(key, dbusInterface); + propertyNames.insert(key, QString::fromStdString(propertyNameCStr)); + QDBusConnection::sessionBus().connect(dbusService, + dbusPath, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + "sa{sv}as", + q, + propertyChangedSlot); + + // FIXME(sbw): hack for qt dbus property changed signal. + // see: https://bugreports.qt.io/browse/QTBUG-48008 + QDBusConnection::sessionBus().connect(dbusService, + dbusPath, + dbusInterface, + QString("%1Changed").arg(propertyName), + "s", + q, + propertyChangedSlot); + + callback(interface.property(propertyNameCStr.c_str())); + } + } + + template + void propertyChanged(const QString &key, const QDBusMessage &msg, Func const &callback) + { + QList arguments = msg.arguments(); + if (1 == arguments.count()) + { + const QString &v = msg.arguments().at(0).toString(); + callback(v); + return; + } else if (3 != arguments.count()) { + qDebug() << "arguments count must be 3"; + return; + } + + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName != propertyInterfaceNames.value(key)) { + qDebug() << "interfaceName mismatch" << interfaceName << propertyInterfaceNames.value(key) << key; + return; + } + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + if (changedProps.contains(propertyNames.value(key))) { + callback(changedProps.value(propertyNames.value(key))); + } + } + + IndicatorTrayItem* indicatorTrayWidget = Q_NULLPTR; + QString indicatorName; + QMap propertyNames; + QMap propertyInterfaceNames; + + IndicatorPlugin *q_ptr; + Q_DECLARE_PUBLIC(IndicatorPlugin) +}; + +void IndicatorPluginPrivate::init() +{ + //Q_Q(IndicatorTray); + + indicatorTrayWidget = new IndicatorTrayItem(indicatorName); + + initDBus(indicatorName); + updateContent(); +} + +void IndicatorPluginPrivate::updateContent() +{ + indicatorTrayWidget->update(); + + Q_EMIT indicatorTrayWidget->iconChanged(); +} + +void IndicatorPluginPrivate::initDBus(const QString &indicatorName) +{ + Q_Q(IndicatorPlugin); + + QString filepath = QString("/etc/dde-dock/indicator/%1.json").arg(indicatorName); + QFile confFile(filepath); + if (!confFile.open(QIODevice::ReadOnly)) { + qCritical() << "read indicator config Error"; + } + + QJsonDocument doc = QJsonDocument::fromJson(confFile.readAll()); + confFile.close(); + auto config = doc.object(); + + auto delay = config.value("delay").toInt(0); + + qDebug() << "delay load" << delay << indicatorName << q; + + QTimer::singleShot(delay, [ = ]() { + auto data = config.value("data").toObject(); + + if (data.contains("text")) { + featData("text", data, SLOT(textPropertyChanged(QDBusMessage)), [ = ](QVariant v) { + if (v.toString().isEmpty()) { + q->m_isLoaded = false; + Q_EMIT q->removed(); + return; + } + q->m_isLoaded = true; + Q_EMIT q->delayLoaded(); + indicatorTrayWidget->setText(v.toString()); + updateContent(); + }); + } + + if (data.contains("icon")) { + featData("icon", data, SLOT(iconPropertyChanged(QDBusMessage)), [ = ](QVariant v) { + if (v.toByteArray().isEmpty()) { + q->m_isLoaded = false; + Q_EMIT q->removed(); + return; + } + q->m_isLoaded = true; + Q_EMIT q->delayLoaded(); + indicatorTrayWidget->setPixmapData(v.toByteArray()); + updateContent(); + }); + } + + const QJsonObject action = config.value("action").toObject(); + if (!action.isEmpty() && indicatorTrayWidget) + q->connect(indicatorTrayWidget, &IndicatorTrayItem::clicked, q, [ = ](uint8_t button_index, int x, int y) { + std::thread t([ = ] ()-> void { + auto triggerConfig = action.value("trigger").toObject(); + auto dbusService = triggerConfig.value("dbus_service").toString(); + auto dbusPath = triggerConfig.value("dbus_path").toString(); + auto dbusInterface = triggerConfig.value("dbus_interface").toString(); + auto methodName = triggerConfig.value("dbus_method").toString(); + auto isSystemBus = triggerConfig.value("system_dbus").toBool(false); + auto bus = isSystemBus ? QDBusConnection::systemBus() : QDBusConnection::sessionBus(); + + QDBusInterface interface(dbusService, dbusPath, dbusInterface, bus); + QDBusReply reply = interface.call(methodName, button_index, x, y); + qDebug() << (reply.isValid() ? reply.error() : interface.call(methodName)); + }); + t.detach(); + }); + }); +} + +IndicatorPlugin::IndicatorPlugin(const QString &indicatorName, QObject *parent) + : QObject(parent) + , d_ptr(new IndicatorPluginPrivate(this)) + , m_isLoaded(false) +{ + Q_D(IndicatorPlugin); + + d->indicatorName = indicatorName; + d->init(); +} + +IndicatorPlugin::~IndicatorPlugin() +{ + +} + +IndicatorTrayItem *IndicatorPlugin::widget() +{ + Q_D(IndicatorPlugin); + + if (!d->indicatorTrayWidget) { + d->init(); + } + + return d->indicatorTrayWidget; +} + +void IndicatorPlugin::removeWidget() +{ + Q_D(IndicatorPlugin); + + d->indicatorTrayWidget = nullptr; +} + +bool IndicatorPlugin::isLoaded() +{ + return m_isLoaded; +} + +void IndicatorPlugin::textPropertyChanged(const QDBusMessage &message) +{ + Q_D(IndicatorPlugin); + + d->propertyChanged("text", message, [ = ] (const QVariant &value) { + if (value.toString().isEmpty()) { + m_isLoaded = false; + Q_EMIT removed(); + return; + } + + if (!d->indicatorTrayWidget) { + d->init(); + } + + d->indicatorTrayWidget->setText(value.toByteArray()); + Q_EMIT delayLoaded(); + }); +} + +void IndicatorPlugin::iconPropertyChanged(const QDBusMessage &message) +{ + Q_D(IndicatorPlugin); + + d->propertyChanged("icon", message, [ = ] (const QVariant &value) { + if (value.toByteArray().isEmpty()) { + m_isLoaded = false; + Q_EMIT removed(); + return; + } + + if (!d->indicatorTrayWidget) { + d->init(); + } + + d->indicatorTrayWidget->setPixmapData(value.toByteArray()); + Q_EMIT delayLoaded(); + }); +} diff --git a/frame/window/tray/widgets/indicatorplugin.h b/frame/window/tray/widgets/indicatorplugin.h new file mode 100644 index 000000000..ca52aa27e --- /dev/null +++ b/frame/window/tray/widgets/indicatorplugin.h @@ -0,0 +1,39 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include "indicatortrayitem.h" + +#include +#include + +class IndicatorPluginPrivate; +class IndicatorPlugin : public QObject +{ + Q_OBJECT +public: + explicit IndicatorPlugin(const QString &indicatorName, QObject *parent = nullptr); + ~IndicatorPlugin(); + + IndicatorTrayItem *widget(); + + void removeWidget(); + + bool isLoaded(); + +signals: + void delayLoaded(); + void removed(); + +private slots: + void textPropertyChanged(const QDBusMessage &message); + void iconPropertyChanged(const QDBusMessage &message); + +private: + QScopedPointer d_ptr; + bool m_isLoaded; + Q_DECLARE_PRIVATE_D(qGetPtrHelper(d_ptr), IndicatorPlugin) +}; diff --git a/frame/window/tray/widgets/indicatortrayitem.cpp b/frame/window/tray/widgets/indicatortrayitem.cpp new file mode 100644 index 000000000..d26636a5c --- /dev/null +++ b/frame/window/tray/widgets/indicatortrayitem.cpp @@ -0,0 +1,118 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "indicatortrayitem.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +IndicatorTrayItem::IndicatorTrayItem(const QString &indicatorName, QWidget *parent, Qt::WindowFlags f) + : BaseTrayWidget(parent, f) + , m_indicatorName(indicatorName) + , m_enableClick(true) +{ + setAttribute(Qt::WA_TranslucentBackground); + + auto layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + m_label = new QLabel(this); + + QPalette p = m_label->palette(); + p.setColor(QPalette::Foreground, Qt::white); + p.setColor(QPalette::Background, Qt::transparent); + m_label->setPalette(p); + + m_label->setAttribute(Qt::WA_TranslucentBackground); + + layout->addWidget(m_label, 0, Qt::AlignCenter); + setLayout(layout); + + // register dbus + auto path = QString("/org/deepin/dde/Dock1/Indicator/") + m_indicatorName; + auto interface = QString("org.deepin.dde.Dock1.Indicator.") + m_indicatorName; + auto sessionBus = QDBusConnection::sessionBus(); + sessionBus.registerObject(path, + interface, + this, + QDBusConnection::ExportScriptableSlots); +} + +IndicatorTrayItem::~IndicatorTrayItem() +{ +} + +QString IndicatorTrayItem::itemKeyForConfig() +{ + return toIndicatorKey(m_indicatorName); +} + +void IndicatorTrayItem::updateIcon() +{ + +} + +void IndicatorTrayItem::sendClick(uint8_t buttonIndex, int x, int y) +{ + if (m_enableClick) + Q_EMIT clicked(buttonIndex, x, y); +} + +void IndicatorTrayItem::enableLabel(bool enable) +{ + QPalette p = m_label->palette(); + if (!enable) { + m_enableClick = false; + p.setColor(QPalette::Disabled, QPalette::Foreground, Qt::lightGray); + p.setColor(QPalette::Disabled, QPalette::Background, Qt::transparent); + m_label->setEnabled(enable); + } else { + m_enableClick = true; + p.setColor(QPalette::Normal, QPalette::BrightText, Qt::white); + p.setColor(QPalette::Normal, QPalette::Background, Qt::transparent); + m_label->setEnabled(enable); + } + + m_label->setPalette(p); + m_label->update(); +} + +QPixmap IndicatorTrayItem::icon() +{ + return QPixmap(); +} + +const QByteArray &IndicatorTrayItem::pixmapData() const +{ + return m_pixmapData; +} + +const QString IndicatorTrayItem::text() const +{ + return m_label->text(); +} + +void IndicatorTrayItem::setPixmapData(const QByteArray &data) +{ + m_pixmapData = data; + auto rawPixmap = QPixmap::fromImage(QImage::fromData(data)); + rawPixmap.setDevicePixelRatio(devicePixelRatioF()); + m_label->setPixmap(rawPixmap); +} + +void IndicatorTrayItem::setText(const QString &text) +{ + m_label->setText(text); +} diff --git a/frame/window/tray/widgets/indicatortrayitem.h b/frame/window/tray/widgets/indicatortrayitem.h new file mode 100644 index 000000000..1eba5610d --- /dev/null +++ b/frame/window/tray/widgets/indicatortrayitem.h @@ -0,0 +1,46 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include +#include + +#include "basetraywidget.h" + +class QGSettings; + +class IndicatorTrayItem: public BaseTrayWidget +{ + Q_OBJECT + +public: + explicit IndicatorTrayItem(const QString &indicatorName, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + ~IndicatorTrayItem() override; + + QString itemKeyForConfig() override; + void updateIcon() override; + void sendClick(uint8_t, int, int) override; + void enableLabel(bool enable); + static QString toIndicatorKey(const QString &indicatorName) { return QString("indicator:%1").arg(indicatorName); } + static bool isIndicatorKey(const QString &itemKey) { return itemKey.startsWith("indicator:"); } + QPixmap icon() override; + const QByteArray &pixmapData() const; + const QString text() const; + +public Q_SLOTS: + Q_SCRIPTABLE void setPixmapData(const QByteArray &data); + Q_SCRIPTABLE void setText(const QString &text); + +Q_SIGNALS: + void clicked(uint8_t, int, int); + +private: + QLabel *m_label; + QString m_indicatorName; + bool m_enableClick; // 置灰时设置为false,不触发click信号 + QByteArray m_pixmapData; +}; + diff --git a/frame/window/tray/widgets/snitrayitemwidget.cpp b/frame/window/tray/widgets/snitrayitemwidget.cpp new file mode 100644 index 000000000..21468b9b9 --- /dev/null +++ b/frame/window/tray/widgets/snitrayitemwidget.cpp @@ -0,0 +1,781 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "snitrayitemwidget.h" +#include "themeappicon.h" +#include "tipswidget.h" +#include "utils.h" + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +DGUI_USE_NAMESPACE + +#define IconSize 20 + +const QStringList ItemCategoryList {"ApplicationStatus", "Communications", "SystemServices", "Hardware"}; +const QStringList ItemStatusList {"Passive", "Active", "NeedsAttention"}; +const QStringList LeftClickInvalidIdList {"sogou-qimpanel",}; +QPointer SNITrayItemWidget::PopupWindow = nullptr; +Dock::Position SNITrayItemWidget::DockPosition = Dock::Position::Bottom; +using namespace Dock; + +SNITrayItemWidget::SNITrayItemWidget(const QString &sniServicePath, QWidget *parent) + : BaseTrayWidget(parent), + m_menu(nullptr), + m_updateIconTimer(new QTimer(this)) + , m_updateOverlayIconTimer(new QTimer(this)) + , m_updateAttentionIconTimer(new QTimer(this)) + , m_sniServicePath(sniServicePath) + , m_popupTipsDelayTimer(new QTimer(this)) + , m_handleMouseReleaseTimer(new QTimer(this)) + , m_tipsLabel(new TipsWidget) + , m_popupShown(false) +{ + m_popupTipsDelayTimer->setInterval(500); + m_popupTipsDelayTimer->setSingleShot(true); + m_handleMouseReleaseTimer->setSingleShot(true); + m_handleMouseReleaseTimer->setInterval(100); + + connect(m_handleMouseReleaseTimer, &QTimer::timeout, this, &SNITrayItemWidget::handleMouseRelease); + connect(m_popupTipsDelayTimer, &QTimer::timeout, this, &SNITrayItemWidget::showHoverTips); + + if (PopupWindow.isNull()) { + DockPopupWindow *arrowRectangle = new DockPopupWindow(nullptr); + arrowRectangle->setShadowBlurRadius(20); + arrowRectangle->setRadius(6); + arrowRectangle->setShadowYOffset(2); + arrowRectangle->setShadowXOffset(0); + arrowRectangle->setArrowWidth(18); + arrowRectangle->setArrowHeight(10); + arrowRectangle->setObjectName("snitraypopup"); + PopupWindow = arrowRectangle; + if (Utils::IS_WAYLAND_DISPLAY) + PopupWindow->setWindowFlags(PopupWindow->windowFlags() | Qt::FramelessWindowHint); + connect(qApp, &QApplication::aboutToQuit, PopupWindow, &DockPopupWindow::deleteLater); + } + + if (m_sniServicePath.startsWith("/") || !m_sniServicePath.contains("/")) { + qDebug() << "SNI service path invalid"; + return; + } + + QPair pair = serviceAndPath(m_sniServicePath); + m_dbusService = pair.first; + m_dbusPath = pair.second; + + QDBusConnection conn = QDBusConnection::sessionBus(); + setOwnerPID(conn.interface()->servicePid(m_dbusService)); + + m_sniInter = new StatusNotifierItem(m_dbusService, m_dbusPath, QDBusConnection::sessionBus(), this); + m_sniInter->setSync(false); + + if (!m_sniInter->isValid()) { + qDebug() << "SNI dbus interface is invalid!" << m_dbusService << m_dbusPath << m_sniInter->lastError(); + return; + } + + m_updateIconTimer->setInterval(100); + m_updateIconTimer->setSingleShot(true); + m_updateOverlayIconTimer->setInterval(500); + m_updateOverlayIconTimer->setSingleShot(true); + m_updateAttentionIconTimer->setInterval(1000); + m_updateAttentionIconTimer->setSingleShot(true); + + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &SNITrayItemWidget::refreshIcon); + connect(m_updateIconTimer, &QTimer::timeout, this, &SNITrayItemWidget::refreshIcon); + connect(m_updateOverlayIconTimer, &QTimer::timeout, this, &SNITrayItemWidget::refreshOverlayIcon); + connect(m_updateAttentionIconTimer, &QTimer::timeout, this, &SNITrayItemWidget::refreshAttentionIcon); + + // SNI property change + // thses signals of properties may not be emit automatically!! + // since the SniInter in on async mode we can not call property's getter function to obtain property directly + // the way to refresh properties(emit the following signals) is call property's getter function and wait these signals + connect(m_sniInter, &StatusNotifierItem::AttentionIconNameChanged, this, &SNITrayItemWidget::onSNIAttentionIconNameChanged); + connect(m_sniInter, &StatusNotifierItem::AttentionIconPixmapChanged, this, &SNITrayItemWidget::onSNIAttentionIconPixmapChanged); + connect(m_sniInter, &StatusNotifierItem::AttentionMovieNameChanged, this, &SNITrayItemWidget::onSNIAttentionMovieNameChanged); + connect(m_sniInter, &StatusNotifierItem::CategoryChanged, this, &SNITrayItemWidget::onSNICategoryChanged); + connect(m_sniInter, &StatusNotifierItem::IconNameChanged, this, &SNITrayItemWidget::onSNIIconNameChanged); + connect(m_sniInter, &StatusNotifierItem::IconPixmapChanged, this, &SNITrayItemWidget::onSNIIconPixmapChanged); + connect(m_sniInter, &StatusNotifierItem::IconThemePathChanged, this, &SNITrayItemWidget::onSNIIconThemePathChanged); + connect(m_sniInter, &StatusNotifierItem::IdChanged, this, &SNITrayItemWidget::onSNIIdChanged); + connect(m_sniInter, &StatusNotifierItem::MenuChanged, this, &SNITrayItemWidget::onSNIMenuChanged); + connect(m_sniInter, &StatusNotifierItem::OverlayIconNameChanged, this, &SNITrayItemWidget::onSNIOverlayIconNameChanged); + connect(m_sniInter, &StatusNotifierItem::OverlayIconPixmapChanged, this, &SNITrayItemWidget::onSNIOverlayIconPixmapChanged); + connect(m_sniInter, &StatusNotifierItem::StatusChanged, this, &SNITrayItemWidget::onSNIStatusChanged); + + // the following signals can be emit automatically + // need refresh cached properties in these slots + connect(m_sniInter, &StatusNotifierItem::NewIcon, [ = ] { + m_sniIconName = m_sniInter->iconName(); + m_sniIconPixmap = m_sniInter->iconPixmap(); + m_sniIconThemePath = m_sniInter->iconThemePath(); + + m_updateIconTimer->start(); + }); + connect(m_sniInter, &StatusNotifierItem::NewOverlayIcon, [ = ] { + m_sniOverlayIconName = m_sniInter->overlayIconName(); + m_sniOverlayIconPixmap = m_sniInter->overlayIconPixmap(); + m_sniIconThemePath = m_sniInter->iconThemePath(); + + m_updateOverlayIconTimer->start(); + }); + connect(m_sniInter, &StatusNotifierItem::NewAttentionIcon, [ = ] { + m_sniAttentionIconName = m_sniInter->attentionIconName(); + m_sniAttentionIconPixmap = m_sniInter->attentionIconPixmap(); + m_sniIconThemePath = m_sniInter->iconThemePath(); + + m_updateAttentionIconTimer->start(); + }); + connect(m_sniInter, &StatusNotifierItem::NewStatus, [ = ] { + onSNIStatusChanged(m_sniInter->status()); + }); + + QMetaObject::invokeMethod(this, &SNITrayItemWidget::initMember, Qt::QueuedConnection); +} + +SNITrayItemWidget::~SNITrayItemWidget() +{ + m_tipsLabel->deleteLater(); +} + +QString SNITrayItemWidget::itemKeyForConfig() +{ + return QString("sni:%1").arg(m_sniId.isEmpty() ? m_sniServicePath : m_sniId); +} + +void SNITrayItemWidget::updateIcon() +{ + m_updateIconTimer->start(); +} + +void SNITrayItemWidget::sendClick(uint8_t mouseButton, int x, int y) +{ + switch (mouseButton) { + case XCB_BUTTON_INDEX_1: { + QFuture future = QtConcurrent::run([ = ] { + StatusNotifierItem inter(m_dbusService, m_dbusPath, QDBusConnection::sessionBus()); + QDBusPendingReply<> reply = inter.Activate(x, y); + // try to invoke context menu while calling activate get a error. + // primarily work for apps using libappindicator. + reply.waitForFinished(); + if (reply.isError()) { + showContextMenu(x,y); + } + }); + } + break; + case XCB_BUTTON_INDEX_2: + m_sniInter->SecondaryActivate(x, y); + break; + case XCB_BUTTON_INDEX_3: + showContextMenu(x, y); + break; + default: + qDebug() << "unknown mouse button key"; + break; + } +} + +bool SNITrayItemWidget::isValid() +{ + return m_sniInter->isValid(); +} + +SNITrayItemWidget::ItemStatus SNITrayItemWidget::status() +{ + if (!ItemStatusList.contains(m_sniStatus)) { + m_sniStatus = "Active"; + return ItemStatus::Active; + } + + return static_cast(ItemStatusList.indexOf(m_sniStatus)); +} + +SNITrayItemWidget::ItemCategory SNITrayItemWidget::category() +{ + if (!ItemCategoryList.contains(m_sniCategory)) { + return UnknownCategory; + } + + return static_cast(ItemCategoryList.indexOf(m_sniCategory)); +} + +QString SNITrayItemWidget::toSNIKey(const QString &sniServicePath) +{ + return QString("sni:%1").arg(sniServicePath); +} + +bool SNITrayItemWidget::isSNIKey(const QString &itemKey) +{ + return itemKey.startsWith("sni:"); +} + +QPair SNITrayItemWidget::serviceAndPath(const QString &servicePath) +{ + QStringList list = servicePath.split("/"); + QPair pair; + pair.first = list.takeFirst(); + + for (auto i : list) { + pair.second.append("/"); + pair.second.append(i); + } + + return pair; +} + +uint SNITrayItemWidget::servicePID(const QString &servicePath) +{ + QString serviceName = serviceAndPath(servicePath).first; + QDBusConnection conn = QDBusConnection::sessionBus(); + return conn.interface()->servicePid(serviceName); +} + +void SNITrayItemWidget::initMenu() +{ + const QString &sniMenuPath = m_sniMenuPath.path(); + if (sniMenuPath.isEmpty()) { + qDebug() << "Error: current sni menu path is empty of dbus service:" << m_dbusService << "id:" << m_sniId; + return; + } + + qDebug() << "using sni service path:" << m_dbusService << "menu path:" << sniMenuPath; + + m_dbusMenuImporter = new DBusMenuImporter(m_dbusService, sniMenuPath, ASYNCHRONOUS, this); + + qDebug() << "generate the sni menu object"; + + m_menu = m_dbusMenuImporter->menu(); + + qDebug() << "the sni menu obect is:" << m_menu; +} + +void SNITrayItemWidget::refreshIcon() +{ + QPixmap pix = newIconPixmap(Icon); + if (pix.isNull()) { + return; + } + + m_pixmap = pix; + update(); + Q_EMIT iconChanged(); + + if (!isVisible()) { + Q_EMIT needAttention(); + } +} + +void SNITrayItemWidget::refreshOverlayIcon() +{ + QPixmap pix = newIconPixmap(OverlayIcon); + if (pix.isNull()) { + return; + } + + m_overlayPixmap = pix; + update(); + Q_EMIT iconChanged(); + + if (!isVisible()) { + Q_EMIT needAttention(); + } +} + +void SNITrayItemWidget::refreshAttentionIcon() +{ + /* TODO: A new approach may be needed to deal with attentionIcon */ + QPixmap pix = newIconPixmap(AttentionIcon); + if (pix.isNull()) { + return; + } + + m_pixmap = pix; + update(); + Q_EMIT iconChanged(); + + if (!isVisible()) { + Q_EMIT needAttention(); + } +} + +void SNITrayItemWidget::showContextMenu(int x, int y) +{ + // 这里的PopupWindow属性是置顶的,如果不隐藏,会导致菜单显示不出来 + hidePopup(); + + // ContextMenu does not work + if (m_sniMenuPath.path().startsWith("/NO_DBUSMENU")) { + m_sniInter->ContextMenu(x, y); + } else { + if (!m_menu) { + qDebug() << "context menu has not be ready, init menu"; + initMenu(); + } + + if (m_menu) + m_menu->popup(QPoint(x, y)); + } +} + +void SNITrayItemWidget::onSNIAttentionIconNameChanged(const QString &value) +{ + m_sniAttentionIconName = value; + + m_updateAttentionIconTimer->start(); +} + +void SNITrayItemWidget::onSNIAttentionIconPixmapChanged(DBusImageList value) +{ + m_sniAttentionIconPixmap = value; + + m_updateAttentionIconTimer->start(); +} + +void SNITrayItemWidget::onSNIAttentionMovieNameChanged(const QString &value) +{ + m_sniAttentionMovieName = value; + + m_updateAttentionIconTimer->start(); +} + +void SNITrayItemWidget::onSNICategoryChanged(const QString &value) +{ + m_sniCategory = value; +} + +void SNITrayItemWidget::onSNIIconNameChanged(const QString &value) +{ + m_sniIconName = value; + + m_updateIconTimer->start(); +} + +void SNITrayItemWidget::onSNIIconPixmapChanged(DBusImageList value) +{ + m_sniIconPixmap = value; + + m_updateIconTimer->start(); +} + +void SNITrayItemWidget::onSNIIconThemePathChanged(const QString &value) +{ + m_sniIconThemePath = value; + + m_updateIconTimer->start(); +} + +void SNITrayItemWidget::onSNIIdChanged(const QString &value) +{ + m_sniId = value; +} + +void SNITrayItemWidget::onSNIMenuChanged(const QDBusObjectPath &value) +{ + m_sniMenuPath = value; +} + +void SNITrayItemWidget::onSNIOverlayIconNameChanged(const QString &value) +{ + m_sniOverlayIconName = value; + + m_updateOverlayIconTimer->start(); +} + +void SNITrayItemWidget::onSNIOverlayIconPixmapChanged(DBusImageList value) +{ + m_sniOverlayIconPixmap = value; + + m_updateOverlayIconTimer->start(); +} + +void SNITrayItemWidget::onSNIStatusChanged(const QString &status) +{ + if (!ItemStatusList.contains(status) || m_sniStatus == status) { + return; + } + + m_sniStatus = status; + + Q_EMIT statusChanged(static_cast(ItemStatusList.indexOf(status))); +} + +void SNITrayItemWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e); + if (!needShow()) { + return; + } + + if (m_pixmap.isNull()) + return; + + QPainter painter; + painter.begin(this); + painter.setRenderHint(QPainter::Antialiasing); + +//#ifdef QT_DEBUG +// painter.fillRect(rect(), Qt::green); +//#endif + + const QRectF &rf = QRect(rect()); + const QRectF &rfp = QRect(m_pixmap.rect()); + const QPointF &p = rf.center() - rfp.center() / m_pixmap.devicePixelRatioF(); + painter.drawPixmap(p, m_pixmap); + + if (!m_overlayPixmap.isNull()) { + painter.drawPixmap(p, m_overlayPixmap); + } + + painter.end(); +} + +QPixmap SNITrayItemWidget::newIconPixmap(IconType iconType) +{ + QPixmap pixmap; + if (iconType == UnknownIconType) { + return pixmap; + } + + QString iconName; + DBusImageList dbusImageList; + + QString iconThemePath = m_sniIconThemePath; + + switch (iconType) { + case Icon: + iconName = m_sniIconName; + dbusImageList = m_sniIconPixmap; + break; + case OverlayIcon: + iconName = m_sniOverlayIconName; + dbusImageList = m_sniOverlayIconPixmap; + break; + case AttentionIcon: + iconName = m_sniAttentionIconName; + dbusImageList = m_sniAttentionIconPixmap; + break; + case AttentionMovieIcon: + iconName = m_sniAttentionMovieName; + break; + default: + break; + } + + const auto ratio = devicePixelRatioF(); + const int iconSizeScaled = IconSize * ratio; + do { + // load icon from sni dbus + if (!dbusImageList.isEmpty() && !dbusImageList.first().pixels.isEmpty()) { + for (DBusImage dbusImage : dbusImageList) { + char *image_data = dbusImage.pixels.data(); + + if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) { + for (int i = 0; i < dbusImage.pixels.size(); i += 4) { + *(qint32 *)(image_data + i) = qFromBigEndian(*(qint32 *)(image_data + i)); + } + } + + QImage image((const uchar *)dbusImage.pixels.constData(), dbusImage.width, dbusImage.height, QImage::Format_ARGB32); + pixmap = QPixmap::fromImage(image.scaled(iconSizeScaled, iconSizeScaled, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + pixmap.setDevicePixelRatio(ratio); + if (!pixmap.isNull()) { + break; + } + } + } + + // load icon from specified file + if (!iconThemePath.isEmpty() && !iconName.isEmpty()) { + QDirIterator it(iconThemePath, QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + if (it.fileName().startsWith(iconName, Qt::CaseInsensitive)) { + QImage image(it.filePath()); + pixmap = QPixmap::fromImage(image.scaled(iconSizeScaled, iconSizeScaled, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + pixmap.setDevicePixelRatio(ratio); + if (!pixmap.isNull()) { + break; + } + } + } + if (!pixmap.isNull()) { + break; + } + } + + // load icon from theme + // Note: this will ensure return a None-Null pixmap + // so, it should be the last fallback + if (!iconName.isEmpty()) { + // ThemeAppIcon::getIcon 会处理高分屏缩放问题 + ThemeAppIcon::getIcon(pixmap, iconName, IconSize); + if (!pixmap.isNull()) { + break; + } + } + + if (pixmap.isNull()) { + qDebug() << "get icon faild!" << iconType; + } + } while (false); + +// QLabel *l = new QLabel; +// l->setPixmap(pixmap); +// l->setFixedSize(100, 100); +// l->show(); + + return pixmap; +} + +void SNITrayItemWidget::enterEvent(QEvent *event) +{ + // 触屏不显示hover效果 + if (!qApp->property(IS_TOUCH_STATE).toBool()) { + m_popupTipsDelayTimer->start(); + } + + BaseTrayWidget::enterEvent(event); +} + +void SNITrayItemWidget::leaveEvent(QEvent *event) +{ + m_popupTipsDelayTimer->stop(); + if (m_popupShown && !PopupWindow->model()) + hidePopup(); + + update(); + + BaseTrayWidget::leaveEvent(event); +} + +void SNITrayItemWidget::mousePressEvent(QMouseEvent *event) +{ + // call QWidget::mousePressEvent means to show dock-context-menu + // when right button of mouse is pressed immediately in fashion mode + + // here we hide the right button press event when it is click in the special area + m_popupTipsDelayTimer->stop(); + if (event->button() == Qt::RightButton && perfectIconRect().contains(event->pos(), true)) { + event->accept(); + setMouseData(event); + return; + } + + QWidget::mousePressEvent(event); +} + +void SNITrayItemWidget::mouseReleaseEvent(QMouseEvent *e) +{ + //e->accept(); + + // 由于 XWindowTrayWidget 中对 发送鼠标事件到X窗口的函数, 如 sendClick/sendHoverEvent 中 + // 使用了 setX11PassMouseEvent, 而每次调用 setX11PassMouseEvent 时都会导致产生 mousePress 和 mouseRelease 事件 + // 因此如果直接在这里处理事件会导致一些问题, 所以使用 Timer 来延迟处理 100 毫秒内的最后一个事件 + setMouseData(e); + + QWidget::mouseReleaseEvent(e); +} + +void SNITrayItemWidget::handleMouseRelease() +{ + Q_ASSERT(sender() == m_handleMouseReleaseTimer); + + // do not dealwith all mouse event of SystemTray, class SystemTrayItem will handle it + if (trayType() == SystemTray) + return; + + const QPoint point(m_lastMouseReleaseData.first - rect().center()); + if (point.manhattanLength() > 24) + return; + + QPoint globalPos = QCursor::pos(); + uint8_t buttonIndex = XCB_BUTTON_INDEX_1; + + switch (m_lastMouseReleaseData.second) { + case Qt:: MiddleButton: + buttonIndex = XCB_BUTTON_INDEX_2; + break; + case Qt::RightButton: + buttonIndex = XCB_BUTTON_INDEX_3; + break; + default: + break; + } + + sendClick(buttonIndex, globalPos.x(), globalPos.y()); + + // left mouse button clicked + if (buttonIndex == XCB_BUTTON_INDEX_1) { + Q_EMIT clicked(); + } +} + +void SNITrayItemWidget::initMember() +{ + onSNIAttentionIconNameChanged(m_sniInter->attentionIconName()); + onSNIAttentionIconPixmapChanged(m_sniInter->attentionIconPixmap()); + onSNIAttentionMovieNameChanged(m_sniInter->attentionMovieName()); + onSNICategoryChanged(m_sniInter->category()); + onSNIIconNameChanged(m_sniInter->iconName()); + onSNIIconPixmapChanged(m_sniInter->iconPixmap()); + onSNIIconThemePathChanged(m_sniInter->iconThemePath()); + onSNIIdChanged(m_sniInter->id()); + onSNIMenuChanged(m_sniInter->menu()); + onSNIOverlayIconNameChanged(m_sniInter->overlayIconName()); + onSNIOverlayIconPixmapChanged(m_sniInter->overlayIconPixmap()); + onSNIStatusChanged(m_sniInter->status()); + + m_updateIconTimer->start(); + m_updateOverlayIconTimer->start(); + m_updateAttentionIconTimer->start(); +} + +void SNITrayItemWidget::showHoverTips() +{ + if (PopupWindow->model()) + return; + + QProcess p; + p.start("qdbus", {m_dbusService}); + if (!p.waitForFinished(1000)) { + qDebug() << "sni dbus service error : " << m_dbusService; + return; + } + + QDBusInterface infc(m_dbusService, m_dbusPath); + QDBusMessage msg = infc.call("Get", "org.kde.StatusNotifierItem", "ToolTip"); + if (msg.type() == QDBusMessage::ReplyMessage) { + QDBusArgument arg = msg.arguments().at(0).value().variant().value(); + DBusToolTip tooltip = qdbus_cast(arg); + + if (tooltip.title.isEmpty()) + return; + + // 当提示信息中有换行符时,需要使用setTextList + if (tooltip.title.contains('\n')) + m_tipsLabel->setTextList(tooltip.title.split('\n')); + else + m_tipsLabel->setText(tooltip.title); + + m_tipsLabel->setAccessibleName(itemKeyForConfig().replace("sni:","")); + + + showPopupWindow(m_tipsLabel); + } +} + +void SNITrayItemWidget::hideNonModel() +{ + // auto hide if popup is not model window + if (m_popupShown && !PopupWindow->model()) + hidePopup(); +} + +void SNITrayItemWidget::popupWindowAccept() +{ + if (!PopupWindow->isVisible()) + return; + + hidePopup(); +} + +void SNITrayItemWidget::hidePopup() +{ + m_popupTipsDelayTimer->stop(); + m_popupShown = false; + PopupWindow->hide(); + + emit PopupWindow->accept(); + emit requestWindowAutoHide(true); +} +// 获取在最外层的窗口(MainWindow)中的位置 +const QPoint SNITrayItemWidget::topleftPoint() const +{ + QPoint p; + const QWidget *w = this; + do { + p += w->pos(); + w = qobject_cast(w->parent()); + } while (w); + + return p; +} + +const QPoint SNITrayItemWidget::popupMarkPoint() const +{ + QPoint p(topleftPoint()); + + const QRect r = rect(); + const QRect wr = window()->rect(); + + switch (DockPosition) { + case Dock::Position::Top: + p += QPoint(r.width() / 2, r.height() + (wr.height() - r.height()) / 2); + break; + case Dock::Position::Bottom: + p += QPoint(r.width() / 2, 0 - (wr.height() - r.height()) / 2); + break; + case Dock::Position::Left: + p += QPoint(r.width() + (wr.width() - r.width()) / 2, r.height() / 2); + break; + case Dock::Position::Right: + p += QPoint(0 - (wr.width() - r.width()) / 2, r.height() / 2); + break; + } + + return p; +} + +QPixmap SNITrayItemWidget::icon() +{ + return m_pixmap; +} + +void SNITrayItemWidget::showPopupWindow(QWidget *const content, const bool model) +{ + m_popupShown = true; + + if (model) + emit requestWindowAutoHide(false); + + DockPopupWindow *popup = PopupWindow.data(); + QWidget *lastContent = popup->getContent(); + if (lastContent) + lastContent->setVisible(false); + + switch (DockPosition) { + case Dock::Position::Top: popup->setArrowDirection(DockPopupWindow::ArrowTop); break; + case Dock::Position::Bottom: popup->setArrowDirection(DockPopupWindow::ArrowBottom); break; + case Dock::Position::Left: popup->setArrowDirection(DockPopupWindow::ArrowLeft); break; + case Dock::Position::Right: popup->setArrowDirection(DockPopupWindow::ArrowRight); break; + } + popup->resize(content->sizeHint()); + popup->setContent(content); + + QPoint p = popupMarkPoint(); + if (!popup->isVisible()) + QMetaObject::invokeMethod(popup, "show", Qt::QueuedConnection, Q_ARG(QPoint, p), Q_ARG(bool, model)); + else + popup->show(p, model); +} + +void SNITrayItemWidget::setMouseData(QMouseEvent *e) +{ + m_lastMouseReleaseData.first = e->pos(); + m_lastMouseReleaseData.second = e->button(); + + m_handleMouseReleaseTimer->start(); +} diff --git a/frame/window/tray/widgets/snitrayitemwidget.h b/frame/window/tray/widgets/snitrayitemwidget.h new file mode 100644 index 000000000..6d4193c58 --- /dev/null +++ b/frame/window/tray/widgets/snitrayitemwidget.h @@ -0,0 +1,140 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SNITRAYWIDGET_H +#define SNITRAYWIDGET_H + +#include "constants.h" +#include "basetraywidget.h" +#include "dockpopupwindow.h" + +#include "org_kde_statusnotifieritem.h" + +#include +#include + +class DBusMenuImporter; +namespace Dock { +class TipsWidget; +} + +using namespace org::kde; + +/** + * @brief The SNITrayWidget class + * @note 系统托盘第三方程序窗口 + */ +class SNITrayItemWidget : public BaseTrayWidget +{ + Q_OBJECT + +public: + enum ItemCategory {UnknownCategory = -1, ApplicationStatus, Communications, SystemServices, Hardware}; + enum ItemStatus {Passive, Active, NeedsAttention}; + enum IconType {UnknownIconType = -1, Icon, OverlayIcon, AttentionIcon, AttentionMovieIcon}; + +public: + SNITrayItemWidget(const QString &sniServicePath, QWidget *parent = Q_NULLPTR); + ~SNITrayItemWidget(); + + QString itemKeyForConfig() override; + void updateIcon() override; + void sendClick(uint8_t mouseButton, int x, int y) override; + + bool isValid() override; + SNITrayItemWidget::ItemStatus status(); + SNITrayItemWidget::ItemCategory category(); + + static QString toSNIKey(const QString &sniServicePath); + static bool isSNIKey(const QString &itemKey); + static QPair serviceAndPath(const QString &servicePath); + static uint servicePID(const QString &servicePath); + + void showHoverTips(); + const QPoint topleftPoint() const; + void showPopupWindow(QWidget *const content, const bool model = false); + const QPoint popupMarkPoint() const; + + static void setDockPostion(const Dock::Position pos) { DockPosition = pos; } + + QPixmap icon() override; + +Q_SIGNALS: + void statusChanged(SNITrayItemWidget::ItemStatus status); + +private Q_SLOTS: + void initMenu(); + void refreshIcon(); + void refreshOverlayIcon(); + void refreshAttentionIcon(); + void showContextMenu(int x, int y); + // SNI property change slot + void onSNIAttentionIconNameChanged(const QString &value); + void onSNIAttentionIconPixmapChanged(DBusImageList value); + void onSNIAttentionMovieNameChanged(const QString &value); + void onSNICategoryChanged(const QString &value); + void onSNIIconNameChanged(const QString &value); + void onSNIIconPixmapChanged(DBusImageList value); + void onSNIIconThemePathChanged(const QString &value); + void onSNIIdChanged(const QString &value); + void onSNIMenuChanged(const QDBusObjectPath &value); + void onSNIOverlayIconNameChanged(const QString &value); + void onSNIOverlayIconPixmapChanged(DBusImageList value); + void onSNIStatusChanged(const QString &status); + void hidePopup(); + void hideNonModel(); + void popupWindowAccept(); + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *e) override; + +private: + void paintEvent(QPaintEvent *e) override; + QPixmap newIconPixmap(IconType iconType); + void setMouseData(QMouseEvent *e); + void handleMouseRelease(); + void initMember(); + +private: + StatusNotifierItem *m_sniInter; + + DBusMenuImporter *m_dbusMenuImporter; + + QMenu *m_menu; + QTimer *m_updateIconTimer; + QTimer *m_updateOverlayIconTimer; + QTimer *m_updateAttentionIconTimer; + + QString m_sniServicePath; + QString m_dbusService; + QString m_dbusPath; + + QPixmap m_pixmap; + QPixmap m_overlayPixmap; + + // SNI propertys + QString m_sniAttentionIconName; + DBusImageList m_sniAttentionIconPixmap; + QString m_sniAttentionMovieName; + QString m_sniCategory; + QString m_sniIconName; + DBusImageList m_sniIconPixmap; + QString m_sniIconThemePath; + QString m_sniId; + QDBusObjectPath m_sniMenuPath; + QString m_sniOverlayIconName; + DBusImageList m_sniOverlayIconPixmap; + QString m_sniStatus; + QTimer *m_popupTipsDelayTimer; + QTimer *m_handleMouseReleaseTimer; + QPair m_lastMouseReleaseData; + static Dock::Position DockPosition; + static QPointer PopupWindow; + Dock::TipsWidget *m_tipsLabel; + bool m_popupShown; +}; + +#endif /* SNIWIDGET_H */ diff --git a/frame/window/tray/widgets/systempluginitem.cpp b/frame/window/tray/widgets/systempluginitem.cpp new file mode 100644 index 000000000..5799bb738 --- /dev/null +++ b/frame/window/tray/widgets/systempluginitem.cpp @@ -0,0 +1,583 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "systempluginitem.h" +#include "utils.h" +#include "dockpopupwindow.h" + +#include +#include +#include +#include + +#include + +Dock::Position SystemPluginItem::DockPosition = Dock::Position::Bottom; +QPointer SystemPluginItem::PopupWindow = nullptr; + +SystemPluginItem::SystemPluginItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent) + : BaseTrayWidget(parent) + , m_popupShown(false) + , m_tapAndHold(false) + , m_contextMenu(new QMenu) + , m_pluginInter(pluginInter) + , m_centralWidget(m_pluginInter->itemWidget(itemKey)) + , m_popupTipsDelayTimer(new QTimer(this)) + , m_popupAdjustDelayTimer(new QTimer(this)) + , m_itemKey(itemKey) + , m_gsettings(Utils::ModuleSettingsPtr(pluginInter->pluginName(), QByteArray(), this)) +{ + qDebug() << "load tray plugins item: " << m_pluginInter->pluginName() << itemKey << m_centralWidget; + + QIcon icon = m_pluginInter->icon(DockPart::SystemPanel); + if (m_centralWidget) { + if (icon.isNull()) { + // 此处先创建一个Layout,在该窗体show的时候将m_centralWidget添加到layout上面 + QBoxLayout *hLayout = new QHBoxLayout(this); + hLayout->setSpacing(0); + hLayout->setMargin(0); + setLayout(hLayout); + m_centralWidget->installEventFilter(this); + } else { + m_centralWidget->setVisible(false); + } + } + + setAccessibleName(m_itemKey); + setAttribute(Qt::WA_TranslucentBackground); + + if (PopupWindow.isNull()) { + DockPopupWindow *arrowRectangle = new DockPopupWindow(nullptr); + arrowRectangle->setShadowBlurRadius(20); + arrowRectangle->setRadius(6); + arrowRectangle->setShadowYOffset(2); + arrowRectangle->setShadowXOffset(0); + arrowRectangle->setArrowWidth(18); + arrowRectangle->setArrowHeight(10); + arrowRectangle->setObjectName("systemtraypopup"); + if (Utils::IS_WAYLAND_DISPLAY) { + Qt::WindowFlags flags = arrowRectangle->windowFlags() | Qt::FramelessWindowHint; + arrowRectangle->setWindowFlags(flags); + } + PopupWindow = arrowRectangle; + connect(qApp, &QApplication::aboutToQuit, PopupWindow, &DockPopupWindow::deleteLater); + } + + if (Utils::IS_WAYLAND_DISPLAY) { + Qt::WindowFlags flags = m_contextMenu->windowFlags() | Qt::FramelessWindowHint; + m_contextMenu->setWindowFlags(flags); + } + + // 必须初始化父窗口,否则当主题切换之后再设置父窗口的时候palette会更改为主题切换前的palette + if (QWidget *w = m_pluginInter->itemPopupApplet(m_itemKey)) { + w->setParent(PopupWindow.data()); + w->setVisible(false); + } + + m_popupTipsDelayTimer->setInterval(500); + m_popupTipsDelayTimer->setSingleShot(true); + + m_popupAdjustDelayTimer->setInterval(10); + m_popupAdjustDelayTimer->setSingleShot(true); + + installEventFilter(this); + + connect(m_popupTipsDelayTimer, &QTimer::timeout, this, &SystemPluginItem::showHoverTips); + connect(m_popupAdjustDelayTimer, &QTimer::timeout, this, &SystemPluginItem::updatePopupPosition, Qt::QueuedConnection); + connect(m_contextMenu, &QMenu::triggered, this, &SystemPluginItem::menuActionClicked); + + if (m_gsettings) + connect(m_gsettings, &QGSettings::changed, this, &SystemPluginItem::onGSettingsChanged); + + grabGesture(Qt::TapAndHoldGesture); +} + +SystemPluginItem::~SystemPluginItem() +{ + if (m_popupShown) + popupWindowAccept(); + m_contextMenu->deleteLater(); +} + +QString SystemPluginItem::itemKeyForConfig() +{ + return m_itemKey; +} + +void SystemPluginItem::updateIcon() +{ + m_pluginInter->refreshIcon(m_itemKey); +} + +void SystemPluginItem::sendClick(uint8_t mouseButton, int x, int y) +{ + Q_UNUSED(mouseButton); + Q_UNUSED(x); + Q_UNUSED(y); + + // do not process this callback + // handle all mouse event in override mouse function +} + +QWidget *SystemPluginItem::trayTipsWidget() +{ + if (m_pluginInter->itemTipsWidget(m_itemKey)) { + m_pluginInter->itemTipsWidget(m_itemKey)->setAccessibleName(m_pluginInter->pluginName()); + } + + return m_pluginInter->itemTipsWidget(m_itemKey); +} + +QWidget *SystemPluginItem::trayPopupApplet() +{ + if (m_pluginInter->itemPopupApplet(m_itemKey)) { + m_pluginInter->itemPopupApplet(m_itemKey)->setAccessibleName(m_pluginInter->pluginName()); + } + + return m_pluginInter->itemPopupApplet(m_itemKey); +} + +const QString SystemPluginItem::trayClickCommand() +{ + return m_pluginInter->itemCommand(m_itemKey); +} + +const QString SystemPluginItem::contextMenu() const +{ + return m_pluginInter->itemContextMenu(m_itemKey); +} + +void SystemPluginItem::invokedMenuItem(const QString &menuId, const bool checked) +{ + m_pluginInter->invokedMenuItem(m_itemKey, menuId, checked); +} + +QWidget *SystemPluginItem::centralWidget() const +{ + return m_centralWidget; +} + +void SystemPluginItem::detachPluginWidget() +{ + QWidget *widget = m_pluginInter->itemWidget(m_itemKey); + if (widget) + widget->setParent(nullptr); +} + +bool SystemPluginItem::event(QEvent *event) +{ + if (m_popupShown) { + switch (event->type()) { + case QEvent::Paint: + if (!m_popupAdjustDelayTimer->isActive()) + m_popupAdjustDelayTimer->start(); + break; + default:; + } + } + + if (event->type() == QEvent::Gesture) + gestureEvent(static_cast(event)); + + return BaseTrayWidget::event(event); +} + +bool SystemPluginItem::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == this && event->type() == QEvent::DeferredDelete + && m_centralWidget && m_centralWidget->parentWidget()) { + m_centralWidget->setParent(nullptr); + m_centralWidget->setVisible(false); + } + + return BaseTrayWidget::eventFilter(watched, event); +} + +void SystemPluginItem::enterEvent(QEvent *event) +{ + if (checkGSettingsControl()) { + //网络需要显示Tips,需要特殊处理。 + if (m_pluginInter->pluginName() != "network") + return; + } + + // 触屏不显示hover效果 + if (!qApp->property(IS_TOUCH_STATE).toBool()) { + m_popupTipsDelayTimer->start(); + } + update(); + + BaseTrayWidget::enterEvent(event); +} + +void SystemPluginItem::leaveEvent(QEvent *event) +{ + m_popupTipsDelayTimer->stop(); + + // auto hide if popup is not model window + if (m_popupShown && !PopupWindow->model()) + hidePopup(); + + update(); + + BaseTrayWidget::leaveEvent(event); +} + +void SystemPluginItem::mousePressEvent(QMouseEvent *event) +{ + if (checkGSettingsControl()) { + return; + } + + m_popupTipsDelayTimer->stop(); + hideNonModel(); + + if (event->button() == Qt::RightButton + && perfectIconRect().contains(event->pos(), true)) { + return (m_gsettings && (!m_gsettings->keys().contains("menuEnable") || m_gsettings->get("menuEnable").toBool())) ? showContextMenu() : void(); + } + + BaseTrayWidget::mousePressEvent(event); +} + +void SystemPluginItem::mouseReleaseEvent(QMouseEvent *event) +{ + if (checkGSettingsControl()) { + return; + } + + if (event->button() != Qt::LeftButton) { + return; + } + + if (checkAndResetTapHoldGestureState() && event->source() == Qt::MouseEventSynthesizedByQt) { + qDebug() << "SystemTray: tap and hold gesture detected, ignore the synthesized mouse release event"; + return; + } + + event->accept(); + + showPopupApplet(trayPopupApplet()); + + if (!trayClickCommand().isEmpty()) { + QProcess::startDetached(trayClickCommand()); + } + + BaseTrayWidget::mouseReleaseEvent(event); +} + +void SystemPluginItem::showEvent(QShowEvent *event) +{ + QTimer::singleShot(0, this, [ = ] { + onGSettingsChanged("enable"); + }); + + return BaseTrayWidget::showEvent(event); +} + +void SystemPluginItem::hideEvent(QHideEvent *event) +{ + if (m_pluginInter->icon(DockPart::SystemPanel).isNull() + && m_centralWidget && m_centralWidget->parentWidget() == this) { + layout()->removeWidget(m_centralWidget); + m_centralWidget->setParent(nullptr); + m_centralWidget->setVisible(false); + } + BaseTrayWidget::hideEvent(event); +} + +void SystemPluginItem::paintEvent(QPaintEvent *event) +{ + QIcon icon = m_pluginInter->icon(DockPart::SystemPanel); + if (icon.isNull()) { + showCentralWidget(); + return BaseTrayWidget::paintEvent(event); + } + + int x = 0; + int y = 0; + QSize iconSize = this->size(); + QList sizes = icon.availableSizes(); + if (sizes.size() > 0) { + QSize availableSize = sizes.first(); + if (iconSize.width() > availableSize.width()) { + x = (iconSize.width() - availableSize.width()) / 2; + y = (iconSize.height() - availableSize.height()) / 2; + iconSize = availableSize; + } + } + + QPixmap pixmap = icon.pixmap(iconSize); + QPainter painter(this); + painter.drawPixmap(QRect(QPoint(x, y), iconSize), pixmap); +} + +const QPoint SystemPluginItem::popupMarkPoint() const +{ + QPoint p(topleftPoint()); + + const QRect r = rect(); + const QRect wr = window()->rect(); + + switch (DockPosition) { + case Dock::Position::Top: + p += QPoint(r.width() / 2, r.height() + (wr.height() - r.height()) / 2); + break; + case Dock::Position::Bottom: + p += QPoint(r.width() / 2, 0 - (wr.height() - r.height()) / 2); + break; + case Dock::Position::Left: + p += QPoint(r.width() + (wr.width() - r.width()) / 2, r.height() / 2); + break; + case Dock::Position::Right: + p += QPoint(0 - (wr.width() - r.width()) / 2, r.height() / 2); + break; + } + + return p; +} + +// 获取在最外层的窗口(MainWindow)中的位置 +const QPoint SystemPluginItem::topleftPoint() const +{ + QPoint p; + const QWidget *w = this; + do { + p += w->pos(); + w = qobject_cast(w->parent()); + } while (w); + + return p; +} + +void SystemPluginItem::hidePopup() +{ + m_popupTipsDelayTimer->stop(); + m_popupAdjustDelayTimer->stop(); + m_popupShown = false; + PopupWindow->hide(); + + DockPopupWindow *popup = PopupWindow.data(); + QWidget *content = popup->getContent(); + if (content) { + content->setVisible(false); + } + + emit PopupWindow->accept(); + emit requestWindowAutoHide(true); +} + +bool SystemPluginItem::containsPoint(QPoint pos) +{ + QPoint ptGlobal = mapToGlobal(QPoint(0, 0)); + QRect rectGlobal(ptGlobal, this->size()); + if (rectGlobal.contains(pos)) + return true; + + // 如果菜单列表隐藏,则认为不在区域内 + if (!m_contextMenu->isVisible()) + return false; + + // 判断鼠标是否在菜单区域 + return m_contextMenu->geometry().contains(pos); +} + +void SystemPluginItem::hideNonModel() +{ + // auto hide if popup is not model window + if (m_popupShown && !PopupWindow->model()) + hidePopup(); +} + +void SystemPluginItem::popupWindowAccept() +{ + if (!PopupWindow->isVisible()) + return; + + disconnect(PopupWindow.data(), &DockPopupWindow::accept, this, &SystemPluginItem::popupWindowAccept); + + hidePopup(); +} + +void SystemPluginItem::showPopupApplet(QWidget *const applet) +{ + if (!applet) + return; + + // another model popup window already exists + if (PopupWindow->model()) { + applet->setVisible(false); + return; + } + + showPopupWindow(applet, true); +} + +void SystemPluginItem::showPopupWindow(QWidget *const content, const bool model) +{ + m_popupShown = true; + m_lastPopupWidget = content; + + if (model) + emit requestWindowAutoHide(false); + + DockPopupWindow *popup = PopupWindow.data(); + QWidget *lastContent = popup->getContent(); + if (lastContent) + lastContent->setVisible(false); + + switch (DockPosition) { + case Dock::Position::Top: popup->setArrowDirection(DockPopupWindow::ArrowTop); break; + case Dock::Position::Bottom: popup->setArrowDirection(DockPopupWindow::ArrowBottom); break; + case Dock::Position::Left: popup->setArrowDirection(DockPopupWindow::ArrowLeft); break; + case Dock::Position::Right: popup->setArrowDirection(DockPopupWindow::ArrowRight); break; + } + popup->resize(content->sizeHint()); + popup->setContent(content); + + QPoint p = popupMarkPoint(); + if (!popup->isVisible()) + QMetaObject::invokeMethod(popup, "show", Qt::QueuedConnection, Q_ARG(QPoint, p), Q_ARG(bool, model)); + else + popup->show(p, model); + + connect(popup, &DockPopupWindow::accept, this, &SystemPluginItem::popupWindowAccept, Qt::UniqueConnection); +} + +void SystemPluginItem::showHoverTips() +{ + // another model popup window already exists + if (PopupWindow->model()) + return; + + // if not in geometry area + const QRect r(topleftPoint(), size()); + if (!r.contains(QCursor::pos())) + return; + + QWidget *const content = trayTipsWidget(); + if (!content) + return; + + showPopupWindow(content); +} + +/*! + * \sa DockItem::checkAndResetTapHoldGestureState + */ +bool SystemPluginItem::checkAndResetTapHoldGestureState() +{ + bool ret = m_tapAndHold; + m_tapAndHold = false; + return ret; +} + +void SystemPluginItem::gestureEvent(QGestureEvent *event) +{ + if (!event) + return; + + QGesture *gesture = event->gesture(Qt::TapAndHoldGesture); + + if (!gesture) + return; + + qDebug() << "SystemTray: got TapAndHoldGesture"; + + m_tapAndHold = true; +} + +void SystemPluginItem::showContextMenu() +{ + const QString menuJson = contextMenu(); + if (menuJson.isEmpty()) + return; + + QJsonDocument jsonDocument = QJsonDocument::fromJson(menuJson.toLocal8Bit().data()); + if (jsonDocument.isNull()) + return; + + QJsonObject jsonMenu = jsonDocument.object(); + + qDeleteAll(m_contextMenu->actions()); + + QJsonArray jsonMenuItems = jsonMenu.value("items").toArray(); + for (auto item : jsonMenuItems) { + QJsonObject itemObj = item.toObject(); + QAction *action = new QAction(itemObj.value("itemText").toString(), m_contextMenu); + action->setCheckable(itemObj.value("isCheckable").toBool()); + action->setChecked(itemObj.value("checked").toBool()); + action->setData(itemObj.value("itemId").toString()); + action->setEnabled(itemObj.value("isActive").toBool()); + m_contextMenu->addAction(action); + } + + hidePopup(); + emit requestWindowAutoHide(false); + + m_contextMenu->exec(QCursor::pos()); + + onContextMenuAccepted(); +} + +void SystemPluginItem::menuActionClicked(QAction *action) +{ + invokedMenuItem(action->data().toString(), true); + Q_EMIT execActionFinished(); +} + +void SystemPluginItem::showCentralWidget() +{ + if (!m_pluginInter->icon(DockPart::SystemPanel).isNull() || !m_centralWidget) + return; + + m_centralWidget->setParent(this); + m_centralWidget->setVisible(true); + layout()->addWidget(m_centralWidget); +} + +void SystemPluginItem::onContextMenuAccepted() +{ + emit requestRefershWindowVisible(); + emit requestWindowAutoHide(true); +} + +void SystemPluginItem::updatePopupPosition() +{ + Q_ASSERT(sender() == m_popupAdjustDelayTimer); + + if (!m_popupShown || !PopupWindow->model()) + return; + + if (PopupWindow->getContent() != m_lastPopupWidget.data()) + return popupWindowAccept(); + + const QPoint p = popupMarkPoint(); + PopupWindow->show(p, PopupWindow->model()); +} + +void SystemPluginItem::onGSettingsChanged(const QString &key) { + if (key != "enable") { + return; + } + + if (m_gsettings && m_gsettings->keys().contains("enable")) { + const bool visible = m_gsettings->get("enable").toBool(); + setVisible(visible); + emit itemVisibleChanged(visible); + } +} + +bool SystemPluginItem::checkGSettingsControl() const +{ + // 优先判断com.deepin.dde.dock.module.systemtray的control值是否为true(优先级更高),如果不为true,再判断每一个托盘对应的gsetting配置的control值 + bool isEnable = Utils::SettingValue("com.deepin.dde.dock.module.systemtray", QByteArray(), "control", false).toBool(); + return (isEnable || (m_gsettings && m_gsettings->get("control").toBool())); +} + +QPixmap SystemPluginItem::icon() +{ + return QPixmap(); +} diff --git a/frame/window/tray/widgets/systempluginitem.h b/frame/window/tray/widgets/systempluginitem.h new file mode 100644 index 000000000..c4177c211 --- /dev/null +++ b/frame/window/tray/widgets/systempluginitem.h @@ -0,0 +1,108 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SYSTEMTRAYITEM_H +#define SYSTEMTRAYITEM_H + +#include "constants.h" +#include "basetraywidget.h" +#include "pluginsiteminterface.h" + +#include + +class QGSettings; +class QMenu; +class DockPopupWindow; +class QHBoxLayout; + +class SystemPluginItem : public BaseTrayWidget +{ + Q_OBJECT + +public: + SystemPluginItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent = nullptr); + ~SystemPluginItem() override; + +public: + QString itemKeyForConfig() override; + void updateIcon() override; + void sendClick(uint8_t mouseButton, int x, int y) override; + inline TrayType trayType() const override { return TrayType::SystemTray; } + QPixmap icon() override; + + QWidget *trayTipsWidget(); + QWidget *trayPopupApplet(); + const QString trayClickCommand(); + const QString contextMenu() const; + void invokedMenuItem(const QString &menuId, const bool checked); + + static void setDockPostion(const Dock::Position pos) { DockPosition = pos; } + + QWidget *centralWidget() const; + void detachPluginWidget(); + void showContextMenu(); + + void showPopupApplet(QWidget * const applet); + void hidePopup(); + bool containsPoint(QPoint pos); + +signals: + void itemVisibleChanged(bool visible); + void execActionFinished(); + +protected: + bool event(QEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event) override; + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + void paintEvent(QPaintEvent *event) override; + +protected: + const QPoint popupMarkPoint() const; + const QPoint topleftPoint() const; + + void hideNonModel(); + void popupWindowAccept(); + + virtual void showPopupWindow(QWidget * const content, const bool model = false); + virtual void showHoverTips(); + + bool checkAndResetTapHoldGestureState(); + virtual void gestureEvent(QGestureEvent *event); + +protected Q_SLOTS: + void onContextMenuAccepted(); + +private: + void updatePopupPosition(); + void onGSettingsChanged(const QString &key); + bool checkGSettingsControl() const; + void menuActionClicked(QAction *action); + void showCentralWidget(); + +private: + bool m_popupShown; + bool m_tapAndHold; + QMenu *m_contextMenu; + + PluginsItemInterface* m_pluginInter; + QWidget *m_centralWidget; + + QTimer *m_popupTipsDelayTimer; + QTimer *m_popupAdjustDelayTimer; + + QPointer m_lastPopupWidget; + QString m_itemKey; + + static Dock::Position DockPosition; + static QPointer PopupWindow; + const QGSettings* m_gsettings; +}; + +#endif // SYSTEMTRAYITEM_H diff --git a/frame/window/tray/widgets/xembedtrayitemwidget.cpp b/frame/window/tray/widgets/xembedtrayitemwidget.cpp new file mode 100644 index 000000000..3dbc81902 --- /dev/null +++ b/frame/window/tray/widgets/xembedtrayitemwidget.cpp @@ -0,0 +1,553 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "constants.h" +#include "xembedtrayitemwidget.h" +#include "platformutils.h" +//#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define NORMAL_WINDOW_PROP_NAME "WM_CLASS" +#define WINE_WINDOW_PROP_NAME "__wine_prefix" +#define IS_WINE_WINDOW_BY_WM_CLASS "explorer.exe" + +static const qreal iconSize = PLUGIN_ICON_MAX_SIZE; + +const bool IS_WAYLAND_DISPLAY = !qgetenv("WAYLAND_DISPLAY").isEmpty(); + +// this static var hold all suffix of tray widget keys. +// that is in order to fix can not show multiple trays provide by one application, +// so only one property: AppName is not enough to identify all trays. +// here we add a suffix for every tray to fix this problem. +// the first suffix is 1, second is 2, etc. +// NOTE: the first suffix will be omit when construct the key of tray widget. +static QMap> AppWinidSuffixMap; + +//using namespace Utils; + +const QPoint rawXPosition(const QPoint &scaledPos) +{ + QRect g = qApp->primaryScreen() ? qApp->primaryScreen()->geometry() : QRect(); + for (auto *screen : qApp->screens()) + { + const QRect &sg = screen->geometry(); + if (sg.contains(scaledPos)) + { + g = sg; + break; + } + } + + return g.topLeft() + (scaledPos - g.topLeft()) * qApp->devicePixelRatio(); +} + +void sni_cleanup_xcb_image(void *data) +{ + xcb_image_destroy(static_cast(data)); +} + +XEmbedTrayItemWidget::XEmbedTrayItemWidget(quint32 winId, xcb_connection_t *cnn, Display *disp, QWidget *parent) + : BaseTrayWidget(parent) + , m_windowId(winId) + , m_appName(PlatformUtils::getAppNameForWindow(winId)) + , m_valid(true) + , m_xcbCnn(cnn) + , m_display(disp) +{ + wrapWindow(); + setOwnerPID(getWindowPID(winId)); + + m_updateTimer = new QTimer(this); + m_updateTimer->setInterval(100); + m_updateTimer->setSingleShot(true); + + m_sendHoverEvent = new QTimer(this); + m_sendHoverEvent->setInterval(100); + m_sendHoverEvent->setSingleShot(true); + + connect(m_updateTimer, &QTimer::timeout, this, &XEmbedTrayItemWidget::refershIconImage); + + setMouseTracking(true); + connect(m_sendHoverEvent, &QTimer::timeout, this, &XEmbedTrayItemWidget::sendHoverEvent); + + m_updateTimer->start(); +} + +XEmbedTrayItemWidget::~XEmbedTrayItemWidget() +{ + AppWinidSuffixMap[m_appName].remove(m_windowId); +} + +QString XEmbedTrayItemWidget::itemKeyForConfig() +{ + return QString("window:%1").arg(PlatformUtils::getAppNameForWindow(m_windowId)); +} + +void XEmbedTrayItemWidget::showEvent(QShowEvent *e) +{ + QWidget::showEvent(e); + + xcb_connection_t *connection = IS_WAYLAND_DISPLAY ? m_xcbCnn : QX11Info::connection(); + if (connection) { + xcb_map_window(connection, m_containerWid); + + xcb_reparent_window(connection, m_windowId, m_containerWid, 0, 0); + } + + m_updateTimer->start(); +} + +void XEmbedTrayItemWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e); + if (!needShow()) { + return; + } + + if (m_image.isNull()) + return m_updateTimer->start(); + + QPainter painter; + painter.begin(this); + painter.setRenderHint(QPainter::Antialiasing); + +//#ifdef QT_DEBUG +// painter.fillRect(rect(), Qt::red); +//#endif + + const QRectF &rf = QRectF(rect()); + const QRectF &rfp = QRectF(m_image.rect()); + const QPointF &p = rf.center() - rfp.center() / m_image.devicePixelRatioF(); + painter.drawImage(p, m_image); + + painter.end(); +} + +void XEmbedTrayItemWidget::mouseMoveEvent(QMouseEvent *e) +{ + BaseTrayWidget::mouseMoveEvent(e); + + // ignore the touchEvent + if (e->source() == Qt::MouseEventSynthesizedByQt) { + return; + } + + m_sendHoverEvent->start(); +} + +void XEmbedTrayItemWidget::configContainerPosition() +{ + auto c = IS_WAYLAND_DISPLAY ? m_xcbCnn : QX11Info::connection(); + if (!c) { + qWarning() << "QX11Info::connection() is " << c; + return; + } + + const QPoint p(rawXPosition(QCursor::pos())); + + const uint32_t containerVals[4] = {uint32_t(p.x()), uint32_t(p.y()), 1, 1}; + xcb_configure_window(c, m_containerWid, + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + containerVals); + + + // move the actual tray window to {0,0}, because tray icons from some wine + // applications (QQ, TIM, etc...) may somehow moved to very long distance positions. + const uint32_t trayVals[2] = { 0, 0 }; + xcb_configure_window(c, m_windowId, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, trayVals); + + xcb_flush(c); +} + +void XEmbedTrayItemWidget::wrapWindow() +{ + auto c = IS_WAYLAND_DISPLAY ? m_xcbCnn : QX11Info::connection(); + if (!c) { + qWarning() << "QX11Info::connection() is " << c; + return; + } + + auto cookie = xcb_get_geometry(c, m_windowId); + xcb_get_geometry_reply_t *clientGeom(xcb_get_geometry_reply(c, cookie, Q_NULLPTR)); + if (!clientGeom) { + m_valid = false; + return; + } + free(clientGeom); + + //create a container window + const auto ratio = devicePixelRatioF(); + auto screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; + m_containerWid = xcb_generate_id(c); + uint32_t values[2]; + auto mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT; + values[0] = ParentRelative; //draw a solid background so the embedded icon doesn't get garbage in it + values[1] = true; //bypass wM + xcb_create_window (c, /* connection */ + XCB_COPY_FROM_PARENT, /* depth */ + m_containerWid, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + iconSize * ratio, iconSize * ratio, /* width, height */ + 0, /* border_width */ + XCB_WINDOW_CLASS_INPUT_OUTPUT,/* class */ + screen->root_visual, /* visual */ + mask, values); /* masks */ + + /* + We need the window to exist and be mapped otherwise the child won't render it's contents + + We also need it to exist in the right place to get the clicks working as GTK will check sendEvent locations to see if our window is in the right place. So even though our contents are drawn via compositing we still put this window in the right place + + We can't composite it away anything parented owned by the root window (apparently) + Stack Under works in the non composited case, but it doesn't seem to work in kwin's composited case (probably need set relevant NETWM hint) + + As a last resort set opacity to 0 just to make sure this container never appears + */ +// const uint32_t stackBelowData[] = {XCB_STACK_MODE_BELOW}; +// xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackBelowData); + + if (!IS_WAYLAND_DISPLAY) { + QWindow * win = QWindow::fromWinId(m_containerWid); + win->setOpacity(0); + } else { + const char* opacityName = "_NET_WM_WINDOW_OPACITY\0"; + xcb_intern_atom_cookie_t opacityCookie = xcb_intern_atom(c, false, strlen(opacityName), opacityName); + xcb_intern_atom_reply_t *opacityReply = xcb_intern_atom_reply(c, opacityCookie, 0); + xcb_atom_t opacityAtom = opacityReply->atom; + quint32 opacity = 10; + xcb_change_property(c, + XCB_PROP_MODE_REPLACE, + m_containerWid, + opacityAtom, + XCB_ATOM_CARDINAL, + 32, + 1, + (uchar *)&opacity); + } + +// setX11PassMouseEvent(true); + + xcb_flush(c); + + if (isVisible()) { + xcb_map_window(c, m_containerWid); + + xcb_reparent_window(c, m_windowId, + m_containerWid, + 0, 0); + } + + /* + * Render the embedded window offscreen + */ + xcb_composite_redirect_window(c, m_windowId, XCB_COMPOSITE_REDIRECT_MANUAL); + + + /* we grab the window, but also make sure it's automatically reparented back + * to the root window if we should die. + */ + xcb_change_save_set(c, XCB_SET_MODE_INSERT, m_windowId); + + //tell client we're embedding it + // xembed_message_send(m_windowId, XEMBED_EMBEDDED_NOTIFY, m_containerWid, 0, 0); + + //move window we're embedding + /* + const uint32_t windowMoveConfigVals[2] = { 0, 0 }; + xcb_configure_window(c, m_windowId, + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, + windowMoveCentially quitting the application. Returns onfigVals); + */ + + //if the window is a clearly stupid size resize to be something sensible + //this is needed as chormium and such when resized just fill the icon with transparent space and only draw in the middle + //however spotify does need this as by default the window size is 900px wide. + //use an artbitrary heuristic to make sure icons are always sensible +// if (clientGeom->width > iconSize || clientGeom->height > iconSize ) + { + const uint32_t windowMoveConfigVals[2] = { uint32_t(iconSize * ratio), uint32_t(iconSize * ratio) }; + xcb_configure_window(c, m_windowId, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + windowMoveConfigVals); + } + + //show the embedded window otherwise nothing happens + xcb_map_window(c, m_windowId); + +// xcb_clear_area(c, 0, m_windowId, 0, 0, qMin(clientGeom->width, iconSize), qMin(clientGeom->height, iconSize)); + + xcb_flush(c); +// setWindowOnTop(false); + setWindowOnTop(true); + setX11PassMouseEvent(true); +} + +void XEmbedTrayItemWidget::sendHoverEvent() +{ + if (!rect().contains(mapFromGlobal(QCursor::pos()))) { + return; + } + + // fake enter event + const QPoint p(rawXPosition(QCursor::pos())); + configContainerPosition(); + setX11PassMouseEvent(false); + setWindowOnTop(true); + Display *display = IS_WAYLAND_DISPLAY ? m_display : QX11Info::display(); + if (display) { + XTestFakeMotionEvent(display, 0, p.x(), p.y(), CurrentTime); + XFlush(display); + } + + QTimer::singleShot(100, this, [=] { setX11PassMouseEvent(true); }); +} + +void XEmbedTrayItemWidget::updateIcon() +{ +// if (!isVisible() && !m_active) +// return; + + m_updateTimer->start(); +} + +//void TrayWidget::hideIcon() +//{ +// auto c = QX11Info::connection(); + +// const uint32_t stackAboveData[] = {XCB_STACK_MODE_BELOW}; +// xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackAboveData); + +// const uint32_t windowMoveConfigVals[2] = {0, 0}; +// xcb_configure_window(c, m_containerWid, +// XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, +// windowMoveConfigVals); + +// hide(); +//} + +void XEmbedTrayItemWidget::sendClick(uint8_t mouseButton, int x, int y) +{ + if (isBadWindow()) + return; + + m_sendHoverEvent->stop(); + + const QPoint p(rawXPosition(QPoint(x, y))); + configContainerPosition(); + setX11PassMouseEvent(false); + setWindowOnTop(true); + + Display *display = IS_WAYLAND_DISPLAY ? m_display : QX11Info::display(); + XTestFakeMotionEvent(display, 0, p.x(), p.y(), CurrentTime); + XFlush(display); + XTestFakeButtonEvent(display, mouseButton, true, CurrentTime); + XFlush(display); + XTestFakeButtonEvent(display, mouseButton, false, CurrentTime); + XFlush(display); + QTimer::singleShot(100, this, [=] { setX11PassMouseEvent(true); }); +} + +QString XEmbedTrayItemWidget::toXEmbedKey(quint32 winId) +{ + return QString("window:%1").arg(winId); +} + +bool XEmbedTrayItemWidget::isXEmbedKey(const QString &itemKey) +{ + return itemKey.startsWith("window:"); +} + +QPixmap XEmbedTrayItemWidget::icon() +{ + return QPixmap::fromImage(m_image); +} + +void XEmbedTrayItemWidget::refershIconImage() +{ + const auto ratio = devicePixelRatioF(); + auto c = IS_WAYLAND_DISPLAY ? m_xcbCnn : QX11Info::connection(); + if (!c) { + qWarning() << "QX11Info::connection() is " << c; + return; + } + + auto cookie = xcb_get_geometry(c, m_windowId); + xcb_get_geometry_reply_t *geom(xcb_get_geometry_reply(c, cookie, Q_NULLPTR)); + if (!geom) { + return; + } + + xcb_expose_event_t expose; + expose.response_type = XCB_EXPOSE; + expose.window = m_containerWid; + expose.x = 0; + expose.y = 0; + expose.width = iconSize * ratio; + expose.height = iconSize * ratio; + xcb_send_event_checked(c, false, m_containerWid, XCB_EVENT_MASK_VISIBILITY_CHANGE, reinterpret_cast(&expose)); + xcb_flush(c); + + xcb_image_t *image = xcb_image_get(c, m_windowId, 0, 0, geom->width, geom->height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP); + if (!image) { + free(geom); + return; + } + + QImage qimage(image->data, image->width, image->height, image->stride, QImage::Format_ARGB32, sni_cleanup_xcb_image, image); + if (qimage.isNull()) { + free(geom); + return; + } + + m_image = qimage.scaled(iconSize * ratio, iconSize * ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation); + m_image.setDevicePixelRatio(ratio); + + update(); + Q_EMIT iconChanged(); + + if (!isVisible()) { + Q_EMIT needAttention(); + } +} + +//int XEmbedTrayWidget::getTrayWidgetKeySuffix(const QString &appName, quint32 winId) +//{ +// int suffix = AppWinidSuffixMap.value(appName).value(winId, 0); + +// // return the exist suffix +// if (suffix != 0) { +// return suffix; +// } + +// // it is the first window for this application +// if (!AppWinidSuffixMap.contains(appName)) { +// QMap winIdSuffixMap; +// winIdSuffixMap.insert(winId, 1); +// AppWinidSuffixMap.insert(appName, winIdSuffixMap); +// return 1; +// } + +// QMap subMap = AppWinidSuffixMap.value(appName); +// QList suffixList = subMap.values(); + +// // suffix will never be 0 +// suffixList.removeAll(0); +// std::sort(suffixList.begin(), suffixList.end()); + +// // get the minimum of useable suffix +// int index = 0; +// for (; index < suffixList.size(); ++index) { +// if (suffixList.at(index) != index + 1) { +// break; +// } +// } +// suffix = index + 1; + +// subMap.insert(winId, suffix); +// AppWinidSuffixMap.insert(appName, subMap); + +// return suffix; +//} + +void XEmbedTrayItemWidget::setX11PassMouseEvent(const bool pass) +{ + if (IS_WAYLAND_DISPLAY) { + //会导致wayland下鼠标穿透到桌面,所以直接return掉 + return; + } + + if (pass) + { + XShapeCombineRectangles(QX11Info::display(), m_containerWid, ShapeBounding, 0, 0, nullptr, 0, ShapeSet, YXBanded); + XShapeCombineRectangles(QX11Info::display(), m_containerWid, ShapeInput, 0, 0, nullptr, 0, ShapeSet, YXBanded); + } + else + { + XRectangle rectangle; + rectangle.x = 0; + rectangle.y = 0; + rectangle.width = 1; + rectangle.height = 1; + + XShapeCombineRectangles(QX11Info::display(), m_containerWid, ShapeBounding, 0, 0, &rectangle, 1, ShapeSet, YXBanded); + XShapeCombineRectangles(QX11Info::display(), m_containerWid, ShapeInput, 0, 0, &rectangle, 1, ShapeSet, YXBanded); + } + + XFlush(QX11Info::display()); +} + +void XEmbedTrayItemWidget::setWindowOnTop(const bool top) +{ + auto c = IS_WAYLAND_DISPLAY ? m_xcbCnn : QX11Info::connection(); + if (!c) { + qWarning() << "QX11Info::connection() is " << c; + return; + } + const uint32_t stackAboveData[] = {top ? XCB_STACK_MODE_ABOVE : XCB_STACK_MODE_BELOW}; + xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackAboveData); + xcb_flush(c); +} + +bool XEmbedTrayItemWidget::isBadWindow() +{ + auto c = IS_WAYLAND_DISPLAY ? m_xcbCnn : QX11Info::connection(); + + auto cookie = xcb_get_geometry(c, m_windowId); + xcb_get_geometry_reply_t *clientGeom = xcb_get_geometry_reply(c, cookie, Q_NULLPTR); + bool result = clientGeom ? false : true; + + free(clientGeom); + + return result; +} + +uint XEmbedTrayItemWidget::getWindowPID(uint winId) +{ + const auto display = IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display(); + if (!display) { + qWarning() << "QX11Info::connection() is " << display; + return 0; + } + + Atom nameAtom = XInternAtom(display, "_NET_WM_PID", 1); + Atom type; + int format, status; + + unsigned long nitems, after; + unsigned char *data; + unsigned int pid = 0; + + status = XGetWindowProperty(display, winId, nameAtom, 0, 1024, 0, + XInternAtom(display, "CARDINAL", 0), &type, &format, &nitems, &after, &data); + if (status == Success && data) { + pid = *((uint*)data); + XFree(data); + } + + if (IS_WAYLAND_DISPLAY) + XCloseDisplay(display); + + return pid; +} diff --git a/frame/window/tray/widgets/xembedtrayitemwidget.h b/frame/window/tray/widgets/xembedtrayitemwidget.h new file mode 100644 index 000000000..788484741 --- /dev/null +++ b/frame/window/tray/widgets/xembedtrayitemwidget.h @@ -0,0 +1,65 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef XEMBEDTRAYWIDGET_H +#define XEMBEDTRAYWIDGET_H + +#include "basetraywidget.h" + +#include +#include + +#include + +typedef struct _XDisplay Display; + +class XEmbedTrayItemWidget : public BaseTrayWidget +{ + Q_OBJECT + +public: + explicit XEmbedTrayItemWidget(quint32 winId, xcb_connection_t *cnn = nullptr, Display *disp = nullptr, QWidget *parent = nullptr); + ~XEmbedTrayItemWidget() override; + + QString itemKeyForConfig() override; + void updateIcon() override; + void sendClick(uint8_t mouseButton, int x, int y) override; + + static QString toXEmbedKey(quint32 winId); + static uint getWindowPID(quint32 winId); + static bool isXEmbedKey(const QString &itemKey); + virtual bool isValid() override {return m_valid;} + QPixmap icon() override; + +private: + void showEvent(QShowEvent *e) override; + void paintEvent(QPaintEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void configContainerPosition(); + + void wrapWindow(); + void sendHoverEvent(); + void refershIconImage(); + +private slots: + void setX11PassMouseEvent(const bool pass); + void setWindowOnTop(const bool top); + bool isBadWindow(); + +private: + bool m_active = false; + WId m_windowId; + WId m_containerWid; + QImage m_image; + QString m_appName; + + QTimer *m_updateTimer; + QTimer *m_sendHoverEvent; + bool m_valid; + xcb_connection_t *m_xcbCnn; + Display* m_display; +}; + +#endif // XEMBEDTRAYWIDGET_H diff --git a/frame/window/traymainwindow.cpp b/frame/window/traymainwindow.cpp new file mode 100644 index 000000000..fdaa307ac --- /dev/null +++ b/frame/window/traymainwindow.cpp @@ -0,0 +1,151 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "traymainwindow.h" +#include "traymanagerwindow.h" +#include "dragwidget.h" +#include "dockscreen.h" +#include "displaymanager.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DOCK_SCREEN DockScreen::instance() +#define DIS_INS DisplayManager::instance() + +TrayMainWindow::TrayMainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent) + : MainWindowBase(multiScreenWorker, parent) + , m_trayManager(new TrayManagerWindow(this)) + , m_multiScreenWorker(multiScreenWorker) +{ + initUI(); + initConnection(); +} + +void TrayMainWindow::setPosition(const Dock::Position &position) +{ + MainWindowBase::setPosition(position); + m_trayManager->setPositon(position); +} + +TrayManagerWindow *TrayMainWindow::trayManagerWindow() const +{ + return m_trayManager; +} + +void TrayMainWindow::setDisplayMode(const Dock::DisplayMode &displayMode) +{ + // 只有在时尚模式下才显示 + setVisible(displayMode == Dock::DisplayMode::Fashion); + MainWindowBase::setDisplayMode(displayMode); + m_trayManager->setDisplayMode(displayMode); +} + +MainWindowBase::DockWindowType TrayMainWindow::windowType() const +{ + return DockWindowType::TrayWindow; +} + +void TrayMainWindow::updateParentGeometry(const Dock::Position &position, const QRect &rect) +{ + QSize trayPanelSize = m_trayManager->suitableSize(position); + // 设置trayManagerWindow的大小和位置 + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + setFixedSize(trayPanelSize.width(), rect.height()); + move(rect.topLeft()); + } else { + setFixedSize(rect.width(), trayPanelSize.height()); + move(rect.topLeft()); + } + + int panelSize = windowSize(); + QRect panelRect = rect; + switch(position) { + case Dock::Position::Left: + m_trayManager->move(width() - panelSize, 0); + panelRect.setWidth(panelSize); + panelRect.setHeight(trayPanelSize.height()); + break; + case Dock::Position::Top: + m_trayManager->move(0, height() - panelSize); + panelRect.setWidth(trayPanelSize.width()); + panelRect.setHeight(panelSize); + break; + case Dock::Position::Right: { + m_trayManager->move(0, 0); + panelRect.setWidth(panelSize); + panelRect.setHeight(trayPanelSize.height()); + break; + } + case Dock::Position::Bottom: { + m_trayManager->move(0, 0); + panelRect.setWidth(trayPanelSize.width()); + panelRect.setHeight(panelSize); + break; + } + } + + // 在从高效模式切换到时尚模式的时候,需要调用该函数来设置托盘区域的尺寸,在设置尺寸的时候会触发 + // 托盘区域的requestUpdate信号,WindowManager接收到requestUpdate会依次对每个顶层界面设置尺寸,此时又会触发该函数 + // 引起无限循环,因此,在设置尺寸的时候阻塞信号,防止进入死循环 + m_trayManager->blockSignals(true); + m_trayManager->setFixedSize(panelRect.size()); + m_trayManager->updateLayout(); + m_trayManager->blockSignals(false); +} + +QSize TrayMainWindow::suitableSize() const +{ + return m_trayManager->suitableSize(); +} + +void TrayMainWindow::resetPanelGeometry() +{ + m_trayManager->setFixedSize(size()); + m_trayManager->move(0, 0); + m_trayManager->updateLayout(); +} + +int TrayMainWindow::dockSpace() const +{ + return 0; +} + +void TrayMainWindow::updateRadius(int borderRadius) +{ + m_trayManager->updateBorderRadius(borderRadius); +} + +QSize TrayMainWindow::suitableSize(const Dock::Position &pos, const int &, const double &) const +{ + return m_trayManager->suitableSize(pos); +} + +void TrayMainWindow::initUI() +{ + m_trayManager->move(0, 0); +} + +void TrayMainWindow::initConnection() +{ + connect(m_trayManager, &TrayManagerWindow::requestUpdate, this, &TrayMainWindow::onRequestUpdate); +} + +void TrayMainWindow::onRequestUpdate() +{ + // 如果当前是高效模式,则无需发送信号 + if (displayMode() == Dock::DisplayMode::Efficient) + return; + + Q_EMIT requestUpdate(); +} diff --git a/frame/window/traymainwindow.h b/frame/window/traymainwindow.h new file mode 100644 index 000000000..113665a0c --- /dev/null +++ b/frame/window/traymainwindow.h @@ -0,0 +1,51 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TRAYMAINWINDOW_H +#define TRAYMAINWINDOW_H + +#include "constants.h" +#include "mainwindowbase.h" + +#include + +class TrayManagerWindow; +class MultiScreenWorker; + +DWIDGET_USE_NAMESPACE + +class TrayMainWindow : public MainWindowBase +{ + Q_OBJECT + +public: + TrayMainWindow(MultiScreenWorker *multiScreenWorker, QWidget *parent = Q_NULLPTR); + void setPosition(const Dock::Position &position) override; + TrayManagerWindow *trayManagerWindow() const; + + void setDisplayMode(const Dock::DisplayMode &displayMode) override; + DockWindowType windowType() const override; + void updateParentGeometry(const Dock::Position &position, const QRect &rect) override; + QSize suitableSize(const Dock::Position &pos, const int &, const double &) const override; + QSize suitableSize() const; + void resetPanelGeometry() override; + +protected: + int dockSpace() const override; + void updateRadius(int borderRadius) override; + +private: + void initUI(); + void initConnection(); + +private Q_SLOTS: + void onRequestUpdate(); + +private: + TrayManagerWindow *m_trayManager; + MultiScreenWorker *m_multiScreenWorker; +}; + +#endif // TRAYMAINWINDOW_H diff --git a/frame/window/traymanagerwindow.cpp b/frame/window/traymanagerwindow.cpp new file mode 100644 index 000000000..f8ec7a17b --- /dev/null +++ b/frame/window/traymanagerwindow.cpp @@ -0,0 +1,518 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "traymanagerwindow.h" +#include "quickpluginwindow.h" +#include "tray_gridview.h" +#include "tray_delegate.h" +#include "tray_model.h" +#include "constants.h" +#include "systempluginwindow.h" +#include "datetimedisplayer.h" +#include "expandiconwidget.h" +#include "quickdragcore.h" +#include "utils.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define CRITLCALHEIGHT 42 +#define CONTENTSPACE 7 +#define SINGLEROWSPACE 4 +// 高度小于等于这个值的时候,间距最小值 +#define MINHIGHT 46 +// 最小值与最大值的差值 +#define MINSPACE 4 +// 当前高度与最小高度差值大于这个值的时候,间距使用最大值 +#define MAXDIFF 3 + +TrayManagerWindow::TrayManagerWindow(QWidget *parent) + : QWidget(parent) + , m_appPluginDatetimeWidget(new QWidget(this)) + , m_dockInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) + , m_systemPluginWidget(new SystemPluginWindow(m_dockInter, this)) + , m_appPluginWidget(new QWidget(m_appPluginDatetimeWidget)) + , m_quickIconWidget(new QuickPluginWindow(Dock::DisplayMode::Fashion, m_appPluginWidget)) + , m_dateTimeWidget(new DateTimeDisplayer(false, m_appPluginDatetimeWidget)) + , m_appPluginLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this)) + , m_mainLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this)) + , m_trayView(new TrayGridView(this)) + , m_model(TrayModel::getDockModel()) + , m_delegate(new TrayDelegate(m_trayView, m_trayView)) + , m_position(Dock::Position::Bottom) + , m_displayMode(Dock::DisplayMode::Fashion) + , m_splitLine(new QLabel(m_appPluginDatetimeWidget)) + , m_singleShow(false) + , m_borderRadius(0) +{ + initUi(); + initConnection(); + + setAcceptDrops(true); + setMouseTracking(true); + + QMetaObject::invokeMethod(this, &TrayManagerWindow::updateLayout, Qt::QueuedConnection); +} + +TrayManagerWindow::~TrayManagerWindow() +{ +} + +void TrayManagerWindow::updateBorderRadius(int borderRadius) +{ + m_borderRadius = borderRadius; + update(); + qApp->setProperty("trayBorderRadius", pathRadius()); +} + +void TrayManagerWindow::updateLayout() +{ + if (!isVisible()) + return; + + int dockSize = 0; + if (Utils::isDraging()) { + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + dockSize = topLevelWidget()->height(); + else + dockSize = topLevelWidget()->width(); + } else { + dockSize = m_dockInter->windowSizeFashion(); + } + + bool lastIsSingle = m_singleShow; + updateItemLayout(dockSize); + // 当插件区域从单行变成两行或者两行变成单行的时候,发送该信号,通知外部重新调整区域大小 + if (lastIsSingle != m_singleShow) + Q_EMIT requestUpdate(); +} + +void TrayManagerWindow::updateItemLayout(int dockSize) +{ + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + m_singleShow = (dockSize <= CRITLCALHEIGHT); + } else { + m_singleShow = true; + } + + if (m_singleShow) + resetSingleDirection(); + else + resetMultiDirection(); + + resetChildWidgetSize(); + // 当尺寸发生变化的时候,通知托盘区域刷新尺寸,让托盘图标始终保持居中显示 + Q_EMIT m_delegate->sizeHintChanged(m_model->index(0, 0)); +} + +int TrayManagerWindow::pathRadius() const +{ + QMargins mainMargin = m_mainLayout->contentsMargins(); + return m_borderRadius - mainMargin.top(); +} + +void TrayManagerWindow::setPositon(Dock::Position position) +{ + if (m_position == position) + return; + + m_position = position; + + if (position == Dock::Position::Top || position == Dock::Position::Bottom) + m_trayView->setOrientation(QListView::Flow::LeftToRight, false); + else + m_trayView->setOrientation(QListView::Flow::TopToBottom, false); + + TrayDelegate *delegate = static_cast(m_trayView->itemDelegate()); + delegate->setPositon(position); + + m_trayView->setPosition(position); + m_quickIconWidget->setPositon(position); + m_dateTimeWidget->setPositon(position); + m_systemPluginWidget->setPositon(position); + m_trayView->onUpdateEditorView(); + updateLayout(); +} + +void TrayManagerWindow::setDisplayMode(Dock::DisplayMode displayMode) +{ + m_displayMode = displayMode; + // 如果当前模式为高效模式,则设置当前的trayView为其计算位置的参照 + if (displayMode == Dock::DisplayMode::Fashion) { + ExpandIconWidget::popupTrayView()->setReferGridView(m_trayView); + updateItemLayout(m_dockInter->windowSizeFashion()); + } +} + +int TrayManagerWindow::appDatetimeSize(const Dock::Position &position) const +{ + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + bool showSingle = m_singleShow; + // 正在从左右切换到上下(m_position当前显示的位置,还未切换),此时根据托盘区域的尺寸来决定显示一行还是两行 + if (m_position == Dock::Position::Left || m_position == Dock::Position::Right) { + showSingle = m_dockInter->windowSizeFashion() < CRITLCALHEIGHT; + } + + // 如果是一行或者是在切换位置(从左右切换到上下) + if (showSingle) { + return m_trayView->suitableSize(position).width() + m_quickIconWidget->suitableSize(position).width() + + m_dateTimeWidget->suitableSize(position).width() + 4; + } + //如果是两行 + int topWidth = m_trayView->suitableSize(position).width() + m_quickIconWidget->suitableSize(position).width(); + int bottomWidth = m_dateTimeWidget->suitableSize(position).width(); + return qMax(topWidth, bottomWidth); + } + + int trayHeight = m_trayView->suitableSize(position).height(); + int traypluginHeight = trayHeight + m_quickIconWidget->suitableSize(position).height() + m_appPluginLayout->spacing(); + return traypluginHeight + m_dateTimeWidget->suitableSize(position).height() + 10; +} + +QSize TrayManagerWindow::suitableSize() const +{ + return suitableSize(m_position); +} + +QSize TrayManagerWindow::suitableSize(const Dock::Position &position) const +{ + QMargins m = m_mainLayout->contentsMargins(); + if (position == Dock::Position::Top || position == Dock::Position::Bottom) { + int width = appDatetimeSize(position); + int systemWidgetWidth = m_systemPluginWidget->suitableSize(position).width(); + if (systemWidgetWidth > 0) { + width += systemWidgetWidth + m_mainLayout->spacing(); + } + width += m.left() + m.right(); + return QSize(width, QWIDGETSIZE_MAX); + } + + int height = appDatetimeSize(position); + int systemWidgetHeight = m_systemPluginWidget->suitableSize(position).height(); + if (systemWidgetHeight > 0) { + height += systemWidgetHeight + m_mainLayout->spacing(); + } + height += m.top() + m.bottom(); + return QSize(QWIDGETSIZE_MAX, height); +} + +// 用于返回需要绘制的圆形区域 +QPainterPath TrayManagerWindow::roundedPaths() +{ + QMargins mainMargin = m_mainLayout->contentsMargins(); + int radius = pathRadius(); + QPainterPath path; + if ((m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + && m_singleShow) { + // 如果是上下方向,且只有一行 + // 计算托盘和快捷插件区域 + QPoint pointPlugin(mainMargin.left(), mainMargin.top()); + QRect rctPlugin(QPoint(mainMargin.left(), mainMargin.top()), m_appPluginWidget->size()); + path.addRoundedRect(rctPlugin, radius, radius); + + // 计算日期时间区域 + QPoint pointDateTime = m_dateTimeWidget->pos(); + pointDateTime = m_dateTimeWidget->parentWidget()->mapTo(this, pointDateTime); + QRect rctDatetime(pointDateTime, m_dateTimeWidget->size()); + path.addRoundedRect(rctDatetime, radius, radius); + // 计算系统插件区域 + path.addRoundedRect(m_systemPluginWidget->geometry(), radius, radius); + } else { + // 添加系统插件区域的位置信息 + path.addRoundedRect(m_appPluginDatetimeWidget->geometry(), radius, radius); + path.addRoundedRect(m_systemPluginWidget->geometry(), radius, radius); + } + + return path; +} + +void TrayManagerWindow::onTrayCountChanged() +{ + resetChildWidgetSize(); + Q_EMIT requestUpdate(); +} + +void TrayManagerWindow::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + updateLayout(); +} + +void TrayManagerWindow::initUi() +{ + m_systemPluginWidget->setDisplayMode(Dock::DisplayMode::Fashion); + m_trayView->setModel(m_model); + m_trayView->setItemDelegate(m_delegate); + m_trayView->setDragDistance(2); + + m_splitLine->setFixedHeight(1); + QPalette pal; + QColor lineColor(Qt::black); + lineColor.setAlpha(static_cast(255 * 0.1)); + pal.setColor(QPalette::Background, lineColor); + m_splitLine->setAutoFillBackground(true); + m_splitLine->setPalette(pal); + + // 左侧的区域,包括应用托盘插件和下方的日期时间区域 + m_appPluginLayout->setContentsMargins(0, 0, 0, 0); + m_appPluginLayout->setSpacing(0); + m_appPluginWidget->setLayout(m_appPluginLayout); + m_appPluginLayout->addWidget(m_trayView); + m_appPluginLayout->addWidget(m_quickIconWidget); + + setLayout(m_mainLayout); + // 通用情况下,设置边距和间距都为7 + m_mainLayout->setContentsMargins(CONTENTSPACE, CONTENTSPACE, CONTENTSPACE, CONTENTSPACE); + m_mainLayout->setSpacing(CONTENTSPACE); + m_mainLayout->addWidget(m_appPluginDatetimeWidget); + m_mainLayout->addWidget(m_systemPluginWidget); +} + +void TrayManagerWindow::initConnection() +{ + connect(m_model, &TrayModel::rowCountChanged, this, &TrayManagerWindow::onTrayCountChanged); + connect(m_model, &TrayModel::rowCountChanged, m_trayView, &TrayGridView::onUpdateEditorView); + connect(m_model, &TrayModel::requestRefreshEditor, m_trayView, &TrayGridView::onUpdateEditorView); + connect(m_quickIconWidget, &QuickPluginWindow::itemCountChanged, this, [ this ] { + // 当插件数量发生变化的时候,需要调整尺寸 + m_quickIconWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + m_quickIconWidget->setFixedWidth(m_quickIconWidget->suitableSize().width()); + else + m_quickIconWidget->setFixedHeight(m_quickIconWidget->suitableSize().height()); + + Q_EMIT requestUpdate(); + }); + + connect(m_systemPluginWidget, &SystemPluginWindow::itemChanged, this, [ this ] { + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + m_systemPluginWidget->setFixedWidth(m_systemPluginWidget->suitableSize().width()); + else + m_systemPluginWidget->setFixedHeight(m_systemPluginWidget->suitableSize().height()); + + Q_EMIT requestUpdate(); + }); + + connect(m_trayView, &TrayGridView::dragLeaved, m_delegate, [ this ]{ + Q_EMIT m_delegate->requestDrag(true); + }); + connect(m_trayView, &TrayGridView::dragFinished, this, [ this ] { + // 如果拖拽结束,则隐藏托盘 + Q_EMIT m_delegate->requestDrag(false); + }); + + connect(m_model, &TrayModel::rowCountChanged, m_trayView, &TrayGridView::onUpdateEditorView); + connect(m_dateTimeWidget, &DateTimeDisplayer::requestUpdate, this, &TrayManagerWindow::requestUpdate); + + m_trayView->installEventFilter(this); + m_quickIconWidget->installEventFilter(this); + installEventFilter(this); + QMetaObject::invokeMethod(this, &TrayManagerWindow::requestUpdate, Qt::QueuedConnection); +} + +void TrayManagerWindow::resetChildWidgetSize() +{ + int count = 0; + for (int i = 0; i < m_model->rowCount(); i++) { + if (!m_trayView->isRowHidden(i)) + count++; + } + + switch (m_position) { + case Dock::Position::Top: + case Dock::Position::Bottom: { + int trayWidth = m_trayView->suitableSize().width(); + int appDateTimeWidth = appDatetimeSize(m_position); + QMargins m = m_appPluginLayout->contentsMargins(); + if (m_singleShow) { + // 单行显示 + int trayHeight = m_appPluginDatetimeWidget->height() - m.top() - m.bottom(); + m_trayView->setFixedSize(trayWidth, trayHeight); + m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize().width(), trayHeight); + m_appPluginWidget->setFixedSize(trayWidth + m_quickIconWidget->suitableSize().width(), trayHeight); + m_dateTimeWidget->setFixedSize(m_dateTimeWidget->suitableSize().width(), trayHeight); + // 设置右侧的电源按钮的尺寸 + m_systemPluginWidget->setFixedSize(m_systemPluginWidget->suitableSize()); + m_mainLayout->setContentsMargins(SINGLEROWSPACE, SINGLEROWSPACE, SINGLEROWSPACE, SINGLEROWSPACE); + m_mainLayout->setSpacing(SINGLEROWSPACE); + // 单行显示需要重新设置插件和时间日期的位置,不显示分割线 + m_splitLine->setVisible(false); + m_appPluginWidget->move(0, 0); + m_dateTimeWidget->move(m_appPluginWidget->x() + m_appPluginWidget->width() + 4, m_appPluginWidget->y()); + } else { + // 多行显示 + m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize()); + int trayHeight = m_appPluginDatetimeWidget->height() / 2 + 4 - m.top() - m.bottom(); + m_trayView->setFixedSize(trayWidth, trayHeight); + m_appPluginWidget->setFixedSize(trayWidth + m_quickIconWidget->suitableSize().width(), trayHeight); + // 因为是两行,所以对于时间控件的尺寸,只能设置最小值 + int dateTimeWidth = qMax(m_appPluginWidget->width(), m_dateTimeWidget->suitableSize().width()); + int dateTimeHeight = m_appPluginDatetimeWidget->height() - - m.top() - m.bottom() - trayHeight; + m_dateTimeWidget->setFixedSize(dateTimeWidth, dateTimeHeight); + m_systemPluginWidget->setFixedSize(m_systemPluginWidget->suitableSize()); + int contentSpace = qMin(MAXDIFF, qMax(((Utils::isDraging() ? height() : (int)m_dockInter->windowSizeFashion()) - MINHIGHT), 0)) + MINSPACE; + m_mainLayout->setContentsMargins(contentSpace, contentSpace, contentSpace, contentSpace); + m_mainLayout->setSpacing(contentSpace); + + // 调整插件和日期窗体的位置显示,这里没有用到布局,是因为在调整任务栏位置的时候, + // 随着布局方向的改变,显示有很大的问题 + m_splitLine->setFixedWidth(appDateTimeWidth); + m_splitLine->setVisible(true); + if (m_position == Dock::Position::Bottom) { + m_appPluginWidget->move(0, 0); + m_splitLine->move(0, m_appPluginWidget->y() + m_appPluginWidget->height()); + m_dateTimeWidget->move(0, m_appPluginWidget->y() + m_appPluginWidget->height() + m_splitLine->height()); + } else { + m_dateTimeWidget->move(0, 0); + m_splitLine->move(0, m_dateTimeWidget->y() + m_dateTimeWidget->height()); + m_appPluginWidget->move(0, m_dateTimeWidget->y() + m_dateTimeWidget->height() + m_splitLine->height()); + } + } + QMargins margin = m_mainLayout->contentsMargins(); + int appDateHeight = height() - margin.top() - margin.bottom(); + m_appPluginDatetimeWidget->setFixedSize(appDateTimeWidth, appDateHeight); + break; + } + case Dock::Position::Left: + case Dock::Position::Right: { + int trayHeight = m_trayView->suitableSize().height(); + int quickAreaHeight = m_quickIconWidget->suitableSize().height(); + QMargins m = m_appPluginLayout->contentsMargins(); + // 左右方向始终只有一列 + int datetimeHeight = m_dateTimeWidget->suitableSize().height(); + int sizeWidth = m_appPluginDatetimeWidget->width() - m.left() - m.right(); + m_trayView->setFixedSize(sizeWidth, trayHeight); + m_quickIconWidget->setFixedSize(sizeWidth, quickAreaHeight); + m_dateTimeWidget->setFixedSize(sizeWidth, datetimeHeight); + m_appPluginWidget->setFixedSize(sizeWidth, trayHeight + quickAreaHeight); + m_systemPluginWidget->setFixedSize(m_systemPluginWidget->suitableSize()); + + int contentSpace = (qMin(MAXDIFF, qMax((Utils::isDraging() ? width() : (int)m_dockInter->windowSizeFashion()) - MINHIGHT, 0)) + MINSPACE); + m_mainLayout->setContentsMargins(contentSpace, contentSpace, contentSpace, contentSpace); + m_mainLayout->setSpacing(contentSpace); + + int appDateWidth = width() - (contentSpace * 2); + m_appPluginDatetimeWidget->setFixedSize(appDateWidth, appDatetimeSize(m_position)); + + // 调整各个部件的位置 + m_appPluginWidget->move(0, 0); + m_splitLine->setFixedWidth(width()); + m_splitLine->setVisible(true); + m_splitLine->move(0, m_appPluginWidget->y() + m_appPluginWidget->height()); + m_dateTimeWidget->move(0, m_appPluginWidget->y() + m_appPluginWidget->height() + m_splitLine->height()); + break; + } + } +} + +void TrayManagerWindow::resetSingleDirection() +{ + switch (m_position) { + case Dock::Position::Top: + case Dock::Position::Bottom: { + m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); + // 应用和时间在一行显示 + m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); + m_splitLine->hide(); + break; + } + case Dock::Position::Left: + case Dock::Position::Right:{ + m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); + m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); + m_splitLine->show(); + break; + } + } + m_dateTimeWidget->setOneRow(true); +} + +void TrayManagerWindow::resetMultiDirection() +{ + switch (m_position) { + case Dock::Position::Top: + case Dock::Position::Bottom: { + m_appPluginLayout->setDirection(QBoxLayout::Direction::LeftToRight); + m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight); + m_splitLine->show(); + m_dateTimeWidget->setOneRow(false); + break; + } + case Dock::Position::Left: + case Dock::Position::Right: { + m_appPluginLayout->setDirection(QBoxLayout::Direction::TopToBottom); + m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom); + m_splitLine->hide(); + m_dateTimeWidget->setOneRow(true); + break; + } + } +} + +void TrayManagerWindow::dragEnterEvent(QDragEnterEvent *e) +{ + e->setDropAction(Qt::CopyAction); + e->accept(); +} + +void TrayManagerWindow::dragMoveEvent(QDragMoveEvent *e) +{ + e->setDropAction(Qt::CopyAction); + e->accept(); +} + +void TrayManagerWindow::dropEvent(QDropEvent *e) +{ + if (!e || !e->mimeData() || e->source() == this) + return; + + if (m_quickIconWidget->isQuickWindow(e->source())) { + const QuickPluginMimeData *mimeData = qobject_cast(e->mimeData()); + if (!mimeData) + return; + + PluginsItemInterface *pluginItem = static_cast(mimeData->pluginItemInterface()); + if (pluginItem) + m_quickIconWidget->dragPlugin(pluginItem); + } else if (qobject_cast(e->source())) { + // 将trayView中的dropEvent扩大到整个区域(this),这样便于随意拖动到这个区域都可以捕获。 + // m_trayView中有e->accept不会导致事件重复处理。 + m_trayView->handleDropEvent(e); + } +} + +void TrayManagerWindow::dragLeaveEvent(QDragLeaveEvent *event) +{ + event->accept(); +} + +void TrayManagerWindow::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + QPainterPath path = roundedPaths(); + QPainter painter(this); + painter.save(); + painter.setRenderHint(QPainter::Antialiasing); + painter.setClipPath(path); + painter.fillRect(rect().adjusted(1, 1, -1, -1), maskColor(102)); + painter.setPen(maskColor(110)); + painter.drawPath(path); + painter.restore(); +} + +QColor TrayManagerWindow::maskColor(uint8_t alpha) const +{ + QColor color = DGuiApplicationHelper::standardPalette(DGuiApplicationHelper::instance()->themeType()).window().color(); + color.setAlpha(alpha); + return color; +} diff --git a/frame/window/traymanagerwindow.h b/frame/window/traymanagerwindow.h new file mode 100644 index 000000000..c624d9e82 --- /dev/null +++ b/frame/window/traymanagerwindow.h @@ -0,0 +1,95 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TRAYMANAGERWINDOW_H +#define TRAYMANAGERWINDOW_H + +#include "constants.h" +#include "dbusutil.h" + +#include "org_deepin_dde_timedate1.h" + +#include + +namespace Dtk { namespace Widget { class DBlurEffectWidget; } } + +using namespace Dtk::Widget; + +using Timedate = org::deepin::dde::Timedate1; + +class QuickPluginWindow; +class QBoxLayout; +class TrayGridView; +class TrayModel; +class TrayDelegate; +class SystemPluginWindow; +class QLabel; +class QDropEvent; +class DateTimeDisplayer; +class QPainterPath; + +class TrayManagerWindow : public QWidget +{ + Q_OBJECT + +public: + explicit TrayManagerWindow(QWidget *parent = nullptr); + ~TrayManagerWindow() override; + + void updateBorderRadius(int borderRadius); + void updateLayout(); + void setPositon(Dock::Position position); + void setDisplayMode(Dock::DisplayMode displayMode); + QSize suitableSize() const; + QSize suitableSize(const Dock::Position &position) const; + +Q_SIGNALS: + void requestUpdate(); + +protected: + void resizeEvent(QResizeEvent *event) override; + void dragEnterEvent(QDragEnterEvent *e) override; + void dragMoveEvent(QDragMoveEvent *e) override; + void dropEvent(QDropEvent *e) override; + void dragLeaveEvent(QDragLeaveEvent *event) override; + void paintEvent(QPaintEvent *event) override; + +private: + void initUi(); + void initConnection(); + + void resetChildWidgetSize(); + void resetMultiDirection(); + void resetSingleDirection(); + QColor maskColor(uint8_t alpha) const; + + int appDatetimeSize(const Dock::Position &position) const; + QPainterPath roundedPaths(); + void updateItemLayout(int dockSize); + int pathRadius() const; + +private Q_SLOTS: + void onTrayCountChanged(); + +private: + QWidget *m_appPluginDatetimeWidget; + DockInter *m_dockInter; + SystemPluginWindow *m_systemPluginWidget; + QWidget *m_appPluginWidget; + QuickPluginWindow *m_quickIconWidget; + DateTimeDisplayer *m_dateTimeWidget; + QBoxLayout *m_appPluginLayout; + QBoxLayout *m_mainLayout; + TrayGridView *m_trayView; + TrayModel *m_model; + TrayDelegate *m_delegate; + Dock::Position m_position; + Dock::DisplayMode m_displayMode; + QLabel *m_splitLine; + bool m_singleShow; // 用于记录当前日期时间和插件区域是显示一行还是显示多行 + int m_borderRadius; // 圆角的值 +}; + +#endif // PLUGINWINDOW_H diff --git a/frame/window/windowmanager.cpp b/frame/window/windowmanager.cpp new file mode 100644 index 000000000..00199bdab --- /dev/null +++ b/frame/window/windowmanager.cpp @@ -0,0 +1,829 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "mainwindow.h" +#include "windowmanager.h" +#include "traymainwindow.h" +#include "multiscreenworker.h" +#include "menuworker.h" +#include "dockitemmanager.h" +#include "dockscreen.h" +#include "displaymanager.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +DGUI_USE_NAMESPACE + +#define SNI_WATCHER_SERVICE "org.kde.StatusNotifierWatcher" +#define SNI_WATCHER_PATH "/StatusNotifierWatcher" + +#define DOCKSCREEN_INS DockScreen::instance() +#define DIS_INS DisplayManager::instance() + +using org::kde::StatusNotifierWatcher; + +WindowManager::WindowManager(MultiScreenWorker *multiScreenWorker, QObject *parent) + : QObject(parent) + , m_multiScreenWorker(multiScreenWorker) + , m_displayMode(Dock::DisplayMode::Efficient) + , m_position(Dock::Position::Bottom) + , m_dbusDaemonInterface(QDBusConnection::sessionBus().interface()) + , m_sniWatcher(new StatusNotifierWatcher(SNI_WATCHER_SERVICE, SNI_WATCHER_PATH, QDBusConnection::sessionBus(), this)) +{ + initSNIHost(); + initConnection(); + initMember(); +} + +WindowManager::~WindowManager() +{ +} + +void WindowManager::addWindow(MainWindowBase *window) +{ + connect(window, &MainWindowBase::requestUpdate, this, [ window, this ] { + updateDockGeometry(window->geometry()); + }); + + window->setPosition(m_multiScreenWorker->position()); + window->setDisplayMode(m_multiScreenWorker->displayMode()); + window->setOrder(m_topWindows.size()); + + m_topWindows << window; +} + +void WindowManager::launch() +{ + if (!qApp->property("CANSHOW").toBool()) + return; + + const QString ¤tScreen = DOCKSCREEN_INS->current(); + if (m_multiScreenWorker->hideMode() == HideMode::KeepShowing) { + onPlayAnimation(currentScreen, m_multiScreenWorker->position(), Dock::AniAction::Show); + } else if (m_multiScreenWorker->hideMode() == HideMode::KeepHidden) { + qApp->setProperty(PROP_HIDE_STATE, HideState::Hide); + onUpdateDockGeometry(HideMode::KeepHidden); + } else if (m_multiScreenWorker->hideMode() == HideMode::SmartHide) { + switch(m_multiScreenWorker->hideState()) { + case HideState::Show: + onPlayAnimation(currentScreen, m_multiScreenWorker->position(), Dock::AniAction::Show); + break; + case HideState::Hide: + onPlayAnimation(currentScreen, m_multiScreenWorker->position(), Dock::AniAction::Hide); + break; + default: + break; + } + + qApp->setProperty(PROP_HIDE_STATE, m_multiScreenWorker->hideState()); + } + + QMetaObject::invokeMethod(this, [ this ] { + for (MainWindowBase *mainWindow : m_topWindows) + mainWindow->setDisplayMode(m_multiScreenWorker->displayMode()); + }, Qt::QueuedConnection); +} + +void WindowManager::sendNotifications() +{ + QStringList actionButton; + actionButton << "reload" << tr("Exit Safe Mode"); + QVariantMap hints; + hints["x-deepin-action-reload"] = QString("dbus-send,--session,--dest=org.deepin.dde.Dock1,--print-reply,/org/deepin/dde/Dock1,org.deepin.dde.Dock1.ReloadPlugins"); + // 在进入安全模式时,执行此DBUS耗时25S左右,导致任务栏显示阻塞,所以使用线程调用 + QtConcurrent::run(QThreadPool::globalInstance(), [ = ] { + DDBusSender() + .service(notificationService) + .path(notificationPath) + .interface(notificationInterface) + .method(QString("Notify")) + .arg(QString("dde-control-center")) // appname + .arg(static_cast(0)) // id + .arg(QString("preferences-system")) // icon + .arg(QString(tr("Dock - Safe Mode"))) // summary + .arg(QString(tr("The Dock is in safe mode, please exit to show it properly"))) // content + .arg(actionButton) // actions + .arg(hints) // hints + .arg(15000) // timeout + .call(); + }); +} + +/** + * @brief MainWindow::callShow + * 此方法是被外部进程通过DBus调用的。 + * @note 当任务栏以-r参数启动时,其不会显示界面,需要在外部通过DBus调用此接口之后才会显示界面, + * 这里是以前为了优化任务栏的启动速度做的处理,当任务栏启动时,此时窗管进程可能还未启动完全, + * 部分设置未初始化完等,导致任务栏显示的界面异常,所以留下此接口,被startdde延后调用 + */ + +void WindowManager::callShow() +{ + static bool flag = false; + if (flag) { + return; + } + flag = true; + + qApp->setProperty("CANSHOW", true); + + launch(); + + // 预留200ms提供给窗口初始化再通知startdde,不影响启动速度 + QTimer::singleShot(200, this, &WindowManager::RegisterDdeSession); +} + +/** 调整任务栏的大小,这个接口提供给dbus使用,一般是控制中心来调用 + * @brief WindowManager::resizeDock + * @param offset + * @param dragging + */ +void WindowManager::resizeDock(int offset, bool dragging) +{ + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (!screen) + return; + + Utils::setIsDraging(dragging); + + int dockSize = qBound(DOCK_MIN_SIZE, offset, DOCK_MAX_SIZE); + for (MainWindowBase *mainWindow : m_topWindows) { + QRect windowRect = mainWindow->getDockGeometry(screen, m_multiScreenWorker->position(), m_multiScreenWorker->displayMode(), Dock::HideState::Hide); + QRect newWindowRect; + switch (m_multiScreenWorker->position()) { + case Top: { + newWindowRect.setX(windowRect.x()); + newWindowRect.setY(windowRect.y()); + newWindowRect.setWidth(windowRect.width()); + newWindowRect.setHeight(dockSize); + break; + } + case Bottom: { + newWindowRect.setX(windowRect.x()); + newWindowRect.setY(windowRect.y() + windowRect.height() - dockSize); + newWindowRect.setWidth(windowRect.width()); + newWindowRect.setHeight(dockSize); + break; + } + case Left: { + newWindowRect.setX(windowRect.x()); + newWindowRect.setY(windowRect.y()); + newWindowRect.setWidth(dockSize); + newWindowRect.setHeight(windowRect.height()); + break; + } + case Right: { + newWindowRect.setX(windowRect.x() + windowRect.width() - dockSize); + newWindowRect.setY(windowRect.y()); + newWindowRect.setWidth(dockSize); + newWindowRect.setHeight(windowRect.height()); + break; + } + } + + // 更新界面大小 + mainWindow->blockSignals(true); + mainWindow->setFixedSize(newWindowRect.size()); + mainWindow->resetPanelGeometry(); + mainWindow->move(newWindowRect.topLeft()); + mainWindow->blockSignals(false); + } + + m_multiScreenWorker->updateDaemonDockSize(dockSize); +} + +/** 获取任务栏的实际大小,这个接口用于获取任务栏的尺寸返回给dbus接口 + * @brief WindowManager::geometry + * @return 任务栏的实际尺寸和位置信息 + */ +QRect WindowManager::geometry() const +{ + int x = 0; + int y = 0; + int width = 0; + int height = 0; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->geometry(); + if (i == 0 || x > windowRect.x()) + x = windowRect.x(); + if (i == 0) { + y = windowRect.y(); + height = windowRect.height(); + } + width += windowRect.width() + mainWindow->dockSpace(); + } + + return QRect(x, y, width, height); + } + + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->geometry(); + if (i == 0 || y > windowRect.y()) + y = windowRect.y(); + + if (i == 0) { + x = windowRect.x(); + width = windowRect.width(); + } + + height += windowRect.height() + mainWindow->dockSpace(); + } + + return QRect(x, y, width, height); +} + +void WindowManager::onUpdateDockGeometry(const Dock::HideMode &hideMode) +{ + Dock::HideState hideState; + if (hideMode == HideMode::KeepShowing || (hideMode == HideMode::SmartHide && m_multiScreenWorker->hideState() == HideState::Show)) + hideState = Dock::HideState::Show; + else + hideState = Dock::HideState::Hide; + + updateMainGeometry(hideState); +} + +void WindowManager::onPositionChanged(const Dock::Position &position) +{ + Position lastPos = m_position; + if (lastPos == position) + return; + + m_position = position; + // 调用设置位置,一会根据需要放到实际的位置 + for (MainWindowBase *mainWindow : m_topWindows) + mainWindow->setPosition(position); + + // 在改变位置后,需要根据当前任务栏是隐藏还是显示,来调整左右两侧区域的大小 + onUpdateDockGeometry(HideMode::KeepHidden); +} + +void WindowManager::onDisplayModeChanged(const Dock::DisplayMode &displayMode) +{ + m_displayMode = displayMode; + + DockItem::setDockDisplayMode(m_displayMode); + qApp->setProperty(PROP_DISPLAY_MODE, QVariant::fromValue(displayMode)); + + for (MainWindowBase *mainWindow : m_topWindows) + mainWindow->setDisplayMode(m_displayMode); + + onUpdateDockGeometry(m_multiScreenWorker->hideMode()); +} + +void WindowManager::onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) +{ + Q_UNUSED(oldOwner); + + if (name == SNI_WATCHER_SERVICE && !newOwner.isEmpty()) { + qDebug() << SNI_WATCHER_SERVICE << "SNI watcher daemon started, register dock to watcher as SNI Host"; + m_sniWatcher->RegisterStatusNotifierHost(m_sniHostService); + } +} + +void WindowManager::showAniFinish() +{ + qApp->setProperty(PROP_HIDE_STATE, HideState::Show); + + // 通知后端更新区域 + onRequestUpdateFrontendGeometry(); + onRequestNotifyWindowManager(); +} + +void WindowManager::animationFinish(bool showOrHide) +{ + for (MainWindowBase *mainWindow : m_topWindows) { + if (!mainWindow->isVisible()) + continue; + + mainWindow->animationFinished(showOrHide); + } +} + +void WindowManager::hideAniFinish() +{ + DockItem::setDockPosition(m_position); + qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_position)); + qApp->setProperty(PROP_HIDE_STATE, HideState::Hide); + // 通知后端更新区域 + onRequestUpdateFrontendGeometry(); + onRequestNotifyWindowManager(); +} + +/**获取整个任务栏区域的位置和尺寸的信息,用于提供给后端设置位置等信息 + * @brief WindowManager::getDockGeometry + * @param withoutScale + * @return + */ +QRect WindowManager::getDockGeometry(bool withoutScale) const +{ + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (!screen) + return QRect(); + + int x = 0; + int y = 0; + int width = 0; + int height = 0; + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) { + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->getDockGeometry(screen, m_position, m_displayMode, Dock::HideState::Show, withoutScale); + if (i == 0 || x > windowRect.x()) + x = windowRect.x(); + + if (i == 0) { + y = windowRect.y(); + height = windowRect.height(); + } + width += windowRect.width() + mainWindow->dockSpace(); + } + } else { + for (int i = 0; i < m_topWindows.size(); i++) { + MainWindowBase *mainWindow = m_topWindows[i]; + if (!mainWindow->isVisible()) + continue; + + QRect windowRect = mainWindow->getDockGeometry(screen, m_position, m_displayMode, Dock::HideState::Show, withoutScale); + if (i == 0 || y > windowRect.y()) + y = windowRect.y(); + + if (i == 0) { + x = windowRect.x(); + width = windowRect.width(); + } + height += windowRect.height() + mainWindow->dockSpace(); + } + } + + return QRect(x, y, width, height); +} + +void WindowManager::RegisterDdeSession() +{ + QString envName("DDE_SESSION_PROCESS_COOKIE_ID"); + + QByteArray cookie = qgetenv(envName.toUtf8().data()); + qunsetenv(envName.toUtf8().data()); + + if (!cookie.isEmpty()) { + QDBusPendingReply r = DDBusSender() + .interface(sessionManagerService) + .path(sessionManagerPath) + .service(sessionManagerInterface) + .method("Register") + .arg(QString(cookie)) + .call(); + + qDebug() << Q_FUNC_INFO << r.value(); + } +} + +void WindowManager::updateDockGeometry(const QRect &rect) +{ + // 如果当前正在执行动画,则无需设置 + if (m_multiScreenWorker->testState(MultiScreenWorker::ChangePositionAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::ShowAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::HideAnimationStart)) + return; + + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (!screen || m_position == Dock::Position(-1)) + return; + + for (MainWindowBase *mainWindow : m_topWindows) { + if (!mainWindow->isVisible()) + continue; + + QRect windowShowSize = mainWindow->getDockGeometry(screen, m_multiScreenWorker->position(), + m_multiScreenWorker->displayMode(), Dock::HideState::Show); + switch(m_position) { + case Dock::Position::Top: { + windowShowSize.setHeight(rect.height()); + break; + } + case Dock::Position::Bottom: { + int bottomY = windowShowSize.y() + windowShowSize.height(); + windowShowSize.setY(bottomY - rect.height()); + windowShowSize.setHeight(rect.height()); + break; + } + case Dock::Position::Left: { + windowShowSize.setWidth(rect.width()); + break; + } + case Dock::Position::Right: { + int righyX = windowShowSize.x() + windowShowSize.width(); + windowShowSize.setX(righyX - rect.width()); + windowShowSize.setWidth(rect.width()); + break; + } + default: break; + } + + mainWindow->blockSignals(true); + mainWindow->raise(); + mainWindow->setFixedSize(windowShowSize.size()); + mainWindow->move(windowShowSize.topLeft()); + mainWindow->resetPanelGeometry(); + mainWindow->blockSignals(false); + } + + // 抛出geometry变化的信号,通知控制中心调整尺寸 + Q_EMIT panelGeometryChanged(); +} + +void WindowManager::initConnection() +{ + connect(m_dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, &WindowManager::onDbusNameOwnerChanged); + + connect(m_multiScreenWorker, &MultiScreenWorker::serviceRestart, this, &WindowManager::onServiceRestart); + connect(m_multiScreenWorker, &MultiScreenWorker::positionChanged, this, &WindowManager::onPositionChanged); + connect(m_multiScreenWorker, &MultiScreenWorker::displayModeChanged, this, &WindowManager::onDisplayModeChanged); + connect(m_multiScreenWorker, &MultiScreenWorker::requestPlayAnimation, this, &WindowManager::onPlayAnimation); + connect(m_multiScreenWorker, &MultiScreenWorker::requestChangeDockPosition, this, &WindowManager::onChangeDockPosition); + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateDockGeometry, this, &WindowManager::onUpdateDockGeometry); + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateFrontendGeometry, this, &WindowManager::onRequestUpdateFrontendGeometry); + connect(m_multiScreenWorker, &MultiScreenWorker::requestNotifyWindowManager, this, &WindowManager::onRequestNotifyWindowManager); + connect(m_multiScreenWorker, &MultiScreenWorker::requestUpdateFrontendGeometry, DockItemManager::instance(), &DockItemManager::requestUpdateDockItem); + connect(DockItemManager::instance(), &DockItemManager::requestWindowAutoHide, m_multiScreenWorker, &MultiScreenWorker::onAutoHideChanged); +} + +void WindowManager::initSNIHost() +{ + QDBusConnection dbusConn = QDBusConnection::sessionBus(); + m_sniHostService = QString("org.kde.StatusNotifierHost-") + QString::number(qApp->applicationPid()); + dbusConn.registerService(m_sniHostService); + dbusConn.registerObject("/StatusNotifierHost", this); + + if (m_sniWatcher->isValid()) { + m_sniWatcher->RegisterStatusNotifierHost(m_sniHostService); + } else { + qDebug() << SNI_WATCHER_SERVICE << "SNI watcher daemon is not exist for now!"; + } +} + +void WindowManager::initMember() +{ + m_displayMode = m_multiScreenWorker->displayMode(); + m_position = m_multiScreenWorker->position(); +} + +// 更新任务栏的位置和尺寸的信息 +void WindowManager::updateMainGeometry(const Dock::HideState &hideState) +{ + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (!screen) + return; + + for (MainWindowBase *mainWindow : m_topWindows) { + QRect windowRect = mainWindow->getDockGeometry(screen, m_multiScreenWorker->position(), m_multiScreenWorker->displayMode(), hideState); + mainWindow->updateParentGeometry(m_position, windowRect); + } + + // 在切换模式的时候,需要根据实际当前是隐藏还是显示来记录当前任务栏是隐藏还是显示,MainPanelWindow会根据这个状态来决定怎么获取图标的尺寸, + // 如果不加上这一行,那么鼠标在唤醒任务栏的时候,左侧区域会有显示问题 + qApp->setProperty(PROP_HIDE_STATE, hideState); +} + +void WindowManager::onPlayAnimation(const QString &screenName, const Dock::Position &pos, Dock::AniAction act, bool containMouse, bool updatePos) +{ + // 如果containMouse= true,则需要计算鼠标是否包含在任务栏的位置, 如果鼠标在任务栏内部,则无需执行动画,这种情况一般用于执行隐藏模式发生变化的时候 + if (containMouse) { + QRect dockGeometry = getDockGeometry(false); + if (dockGeometry.contains(QCursor::pos())) + return; + } + + if (act == Dock::AniAction::Show) { + for (MainWindowBase *mainWindow : m_topWindows) { + if (mainWindow->windowType() != MainWindowBase::DockWindowType::MainWindow) + continue; + + // 如果请求显示的动画,且当前任务栏已经显示,则不继续执行动画 + if (mainWindow->width() > 0 && mainWindow->height() > 0) + return; + } + } + + QScreen *screen = DIS_INS->screen(screenName); + if (!m_multiScreenWorker->testState(MultiScreenWorker::RunState::AutoHide) || qApp->property("DRAG_STATE").toBool() + || m_multiScreenWorker->testState(MultiScreenWorker::RunState::ChangePositionAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::RunState::HideAnimationStart) + || m_multiScreenWorker->testState(MultiScreenWorker::RunState::ShowAnimationStart) + || !screen) + return; + + QParallelAnimationGroup *group = createAnimationGroup(act, screenName, pos); + if (!group) + return; + + switch (act) { + case Dock::AniAction::Show: + m_multiScreenWorker->setStates(MultiScreenWorker::ShowAnimationStart); + break; + case Dock::AniAction::Hide: + m_multiScreenWorker->setStates(MultiScreenWorker::HideAnimationStart); + } + + connect(group, &QParallelAnimationGroup::finished, this, [ = ] { + switch (act) { + case Dock::AniAction::Show: + showAniFinish(); + if (updatePos) + onPositionChanged(m_multiScreenWorker->position()); + m_multiScreenWorker->setStates(MultiScreenWorker::ShowAnimationStart, false); + animationFinish(true); + break; + case Dock::AniAction::Hide: + hideAniFinish(); + if (updatePos) + onPositionChanged(m_multiScreenWorker->position()); + m_multiScreenWorker->setStates(MultiScreenWorker::HideAnimationStart, false); + animationFinish(false); + break; + } + }); + + group->stop(); + group->start(QVariantAnimation::DeleteWhenStopped); +} + +/**创建动画,在时尚模式先同时创建左区域和右区域的动画 + * @brief WindowManager::createAnimationGroup + * @param aniAction 显示动画还是隐藏动画 + * @param screenName 执行动画的屏幕 + * @param position 执行动画的位置(上下左右) + * @return 要执行的动画组(左右侧区域同时执行的动画组) + */ +QParallelAnimationGroup *WindowManager::createAnimationGroup(const Dock::AniAction &aniAction, const QString &screenName, const Dock::Position &position) const +{ + QScreen *screen = DIS_INS->screen(screenName); + if (!screen) + return nullptr; + + bool stopAnimation = false; + QList animations; + for (MainWindowBase *mainWindow : m_topWindows) { + if (!mainWindow->isVisible()) + continue; + + QVariantAnimation *ani = mainWindow->createAnimation(screen, position, aniAction); + if (!ani) { + stopAnimation = true; + continue; + } + + animations << ani; + } + + if (stopAnimation) { + qDeleteAll(animations.begin(), animations.end()); + return nullptr; + } + + QParallelAnimationGroup *aniGroup = new QParallelAnimationGroup; + for (QVariantAnimation *ani : animations) { + ani->setParent(aniGroup); + aniGroup->addAnimation(ani); + } + + return aniGroup; +} + +void WindowManager::onChangeDockPosition(QString fromScreen, QString toScreen, const Dock::Position &fromPos, const Dock::Position &toPos) +{ + QList animations; + // 获取隐藏的动作 + QParallelAnimationGroup *hideGroup = createAnimationGroup(Dock::AniAction::Hide, fromScreen, fromPos); + if (hideGroup) { + connect(hideGroup, &QParallelAnimationGroup::finished, this, [ = ] { + // 在隐藏动画结束的时候,开始设置位置信息 + onPositionChanged(m_multiScreenWorker->position()); + DockItem::setDockPosition(m_multiScreenWorker->position()); + qApp->setProperty(PROP_POSITION, QVariant::fromValue(m_multiScreenWorker->position())); + }); + animations << hideGroup; + } + // 获取显示的动作 + QParallelAnimationGroup *showGroup = createAnimationGroup(Dock::AniAction::Show, toScreen, toPos); + if (showGroup) + animations << showGroup; + + if (animations.size() == 0) + return; + + m_multiScreenWorker->setStates(MultiScreenWorker::ChangePositionAnimationStart); + + QSequentialAnimationGroup *group = new QSequentialAnimationGroup; + connect(group, &QVariantAnimation::finished, this, [ = ] { + // 结束之后需要根据确定需要再隐藏 + showAniFinish(); + m_multiScreenWorker->setStates(MultiScreenWorker::ChangePositionAnimationStart, false); + animationFinish(true); + emit panelGeometryChanged(); + }); + + for (QParallelAnimationGroup *ani : animations) { + ani->setParent(group); + group->addAnimation(ani); + } + + group->start(QVariantAnimation::DeleteWhenStopped); +} + +void WindowManager::onRequestUpdateFrontendGeometry() +{ + QRect rect = getDockGeometry(true); + // org.deepin.dde.daemon.Dock1的SetFrontendWindowRect接口设置区域时,此区域的高度或宽度不能为0,否则会导致其HideState属性循环切换,造成任务栏循环显示或隐藏 + if (rect.width() == 0 || rect.height() == 0) + return; + + int x = rect.x(); + int y = rect.y(); + if (m_displayMode == Dock::DisplayMode::Fashion) { + QScreen *screen = DIS_INS->screen(DOCKSCREEN_INS->current()); + if (screen) { + if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) + x = qMax(0, (int)((screen->handle()->geometry().width() - (rect.width() * qApp->devicePixelRatio())) / 2)); + else + y = qMax(0, (int)((screen->handle()->geometry().height() - (rect.height() * qApp->devicePixelRatio())) / 2)); + } + } + + DockInter dockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus()); + dockInter.SetFrontendWindowRect(x, y, uint(rect.width()), uint(rect.height())); +} + +void WindowManager::onRequestNotifyWindowManager() +{ + static QRect lastRect = QRect(); + static int lastScreenWidth = 0; + static int lastScreenHeight = 0; + + // 从列表中查找主窗口 + MainWindowBase *mainWindow = nullptr; + for (MainWindowBase *window : m_topWindows) { + if (window->windowType() != MainWindowBase::DockWindowType::MainWindow) + continue; + + mainWindow = window; + break; + } + + if (!mainWindow) + return; + + /* 在非主屏或非一直显示状态时,清除任务栏区域,不挤占应用 */ + if ((!DIS_INS->isCopyMode() && DOCKSCREEN_INS->current() != DOCKSCREEN_INS->primary()) || m_multiScreenWorker->hideMode() != HideMode::KeepShowing) { + lastRect = QRect(); + + if (Utils::IS_WAYLAND_DISPLAY) { + QList varList; + varList.append(0);//dock位置 + varList.append(0);//dock高度/宽度 + varList.append(0);//start值 + varList.append(0);//end值 + + // 此处只需获取左侧主窗口部分即可 + QPlatformWindow *windowHandle = mainWindow->windowHandle()->handle(); + if (windowHandle) + QGuiApplication::platformNativeInterface()->setWindowProperty(windowHandle, "_d_dwayland_dockstrut", varList); + + } else { + const auto display = QX11Info::display(); + if (!display) { + qWarning() << "QX11Info::display() is " << display; + return; + } + + XcbMisc::instance()->clear_strut_partial(xcb_window_t(mainWindow->winId())); + } + + return; + } + + QRect dockGeometry = getDockGeometry(true); + if (lastRect == dockGeometry + && lastScreenWidth == DIS_INS->screenRawWidth() + && lastScreenHeight == DIS_INS->screenRawHeight()) { + return; + } + + lastRect = dockGeometry; + lastScreenWidth = DIS_INS->screenRawWidth(); + lastScreenHeight = DIS_INS->screenRawHeight(); + qDebug() << "dock real geometry:" << dockGeometry; + qDebug() << "screen width:" << DIS_INS->screenRawWidth() << ", height:" << DIS_INS->screenRawHeight(); + + const qreal &ratio = qApp->devicePixelRatio(); + if (Utils::IS_WAYLAND_DISPLAY) { + QList varList = {0, 0, 0, 0}; + switch (m_position) { + case Position::Top: + varList[0] = 1; + varList[1] = dockGeometry.y() + dockGeometry.height() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.x(); + varList[3] = dockGeometry.x() + dockGeometry.width(); + break; + case Position::Bottom: + varList[0] = 3; + varList[1] = DIS_INS->screenRawHeight() - dockGeometry.y() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.x(); + varList[3] = dockGeometry.x() + dockGeometry.width(); + break; + case Position::Left: + varList[0] = 0; + varList[1] = dockGeometry.x() + dockGeometry.width() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.y(); + varList[3] = dockGeometry.y() + dockGeometry.height(); + break; + case Position::Right: + varList[0] = 2; + varList[1] = DIS_INS->screenRawWidth() - dockGeometry.x() + WINDOWMARGIN * ratio; + varList[2] = dockGeometry.y(); + varList[3] = dockGeometry.y() + dockGeometry.height(); + break; + } + + QPlatformWindow *windowHandle = mainWindow->windowHandle()->handle(); + if (windowHandle) { + QGuiApplication::platformNativeInterface()->setWindowProperty(windowHandle,"_d_dwayland_dockstrut", varList); + } + } else { + XcbMisc::Orientation orientation = XcbMisc::OrientationTop; + double strut = 0; + double strutStart = 0; + double strutEnd = 0; + + switch (m_position) { + case Position::Top: + orientation = XcbMisc::OrientationTop; + strut = dockGeometry.y() + dockGeometry.height(); + strutStart = dockGeometry.x(); + strutEnd = qMin(dockGeometry.x() + dockGeometry.width(), dockGeometry.right()); + break; + case Position::Bottom: + orientation = XcbMisc::OrientationBottom; + strut = DIS_INS->screenRawHeight() - dockGeometry.y(); + strutStart = dockGeometry.x(); + strutEnd = qMin(dockGeometry.x() + dockGeometry.width(), dockGeometry.right()); + break; + case Position::Left: + orientation = XcbMisc::OrientationLeft; + strut = dockGeometry.x() + dockGeometry.width(); + strutStart = dockGeometry.y(); + strutEnd = qMin(dockGeometry.y() + dockGeometry.height(), dockGeometry.bottom()); + break; + case Position::Right: + orientation = XcbMisc::OrientationRight; + strut = DIS_INS->screenRawWidth() - dockGeometry.x(); + strutStart = dockGeometry.y(); + strutEnd = qMin(dockGeometry.y() + dockGeometry.height(), dockGeometry.bottom()); + break; + } + + qDebug() << "set reserved area to xcb:" << strut << strutStart << strutEnd; + + const auto display = QX11Info::display(); + if (!display) { + qWarning() << "QX11Info::display() is " << display; + return; + } + + XcbMisc::instance()->set_strut_partial(static_cast(mainWindow->winId()), orientation, + static_cast(strut + WINDOWMARGIN * ratio), // 设置窗口与屏幕边缘距离,需要乘缩放 + static_cast(strutStart), // 设置任务栏起点坐标(上下为x,左右为y) + static_cast(strutEnd)); // 设置任务栏终点坐标(上下为x,左右为y) + } +} + +void WindowManager::onServiceRestart() +{ + for (MainWindowBase *mainWindow : m_topWindows) + mainWindow->serviceRestart(); +} diff --git a/frame/window/windowmanager.h b/frame/window/windowmanager.h new file mode 100644 index 000000000..a00f69a8b --- /dev/null +++ b/frame/window/windowmanager.h @@ -0,0 +1,84 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef WINDOWMANAGER_H +#define WINDOWMANAGER_H + +#include "constants.h" +#include "statusnotifierwatcher_interface.h" + +#include + +namespace Dtk {namespace Gui { class DWindowManagerHelper; }} + +class MainWindowBase; +class MainWindow; +class TrayMainWindow; +class MultiScreenWorker; +class MenuWorker; +class QDBusConnectionInterface; + +using namespace Dtk::Gui; + +class WindowManager : public QObject +{ + Q_OBJECT + +public: + explicit WindowManager(MultiScreenWorker *multiScreenWorker, QObject *parent = nullptr); + ~WindowManager() override; + + void addWindow(MainWindowBase *window); + void launch(); + void sendNotifications(); + void callShow(); + void resizeDock(int offset, bool dragging); + QRect geometry() const; + +Q_SIGNALS: + void panelGeometryChanged(); + +private: + void initConnection(); + void initSNIHost(); + void initMember(); + void updateMainGeometry(const Dock::HideState &hideState); + QParallelAnimationGroup *createAnimationGroup(const Dock::AniAction &aniAction, const QString &screenName, const Dock::Position &position) const; + + void showAniFinish(); + void animationFinish(bool showOrHide); + void hideAniFinish(); + QRect getDockGeometry(bool withoutScale = false) const; // 计算左右侧加起来的区域大小 + + void RegisterDdeSession(); + void updateDockGeometry(const QRect &rect); + +private Q_SLOTS: + void onUpdateDockGeometry(const Dock::HideMode &hideMode); + void onPositionChanged(const Dock::Position &position); + void onDisplayModeChanged(const Dock::DisplayMode &displayMode); + + void onDbusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); + + void onPlayAnimation(const QString &screenName, const Dock::Position &pos, Dock::AniAction act, bool containMouse = false, bool updatePos = false); + void onChangeDockPosition(QString fromScreen, QString toScreen, const Dock::Position &fromPos, const Dock::Position &toPos); + void onRequestUpdateFrontendGeometry(); + void onRequestNotifyWindowManager(); + + void onServiceRestart(); + +private: + MultiScreenWorker *m_multiScreenWorker; + QString m_sniHostService; + + Dock::DisplayMode m_displayMode; + Dock::Position m_position; + + QDBusConnectionInterface *m_dbusDaemonInterface; + org::kde::StatusNotifierWatcher *m_sniWatcher; // DBUS状态通知 + QList m_topWindows; +}; + +#endif // WINDOWMANAGER_H diff --git a/frame/xcb/xcb_misc.cpp b/frame/xcb/xcb_misc.cpp index a8330cec7..9627ff236 100644 --- a/frame/xcb/xcb_misc.cpp +++ b/frame/xcb/xcb_misc.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/frame/xcb/xcb_misc.h b/frame/xcb/xcb_misc.h index e0a8c60a8..821de9e40 100644 --- a/frame/xcb/xcb_misc.h +++ b/frame/xcb/xcb_misc.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/gschema/com.deepin.dde.dock.module.gschema.xml b/gschema/com.deepin.dde.dock.module.gschema.xml index a3cd77ed9..bb662789e 100644 --- a/gschema/com.deepin.dde.dock.module.gschema.xml +++ b/gschema/com.deepin.dde.dock.module.gschema.xml @@ -551,7 +551,7 @@ Control duration of dock switch in monitors - true + false Determine to show dock only in primary monitor diff --git a/interfaces/constants.h b/interfaces/constants.h index 4bd4ff68e..3fa66f24a 100644 --- a/interfaces/constants.h +++ b/interfaces/constants.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -10,9 +11,10 @@ namespace Dock { #define DOCK_PLUGIN_MIME "dock/plugin" -#define DOCK_PLUGIN_API_VERSION "1.2.3" +#define DOCK_PLUGIN_API_VERSION "2.0.0" #define PROP_DISPLAY_MODE "DisplayMode" +#define PROP_DOCK_DRAGING "isDraging" #define PLUGIN_BACKGROUND_MAX_SIZE 40 #define PLUGIN_BACKGROUND_MIN_SIZE 20 @@ -20,12 +22,18 @@ namespace Dock { #define PLUGIN_ICON_MAX_SIZE 20 #define PLUGIN_ITEM_WIDTH 300 +#define QUICK_PATH "/plugins/quick-trays" +#define PLUGIN_PATH "/plugins" +#define TRAY_PATH "/plugins/system-trays" + // 需求变更成插件图标始终保持20x20,但16x16的资源还在。所以暂时保留此宏 #define PLUGIN_ICON_MIN_SIZE 20 // 插件最小尺寸,图标采用深色 #define PLUGIN_MIN_ICON_NAME "-dark" +// dock最小尺寸 +#define DOCK_MIN_SIZE 40 // dock最大尺寸 #define DOCK_MAX_SIZE 100 /// @@ -47,7 +55,7 @@ enum DisplayMode { enum HideMode { KeepShowing = 0, KeepHidden = 1, - SmartHide = 3, + SmartHide = 2 }; #define PROP_POSITION "Position" @@ -75,6 +83,11 @@ enum HideState { Hide = 2, }; +enum class AniAction { + Show = 0, + Hide +}; + #define IS_TOUCH_STATE "isTouchState" } diff --git a/interfaces/pluginmanagerinterface.h b/interfaces/pluginmanagerinterface.h new file mode 100644 index 000000000..fe97fd130 --- /dev/null +++ b/interfaces/pluginmanagerinterface.h @@ -0,0 +1,29 @@ +// Copyright (C) 2023 ~ 2023 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef PLUGINMANAGERINTERFACE_H +#define PLUGINMANAGERINTERFACE_H + +#include +#include + +class PluginsItemInterface; + +class PluginManagerInterface : public QObject +{ + Q_OBJECT + +public: + virtual QList plugins() const = 0; + virtual QList pluginsInSetting() const = 0; + virtual QList currentPlugins() const = 0; + virtual QString itemKey(PluginsItemInterface *itemInter) const = 0; + virtual QJsonObject metaData(PluginsItemInterface *itemInter) const = 0; + +Q_SIGNALS: + void pluginLoadFinished(); +}; + +#endif // PLUGINMANAGERINTERFACE_H diff --git a/interfaces/pluginproxyinterface.h b/interfaces/pluginproxyinterface.h index 60ca93931..224f5642d 100644 --- a/interfaces/pluginproxyinterface.h +++ b/interfaces/pluginproxyinterface.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -10,6 +11,8 @@ #include class PluginsItemInterface; +enum class DockPart; + class PluginProxyInterface { public: @@ -40,6 +43,7 @@ public: /// \param itemKey /// virtual void itemRemoved(PluginsItemInterface * const itemInter, const QString &itemKey) = 0; + /// /// \brief requestContextMenu /// request show context menu @@ -76,6 +80,12 @@ public: /// SeeAlse: saveValue /// virtual void removeValue(PluginsItemInterface *const itemInter, const QStringList &keyList) = 0; + + /// + /// update display or information + /// + /// + virtual void updateDockInfo(PluginsItemInterface *const, const DockPart &) {} }; #endif // PLUGINPROXYINTERFACE_H diff --git a/interfaces/pluginsiteminterface.h b/interfaces/pluginsiteminterface.h index c8b8eb511..2d62354d7 100644 --- a/interfaces/pluginsiteminterface.h +++ b/interfaces/pluginsiteminterface.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,14 +8,52 @@ #include "pluginproxyinterface.h" +#include + #include #include +DGUI_USE_NAMESPACE + +// 任务栏的部件位置 +enum class DockPart { + QuickShow = 0, // 快捷插件显示区域 + QuickPanel, // 快捷面板区域 + SystemPanel, // 系统插件显示区域 + DCCSetting // 显示在控制中心个性化设置的图标 +}; + +enum PluginFlag { + Type_NoneFlag = 0x1, // 插件类型-没有任何的属性,不在任何地方显示 + Type_Common = 0x2, // 插件类型-快捷插件区 + Type_Tool = 0x4, // 插件类型-工具插件,例如回收站 + Type_System = 0x8, // 插件类型-系统插件,例如关机插件 + Type_Tray = 0x10, // 插件类型-托盘区,例如U盘插件 + Type_Fixed = 0x20, // 插件类型-固定区域,例如多任务视图和显示桌面 + + Quick_Single = 0x40, // 当插件类型为Common时,快捷插件区域只有一列的那种插件 + Quick_Multi = 0x80, // 当插件类型为Common时,快捷插件区占两列的那种插件 + Quick_Full = 0x100, // 当插件类型为Common时,快捷插件区占用4列的那种插件,例如声音、亮度设置和音乐等 + + Attribute_CanDrag = 0x200, // 插件属性-是否支持拖动 + Attribute_CanInsert = 0x400, // 插件属性-是否支持在其前面插入其他的插件,普通的快捷插件是支持的 + Attribute_CanSetting = 0x800, // 插件属性-是否可以在控制中心设置显示或隐藏 + Attribute_ForceDock = 0x1000, // 插件属性-强制显示在任务栏上 + + FlagMask = 0xffffffff // 掩码 +}; + +Q_DECLARE_FLAGS(PluginFlags, PluginFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(PluginFlags) + +// 快捷面板详情页面的itemWidget对应的itemKey +#define QUICK_ITEM_KEY "quick_item_key" /// /// \brief The PluginsItemInterface class /// the dock plugins item interface, all dock plugins should /// inheirt this class and override all pure virtual function. /// + class PluginsItemInterface { public: @@ -31,6 +70,12 @@ public: Custom = 1 << 1 // The custom }; + enum PluginMode { + Deactive = 0, + Active, + Disabled + }; + /// /// \brief ~PluginsItemInterface /// DON'T try to delete m_proxyInter. @@ -226,6 +271,36 @@ public: /// virtual PluginSizePolicy pluginSizePolicy() const { return System; } + /// + /// the plugin status + /// + /// + virtual PluginMode status() const { return PluginMode::Deactive; } + + /// + /// return the detail value, it will display in the center + /// + /// + virtual QString description() const { return QString(); } + + /// + /// the icon for the plugin + /// themeType {0:UnknownType 1:LightType 2:DarkType} + /// + virtual QIcon icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType = DGuiApplicationHelper::instance()->themeType()) { return QIcon(); } + + /// + /// \brief m_proxyInter + /// return the falgs for current plugin + /// + virtual PluginFlags flags() const { return PluginFlag::Type_Common | PluginFlag::Quick_Single | PluginFlag::Attribute_CanDrag | PluginFlag::Attribute_CanInsert | PluginFlag::Attribute_CanSetting; } + + /// + /// \brief m_proxyInter + /// + /// + virtual bool eventHandler(QEvent *event) { return false; } + protected: /// /// \brief m_proxyInter @@ -236,7 +311,7 @@ protected: QT_BEGIN_NAMESPACE -#define ModuleInterface_iid "com.deepin.dock.PluginsItemInterface" +#define ModuleInterface_iid "com.deepin.dock.PluginsItemInterface_2_0_0" Q_DECLARE_INTERFACE(PluginsItemInterface, ModuleInterface_iid) QT_END_NAMESPACE diff --git a/lupdate.sh b/lupdate.sh index 8faa1d0b0..993e032b5 100755 --- a/lupdate.sh +++ b/lupdate.sh @@ -2,6 +2,6 @@ cp ".transifexrc" ${HOME}/ lupdate ./ -ts -no-obsolete translations/dde-dock.ts -lupdate ./ -ts -no-obsolete plugins/dcc-dock-plugin/translations/dcc-dock-plugin.ts +#lupdate ./ -ts -no-obsolete plugins/dcc-dock-plugin/translations/dcc-dock-plugin.ts -tx push -s -b m20 +tx push -s -b m23 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 0876aacbb..bb7858de3 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,9 +1,10 @@ -add_subdirectory("datetime") -#add_subdirectory("disk-mount") +#add_subdirectory("datetime") add_subdirectory("shutdown") add_subdirectory("power") add_subdirectory("sound") -add_subdirectory("tray") +add_subdirectory("display") +add_subdirectory("media") +add_subdirectory("pluginmanager") add_subdirectory("trash") add_subdirectory("keyboard-layout") add_subdirectory("onboard") @@ -11,5 +12,4 @@ add_subdirectory("overlay-warning") add_subdirectory("show-desktop") add_subdirectory("multitasking") add_subdirectory("bluetooth") -add_subdirectory("dcc-dock-plugin") add_subdirectory("airplane-mode") diff --git a/plugins/airplane-mode/CMakeLists.txt b/plugins/airplane-mode/CMakeLists.txt index 35df5c525..fa4b51fc5 100644 --- a/plugins/airplane-mode/CMakeLists.txt +++ b/plugins/airplane-mode/CMakeLists.txt @@ -3,8 +3,17 @@ set(PLUGIN_NAME "airplane-mode") project(${PLUGIN_NAME}) +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + # Sources files -file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp" "../../frame/util/imageutil.h" "../../frame/util/imageutil.cpp") +file(GLOB_RECURSE SRCS "*.h" + "*.cpp" + "../../widgets/tipswidget.h" + "../../widgets/tipswidget.cpp" + "../../frame/util/imageutil.h" + "../../frame/util/imageutil.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) @@ -13,28 +22,27 @@ find_package(Qt5DBus REQUIRED) find_package(DtkWidget REQUIRED) pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) pkg_check_modules(QGSettings REQUIRED gsettings-qt) add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") add_library(${PLUGIN_NAME} SHARED ${SRCS} resources/airplane_mode.qrc) -set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../system-trays) +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ..) + target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} ${QGSettings_INCLUDE_DIRS} ../../interfaces ../../widgets ../../frame ../../frame/util - ) + ../../frame/qtdbusextended + ./dbusinterface/generation_dbus_interface) + target_link_libraries(${PLUGIN_NAME} PRIVATE ${XCB_EWMH_LIBRARIES} ${DtkWidget_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} ${QGSettings_LIBRARIES} ${Qt5DBus_LIBRARIES} ${Qt5Widgets_LIBRARIES} - ${Qt5Svg_LIBRARIES} -) + ${Qt5Svg_LIBRARIES}) -install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/system-trays) +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins) diff --git a/plugins/airplane-mode/airplanemode.json b/plugins/airplane-mode/airplanemode.json index cbfdea8e9..cc6819b7a 100644 --- a/plugins/airplane-mode/airplanemode.json +++ b/plugins/airplane-mode/airplanemode.json @@ -1,4 +1,4 @@ { - "api": "1.1.1", + "api": "2.0.0", "depends-daemon-dbus-service": "" } diff --git a/plugins/airplane-mode/airplanemodeapplet.cpp b/plugins/airplane-mode/airplanemodeapplet.cpp index f9904ed81..241bb10b4 100644 --- a/plugins/airplane-mode/airplanemodeapplet.cpp +++ b/plugins/airplane-mode/airplanemodeapplet.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2020 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -16,14 +17,10 @@ AirplaneModeApplet::AirplaneModeApplet(QWidget *parent) : QWidget(parent) , m_switchBtn(new DSwitchButton(this)) { - setMinimumWidth(PLUGIN_ITEM_WIDTH - 40); - setFixedHeight(40); + setMinimumWidth(PLUGIN_ITEM_WIDTH); + setFixedHeight(30); QLabel *title = new QLabel(this); title->setText(tr("Airplane Mode")); - QFont font; - font.setPixelSize(17); - title->setFont(font); - title->setForegroundRole(QPalette::BrightText); QHBoxLayout *appletlayout = new QHBoxLayout(this); appletlayout->setMargin(0); appletlayout->setSpacing(0); @@ -32,8 +29,8 @@ AirplaneModeApplet::AirplaneModeApplet(QWidget *parent) appletlayout->addStretch(); appletlayout->addWidget(m_switchBtn); appletlayout->addSpacing(0); - appletlayout->setContentsMargins(20, 0, 6, 0); setLayout(appletlayout); + connect(m_switchBtn, &DSwitchButton::checkedChanged, this, &AirplaneModeApplet::enableChanged); } diff --git a/plugins/airplane-mode/airplanemodeapplet.h b/plugins/airplane-mode/airplanemodeapplet.h index 1cc53bc11..e2567f432 100644 --- a/plugins/airplane-mode/airplanemodeapplet.h +++ b/plugins/airplane-mode/airplanemodeapplet.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2020 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/airplane-mode/airplanemodeitem.cpp b/plugins/airplane-mode/airplanemodeitem.cpp index 89317eb5e..9b3e361fe 100644 --- a/plugins/airplane-mode/airplanemodeitem.cpp +++ b/plugins/airplane-mode/airplanemodeitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2020 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -15,7 +16,6 @@ #include #include #include -#include DGUI_USE_NAMESPACE @@ -26,8 +26,8 @@ AirplaneModeItem::AirplaneModeItem(QWidget *parent) : QWidget(parent) , m_tipsLabel(new Dock::TipsWidget(this)) , m_applet(new AirplaneModeApplet(this)) - , m_airplaneModeInter(new DBusAirplaneMode("com.deepin.daemon.AirplaneMode", - "/com/deepin/daemon/AirplaneMode", + , m_airplaneModeInter(new DBusAirplaneMode("org.deepin.dde.AirplaneMode1", + "/org/deepin/dde/AirplaneMode1", QDBusConnection::systemBus(), this)) { @@ -92,17 +92,19 @@ void AirplaneModeItem::invokeMenuItem(const QString menuId, const bool checked) Q_UNUSED(menuId); Q_UNUSED(checked); + /* 控制中心暂未实现 if (menuId == SHIFT) m_airplaneModeInter->Enable(!m_airplaneModeInter->enabled()); else if (menuId == SETTINGS) DDBusSender() - .service("com.deepin.dde.ControlCenter") - .interface("com.deepin.dde.ControlCenter") - .path("/com/deepin/dde/ControlCenter") + .service("org.deepin.dde.ControlCenter1") + .interface("org.deepin.dde.ControlCenter1") + .path("/org/deepin/dde/ControlCenter1") .method(QString("ShowPage")) .arg(QString("network")) .arg(QString("Airplane Mode")) .call(); + */ } void AirplaneModeItem::refreshIcon() @@ -113,14 +115,11 @@ void AirplaneModeItem::refreshIcon() else iconString = "airplane-off"; + const auto ratio = devicePixelRatioF(); + int iconSize = PLUGIN_ICON_MAX_SIZE; if (height() <= PLUGIN_BACKGROUND_MIN_SIZE && DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) iconString.append(PLUGIN_MIN_ICON_NAME); - - const auto ratio = devicePixelRatioF(); - QSize pixmapSize = QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? QSize(20, 20) : (QSize(20, 20) * ratio); - m_iconPixmap = QIcon::fromTheme(iconString, QIcon::fromTheme("://" + iconString + ".svg")).pixmap(pixmapSize); - m_iconPixmap.setDevicePixelRatio(ratio); - + m_iconPixmap = ImageUtil::loadSvg(iconString, ":/", iconSize, ratio); update(); } @@ -157,10 +156,8 @@ void AirplaneModeItem::paintEvent(QPaintEvent *e) { QWidget::paintEvent(e); - const auto ratio = devicePixelRatioF(); - QPainter painter(this); const QRectF &rf = QRectF(rect()); const QRectF &rfp = QRectF(m_iconPixmap.rect()); - painter.drawPixmap(rf.center() - rfp.center() / ratio, m_iconPixmap); + painter.drawPixmap(rf.center() - rfp.center() / m_iconPixmap.devicePixelRatioF(), m_iconPixmap); } diff --git a/plugins/airplane-mode/airplanemodeitem.h b/plugins/airplane-mode/airplanemodeitem.h index 781164bb8..e08059bac 100644 --- a/plugins/airplane-mode/airplanemodeitem.h +++ b/plugins/airplane-mode/airplanemodeitem.h @@ -1,15 +1,16 @@ -// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2020 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef AIRPLANEMODEITEM_H #define AIRPLANEMODEITEM_H -#include +#include "org_deepin_dde_airplanemode1.h" #include -using DBusAirplaneMode = com::deepin::daemon::AirplaneMode; +using DBusAirplaneMode = org::deepin::dde::AirplaneMode1; namespace Dock { class TipsWidget; diff --git a/plugins/airplane-mode/airplanemodeplugin.cpp b/plugins/airplane-mode/airplanemodeplugin.cpp index 946a6c290..3e8250d74 100644 --- a/plugins/airplane-mode/airplanemodeplugin.cpp +++ b/plugins/airplane-mode/airplanemodeplugin.cpp @@ -1,22 +1,19 @@ -// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2020 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "airplanemodeplugin.h" #include "airplanemodeitem.h" -#include #define AIRPLANEMODE_KEY "airplane-mode-key" #define STATE_KEY "enable" -DCORE_USE_NAMESPACE AirplaneModePlugin::AirplaneModePlugin(QObject *parent) : QObject(parent) , m_item(new AirplaneModeItem) - , m_dconfig(DConfig::create("org.deepin.dde.network", "org.deepin.dde.network", QString(), this)) { connect(m_item, &AirplaneModeItem::airplaneEnableChanged, this, &AirplaneModePlugin::onAirplaneEnableChanged); - connect(m_dconfig, &DConfig::valueChanged, this, &AirplaneModePlugin::onWirelessAccessPointsOrAdapterChange); } const QString AirplaneModePlugin::pluginName() const @@ -31,38 +28,21 @@ const QString AirplaneModePlugin::pluginDisplayName() const void AirplaneModePlugin::init(PluginProxyInterface *proxyInter) { + if (m_proxyInter == proxyInter) + return; + m_proxyInter = proxyInter; - if (getAirplaneDconfig()) { - m_networkInter = new NetworkInter("com.deepin.daemon.Network", "/com/deepin/daemon/Network", QDBusConnection::sessionBus(), this); - connect(m_networkInter, &NetworkInter::WirelessAccessPointsChanged, this, &AirplaneModePlugin::onWirelessAccessPointsOrAdapterChange); - - m_bluetoothInter = new BluetoothInter("com.deepin.daemon.Bluetooth", "/com/deepin/daemon/Bluetooth", QDBusConnection::sessionBus(), this); - connect(m_bluetoothInter, &BluetoothInter::AdapterAdded, this, &AirplaneModePlugin::onWirelessAccessPointsOrAdapterChange); - connect(m_bluetoothInter, &BluetoothInter::AdapterRemoved, this, &AirplaneModePlugin::onWirelessAccessPointsOrAdapterChange); - } - - if (!pluginIsDisable()) { - if (supportAirplaneMode()) { - m_proxyInter->itemAdded(this, AIRPLANEMODE_KEY); - } - } + m_proxyInter->itemAdded(this, AIRPLANEMODE_KEY); refreshAirplaneEnableState(); } void AirplaneModePlugin::pluginStateSwitched() { - m_proxyInter->saveValue(this, STATE_KEY, pluginIsDisable()); - refreshAirplaneEnableState(); } -bool AirplaneModePlugin::pluginIsDisable() -{ - return !m_proxyInter->getValue(this, STATE_KEY, true).toBool(); -} - QWidget *AirplaneModePlugin::itemWidget(const QString &itemKey) { if (itemKey == AIRPLANEMODE_KEY) { @@ -81,39 +61,6 @@ QWidget *AirplaneModePlugin::itemTipsWidget(const QString &itemKey) return nullptr; } -QWidget *AirplaneModePlugin::itemPopupApplet(const QString &itemKey) -{ - if (!supportAirplaneMode()) { - return nullptr; - } - - if (itemKey == AIRPLANEMODE_KEY) { - return m_item->popupApplet(); - } - - return nullptr; -} - -const QString AirplaneModePlugin::itemContextMenu(const QString &itemKey) -{ - if (!supportAirplaneMode()) { - return QString(); - } - - if (itemKey == AIRPLANEMODE_KEY) { - return m_item->contextMenu(); - } - - return QString(); -} - -void AirplaneModePlugin::invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) -{ - if (itemKey == AIRPLANEMODE_KEY) { - m_item->invokeMenuItem(menuId, checked); - } -} - int AirplaneModePlugin::itemSortKey(const QString &itemKey) { const QString key = QString("pos_%1_%2").arg(itemKey).arg(Dock::Efficient); @@ -145,90 +92,14 @@ void AirplaneModePlugin::onAirplaneEnableChanged(bool enable) if (!m_proxyInter) return; - if (supportAirplaneMode()) { + if (enable) { m_proxyInter->itemAdded(this, AIRPLANEMODE_KEY); - if (enable) { - m_proxyInter->saveValue(this, STATE_KEY, true); - } - else { - m_proxyInter->saveValue(this, STATE_KEY, false); - } - } else { - if (enable) { - m_proxyInter->itemAdded(this, AIRPLANEMODE_KEY); - } else { - m_proxyInter->itemRemoved(this, AIRPLANEMODE_KEY); - } + m_proxyInter->saveValue(this, STATE_KEY, true); } -} - -void AirplaneModePlugin::onWirelessAccessPointsOrAdapterChange() -{ - if (!supportAirplaneMode()) { + else { m_proxyInter->itemRemoved(this, AIRPLANEMODE_KEY); - } else { - m_proxyInter->itemAdded(this, AIRPLANEMODE_KEY); + m_proxyInter->saveValue(this, STATE_KEY, false); } } -bool AirplaneModePlugin::supportAirplaneMode() const -{ - // dde-dconfig配置优先级高于设备优先级 - bool bAirplane = false; - if (m_dconfig && m_dconfig->isValid()) { - bAirplane = m_dconfig->value("networkAirplaneMode", false).toBool(); - } - if (!bAirplane) { - return bAirplane; - } - - // 蓝牙和无线网络,只要有其中一个就允许显示飞行模式 - QDBusInterface inter("com.deepin.system.Bluetooth", - "/com/deepin/system/Bluetooth", - "com.deepin.system.Bluetooth", - QDBusConnection::systemBus()); - if (inter.isValid()) { - QDBusReply reply = inter.call("GetAdapters"); - QString replyStr = reply.value(); - QJsonDocument json = QJsonDocument::fromJson(replyStr.toUtf8()); - QJsonArray array = json.array(); - if (array.size() > 0 && !array[0].toObject()["Path"].toString().isEmpty()) { - return true; - } - } - - QDBusInterface networkInter("org.freedesktop.NetworkManager", - "/org/freedesktop/NetworkManager", - "org.freedesktop.NetworkManager", - QDBusConnection::systemBus()); - if (networkInter.isValid()) { - QDBusReply> reply = networkInter.call("GetAllDevices"); - QList replyStrList = reply.value(); - for (QDBusObjectPath objPath : replyStrList) { - QDBusInterface deviceInter("org.freedesktop.NetworkManager", - objPath.path(), - "org.freedesktop.NetworkManager.Device", - QDBusConnection::systemBus()); - if (deviceInter.isValid()) { - QVariant reply = deviceInter.property("DeviceType"); - // 2 NM_DEVICE_TYPE_WIFI - if (2 == reply.toUInt()) { - return true; - } - } - } - } - - return false; -} - -bool AirplaneModePlugin::getAirplaneDconfig() const -{ - bool airplane = false; - if (m_dconfig && m_dconfig->isValid()) { - airplane = m_dconfig->value("networkAirplaneMode", false).toBool(); - } - return airplane; -} - diff --git a/plugins/airplane-mode/airplanemodeplugin.h b/plugins/airplane-mode/airplanemodeplugin.h index e10f3a392..750f19f39 100644 --- a/plugins/airplane-mode/airplanemodeplugin.h +++ b/plugins/airplane-mode/airplanemodeplugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2020 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,15 +7,6 @@ #define AIRPLANEMODEPLUGIN_H #include "pluginsiteminterface.h" -#include "com_deepin_daemon_network.h" -#include "com_deepin_daemon_bluetooth.h" -#include "dtkcore_global.h" - -using NetworkInter = com::deepin::daemon::Network; -using BluetoothInter = com::deepin::daemon::Bluetooth; -DCORE_BEGIN_NAMESPACE -class DConfig; -DCORE_END_NAMESPACE class AirplaneModeItem; class AirplaneModePlugin : public QObject, PluginsItemInterface @@ -31,30 +23,18 @@ public: void init(PluginProxyInterface *proxyInter) Q_DECL_OVERRIDE; void pluginStateSwitched() Q_DECL_OVERRIDE; bool pluginIsAllowDisable() Q_DECL_OVERRIDE { return true; } - bool pluginIsDisable() Q_DECL_OVERRIDE; QWidget *itemWidget(const QString &itemKey) Q_DECL_OVERRIDE; QWidget *itemTipsWidget(const QString &itemKey) Q_DECL_OVERRIDE; - QWidget *itemPopupApplet(const QString &itemKey) Q_DECL_OVERRIDE; - const QString itemContextMenu(const QString &itemKey) Q_DECL_OVERRIDE; - void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) Q_DECL_OVERRIDE; int itemSortKey(const QString &itemKey) Q_DECL_OVERRIDE; void setSortKey(const QString &itemKey, const int order) Q_DECL_OVERRIDE; void refreshIcon(const QString &itemKey) Q_DECL_OVERRIDE; -private: - bool supportAirplaneMode() const; - bool getAirplaneDconfig() const; - public slots: void refreshAirplaneEnableState(); void onAirplaneEnableChanged(bool enable); - void onWirelessAccessPointsOrAdapterChange(); private: AirplaneModeItem *m_item; - NetworkInter *m_networkInter; - BluetoothInter *m_bluetoothInter; - DTK_CORE_NAMESPACE::DConfig *m_dconfig; }; #endif // AIRPLANEMODEPLUGIN_H diff --git a/plugins/airplane-mode/dbusinterface/xml/org.deepin.dde.AirplaneMode1.xml b/plugins/airplane-mode/dbusinterface/xml/org.deepin.dde.AirplaneMode1.xml new file mode 100644 index 000000000..31a4284b4 --- /dev/null +++ b/plugins/airplane-mode/dbusinterface/xml/org.deepin.dde.AirplaneMode1.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/bluetooth/CMakeLists.txt b/plugins/bluetooth/CMakeLists.txt index fe091ff8c..5cd2a03ec 100644 --- a/plugins/bluetooth/CMakeLists.txt +++ b/plugins/bluetooth/CMakeLists.txt @@ -3,11 +3,21 @@ set(PLUGIN_NAME "bluetooth") project(${PLUGIN_NAME}) +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + # Sources files -file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp" - "../../frame/util/imageutil.h" "../../frame/util/imageutil.cpp" - "../../frame/util/statebutton.h" "../../frame/util/statebutton.cpp" - "../../frame/util/horizontalseperator.h" "../../frame/util/horizontalseperator.cpp") +file(GLOB_RECURSE SRCS "*.h" + "*.cpp" + "../../widgets/tipswidget.h" + "../../widgets/tipswidget.cpp" + "../../frame/util/imageutil.h" + "../../frame/util/imageutil.cpp" + "../../frame/util/statebutton.h" + "../../frame/util/statebutton.cpp" + "../../frame/util/horizontalseperator.h" + "../../frame/util/horizontalseperator.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) @@ -16,27 +26,26 @@ find_package(Qt5DBus REQUIRED) find_package(DtkWidget REQUIRED) pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) pkg_check_modules(QGSettings REQUIRED gsettings-qt) add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") add_library(${PLUGIN_NAME} SHARED ${SRCS} resources/bluetooth.qrc) -set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../system-trays) +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../quick-trays) target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} ${QGSettings_INCLUDE_DIRS} ../../interfaces ../../frame + ../../frame/qtdbusextended + ./dbusinterface/generation_dbus_interface componments) target_link_libraries(${PLUGIN_NAME} PRIVATE ${XCB_EWMH_LIBRARIES} ${DtkWidget_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} ${QGSettings_LIBRARIES} ${Qt5DBus_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Svg_LIBRARIES} ) -install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/system-trays) +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/quick-trays) diff --git a/plugins/bluetooth/bloothadapterwidget.cpp b/plugins/bluetooth/bloothadapterwidget.cpp new file mode 100644 index 000000000..d9d46e3a6 --- /dev/null +++ b/plugins/bluetooth/bloothadapterwidget.cpp @@ -0,0 +1,195 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "bloothadapterwidget.h" +#include "adapter.h" +#include "device.h" + +#include +#include + +#define ITEMHEIGHT 45 + +BloothAdapterWidget::BloothAdapterWidget(Adapter *adapter, QWidget *parent) + : QWidget(parent) + , m_adapter(adapter) + , m_myDeviceLabel(new QLabel(tr("My Devices"), this)) + , m_myDeviceView(new DListView(this)) + , m_otherDeviceLabel(new QLabel(tr("Other Devices"), this)) + , m_otherDeviceView(new DListView(this)) + , m_myDeviceModel(new QStandardItemModel(this)) + , m_otherDeviceModel(new QStandardItemModel(this)) +{ + initUi(); + initConnection(); + initDevice(); +} + +Adapter *BloothAdapterWidget::adapter() +{ + return m_adapter; +} + +void BloothAdapterWidget::onDeviceAdded(const Device *device) +{ + if (device->name().isEmpty()) + return; + + DStandardItem *deviceItem = new DStandardItem; + deviceItem->setData(QVariant::fromValue(const_cast(device)), Dtk::UserRole + 1); + deviceItem->setText(device->name()); + if (device->paired()) { + // 我的设备 + m_myDeviceModel->insertRow(0, deviceItem); + } else { + // 其他设备 + m_otherDeviceModel->insertRow(0, deviceItem); + } + + updateDeviceVisible(); +} + +void BloothAdapterWidget::onDeviceRemoved(const Device *device) +{ + auto removeDeviceItem = [ = ](QStandardItemModel *model) { + for (int i = 0; i < model->rowCount(); i++) { + Device *tmpDevice = model->item(i)->data(Dtk::UserRole + 1).value(); + if (tmpDevice == device) { + model->removeRow(i); + return true; + } + } + + return false; + }; + + if (!removeDeviceItem(m_myDeviceModel)) + removeDeviceItem(m_otherDeviceModel); + + updateDeviceVisible(); +} + +void BloothAdapterWidget::onDeviceNameUpdated(const Device *device) const +{ + auto findDeviceItem = [ = ](QStandardItemModel *model)->DStandardItem * { + for (int i = 0; i < model->rowCount(); i++) { + DStandardItem *item = static_cast(model->item(i)); + Device *tmpDevice = item->data(Dtk::UserRole + 1).value(); + if (tmpDevice == device) { + return item; + } + } + + return nullptr; + }; + DStandardItem *item = findDeviceItem(m_myDeviceModel); + if (!item) + item = findDeviceItem(m_otherDeviceModel); + if (item) + item->setText(device->name()); +} + +void BloothAdapterWidget::onPoweredChanged(const bool powered) +{ + initDevice(); + updateDeviceVisible(); +} + +void BloothAdapterWidget::onOtherClicked(const QModelIndex &index) +{ + Device *device = index.data(Dtk::UserRole + 1).value(); + if (!device || device->state() == Device::State::StateConnected) + return; + + if (device->deviceType() == "audio-card" + && device->state() == Device::State::StateAvailable + && device->deviceType() == "pheadset") { + return; + } + + Q_EMIT requestConnectDevice(device); +} + +void BloothAdapterWidget::initUi() +{ + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + mainLayout->addWidget(m_myDeviceLabel); + mainLayout->addWidget(m_myDeviceView); + mainLayout->addSpacing(20); + mainLayout->addWidget(m_otherDeviceLabel); + mainLayout->addSpacing(6); + mainLayout->addWidget(m_otherDeviceView); + + m_myDeviceLabel->setVisible(false); + m_myDeviceView->setVisible(false); + m_myDeviceView->setModel(m_myDeviceModel); + m_myDeviceView->setFixedHeight(0); + m_myDeviceView->setItemSpacing(5); + + m_otherDeviceLabel->setVisible(false); + m_otherDeviceView->setVisible(false); + m_otherDeviceView->setModel(m_otherDeviceModel); + m_otherDeviceView->setFixedHeight(0); + m_otherDeviceView->setItemSpacing(5); +} + +void BloothAdapterWidget::initConnection() +{ + connect(m_adapter, &Adapter::deviceAdded, this, &BloothAdapterWidget::onDeviceAdded); + connect(m_adapter, &Adapter::deviceRemoved, this, &BloothAdapterWidget::onDeviceRemoved); + connect(m_adapter, &Adapter::deviceNameUpdated, this, &BloothAdapterWidget::onDeviceNameUpdated); + connect(m_adapter, &Adapter::poweredChanged, this, &BloothAdapterWidget::onPoweredChanged); + + connect(m_otherDeviceView, &DListView::clicked, this, &BloothAdapterWidget::onOtherClicked); +} + +void BloothAdapterWidget::initDevice() +{ + m_myDeviceModel->clear(); + m_otherDeviceModel->clear(); + QMap devices = m_adapter->devices(); + for (auto it = devices.begin(); it != devices.end(); it++) + onDeviceAdded(it.value()); +} + +void BloothAdapterWidget::adjustHeight() +{ + int height = m_myDeviceView->height() + 20 + m_otherDeviceView->height() + 5; + + if (m_myDeviceLabel->isVisible()) + height += m_myDeviceLabel->height(); + if (m_otherDeviceLabel->isVisible()) + height += m_otherDeviceLabel->height(); + + setFixedHeight(height); +} + +void BloothAdapterWidget::updateDeviceVisible() +{ + bool powered = m_adapter->powered(); + if (powered) { + m_myDeviceLabel->setVisible(m_myDeviceModel->rowCount() > 0); + m_myDeviceView->setVisible(m_myDeviceModel->rowCount() > 0); + m_myDeviceView->setFixedHeight(std::min(m_myDeviceModel->rowCount(), 10) * ITEMHEIGHT); + + m_otherDeviceLabel->setVisible(m_adapter->powered() && m_otherDeviceModel->rowCount() > 0); + m_otherDeviceView->setVisible(m_adapter->powered() && m_otherDeviceModel->rowCount() > 0); + m_otherDeviceView->setFixedHeight(std::min(m_otherDeviceModel->rowCount(), 10) * ITEMHEIGHT); + } else { + m_myDeviceLabel->setVisible(false); + m_myDeviceView->setVisible(false); + m_myDeviceView->setFixedHeight(0); + + m_otherDeviceLabel->setVisible(false); + m_otherDeviceView->setVisible(false); + m_otherDeviceView->setFixedHeight(0); + } + + adjustHeight(); + Q_EMIT requestUpdate(); + +} diff --git a/plugins/bluetooth/bloothadapterwidget.h b/plugins/bluetooth/bloothadapterwidget.h new file mode 100644 index 000000000..4a9098b09 --- /dev/null +++ b/plugins/bluetooth/bloothadapterwidget.h @@ -0,0 +1,58 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef BLOOTHADAPTERWIDGET_H +#define BLOOTHADAPTERWIDGET_H + +#include + +#include + +class Adapter; +class QLabel; +class Device; +class QStandardItemModel; + +using namespace Dtk::Widget; + +class BloothAdapterWidget : public QWidget +{ + Q_OBJECT + +public: + explicit BloothAdapterWidget(Adapter *adapter, QWidget *parent = nullptr); + + Adapter *adapter(); + +Q_SIGNALS: + void requestConnectDevice(Device *device); + void requestUpdate() const; + +protected Q_SLOTS: + void onDeviceAdded(const Device *device); + void onDeviceRemoved(const Device *device); + void onDeviceNameUpdated(const Device *device) const; + void onPoweredChanged(const bool powered); + + void onOtherClicked(const QModelIndex &index); + +private: + void initUi(); + void initConnection(); + void initDevice(); + void adjustHeight(); + void updateDeviceVisible(); + +private: + Adapter *m_adapter; + QLabel *m_myDeviceLabel; + DListView *m_myDeviceView; + QLabel *m_otherDeviceLabel; + DListView *m_otherDeviceView; + QStandardItemModel *m_myDeviceModel; + QStandardItemModel *m_otherDeviceModel; +}; + +#endif // BLOOTHADAPTERWIDGET_H diff --git a/plugins/bluetooth/bluetooth.json b/plugins/bluetooth/bluetooth.json index 5b1e078b2..eb60829b1 100644 --- a/plugins/bluetooth/bluetooth.json +++ b/plugins/bluetooth/bluetooth.json @@ -1,4 +1,4 @@ { - "api": "1.1.1", - "depends-daemon-dbus-service": "com.deepin.daemon.Bluetooth" + "api": "2.0.0", + "depends-daemon-dbus-service": "org.deepin.dde.Bluetooth1" } diff --git a/plugins/bluetooth/bluetoothitem.cpp b/plugins/bluetooth/bluetoothitem.cpp index 803c0bd62..2840cc086 100644 --- a/plugins/bluetooth/bluetoothitem.cpp +++ b/plugins/bluetooth/bluetoothitem.cpp @@ -1,8 +1,10 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "bluetoothitem.h" +#include "adaptersmanager.h" #include "constants.h" #include "../widgets/tipswidget.h" #include "../frame/util/imageutil.h" @@ -11,6 +13,7 @@ #include #include #include +#include #include @@ -23,10 +26,10 @@ DGUI_USE_NAMESPACE using namespace Dock; -BluetoothItem::BluetoothItem(QWidget *parent) +BluetoothItem::BluetoothItem(AdaptersManager *adapterManager, QWidget *parent) : QWidget(parent) , m_tipsLabel(new TipsWidget(this)) - , m_applet(new BluetoothApplet(this)) + , m_applet(new BluetoothApplet(adapterManager, this)) , m_devState(Device::State::StateUnavailable) , m_adapterPowered(m_applet->poweredInitState()) { @@ -47,6 +50,7 @@ BluetoothItem::BluetoothItem(QWidget *parent) connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &BluetoothItem::refreshIcon); connect(m_applet, &BluetoothApplet::noAdapter, this, &BluetoothItem::noAdapter); connect(m_applet, &BluetoothApplet::justHasAdapter, this, &BluetoothItem::justHasAdapter); + connect(m_applet, &BluetoothApplet::requestHide, this, &BluetoothItem::requestHide); } QWidget *BluetoothItem::tipsWidget() @@ -100,10 +104,10 @@ void BluetoothItem::invokeMenuItem(const QString menuId, const bool checked) m_applet->setAdapterPowered(!m_adapterPowered); } else if (menuId == SETTINGS) { DDBusSender() - .service("com.deepin.dde.ControlCenter") - .interface("com.deepin.dde.ControlCenter") - .path("/com/deepin/dde/ControlCenter") - .method(QString("ShowModule")) + .service("org.deepin.dde.ControlCenter1") + .interface("org.deepin.dde.ControlCenter1") + .path("/org/deepin/dde/ControlCenter1") + .method(QString("ShowPage")) .arg(QString("bluetooth")) .call(); } @@ -167,6 +171,19 @@ bool BluetoothItem::hasAdapter() return m_applet->hasAadapter(); } +bool BluetoothItem::isPowered() +{ + if (!m_applet->hasAadapter()) + return false; + + QList adapters = m_applet->adaptersManager()->adapters(); + for (const Adapter *adapter : adapters) { + if (adapter->powered()) + return true; + } + return false; +} + void BluetoothItem::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); diff --git a/plugins/bluetooth/bluetoothitem.h b/plugins/bluetooth/bluetoothitem.h index aabb5fe04..81b7f055e 100644 --- a/plugins/bluetooth/bluetoothitem.h +++ b/plugins/bluetooth/bluetoothitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -12,6 +13,7 @@ #define BLUETOOTH_KEY "bluetooth-item-key" class BluetoothApplet; +class AdaptersManager; namespace Dock { class TipsWidget; @@ -21,7 +23,7 @@ class BluetoothItem : public QWidget Q_OBJECT public: - explicit BluetoothItem(QWidget *parent = nullptr); + explicit BluetoothItem(AdaptersManager *adapterManager, QWidget *parent = nullptr); QWidget *tipsWidget(); QWidget *popupApplet(); @@ -33,6 +35,7 @@ public: void refreshTips(); bool hasAdapter(); + bool isPowered(); protected: void resizeEvent(QResizeEvent *event); @@ -42,6 +45,7 @@ signals: void requestContextMenu() const; void noAdapter(); void justHasAdapter(); + void requestHide(); private: Dock::TipsWidget *m_tipsLabel; diff --git a/plugins/bluetooth/bluetoothmainwidget.cpp b/plugins/bluetooth/bluetoothmainwidget.cpp new file mode 100644 index 000000000..7eb9dfe38 --- /dev/null +++ b/plugins/bluetooth/bluetoothmainwidget.cpp @@ -0,0 +1,194 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "bluetoothmainwidget.h" +#include "bluetoothitem.h" +#include "adaptersmanager.h" +#include "adapter.h" + +#include +#include + +#include +#include +#include +#include +#include + +DGUI_USE_NAMESPACE +DWIDGET_USE_NAMESPACE + +BluetoothMainWidget::BluetoothMainWidget(AdaptersManager *adapterManager, QWidget *parent) + : QWidget(parent) + , m_adapterManager(adapterManager) + , m_iconWidget(new QWidget(this)) + , m_nameLabel(new QLabel(this)) + , m_stateLabel(new QLabel(this)) + , m_expandLabel(new QLabel(this)) + , m_mouseEnter(false) +{ + initUi(); + initConnection(); +} + +BluetoothMainWidget::~BluetoothMainWidget() +{ +} + +bool BluetoothMainWidget::eventFilter(QObject *watcher, QEvent *event) +{ + if (watcher == m_iconWidget) { + switch (event->type()) { + case QEvent::Paint: { + QPainter painter(m_iconWidget); + // 在区域最中间绘制 + QRect iconRect = m_iconWidget->rect(); + int size = qMin(iconRect.height(), iconRect.width()); + QPoint ptCenter(iconRect.center()); + painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + // 填充原型路径 + QPainterPath path; + path.addEllipse(ptCenter, size / 2 - 1, size / 2 - 1); + // 设置黑色背景色 + QColor backColor = (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::ColorType::LightType ? Qt::black : Qt::white); + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::ColorType::LightType) + backColor.setAlphaF(m_mouseEnter ? 0.2 : 0.1); + else + backColor.setAlphaF(m_mouseEnter ? 0.1 : 0.2); + painter.setBrush(backColor); + painter.fillPath(path, backColor); + // 添加图标 + bool blueStatus = isOpen(); + QPixmap pixmap(bluetoothIcon(blueStatus)); + if (blueStatus) { + QPainter pa(&pixmap); + pa.setCompositionMode(QPainter::CompositionMode_SourceIn); + pa.fillRect(pixmap.rect(), qApp->palette().highlight()); + } + painter.drawPixmap(QPoint(ptCenter.x() - pixmap.size().width() / 2, ptCenter.y() - pixmap.size().height() / 2), pixmap); + return true; + } + case QEvent::Enter: { + m_mouseEnter = true; + m_iconWidget->update(); + break; + } + case QEvent::Leave: { + m_mouseEnter = false; + m_iconWidget->update(); + break; + } + case QEvent::MouseButtonRelease: { + bool status = !(isOpen()); + for (const Adapter *adapter : m_adapterManager->adapters()) + m_adapterManager->setAdapterPowered(adapter, status); + + return true; + } + default: + break; + } + } + if (watcher == m_expandLabel && event->type() == QEvent::MouseButtonRelease) { + Q_EMIT requestExpand(); + return true; + } + if (watcher == m_nameLabel && event->type() == QEvent::Resize) { + m_nameLabel->setText(QFontMetrics(m_nameLabel->font()).elidedText(tr("Bluetooth"), Qt::TextElideMode::ElideRight, m_nameLabel->width())); + } + return QWidget::eventFilter(watcher, event); +} + +void BluetoothMainWidget::initUi() +{ + QHBoxLayout *mainLayout = new QHBoxLayout(this); + // 添加左侧的图标 + m_iconWidget->setFixedWidth(36); + // 添加中间的文本 + QWidget *textWidget = new QWidget(this); + QVBoxLayout *textLayout = new QVBoxLayout(textWidget); + textLayout->setContentsMargins(0, 10, 0, 10); + textLayout->setSpacing(0); + QFont nameFont = DFontSizeManager::instance()->t6(); + nameFont.setBold(true); + + m_nameLabel->setParent(textWidget); + m_nameLabel->setFont(nameFont); + + m_stateLabel->setParent(textWidget); + m_stateLabel->setFont(DFontSizeManager::instance()->t10()); + textLayout->addWidget(m_nameLabel); + textLayout->addWidget(m_stateLabel); + + // 添加右侧的展开按钮 + QWidget *expandWidget = new QWidget(this); + QVBoxLayout *expandLayout = new QVBoxLayout(expandWidget); + expandLayout->setContentsMargins(0, 0, 0, 0); + expandLayout->setSpacing(0); + expandLayout->addWidget(m_expandLabel); + + // 设置图标和文本 + m_nameLabel->setText(tr("Bluetooth")); + updateExpandIcon(); + + // 将所有的窗体都添加到主布局中 + mainLayout->setContentsMargins(10, 0, 10, 0); + mainLayout->setSpacing(0); + mainLayout->addWidget(m_iconWidget); + mainLayout->addSpacing(10); + mainLayout->addWidget(textWidget); + mainLayout->addStretch(); + mainLayout->addWidget(expandWidget); + + m_iconWidget->installEventFilter(this); + m_expandLabel->installEventFilter(this); + m_nameLabel->installEventFilter(this); +} + +void BluetoothMainWidget::initConnection() +{ + connect(m_adapterManager, &AdaptersManager::adapterIncreased, this, &BluetoothMainWidget::onAdapterChanged); + connect(m_adapterManager, &AdaptersManager::adapterDecreased, this, &BluetoothMainWidget::onAdapterChanged); + connect(m_adapterManager, &AdaptersManager::adapterIncreased, this, [ = ](Adapter *adapter) { + connect(adapter, &Adapter::poweredChanged, this, &BluetoothMainWidget::onAdapterChanged); + }); + + for (const Adapter *adapter : m_adapterManager->adapters()) + connect(adapter, &Adapter::poweredChanged, this, &BluetoothMainWidget::onAdapterChanged); + + onAdapterChanged(); +} + +void BluetoothMainWidget::updateExpandIcon() +{ + QPixmap enterPixmap = DStyle::standardIcon(style(), DStyle::SP_ArrowEnter).pixmap(QSize(16, 16)); + m_expandLabel->setPixmap(enterPixmap); +} + +bool BluetoothMainWidget::isOpen() const +{ + QList adapters = m_adapterManager->adapters(); + for (const Adapter *adapter : adapters) { + if (adapter->powered()) + return true; + } + + return false; +} + +QString BluetoothMainWidget::bluetoothIcon(bool isOpen) const +{ + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::ColorType::LightType) + return isOpen ? ":/bluetooth-active-symbolic-dark.svg" : ":/bluetooth-disable-symbolic-dark.svg"; + + return isOpen ? ":/bluetooth-active-symbolic.svg" : ":/bluetooth-disable-symbolic.svg"; +} + +void BluetoothMainWidget::onAdapterChanged() +{ + bool bluetoothIsOpen = isOpen(); + m_stateLabel->setText(bluetoothIsOpen ? tr("Turn on") : tr("Turn off")); + m_iconWidget->update(); +} diff --git a/plugins/bluetooth/bluetoothmainwidget.h b/plugins/bluetooth/bluetoothmainwidget.h new file mode 100644 index 000000000..062ec7f03 --- /dev/null +++ b/plugins/bluetooth/bluetoothmainwidget.h @@ -0,0 +1,50 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef BLUETOOTHMAINWIDGET_H +#define BLUETOOTHMAINWIDGET_H + +#include + +class AdaptersManager; +class QLabel; +class Adapter; + +class BluetoothMainWidget : public QWidget +{ + Q_OBJECT + +public: + explicit BluetoothMainWidget(AdaptersManager *adapterManager, QWidget *parent = nullptr); + ~BluetoothMainWidget(); + +Q_SIGNALS: + void requestExpand(); + +protected: + bool eventFilter(QObject *watcher, QEvent *event) override; + +private: + void initUi(); + void initConnection(); + + void updateExpandIcon(); + + bool isOpen() const; + QString bluetoothIcon(bool isOpen) const; + +private Q_SLOTS: + void onAdapterChanged(); + +private: + AdaptersManager *m_adapterManager; + QWidget *m_iconWidget; + QLabel *m_nameLabel; + QLabel *m_stateLabel; + QLabel *m_expandLabel; + bool m_mouseEnter; +}; + +#endif // BLUETOOTHMAINWIDGET_H diff --git a/plugins/bluetooth/bluetoothplugin.cpp b/plugins/bluetooth/bluetoothplugin.cpp index 521b908c2..b2f790518 100644 --- a/plugins/bluetooth/bluetoothplugin.cpp +++ b/plugins/bluetooth/bluetoothplugin.cpp @@ -1,14 +1,24 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "bluetoothplugin.h" +#include "adaptersmanager.h" +#include "bluetoothmainwidget.h" +#include "imageutil.h" + +#include #define STATE_KEY "enable" +DGUI_USE_NAMESPACE + BluetoothPlugin::BluetoothPlugin(QObject *parent) - : QObject(parent), - m_bluetoothItem(nullptr) + : QObject(parent) + , m_adapterManager(new AdaptersManager(this)) + , m_bluetoothItem(nullptr) + , m_bluetoothWidget(nullptr) { } @@ -29,33 +39,27 @@ void BluetoothPlugin::init(PluginProxyInterface *proxyInter) if (m_bluetoothItem) return; - m_bluetoothItem.reset(new BluetoothItem); + m_bluetoothItem.reset(new BluetoothItem(m_adapterManager)); - connect(m_bluetoothItem.data(), &BluetoothItem::justHasAdapter, [&] { - m_enableState = true; - refreshPluginItemsVisible(); - }); - connect(m_bluetoothItem.data(), &BluetoothItem::noAdapter, [&] { - m_enableState = false; - refreshPluginItemsVisible(); - }); + m_bluetoothWidget.reset(new BluetoothMainWidget(m_adapterManager)); - m_enableState = m_bluetoothItem->hasAdapter(); - - if (!pluginIsDisable()) + connect(m_bluetoothItem.data(), &BluetoothItem::justHasAdapter, [ this ] { m_proxyInter->itemAdded(this, BLUETOOTH_KEY); -} + }); + connect(m_bluetoothItem.data(), &BluetoothItem::requestHide, [ this ] { + m_proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, false); + }); + connect(m_bluetoothItem.data(), &BluetoothItem::noAdapter, [ this ] { + m_proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, false); + m_proxyInter->requestSetAppletVisible(this, BLUETOOTH_KEY, false); + m_proxyInter->itemRemoved(this, BLUETOOTH_KEY); + }); + connect(m_bluetoothWidget.data(), &BluetoothMainWidget::requestExpand, this, [ this ] { + m_proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, true); + }); -void BluetoothPlugin::pluginStateSwitched() -{ - m_proxyInter->saveValue(this, STATE_KEY, pluginIsDisable()); - - refreshPluginItemsVisible(); -} - -bool BluetoothPlugin::pluginIsDisable() -{ - return !m_proxyInter->getValue(this, STATE_KEY, m_enableState).toBool(); + if (m_bluetoothItem->hasAdapter()) + m_proxyInter->itemAdded(this, BLUETOOTH_KEY); } QWidget *BluetoothPlugin::itemWidget(const QString &itemKey) @@ -64,6 +68,9 @@ QWidget *BluetoothPlugin::itemWidget(const QString &itemKey) return m_bluetoothItem.data(); } + if (itemKey == QUICK_ITEM_KEY) + return m_bluetoothWidget.data(); + return nullptr; } @@ -82,16 +89,11 @@ QWidget *BluetoothPlugin::itemPopupApplet(const QString &itemKey) return m_bluetoothItem->popupApplet(); } - return nullptr; -} - -const QString BluetoothPlugin::itemContextMenu(const QString &itemKey) -{ - if (itemKey == BLUETOOTH_KEY) { - return m_bluetoothItem->contextMenu(); + if (itemKey == QUICK_ITEM_KEY) { + return m_bluetoothItem->popupApplet(); } - return QString(); + return nullptr; } void BluetoothPlugin::invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) @@ -122,15 +124,51 @@ void BluetoothPlugin::refreshIcon(const QString &itemKey) } } -void BluetoothPlugin::pluginSettingsChanged() +QIcon BluetoothPlugin::icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) { - refreshPluginItemsVisible(); + if (dockPart == DockPart::QuickPanel) + return QIcon(); + + QString iconFile; + if (themeType == DGuiApplicationHelper::ColorType::DarkType) + iconFile = ":/bluetooth-active-symbolic.svg"; + else + iconFile = ":/bluetooth-active-symbolic-dark.svg"; + + switch (dockPart) { + case DockPart::DCCSetting: + return ImageUtil::loadSvg(iconFile, QSize(18, 18)); + case DockPart::QuickShow: + return ImageUtil::loadSvg(iconFile, QSize(18, 16)); + default: + break; + } + + return QIcon(); } -void BluetoothPlugin::refreshPluginItemsVisible() +PluginsItemInterface::PluginMode BluetoothPlugin::status() const { - if (pluginIsDisable()) - m_proxyInter->itemRemoved(this, BLUETOOTH_KEY); - else - m_proxyInter->itemAdded(this, BLUETOOTH_KEY); + if (m_bluetoothItem.data()->isPowered()) + return PluginMode::Active; + + return PluginMode::Deactive; } + +QString BluetoothPlugin::description() const +{ + if (m_bluetoothItem.data()->isPowered()) + return tr("Turn on"); + + return tr("Turn off"); +} + +PluginFlags BluetoothPlugin::flags() const +{ + return PluginFlag::Type_Common + | PluginFlag::Quick_Multi + | PluginFlag::Attribute_CanDrag + | PluginFlag::Attribute_CanInsert + | PluginFlag::Attribute_CanSetting; +} + diff --git a/plugins/bluetooth/bluetoothplugin.h b/plugins/bluetooth/bluetoothplugin.h index 3525be369..d64f5374e 100644 --- a/plugins/bluetooth/bluetoothplugin.h +++ b/plugins/bluetooth/bluetoothplugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -10,6 +11,10 @@ #include +class BluetoothMainWidget; + +class AdaptersManager; + class BluetoothPlugin : public QObject, PluginsItemInterface { Q_OBJECT @@ -22,24 +27,24 @@ public: const QString pluginName() const override; const QString pluginDisplayName() const override; void init(PluginProxyInterface *proxyInter) override; - void pluginStateSwitched() override; bool pluginIsAllowDisable() override { return true; } - bool pluginIsDisable() override; QWidget *itemWidget(const QString &itemKey) override; QWidget *itemTipsWidget(const QString &itemKey) override; QWidget *itemPopupApplet(const QString &itemKey) override; - const QString itemContextMenu(const QString &itemKey) override; void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) override; int itemSortKey(const QString &itemKey) override; void setSortKey(const QString &itemKey, const int order) override; void refreshIcon(const QString &itemKey) override; - void pluginSettingsChanged() override; - -private: - void refreshPluginItemsVisible(); + + QIcon icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) override; + PluginMode status() const override; + QString description() const override; + PluginFlags flags() const override; private: + AdaptersManager *m_adapterManager; QScopedPointer m_bluetoothItem; + QScopedPointer m_bluetoothWidget; bool m_enableState = true; }; diff --git a/plugins/bluetooth/componments/adapter.cpp b/plugins/bluetooth/componments/adapter.cpp index a79359678..e850da72d 100644 --- a/plugins/bluetooth/componments/adapter.cpp +++ b/plugins/bluetooth/componments/adapter.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/bluetooth/componments/adapter.h b/plugins/bluetooth/componments/adapter.h index 22d6bb729..236b4f74d 100644 --- a/plugins/bluetooth/componments/adapter.h +++ b/plugins/bluetooth/componments/adapter.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/bluetooth/componments/adaptersmanager.cpp b/plugins/bluetooth/componments/adaptersmanager.cpp index ebbacfa25..c4180424a 100644 --- a/plugins/bluetooth/componments/adaptersmanager.cpp +++ b/plugins/bluetooth/componments/adaptersmanager.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,8 +14,8 @@ AdaptersManager::AdaptersManager(QObject *parent) : QObject(parent) - , m_bluetoothInter(new DBusBluetooth("com.deepin.daemon.Bluetooth", - "/com/deepin/daemon/Bluetooth", + , m_bluetoothInter(new DBusBluetooth("org.deepin.dde.Bluetooth1", + "/org/deepin/dde/Bluetooth1", QDBusConnection::sessionBus(), this)) { @@ -47,9 +48,9 @@ AdaptersManager::AdaptersManager(QObject *parent) }); #endif - QDBusInterface inter("com.deepin.daemon.Bluetooth", - "/com/deepin/daemon/Bluetooth", - "com.deepin.daemon.Bluetooth", + QDBusInterface inter("org.deepin.dde.Bluetooth1", + "/org/deepin/dde/Bluetooth1", + "org.deepin.dde.Bluetooth1", QDBusConnection::sessionBus()); QDBusReply reply = inter.call(QDBus::Block, "GetAdapters"); const QString replyStr = reply.value(); @@ -155,6 +156,7 @@ void AdaptersManager::onRemoveAdapter(const QString &json) Adapter *adapter = const_cast(result); if (adapter) { m_adapters.remove(id); + m_adapterIds.removeOne(id); emit adapterDecreased(adapter); adapter->deleteLater(); } @@ -209,28 +211,23 @@ void AdaptersManager::adapterAdd(Adapter *adapter, const QJsonObject &adpterObj) QDBusObjectPath dPath(adpterObj["Path"].toString()); QDBusPendingCall call = m_bluetoothInter->GetDevices(dPath); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); - connect(watcher, &QDBusPendingCallWatcher::finished, [this, adapter, call, watcher] { - if (adapter) { - if (!call.isError()) { - QDBusReply reply = call.reply(); - const QString replyStr = reply.value(); - QJsonDocument doc = QJsonDocument::fromJson(replyStr.toUtf8()); - adapter->initDevicesList(doc); - emit this->adapterIncreased(adapter); - } else { - qWarning() << call.error().message(); - } + connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QDBusPendingCallWatcher::deleteLater); + connect(watcher, &QDBusPendingCallWatcher::finished, [ this, adapter, call ] { + if (!call.isError()) { + QDBusReply reply = call.reply(); + const QString replyStr = reply.value(); + QJsonDocument doc = QJsonDocument::fromJson(replyStr.toUtf8()); + adapter->initDevicesList(doc); + emit this->adapterIncreased(adapter); + } else { + qWarning() << call.error().message(); } - delete watcher; }); QString id = adapter->id(); - if (!id.isEmpty()) { - if (!m_adapters.contains(id)) { - m_adapters[id] = adapter; - } else if (m_adapters[id] == nullptr) { - m_adapters[id] = adapter; - } + if (!id.isEmpty() && (!m_adapters.contains(id) || !m_adapters[id])) { + m_adapters[id] = adapter; + m_adapterIds << id; } } @@ -255,3 +252,12 @@ void AdaptersManager::adapterRefresh(const Adapter *adapter) QDBusObjectPath dPath(adapter->id()); m_bluetoothInter->RequestDiscovery(dPath); } + +QList AdaptersManager::adapters() +{ + QList allAdapter = m_adapters.values(); + std::sort(allAdapter.begin(), allAdapter.end(), [ & ](const Adapter *adapter1, const Adapter *adapter2) { + return m_adapterIds.indexOf(adapter1->id()) < m_adapterIds.indexOf(adapter2->id()); + }); + return allAdapter; +} diff --git a/plugins/bluetooth/componments/adaptersmanager.h b/plugins/bluetooth/componments/adaptersmanager.h index bf5789c60..16e8cf068 100644 --- a/plugins/bluetooth/componments/adaptersmanager.h +++ b/plugins/bluetooth/componments/adaptersmanager.h @@ -1,12 +1,13 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef ADAPTERSMANAGER_H #define ADAPTERSMANAGER_H -#include -using DBusBluetooth = com::deepin::daemon::Bluetooth; +#include "org_deepin_dde_bluetooth1.h" +using DBusBluetooth = org::deepin::dde::Bluetooth1; class Adapter; class Device; @@ -20,6 +21,7 @@ public: void connectDevice(const Device *device, Adapter *adapter); int adaptersCount(); void adapterRefresh(const Adapter *adapter); + QList adapters(); signals: void adapterIncreased(Adapter *adapter); @@ -42,6 +44,7 @@ private: private: DBusBluetooth *m_bluetoothInter; QMap m_adapters; + QStringList m_adapterIds; // 用于记录蓝牙适配器的排序 }; #endif // ADAPTERSMANAGER_H diff --git a/plugins/bluetooth/componments/bluetoothadapteritem.cpp b/plugins/bluetooth/componments/bluetoothadapteritem.cpp index 5da0d47b9..f946f77a6 100644 --- a/plugins/bluetooth/componments/bluetoothadapteritem.cpp +++ b/plugins/bluetooth/componments/bluetoothadapteritem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -26,7 +27,7 @@ BluetoothDeviceItem::BluetoothDeviceItem(QStyle *style, const Device *device, DL , m_labelAction(nullptr) , m_stateAction(nullptr) , m_connAction(nullptr) - , m_loading(new DSpinner(parent->viewport())) + , m_loading(new DSpinner(parent)) , m_iconWidget(new QWidget(parent->viewport())) , m_connButton(new StateButton(m_iconWidget)) { @@ -106,25 +107,20 @@ void BluetoothDeviceItem::updateIconTheme(DGuiApplicationHelper::ColorType type) void BluetoothDeviceItem::updateDeviceState(Device::State state) { m_labelAction->setText(m_device->alias()); - - m_connAction->setVisible(state == Device::StateConnected); - m_stateAction->setVisible(state == Device::StateAvailable); - if (state == Device::StateAvailable) { m_loading->start(); + m_stateAction->setVisible(true); + m_connAction->setVisible(false); } else if (state == Device::StateConnected) { m_loading->stop(); + m_stateAction->setVisible(false); + m_connAction->setVisible(true); emit requestTopDeviceItem(m_standarditem); - - /* 已连接的Item插入到首位后,其设置的 DViewItemAction 对象的位置未更新,导致还是显示在原位置 - 手动设置其位置到首位,触发 DViewItemAction 对象的位置更新,规避该问题,该问题待后期DTK优化 */ - QRect loadingRect = m_loading->geometry(); - loadingRect.setY(0); - m_loading->setGeometry(loadingRect); } else { m_loading->stop(); + m_stateAction->setVisible(false); + m_connAction->setVisible(false); } - emit deviceStateChanged(m_device); } @@ -137,9 +133,8 @@ BluetoothAdapterItem::BluetoothAdapterItem(Adapter *adapter, QWidget *parent) , m_itemDelegate(new DStyledItemDelegate(m_deviceListview)) , m_deviceModel(new QStandardItemModel(m_deviceListview)) , m_refreshBtn(new RefreshButton(this)) - , m_bluetoothInter(new DBusBluetooth("com.deepin.daemon.Bluetooth", "/com/deepin/daemon/Bluetooth", QDBusConnection::sessionBus(), this)) + , m_bluetoothInter(new DBusBluetooth("org.deepin.dde.Bluetooth1", "/org/deepin/dde/Bluetooth1", QDBusConnection::sessionBus(), this)) , m_showUnnamedDevices(false) - , m_stateBtnEnabled(true) , m_seperator(new HorizontalSeperator(this)) { initData(); @@ -175,11 +170,10 @@ void BluetoothAdapterItem::onTopDeviceItem(DStandardItem *item) if (!item || item->row() == -1 || item->row() == 0) return; - int row = item->row(); - // 先获取,再移除,后插入 - QStandardItem *sItem = m_deviceModel->takeItem(row, 0); - m_deviceModel->removeRow(row); - m_deviceModel->insertRow(0, sItem); + int index1 = item->row(); + QStandardItem *index = m_deviceModel->takeItem(index1, 0); + m_deviceModel->removeRow(index1); + m_deviceModel->insertRow(0, index); } void BluetoothAdapterItem::onAdapterNameChanged(const QString name) @@ -189,17 +183,10 @@ void BluetoothAdapterItem::onAdapterNameChanged(const QString name) void BluetoothAdapterItem::updateIconTheme(DGuiApplicationHelper::ColorType type) { - QPalette widgetBackgroud; - if (type == DGuiApplicationHelper::LightType) { - m_refreshBtn->setRotateIcon(":/refresh_dark.svg"); - widgetBackgroud.setColor(QPalette::Background, QColor(255, 255, 255, 0.03 * 255)); - } else { - widgetBackgroud.setColor(QPalette::Background, QColor(0, 0, 0, 0.03 * 255)); - m_refreshBtn->setRotateIcon(":/refresh.svg"); - } - - m_adapterLabel->label()->setAutoFillBackground(true); - m_adapterLabel->label()->setPalette(widgetBackgroud); + if (type == DGuiApplicationHelper::LightType) + m_refreshBtn->setRotateIcon(":/wireless/resources/wireless/refresh_dark.svg"); + else + m_refreshBtn->setRotateIcon(":/wireless/resources/wireless/refresh.svg"); } QSize BluetoothAdapterItem::sizeHint() const @@ -227,22 +214,10 @@ QStringList BluetoothAdapterItem::connectedDevicesName() return devsName; } -void BluetoothAdapterItem::setStateBtnEnabled(bool enable) -{ - if (m_stateBtnEnabled != enable) { - m_stateBtnEnabled = enable; - } - - if (m_adapterStateBtn) { - m_adapterStateBtn->setEnabled(m_stateBtnEnabled); - } -} - void BluetoothAdapterItem::initData() { m_showUnnamedDevices = m_bluetoothInter->displaySwitch(); - - if (m_adapter && !m_adapter->powered()) + if (!m_adapter->powered()) return; foreach (const auto device, m_adapter->devices()) { @@ -272,31 +247,20 @@ void BluetoothAdapterItem::onDeviceAdded(const Device *device) } }); - if (!m_showUnnamedDevices && device->name().isEmpty()) + m_deviceItems.insert(device->id(), item); + if (!m_showUnnamedDevices && device->name().isEmpty() && Device::StateConnected != device->state()) return; - m_deviceItems.insert(device->id(), item); m_deviceModel->insertRow(insertRow, item->standardItem()); emit deviceCountChanged(); } void BluetoothAdapterItem::onDeviceRemoved(const Device *device) { - if (m_deviceItems.isEmpty()) + if (m_deviceItems.isEmpty() || !m_deviceItems.keys().contains(device->id())) return; - int row = -1; - if (!m_deviceItems.value(device->id())) - return; - - row = m_deviceItems.value(device->id())->standardItem()->row(); - if ((row < 0) || (row > m_deviceItems.size() - 1)) { - m_deviceItems.value(device->id())->deleteLater(); - m_deviceItems.remove(device->id()); - return; - } - - m_deviceModel->removeRow(row); + m_deviceModel->removeRow(m_deviceItems.value(device->id())->standardItem()->row()); m_deviceItems.value(device->id())->deleteLater(); m_deviceItems.remove(device->id()); emit deviceCountChanged(); @@ -393,7 +357,7 @@ void BluetoothAdapterItem::initConnect() m_deviceListview->setVisible(state); m_seperator->setVisible(state); m_adapterStateBtn->setChecked(state); - m_adapterStateBtn->setEnabled(m_stateBtnEnabled); + m_adapterStateBtn->setEnabled(true); emit adapterPowerChanged(); }); connect(m_adapterStateBtn, &DSwitchButton::clicked, this, [ = ](bool state) { @@ -443,6 +407,7 @@ void BluetoothAdapterItem::setUnnamedDevicesVisible(bool isShow) return; } + for (i = m_deviceItems.begin(); i != m_deviceItems.end(); ++i) { BluetoothDeviceItem *deviceItem = i.value(); diff --git a/plugins/bluetooth/componments/bluetoothadapteritem.h b/plugins/bluetooth/componments/bluetoothadapteritem.h index cd1b32d0b..57aadc36f 100644 --- a/plugins/bluetooth/componments/bluetoothadapteritem.h +++ b/plugins/bluetooth/componments/bluetoothadapteritem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -14,9 +15,9 @@ #include #include -#include +#include "org_deepin_dde_bluetooth1.h" -using DBusBluetooth = com::deepin::daemon::Bluetooth; +using DBusBluetooth = org::deepin::dde::Bluetooth1; DWIDGET_USE_NAMESPACE @@ -84,7 +85,6 @@ public: ~BluetoothAdapterItem(); Adapter *adapter() { return m_adapter; } QStringList connectedDevicesName(); - void setStateBtnEnabled(bool); public slots: // 添加蓝牙设备 @@ -126,7 +126,6 @@ private: RefreshButton *m_refreshBtn; DBusBluetooth *m_bluetoothInter; bool m_showUnnamedDevices; - bool m_stateBtnEnabled; QMap m_deviceItems; HorizontalSeperator *m_seperator; diff --git a/plugins/bluetooth/componments/bluetoothapplet.cpp b/plugins/bluetooth/componments/bluetoothapplet.cpp index d65ee47a4..e2dd23c11 100644 --- a/plugins/bluetooth/componments/bluetoothapplet.cpp +++ b/plugins/bluetooth/componments/bluetoothapplet.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -42,7 +43,9 @@ SettingLabel::SettingLabel(QString text, QWidget *parent) p.setColor(QPalette::Background, Qt::transparent); this->setPalette(p); - m_label->setForegroundRole(QPalette::BrightText); + onThemeTypeChanged(DGuiApplicationHelper::instance()->themeType()); + updateEnabledStatus(); + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &SettingLabel::onThemeTypeChanged); } void SettingLabel::addButton(QWidget *button, int space) @@ -51,6 +54,35 @@ void SettingLabel::addButton(QWidget *button, int space) m_layout->addSpacing(space); } +void SettingLabel::updateEnabledStatus() +{ + QPalette p = m_label->palette(); + if (m_label->isEnabled()) + p.setColor(QPalette::BrightText, QColor(0, 0, 0)); + else + p.setColor(QPalette::BrightText, QColor(51, 51, 51)); + m_label->setPalette(p); +} + +void SettingLabel::onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType) +{ + QPalette palette = m_label->palette(); + if (themeType == DGuiApplicationHelper::ColorType::LightType) + palette.setColor(QPalette::BrightText, Qt::black); + else + palette.setColor(QPalette::BrightText, Qt::white); + + m_label->setPalette(palette); +} + +void SettingLabel::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::EnabledChange) + updateEnabledStatus(); + + QWidget::changeEvent(event); +} + void SettingLabel::mousePressEvent(QMouseEvent *ev) { if (ev->button() == Qt::LeftButton) { @@ -75,20 +107,27 @@ void SettingLabel::paintEvent(QPaintEvent *event) return QWidget::paintEvent(event); } -BluetoothApplet::BluetoothApplet(QWidget *parent) +BluetoothApplet::BluetoothApplet(AdaptersManager *adapterManager, QWidget *parent) : QWidget(parent) , m_scroarea(nullptr) , m_contentWidget(new QWidget(this)) - , m_adaptersManager(new AdaptersManager(this)) + , m_adaptersManager(adapterManager) , m_settingLabel(new SettingLabel(tr("Bluetooth settings"), this)) , m_mainLayout(new QVBoxLayout(this)) , m_contentLayout(new QVBoxLayout(m_contentWidget)) , m_seperator(new HorizontalSeperator(this)) - , m_airPlaneModeInter(new DBusAirplaneMode("com.deepin.daemon.AirplaneMode", "/com/deepin/daemon/AirplaneMode", QDBusConnection::systemBus(), this)) + , m_airPlaneModeInter(new DBusAirplaneMode("org.deepin.dde.AirplaneMode1", "/org/deepin/dde/AirplaneMode1", QDBusConnection::systemBus(), this)) , m_airplaneModeEnable(false) { initUi(); initConnect(); + initAdapters(); + + QScroller::grabGesture(m_scroarea, QScroller::LeftMouseButtonGesture); + QScrollerProperties propertiesOne = QScroller::scroller(m_scroarea)->scrollerProperties(); + QVariant overshootPolicyOne = QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff); + propertiesOne.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, overshootPolicyOne); + QScroller::scroller(m_scroarea)->setScrollerProperties(propertiesOne); } bool BluetoothApplet::poweredInitState() @@ -135,13 +174,17 @@ QStringList BluetoothApplet::connectedDevicesName() return deviceList; } +AdaptersManager *BluetoothApplet::adaptersManager() +{ + return m_adaptersManager; +} + void BluetoothApplet::onAdapterAdded(Adapter *adapter) { - if (!m_adapterItems.size()) { - emit justHasAdapter(); - } + bool needJustHasAdapter = (m_adapterItems.size() == 0); if (m_adapterItems.contains(adapter->id())) { onAdapterRemoved(m_adapterItems.value(adapter->id())->adapter()); + needJustHasAdapter = (m_adapterItems.size() == 0); } BluetoothAdapterItem *adapterItem = new BluetoothAdapterItem(adapter, this); @@ -154,14 +197,13 @@ void BluetoothApplet::onAdapterAdded(Adapter *adapter) m_adapterItems.insert(adapter->id(), adapterItem); - // 如果开启了飞行模式,置灰蓝牙适配器使能开关 - foreach (const auto item, m_adapterItems) { - item->setStateBtnEnabled(!m_airPlaneModeInter->enabled()); - } - - m_contentLayout->insertWidget(0, adapterItem, Qt::AlignTop | Qt::AlignVCenter); + // 将最新的设备插入到蓝牙设置前面 + m_contentLayout->insertWidget(m_contentLayout->count() - 1, adapterItem, Qt::AlignTop | Qt::AlignVCenter); updateBluetoothPowerState(); updateSize(); + + if (needJustHasAdapter) + emit justHasAdapter(); } void BluetoothApplet::onAdapterRemoved(Adapter *adapter) @@ -210,19 +252,14 @@ void BluetoothApplet::initUi() m_contentLayout->addWidget(m_settingLabel, 0, Qt::AlignBottom | Qt::AlignVCenter); m_scroarea = new QScrollArea(this); - m_scroarea->setWidgetResizable(true); - m_scroarea->setWidget(m_contentWidget); - m_scroarea->setFrameShape(QFrame::NoFrame); - m_scroarea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - m_scroarea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - m_scroarea->setAutoFillBackground(true); - m_scroarea->viewport()->setAutoFillBackground(true); - QScroller::grabGesture(m_scroarea->viewport(), QScroller::LeftMouseButtonGesture); - QScroller *scroller = QScroller::scroller(m_scroarea); - QScrollerProperties sp; - sp.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff); - scroller->setScrollerProperties(sp); + m_scroarea->setWidgetResizable(true); + m_scroarea->setFrameStyle(QFrame::NoFrame); + m_scroarea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_scroarea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_scroarea->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + m_scroarea->setContentsMargins(0, 0, 0, 0); + m_scroarea->setWidget(m_contentWidget); updateIconTheme(); @@ -233,29 +270,26 @@ void BluetoothApplet::initUi() updateSize(); setAirplaneModeEnabled(m_airPlaneModeInter->enabled()); + setDisabled(m_airPlaneModeInter->enabled()); } void BluetoothApplet::initConnect() { connect(m_adaptersManager, &AdaptersManager::adapterIncreased, this, &BluetoothApplet::onAdapterAdded); connect(m_adaptersManager, &AdaptersManager::adapterDecreased, this, &BluetoothApplet::onAdapterRemoved); - connect(m_settingLabel, &SettingLabel::clicked, this, [ = ] { DDBusSender() - .service("com.deepin.dde.ControlCenter") - .interface("com.deepin.dde.ControlCenter") - .path("/com/deepin/dde/ControlCenter") - .method(QString("ShowModule")) + .service("org.deepin.dde.ControlCenter1") + .interface("org.deepin.dde.ControlCenter1") + .path("/org/deepin/dde/ControlCenter1") + .method(QString("ShowPage")) .arg(QString("bluetooth")) .call(); + emit requestHide(); }); connect(DApplicationHelper::instance(), &DApplicationHelper::themeTypeChanged, this, &BluetoothApplet::updateIconTheme); connect(m_airPlaneModeInter, &DBusAirplaneMode::EnabledChanged, this, &BluetoothApplet::setAirplaneModeEnabled); - connect(m_airPlaneModeInter, &DBusAirplaneMode::EnabledChanged, this, [this](bool enabled) { - foreach (const auto item, m_adapterItems) { - item->setStateBtnEnabled(!enabled); - } - }); + connect(m_airPlaneModeInter, &DBusAirplaneMode::EnabledChanged, this, &BluetoothApplet::setDisabled); } /** @@ -277,6 +311,13 @@ void BluetoothApplet::updateIconTheme() m_scroarea->setPalette(scroareaBackgroud); } +void BluetoothApplet::initAdapters() +{ + QList adapters = m_adaptersManager->adapters(); + for (const Adapter *adapter : adapters) + onAdapterAdded(const_cast(adapter)); +} + void BluetoothApplet::setAirplaneModeEnabled(bool enable) { if (m_airplaneModeEnable == enable) diff --git a/plugins/bluetooth/componments/bluetoothapplet.h b/plugins/bluetooth/componments/bluetoothapplet.h index 3548f70e2..8154d733b 100644 --- a/plugins/bluetooth/componments/bluetoothapplet.h +++ b/plugins/bluetooth/componments/bluetoothapplet.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -10,8 +11,9 @@ #include #include +#include -#include +#include "org_deepin_dde_airplanemode1.h" class QVBoxLayout; class QHBoxLayout; @@ -29,8 +31,9 @@ class DListView; DWIDGET_END_NAMESPACE DWIDGET_USE_NAMESPACE +DGUI_USE_NAMESPACE -using DBusAirplaneMode = com::deepin::daemon::AirplaneMode; +using DBusAirplaneMode = org::deepin::dde::AirplaneMode1; class SettingLabel : public QWidget { @@ -46,6 +49,12 @@ signals: protected: void mousePressEvent(QMouseEvent *ev) override; void paintEvent(QPaintEvent *event) override; + void changeEvent(QEvent *event) override; + + void updateEnabledStatus(); + +private Q_SLOTS: + void onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType); private: DLabel *m_label; @@ -56,7 +65,7 @@ class BluetoothApplet : public QWidget { Q_OBJECT public: - explicit BluetoothApplet(QWidget *parent = nullptr); + explicit BluetoothApplet(AdaptersManager *adapterManager, QWidget *parent = nullptr); bool poweredInitState(); // 当前是否有蓝牙适配器 bool hasAadapter(); @@ -68,12 +77,15 @@ public: QStringList connectedDevicesName(); inline bool airplaneModeEnable() const { return m_airplaneModeEnable;} + // 返回蓝牙适配器 + AdaptersManager *adaptersManager(); signals: void noAdapter(); void justHasAdapter(); void powerChanged(bool state); void deviceStateChanged(const Device *device); + void requestHide(); public slots: // 蓝牙适配器增加 @@ -92,6 +104,7 @@ private: // 更新蓝牙插件主界面大小 void updateSize(); void updateIconTheme(); + void initAdapters(); private: QScrollArea *m_scroarea; diff --git a/plugins/bluetooth/componments/bluetoothconstants.h b/plugins/bluetooth/componments/bluetoothconstants.h index 073baf344..235985b31 100644 --- a/plugins/bluetooth/componments/bluetoothconstants.h +++ b/plugins/bluetooth/componments/bluetoothconstants.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/bluetooth/componments/device.cpp b/plugins/bluetooth/componments/device.cpp index df36c457d..01445ca56 100644 --- a/plugins/bluetooth/componments/device.cpp +++ b/plugins/bluetooth/componments/device.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/bluetooth/componments/device.h b/plugins/bluetooth/componments/device.h index 33c23cae8..4d8953759 100644 --- a/plugins/bluetooth/componments/device.h +++ b/plugins/bluetooth/componments/device.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2016 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/bluetooth/componments/refreshbutton.cpp b/plugins/bluetooth/componments/refreshbutton.cpp index ee2d507d8..9447095b2 100644 --- a/plugins/bluetooth/componments/refreshbutton.cpp +++ b/plugins/bluetooth/componments/refreshbutton.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/bluetooth/componments/refreshbutton.h b/plugins/bluetooth/componments/refreshbutton.h index a02ee0d6e..deb8b23e0 100644 --- a/plugins/bluetooth/componments/refreshbutton.h +++ b/plugins/bluetooth/componments/refreshbutton.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/bluetooth/dbusinterface/xml/org.deepin.dde.AirplaneMode1.xml b/plugins/bluetooth/dbusinterface/xml/org.deepin.dde.AirplaneMode1.xml new file mode 100644 index 000000000..31a4284b4 --- /dev/null +++ b/plugins/bluetooth/dbusinterface/xml/org.deepin.dde.AirplaneMode1.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/bluetooth/dbusinterface/xml/org.deepin.dde.Bluetooth1.xml b/plugins/bluetooth/dbusinterface/xml/org.deepin.dde.Bluetooth1.xml new file mode 100644 index 000000000..2060c2fa1 --- /dev/null +++ b/plugins/bluetooth/dbusinterface/xml/org.deepin.dde.Bluetooth1.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/bluetooth/resources/arrow-right-dark.svg b/plugins/bluetooth/resources/arrow-right-dark.svg new file mode 100644 index 000000000..04d121e0b --- /dev/null +++ b/plugins/bluetooth/resources/arrow-right-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/plugins/bluetooth/resources/arrow-right.svg b/plugins/bluetooth/resources/arrow-right.svg new file mode 100644 index 000000000..25a187ff1 --- /dev/null +++ b/plugins/bluetooth/resources/arrow-right.svg @@ -0,0 +1,18 @@ + + + + arrow-right + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/bluetooth/resources/bluetooth.qrc b/plugins/bluetooth/resources/bluetooth.qrc index ece8036ac..0433881a9 100644 --- a/plugins/bluetooth/resources/bluetooth.qrc +++ b/plugins/bluetooth/resources/bluetooth.qrc @@ -6,6 +6,8 @@ bluetooth-disable-symbolic.svg bluetooth-waiting-symbolic-dark.svg bluetooth-waiting-symbolic.svg + arrow-right.svg + arrow-right-dark.svg list_select.png list_select@2x.png notify_close_press.png diff --git a/plugins/datetime/CMakeLists.txt b/plugins/datetime/CMakeLists.txt index ee7c614c5..a4962985f 100644 --- a/plugins/datetime/CMakeLists.txt +++ b/plugins/datetime/CMakeLists.txt @@ -3,17 +3,22 @@ set(PLUGIN_NAME "datetime") project(${PLUGIN_NAME}) +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + # Sources files -file(GLOB SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp") +file(GLOB_RECURSE SRCS "*.h" + "*.cpp" + "../../widgets/*.h" + "../../widgets/*.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp" "") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) find_package(Qt5Svg REQUIRED) find_package(Qt5DBus REQUIRED) find_package(DtkWidget REQUIRED) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) pkg_check_modules(QGSettings REQUIRED gsettings-qt) add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") @@ -21,15 +26,17 @@ add_library(${PLUGIN_NAME} SHARED ${SRCS} datetime.qrc) set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../) target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} ${QGSettings_INCLUDE_DIRS} - ../../interfaces) + ../../interfaces + ../../frame/qtdbusextended + ./dbusinterface/ + ./dbusinterface/generation_dbus_interface) + target_link_libraries(${PLUGIN_NAME} PRIVATE ${Qt5DBus_LIBRARIES} ${DtkWidget_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Svg_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} ${QGSettings_LIBRARIES} ) diff --git a/plugins/datetime/datetime.json b/plugins/datetime/datetime.json index 0404bcb19..b69248a3b 100644 --- a/plugins/datetime/datetime.json +++ b/plugins/datetime/datetime.json @@ -1,4 +1,4 @@ { - "api": "1.2.3", - "depends-daemon-dbus-service": "com.deepin.daemon.Timedate" + "api": "2.0.0", + "depends-daemon-dbus-service": "org.deepin.dde.Timedate1" } diff --git a/plugins/datetime/datetimeplugin.cpp b/plugins/datetime/datetimeplugin.cpp index eb38d3e55..c3c6f37bf 100644 --- a/plugins/datetime/datetimeplugin.cpp +++ b/plugins/datetime/datetimeplugin.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -25,7 +26,7 @@ DatetimePlugin::DatetimePlugin(QObject *parent) , m_pluginLoaded(false) { QDBusConnection sessionBus = QDBusConnection::sessionBus(); - sessionBus.connect("com.deepin.daemon.Timedate", "/com/deepin/daemon/Timedate", "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(propertiesChanged())); + sessionBus.connect("org.deepin.dde.Timedate1", "/org/deepin/dde/Timedate1", "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(propertiesChanged())); } PluginsItemInterface::PluginSizePolicy DatetimePlugin::pluginSizePolicy() const @@ -132,7 +133,7 @@ const QString DatetimePlugin::itemCommand(const QString &itemKey) { Q_UNUSED(itemKey); - return "dbus-send --print-reply --dest=com.deepin.Calendar /com/deepin/Calendar com.deepin.Calendar.RaiseWindow"; + return "dbus-send --print-reply --dest=org.deepin.dde.Widgets1 /org/deepin/dde/Widgets1 org.deepin.dde.Widgets1.Toggle"; } const QString DatetimePlugin::itemContextMenu(const QString &itemKey) @@ -174,10 +175,10 @@ void DatetimePlugin::invokedMenuItem(const QString &itemKey, const QString &menu if (menuId == "open") { DDBusSender() - .service("com.deepin.dde.ControlCenter") - .interface("com.deepin.dde.ControlCenter") - .path("/com/deepin/dde/ControlCenter") - .method(QString("ShowModule")) + .service("org.deepin.dde.ControlCenter1") + .interface("org.deepin.dde.ControlCenter1") + .path("/org/deepin/dde/ControlCenter1") + .method(QString("ShowPage")) .arg(QString("datetime")) .call(); } else { @@ -204,9 +205,10 @@ void DatetimePlugin::updateCurrentTimeString() { const QDateTime currentDateTime = QDateTime::currentDateTime(); - // 实时刷新日期,防止日期显示错误 - m_centralWidget->updateDateTimeString(); - m_dateTipsLabel->setText(m_centralWidget->getDateTime()); + if (m_centralWidget->is24HourFormat()) + m_dateTipsLabel->setText(currentDateTime.date().toString(Qt::SystemLocaleLongDate) + currentDateTime.toString(" HH:mm:ss")); + else + m_dateTipsLabel->setText(currentDateTime.date().toString(Qt::SystemLocaleLongDate) + currentDateTime.toString(" hh:mm:ss A")); const QString currentString = currentDateTime.toString("yyyy/MM/dd hh:mm"); @@ -240,11 +242,11 @@ void DatetimePlugin::propertiesChanged() QDBusInterface* DatetimePlugin::timedateInterface() { if (!m_interface) { - if (QDBusConnection::sessionBus().interface()->isServiceRegistered("com.deepin.daemon.Timedate")) { - m_interface = new QDBusInterface("com.deepin.daemon.Timedate", "/com/deepin/daemon/Timedate", "com.deepin.daemon.Timedate", QDBusConnection::sessionBus(), this); + if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.deepin.dde.Timedate1")) { + m_interface = new QDBusInterface("org.deepin.dde.Timedate1", "/org/deepin/dde/Timedate1", "org.deepin.dde.Timedate1", QDBusConnection::sessionBus(), this); } else { - const QString path = QString("/com/deepin/daemon/Accounts/User%1").arg(QString::number(getuid())); - QDBusInterface * systemInterface = new QDBusInterface("com.deepin.daemon.Accounts", path, "com.deepin.daemon.Accounts.User", + const QString path = QString("/org/deepin/dde/Accounts1/User%1").arg(QString::number(getuid())); + QDBusInterface * systemInterface = new QDBusInterface("org.deepin.dde.Accounts1", path, "org.deepin.dde.Accounts1.User", QDBusConnection::systemBus(), this); return systemInterface; } diff --git a/plugins/datetime/datetimeplugin.h b/plugins/datetime/datetimeplugin.h index 27b2b57b2..beeb22a6b 100644 --- a/plugins/datetime/datetimeplugin.h +++ b/plugins/datetime/datetimeplugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/datetime/datetimewidget.cpp b/plugins/datetime/datetimewidget.cpp index b3b61292d..faee69dd5 100644 --- a/plugins/datetime/datetimewidget.cpp +++ b/plugins/datetime/datetimewidget.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -22,28 +23,17 @@ DWIDGET_USE_NAMESPACE DatetimeWidget::DatetimeWidget(QWidget *parent) : QWidget(parent) , m_24HourFormat(false) - , m_longDateFormatType(0) - , m_weekdayFormatType(0) , m_timeOffset(false) - , m_timedateInter(new Timedate("com.deepin.daemon.Timedate", "/com/deepin/daemon/Timedate", QDBusConnection::sessionBus(), this)) + , m_timedateInter(new Timedate("org.deepin.dde.Timedate1", "/org/deepin/dde/Timedate1", QDBusConnection::sessionBus(), this)) , m_shortDateFormat("yyyy-MM-dd") , m_shortTimeFormat("hh:mm") - , m_longTimeFormat(" hh:mm:ss") { setMinimumSize(PLUGIN_BACKGROUND_MIN_SIZE, PLUGIN_BACKGROUND_MIN_SIZE); setShortDateFormat(m_timedateInter->shortDateFormat()); setShortTimeFormat(m_timedateInter->shortTimeFormat()); - setWeekdayFormat(m_timedateInter->weekdayFormat()); - setLongDateFormat(m_timedateInter->longDateFormat()); - setLongTimeFormat(m_timedateInter->longTimeFormat()); - set24HourFormat(m_timedateInter->use24HourFormat()); - updateDateTimeString(); connect(m_timedateInter, &Timedate::ShortDateFormatChanged, this, &DatetimeWidget::setShortDateFormat); connect(m_timedateInter, &Timedate::ShortTimeFormatChanged, this, &DatetimeWidget::setShortTimeFormat); - connect(m_timedateInter, &Timedate::LongDateFormatChanged, this, &DatetimeWidget::setLongDateFormat); - connect(m_timedateInter, &Timedate::WeekdayFormatChanged, this, &DatetimeWidget::setWeekdayFormat); - connect(m_timedateInter, &Timedate::LongTimeFormatChanged, this, &DatetimeWidget::setLongTimeFormat); //连接日期时间修改信号,更新日期时间插件的布局 connect(m_timedateInter, &Timedate::TimeUpdate, this, [ = ]{ if (isVisible()) { @@ -59,7 +49,6 @@ void DatetimeWidget::set24HourFormat(const bool value) } m_24HourFormat = value; - updateLongTimeFormat(); update(); if (isVisible()) { @@ -80,11 +69,9 @@ void DatetimeWidget::setShortDateFormat(int type) case 3: m_shortDateFormat = "yyyy/MM/dd"; break; case 4: m_shortDateFormat = "yyyy-MM-dd"; break; case 5: m_shortDateFormat = "yyyy.MM.dd"; break; - case 6: m_shortDateFormat = "MM.dd.yyyy"; break; - case 7: m_shortDateFormat = "dd.MM.yyyy"; break; - case 8: m_shortDateFormat = "yy/M/d"; break; - case 9: m_shortDateFormat = "yy-M-d"; break; - case 10: m_shortDateFormat = "yy.M.d"; break; + case 6: m_shortDateFormat = "yy/M/d"; break; + case 7: m_shortDateFormat = "yy-M-d"; break; + case 8: m_shortDateFormat = "yy.M.d"; break; default: m_shortDateFormat = "yyyy-MM-dd"; break; } update(); @@ -112,192 +99,6 @@ void DatetimeWidget::setShortTimeFormat(int type) } } -/** - * @brief DatetimeWidget::setLongDateFormat 根据类型设置长时间显示格式 - * @param type 自定义类型 - */ -void DatetimeWidget::setLongDateFormat(int type) -{ - if (m_longDateFormatType == type) - return; - - m_longDateFormatType = type; - updateDateTimeString(); -} - -/** - * @brief DatetimeWidget::setWeekdayFormat 根据类型设置周显示格式 - * @param type 自定义类型 - */ -void DatetimeWidget::setWeekdayFormat(int type) -{ - if (m_weekdayFormatType == type) - return; - - m_weekdayFormatType = type; - updateWeekdayFormat(); - updateDateTimeString(); -} - -/** - * @brief DatetimeWidget::setLongTimeFormat 根据类型设置长时间的显示格式 - * @param type 自定义类型 - */ -void DatetimeWidget::setLongTimeFormat(int type) -{ - if (m_longTimeFormatType == type) - return; - - m_longTimeFormatType = type; - updateLongTimeFormat(); - updateDateTimeString(); -} - -/** - * @brief DatetimeWidget::updateWeekdayFormat 更新周的显示格式 - */ -void DatetimeWidget::updateWeekdayFormat() -{ - const QDateTime currentDateTime = QDateTime::currentDateTime(); - auto dayOfWeek = currentDateTime.date().dayOfWeek(); - - if (0 == m_weekdayFormatType) { - switch (dayOfWeek) { - case 1: - m_weekFormat = tr("Monday"); //星期一 - break; - case 2: - m_weekFormat = tr("Tuesday"); //星期二 - break; - case 3: - m_weekFormat = tr("Wednesday"); //星期三 - break; - case 4: - m_weekFormat = tr("Thursday"); //星期四 - break; - case 5: - m_weekFormat = tr("Friday"); //星期五 - break; - case 6: - m_weekFormat = tr("Saturday"); //星期六 - break; - case 7: - m_weekFormat = tr("Sunday"); //星期天 - break; - default: - m_weekFormat = tr("Monday"); //星期一 - break; - } - } else { - switch (dayOfWeek) { - case 1: - m_weekFormat = tr("monday"); //周一 - break; - case 2: - m_weekFormat = tr("tuesday"); //周二 - break; - case 3: - m_weekFormat = tr("wednesday"); //周三 - break; - case 4: - m_weekFormat = tr("thursday"); //周四 - break; - case 5: - m_weekFormat = tr("friday"); //周五 - break; - case 6: - m_weekFormat = tr("saturday"); //周六 - break; - case 7: - m_weekFormat = tr("sunday"); //周天 - break; - default: - m_weekFormat = tr("monday"); //周一 - break; - } - } -} - -void DatetimeWidget::updateLongTimeFormat() -{ - if (m_24HourFormat) { - switch (m_longTimeFormatType) { - case 0: m_longTimeFormat = " h:mm:ss"; break; - case 1: m_longTimeFormat = " hh:mm:ss"; break; - default: m_longTimeFormat = " hh:mm:ss"; break; - } - } else { - switch (m_longTimeFormatType) { - case 0: m_longTimeFormat = " h:mm:ss A"; break; - case 1: m_longTimeFormat = " hh:mm:ss A"; break; - default: m_longTimeFormat = " hh:mm:ss A"; break; - } - } -} - -/** - * @brief DatetimeWidget::updateWeekdayTimeString 更新任务栏时间标签的显示 - */ -void DatetimeWidget::updateDateTimeString() -{ - QString longTimeFormat(""); - const QDateTime currentDateTime = QDateTime::currentDateTime(); - int year = currentDateTime.date().year(); - int month = currentDateTime.date().month(); - int day = currentDateTime.date().day(); - - auto lang = QLocale::system().language(); - bool isZhLocale = lang == QLocale::Chinese || lang == QLocale::Tibetan || lang == QLocale::Uighur; - - // 根据相应语言去显示对应的格式 - // 中文: 格式为xxxx年xx月xx日 星期x hh:mm:ss,如:2022年7月25日 星期- 12:00:00 - // 英文: 格式为x x,xxxx,x hh:mm:ss, 如:July 25,2022,Monday 12:00:00 - // 其他语言:按照国际当地长时间格式显示 - if (isZhLocale) { - longTimeFormat = QString(tr("%1year%2month%3day")).arg(year).arg(month).arg(day); - - // 实时更新周的日期显示 - updateWeekdayFormat(); - - switch (m_longDateFormatType) { - case 0: - m_dateTime = longTimeFormat + currentDateTime.toString(m_longTimeFormat); - break; - case 1: - m_dateTime = longTimeFormat + QString(" ") + m_weekFormat + currentDateTime.toString(m_longTimeFormat); - break; - case 2: - m_dateTime = m_weekFormat + QString(" ") + longTimeFormat + currentDateTime.toString(m_longTimeFormat); - break; - default: - m_dateTime = longTimeFormat + QString(" ") + m_weekFormat + currentDateTime.toString(m_longTimeFormat); - break; - } - } else if (lang == QLocale::English) { - auto longDateString = currentDateTime.date().toString(Qt::SystemLocaleLongDate); - auto week = longDateString.split(",").at(0); - // 获取英文的日期格式字符串,-2是去掉","和" " - auto longDateTimeFormat = longDateString.right(longDateString.size() - week.size() - 2); - - switch (m_longDateFormatType) { - case 0: - m_dateTime = longDateTimeFormat + currentDateTime.toString(m_longTimeFormat); - break; - case 1: - m_dateTime = longDateTimeFormat + QString(", ") + week + currentDateTime.toString(m_longTimeFormat); - break; - case 2: - m_dateTime = week + QString(", ") + longDateTimeFormat + currentDateTime.toString(m_longTimeFormat); - break; - default: - m_dateTime = longDateTimeFormat + QString(", ") + week + currentDateTime.toString(m_longTimeFormat); - break; - } - } else { - m_dateTime = currentDateTime.date().toString(Qt::SystemLocaleLongDate) + currentDateTime.toString(m_longTimeFormat); - } -} - /** * @brief DatetimeWidget::curTimeSize 调整时间日期字体大小 * @return 返回时间和日期绘制的区域大小 @@ -335,7 +136,7 @@ QSize DatetimeWidget::curTimeSize() const dateSize.setWidth(maxWidth); if (position == Dock::Bottom || position == Dock::Top) { - while (QFontMetrics(m_timeFont).boundingRect(timeString).height() + QFontMetrics(m_dateFont).boundingRect(dateString).height() > height() && m_timeFont.pixelSize() > 1) { + while (QFontMetrics(m_timeFont).boundingRect(timeString).height() + QFontMetrics(m_dateFont).boundingRect(dateString).height() > height()) { m_timeFont.setPixelSize(m_timeFont.pixelSize() - 1); maxWidth = std::max(QFontMetrics(m_timeFont).boundingRect(timeString).size().width(), QFontMetrics(m_timeFont).horizontalAdvance(timeString)); timeSize.setWidth(maxWidth); @@ -347,7 +148,7 @@ QSize DatetimeWidget::curTimeSize() const } return QSize(std::max(timeSize.width(), dateSize.width()), timeSize.height() + dateSize.height()); } else { - while (std::max(QFontMetrics(m_timeFont).boundingRect(timeString).size().width(), QFontMetrics(m_dateFont).boundingRect(dateString).size().width()) > (width() - 4) && m_timeFont.pixelSize() > 1) { + while (std::max(QFontMetrics(m_timeFont).boundingRect(timeString).size().width(), QFontMetrics(m_dateFont).boundingRect(dateString).size().width()) > (width() - 4)) { m_timeFont.setPixelSize(m_timeFont.pixelSize() - 1); if (m_24HourFormat) { timeSize.setHeight(QFontMetrics(m_timeFont).boundingRect(timeString).size().height()); diff --git a/plugins/datetime/datetimewidget.h b/plugins/datetime/datetimewidget.h index 51a8695a5..3f7e2f08f 100644 --- a/plugins/datetime/datetimewidget.h +++ b/plugins/datetime/datetimewidget.h @@ -1,26 +1,26 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DATETIMEWIDGET_H #define DATETIMEWIDGET_H -#include +#include "org_deepin_dde_timedate1.h" #include -using Timedate = com::deepin::daemon::Timedate; +using Timedate = org::deepin::dde::Timedate1; class DatetimeWidget : public QWidget { Q_OBJECT public: - explicit DatetimeWidget(QWidget *parent = nullptr); + explicit DatetimeWidget(QWidget *parent = 0); + bool is24HourFormat() const { return m_24HourFormat; } QSize sizeHint() const; - inline bool is24HourFormat() const { return m_24HourFormat; } - inline QString getDateTime() { return m_dateTime; } protected: void resizeEvent(QResizeEvent *event); @@ -31,34 +31,22 @@ signals: public slots: void set24HourFormat(const bool value); - void updateDateTimeString(); private Q_SLOTS: void setShortDateFormat(int type); void setShortTimeFormat(int type); - void setLongDateFormat(int type); - void setWeekdayFormat(int type); - void setLongTimeFormat(int type); private: QSize curTimeSize() const; - void updateWeekdayFormat(); - void updateLongTimeFormat(); private: bool m_24HourFormat; - int m_longDateFormatType; - int m_longTimeFormatType; - int m_weekdayFormatType; mutable QFont m_timeFont; mutable QFont m_dateFont; mutable int m_timeOffset; Timedate *m_timedateInter; QString m_shortDateFormat; QString m_shortTimeFormat; - QString m_dateTime; - QString m_weekFormat; - QString m_longTimeFormat; }; #endif // DATETIMEWIDGET_H diff --git a/plugins/datetime/dbusinterface/types/zoneinfo.cpp b/plugins/datetime/dbusinterface/types/zoneinfo.cpp new file mode 100644 index 000000000..cc449823a --- /dev/null +++ b/plugins/datetime/dbusinterface/types/zoneinfo.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "zoneinfo.h" + +ZoneInfo::ZoneInfo() +{ + +} + +bool ZoneInfo::operator ==(const ZoneInfo &what) const +{ + // TODO: 这里只判断这两个成员应该就可以了 + return m_zoneName == what.m_zoneName && + m_utcOffset == what.m_utcOffset; +} + +QDebug operator<<(QDebug argument, const ZoneInfo & info) +{ + argument << info.m_zoneName << ',' << info.m_zoneCity << ',' << info.m_utcOffset << ','; + argument << info.i2 << ',' << info.i3 << ',' << info.i4 << endl; + + return argument; +} + +QDBusArgument &operator<<(QDBusArgument & argument, const ZoneInfo & info) +{ + argument.beginStructure(); + argument << info.m_zoneName << info.m_zoneCity << info.m_utcOffset; + argument.beginStructure(); + argument << info.i2 << info.i3 << info.i4; + argument.endStructure(); + argument.endStructure(); + + return argument; +} + +QDataStream &operator<<(QDataStream & argument, const ZoneInfo & info) +{ + argument << info.m_zoneName << info.m_zoneCity << info.m_utcOffset; + argument << info.i2 << info.i3 << info.i4; + + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument & argument, ZoneInfo & info) +{ + argument.beginStructure(); + argument >> info.m_zoneName >> info.m_zoneCity >> info.m_utcOffset; + argument.beginStructure(); + argument >> info.i2 >> info.i3 >> info.i4; + argument.endStructure(); + argument.endStructure(); + + return argument; +} + +const QDataStream &operator>>(QDataStream & argument, ZoneInfo & info) +{ + argument >> info.m_zoneName >> info.m_zoneCity >> info.m_utcOffset; + argument >> info.i2 >> info.i3 >> info.i4; + + return argument; +} + +void registerZoneInfoMetaType() +{ + qRegisterMetaType("ZoneInfo"); + qDBusRegisterMetaType(); +} diff --git a/plugins/datetime/dbusinterface/types/zoneinfo.h b/plugins/datetime/dbusinterface/types/zoneinfo.h new file mode 100644 index 000000000..e9af23dcc --- /dev/null +++ b/plugins/datetime/dbusinterface/types/zoneinfo.h @@ -0,0 +1,46 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef ZONEINFO_H +#define ZONEINFO_H + +#include +#include +#include +#include +#include + +class ZoneInfo +{ +public: + ZoneInfo(); + + friend QDebug operator<<(QDebug argument, const ZoneInfo &info); + friend QDBusArgument &operator<<(QDBusArgument &argument, const ZoneInfo &info); + friend QDataStream &operator<<(QDataStream &argument, const ZoneInfo &info); + friend const QDBusArgument &operator>>(const QDBusArgument &argument, ZoneInfo &info); + friend const QDataStream &operator>>(QDataStream &argument, ZoneInfo &info); + + bool operator==(const ZoneInfo &what) const; + +public: + inline QString getZoneName() const {return m_zoneName;} + inline QString getZoneCity() const {return m_zoneCity;} + inline int getUTCOffset() const {return m_utcOffset;} + +private: + QString m_zoneName; + QString m_zoneCity; + int m_utcOffset; + qint64 i2; + qint64 i3; + int i4; +}; + +Q_DECLARE_METATYPE(ZoneInfo) + +void registerZoneInfoMetaType(); + +#endif // ZONEINFO_H diff --git a/plugins/datetime/dbusinterface/xml/org.deepin.dde.Timedate1.xml b/plugins/datetime/dbusinterface/xml/org.deepin.dde.Timedate1.xml new file mode 100644 index 000000000..f3a46e3bf --- /dev/null +++ b/plugins/datetime/dbusinterface/xml/org.deepin.dde.Timedate1.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/dcc-dock-plugin/.tx/config b/plugins/dcc-dock-plugin/.tx/config deleted file mode 100644 index fa112435f..000000000 --- a/plugins/dcc-dock-plugin/.tx/config +++ /dev/null @@ -1,10 +0,0 @@ -[main] -host = https://www.transifex.com -minimum_perc = 80 -mode = developer - -[deepin-desktop-environment.dcc-dock-plugin] -file_filter = translations/dcc-dock-plugin_.ts -source_file = translations/dcc-dock-plugin.ts -source_lang = en -type = QT diff --git a/plugins/dcc-dock-plugin/CMakeLists.txt b/plugins/dcc-dock-plugin/CMakeLists.txt deleted file mode 100644 index 1fce9c861..000000000 --- a/plugins/dcc-dock-plugin/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -cmake_minimum_required(VERSION 3.7) - -set(PLUGIN_NAME "dcc-dock-plugin") - -project(${PLUGIN_NAME}) - -set(CMAKE_AUTOMOC ON) - -file(GLOB_RECURSE SRCS - "*.h" - "*.cpp") - -find_package(Qt5 COMPONENTS Core Widgets DBus Svg LinguistTools REQUIRED) -find_package(DdeControlCenter REQUIRED) -find_package(PkgConfig REQUIRED) -find_package(DtkWidget REQUIRED) - -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) -pkg_check_modules(QGSettings REQUIRED gsettings-qt) - -add_library(${PLUGIN_NAME} SHARED ${SRCS} resources.qrc) -set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ./) -target_include_directories(${PLUGIN_NAME} PUBLIC - ../src - ../../frame/util - ${Qt5Widgets_INCLUDE_DIRS} - ${Qt5Svg_INCLUDE_DIRS} - ${DtkWidget_INCLUDE_DIRS} - ${DdeControlCenter_INCLUDE_DIR} - ${DFrameworkDBus_INCLUDE_DIRS} - ${QGSettings_INCLUDE_DIRS} - ${Qt5DBus_INCLUDE_DIRS} - ) -target_link_libraries(${PLUGIN_NAME} PRIVATE - ${Qt5Widgets_LIBRARIES} - ${Qt5Svg_LIBRARIES} - ${DtkWidget_LIBRARIES} - ${DdeControlCenter_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} - ${QGSettings_LIBRARIES} - ${Qt5DBus_LIBRARIES} - ) - -file(GLOB TS_FILES "translations/*.ts") -qt5_add_translation(QM_FILES ${TS_FILES}) -add_custom_target(translations ALL DEPENDS ${QM_FILES}) -install(FILES ${QM_FILES} DESTINATION share/${PLUGIN_NAME}/translations) - -# dconfig -file(GLOB DCONFIG_FILES "org.deepin.dde.dock.plugin.json") -dconfig_meta_files(APPID org.deepin.dde.control-center FILES ${DCONFIG_FILES}) - -install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-control-center/modules) diff --git a/plugins/dcc-dock-plugin/actions/icon_dock_32px.svg b/plugins/dcc-dock-plugin/actions/icon_dock_32px.svg deleted file mode 100644 index a9aa35d8f..000000000 --- a/plugins/dcc-dock-plugin/actions/icon_dock_32px.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - list2_icon/dock/normal - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/com_deepin_dde_dock.cpp b/plugins/dcc-dock-plugin/com_deepin_dde_dock.cpp deleted file mode 100644 index 1d44bc6a6..000000000 --- a/plugins/dcc-dock-plugin/com_deepin_dde_dock.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "com_deepin_dde_dock.h" - -/* - * Implementation of interface class _Dock - */ - -class _DockPrivate -{ -public: - _DockPrivate() = default; - - // begin member variables - bool showInPrimary; - -public: - QMap m_processingCalls; - QMap> m_waittingCalls; -}; - -_Dock::_Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) - : DBusExtendedAbstractInterface(service, path, staticInterfaceName(), connection, parent) - , d_ptr(new _DockPrivate) -{ - connect(this, &_Dock::propertyChanged, this, &_Dock::onPropertyChanged); - -} - -_Dock::~_Dock() -{ - qDeleteAll(d_ptr->m_processingCalls.values()); - delete d_ptr; -} - -void _Dock::onPropertyChanged(const QString &propName, const QVariant &value) -{ - if (propName == QStringLiteral("showInPrimary")) - { - const bool &showInPrimary = qvariant_cast(value); - if (d_ptr->showInPrimary != showInPrimary) - { - d_ptr->showInPrimary = showInPrimary; - Q_EMIT ShowInPrimaryChanged(d_ptr->showInPrimary); - } - return; - } - - qWarning() << "property not handle: " << propName; - return; -} - -bool _Dock::showInPrimary() -{ - return qvariant_cast(internalPropGet("showInPrimary", &d_ptr->showInPrimary)); -} - -void _Dock::setShowInPrimary(bool value) -{ - - internalPropSet("showInPrimary", QVariant::fromValue(value), &d_ptr->showInPrimary); -} - -void _Dock::CallQueued(const QString &callName, const QList &args) -{ - if (d_ptr->m_waittingCalls.contains(callName)) - { - d_ptr->m_waittingCalls[callName] = args; - return; - } - if (d_ptr->m_processingCalls.contains(callName)) - { - d_ptr->m_waittingCalls.insert(callName, args); - } else { - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCallWithArgumentList(callName, args)); - connect(watcher, &QDBusPendingCallWatcher::finished, this, &_Dock::onPendingCallFinished); - d_ptr->m_processingCalls.insert(callName, watcher); - } -} - -void _Dock::onPendingCallFinished(QDBusPendingCallWatcher *w) -{ - w->deleteLater(); - const auto callName = d_ptr->m_processingCalls.key(w); - Q_ASSERT(!callName.isEmpty()); - if (callName.isEmpty()) - return; - d_ptr->m_processingCalls.remove(callName); - if (!d_ptr->m_waittingCalls.contains(callName)) - return; - const auto args = d_ptr->m_waittingCalls.take(callName); - CallQueued(callName, args); -} diff --git a/plugins/dcc-dock-plugin/com_deepin_dde_dock.h b/plugins/dcc-dock-plugin/com_deepin_dde_dock.h deleted file mode 100644 index ca144a92b..000000000 --- a/plugins/dcc-dock-plugin/com_deepin_dde_dock.h +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef COM_DEEPIN_DDE_DOCK_H -#define COM_DEEPIN_DDE_DOCK_H - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* - * Proxy class for interface com.deepin.dde.Dock - */ -class _DockPrivate; -class _Dock : public DBusExtendedAbstractInterface -{ - Q_OBJECT - -public: - static inline const char *staticInterfaceName() - { return "com.deepin.dde.Dock"; } - -public: - explicit _Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); - - ~_Dock(); - - Q_PROPERTY(bool showInPrimary READ showInPrimary WRITE setShowInPrimary NOTIFY ShowInPrimaryChanged) - bool showInPrimary(); - void setShowInPrimary(bool value); - -public Q_SLOTS: // METHODS - inline QDBusPendingReply GetLoadedPlugins() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("GetLoadedPlugins"), argumentList); - } - - - - inline QDBusPendingReply<> ReloadPlugins() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("ReloadPlugins"), argumentList); - } - - inline void ReloadPluginsQueued() - { - QList argumentList; - - CallQueued(QStringLiteral("ReloadPlugins"), argumentList); - } - - - inline QDBusPendingReply<> callShow() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("callShow"), argumentList); - } - - inline void callShowQueued() - { - QList argumentList; - - CallQueued(QStringLiteral("callShow"), argumentList); - } - - - inline QDBusPendingReply getPluginKey(const QString &pluginName) - { - QList argumentList; - argumentList << QVariant::fromValue(pluginName); - return asyncCallWithArgumentList(QStringLiteral("getPluginKey"), argumentList); - } - - - - inline QDBusPendingReply getPluginVisible(const QString &pluginName) - { - QList argumentList; - argumentList << QVariant::fromValue(pluginName); - return asyncCallWithArgumentList(QStringLiteral("getPluginVisible"), argumentList); - } - - - - inline QDBusPendingReply<> resizeDock(int offset, bool dragging) - { - QList argumentList; - argumentList << QVariant::fromValue(offset) << QVariant::fromValue(dragging); - return asyncCallWithArgumentList(QStringLiteral("resizeDock"), argumentList); - } - - inline void resizeDockQueued(int offset, bool dragging) - { - QList argumentList; - argumentList << QVariant::fromValue(offset) << QVariant::fromValue(dragging); - - CallQueued(QStringLiteral("resizeDock"), argumentList); - } - - - inline QDBusPendingReply<> setPluginVisible(const QString &pluginName, bool visible) - { - QList argumentList; - argumentList << QVariant::fromValue(pluginName) << QVariant::fromValue(visible); - return asyncCallWithArgumentList(QStringLiteral("setPluginVisible"), argumentList); - } - - inline void setPluginVisibleQueued(const QString &pluginName, bool visible) - { - QList argumentList; - argumentList << QVariant::fromValue(pluginName) << QVariant::fromValue(visible); - - CallQueued(QStringLiteral("setPluginVisible"), argumentList); - } - - - -Q_SIGNALS: // SIGNALS - void pluginVisibleChanged(const QString &in0, bool in1); - // begin property changed signals - void ShowInPrimaryChanged(bool value) const; - -public Q_SLOTS: - void CallQueued(const QString &callName, const QList &args); - -private Q_SLOTS: - void onPendingCallFinished(QDBusPendingCallWatcher *w); - void onPropertyChanged(const QString &propName, const QVariant &value); - -private: - _DockPrivate *d_ptr; -}; - -namespace com { - namespace deepin { - namespace dde { - typedef ::_Dock Dock; - } - } -} -#endif diff --git a/plugins/dcc-dock-plugin/config_watcher.cpp b/plugins/dcc-dock-plugin/config_watcher.cpp deleted file mode 100644 index 3ddad2c25..000000000 --- a/plugins/dcc-dock-plugin/config_watcher.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "config_watcher.h" -#include "utils.h" - -#include -#include -#include -#include -#include -#include - -#include - -using namespace dcc_dock_plugin; - -DCORE_USE_NAMESPACE -/** - * @brief GSettingWatcher::GSettingWatcher 用于监听处于 \a baseSchemasId + "." + \a module 配置下的配置项内容变化,并将变化应用到绑定的控件上 - */ -ConfigWatcher::ConfigWatcher(const QString &appId, const QString &fileName, QObject *parent) - : QObject(parent) - , m_config(DConfig::create(appId, fileName, QString(), this)) -{ - if (m_config->isValid()) { - connect(m_config, &DConfig::valueChanged, this, &ConfigWatcher::onStatusModeChanged); - } else { - qWarning() << "config parse failed:" << fileName; - } -} - -ConfigWatcher::~ConfigWatcher() -{ - m_map.clear(); -} - -void ConfigWatcher::bind(const QString &key, QWidget *binder) -{ - m_map.insert(key, binder); - - setStatus(key, binder); - // 自动解绑 - connect(binder, &QObject::destroyed, this, [=] { - m_map.remove(m_map.key(binder), binder); - }); -} - -void ConfigWatcher::setStatus(const QString &key, QWidget *binder) -{ - if (!binder || !m_config->isValid() || !m_config->keyList().contains(key)) - return; - - const QString setting = m_config->value(key).toString(); - - if ("Enabled" == setting) { - binder->setEnabled(true); - } else if ("Disabled" == setting) { - binder->setEnabled(false); - } - - binder->setVisible("Hidden" != setting); -} - -void ConfigWatcher::onStatusModeChanged(const QString &key) -{ - if (!m_map.isEmpty() && m_map.contains(key)) { - for (auto it = m_map.begin(); it != m_map.end(); ++it) { - if (key == it.key()) { - setStatus(key, it.value()); - } - } - } -} diff --git a/plugins/dcc-dock-plugin/config_watcher.h b/plugins/dcc-dock-plugin/config_watcher.h deleted file mode 100644 index db58a97be..000000000 --- a/plugins/dcc-dock-plugin/config_watcher.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef GSETTINGWATCHER_H -#define GSETTINGWATCHER_H - -#include - -#include -#include -#include - -class QGSettings; -class QListView; -class QStandardItem; - -DCORE_BEGIN_NAMESPACE -class DConfig; -DCORE_END_NAMESPACE - -namespace dcc_dock_plugin { -class ConfigWatcher : public QObject -{ - Q_OBJECT - -public: - ConfigWatcher(const QString &appId, const QString &fileName, QObject *parent = nullptr); - ~ConfigWatcher(); - - void bind(const QString &key, QWidget *binder); - -private: - void setStatus(const QString &key, QWidget *binder); - void onStatusModeChanged(const QString &key); - -private: - QMultiHash m_map; - DTK_CORE_NAMESPACE::DConfig *m_config; -}; -} - -#endif // GSETTINGWATCHER_H diff --git a/plugins/dcc-dock-plugin/dock_settings.json b/plugins/dcc-dock-plugin/dock_settings.json deleted file mode 100644 index dbc6b7b2e..000000000 --- a/plugins/dcc-dock-plugin/dock_settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "api" : "1.0.0" -} \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/module_widget.cpp b/plugins/dcc-dock-plugin/module_widget.cpp deleted file mode 100644 index 2af9dd849..000000000 --- a/plugins/dcc-dock-plugin/module_widget.cpp +++ /dev/null @@ -1,437 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "module_widget.h" -#include "utils.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DWIDGET_USE_NAMESPACE - -enum DisplayMode { - Fashion = 0, - Efficient = 1, -}; - -enum HideMode { - KeepShowing = 0, - KeepHidden = 1, - SmartHide = 3, -}; - -enum Position { - Top = 0, - Right = 1, - Bottom = 2, - Left = 3, -}; - -ModuleWidget::ModuleWidget(QWidget *parent) - : QScrollArea(parent) - , m_modeComboxWidget(new ComboxWidget(this)) - , m_positionComboxWidget(new ComboxWidget(this)) - , m_stateComboxWidget(new ComboxWidget(this)) - , m_screenSettingComboxWidget(new ComboxWidget(this)) - , m_pluginTips(new DTipLabel(tr("Select which icons appear in the Dock"), this)) - , m_pluginView(new DListView(this)) - , m_pluginModel(new QStandardItemModel(this)) - , m_daemonDockInter(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus(), this)) - , m_dockInter(new DBusInter("com.deepin.dde.Dock", "/com/deepin/dde/Dock", QDBusConnection::sessionBus(), this)) - , m_dconfigWatcher(new ConfigWatcher("org.deepin.dde.control-center", "org.deepin.dde.dock.plugin", this)) - , m_sliderPressed(false) -{ - //~ contents_path /personalization/Dock - //~ child_page Dock - m_pluginAreaTitle = new TitleLabel(tr("Plugin Area"), this); - - //~ contents_path /personalization/Dock - //~ child_page Dock - m_sizeSlider = new TitledSliderItem(tr("Size"), this); - - //~ contents_path /personalization/Dock - //~ child_page Dock - m_screenSettingTitle = new TitleLabel(tr("Multiple Displays"), this); - - // 异步,否则频繁调用可能会导致卡顿 - m_daemonDockInter->setSync(false); - initUI(); - - connect(m_dockInter, &DBusInter::pluginVisibleChanged, this, &ModuleWidget::updateItemCheckStatus); -} - -ModuleWidget::~ModuleWidget() -{ -} - -void ModuleWidget::initUI() -{ - setBackgroundRole(QPalette::Base); - setFrameShape(QFrame::NoFrame); - setWidgetResizable(true); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - QVBoxLayout *layout = new QVBoxLayout; - layout->setContentsMargins(10, 10, 10, 10); - layout->setSpacing(0); - - static QMap g_modeMap = {{tr("Fashion mode"), Fashion} - , {tr("Efficient mode"), Efficient}}; - // 模式 - if (Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "modeVisible", true).toBool()) { - //~ contents_path /personalization/Dock - //~ child_page Dock - m_modeComboxWidget->setTitle(tr("Mode")); - m_modeComboxWidget->addBackground(); - m_modeComboxWidget->setComboxOption(QStringList() << tr("Fashion mode") << tr("Efficient mode")); - m_modeComboxWidget->setCurrentText(g_modeMap.key(m_daemonDockInter->displayMode())); - connect(m_modeComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) { - m_daemonDockInter->setDisplayMode(g_modeMap.value(text)); - }); - connect(m_daemonDockInter, &DBusDock::DisplayModeChanged, this, [ = ] (int value) { - DisplayMode mode = static_cast(value); - if (g_modeMap.key(mode) == m_modeComboxWidget->comboBox()->currentText()) - return; - - m_modeComboxWidget->setCurrentText(g_modeMap.key(mode)); - }); - layout->addWidget(m_modeComboxWidget); - m_dconfigWatcher->bind("dockModel", m_modeComboxWidget); - } else { - m_modeComboxWidget->setVisible(false); - } - - if (Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "locationVisible", true).toBool()) { - // 位置 - static QMap g_positionMap = {{tr("Top"), Top} - , {tr("Bottom"), Bottom} - , {tr("Left"), Left} - , {tr("Right"), Right}}; - - //~ contents_path /personalization/Dock - //~ child_page Dock - m_positionComboxWidget->setTitle(tr("Location")); - m_positionComboxWidget->addBackground(); - m_positionComboxWidget->setComboxOption(QStringList() << tr("Top") << tr("Bottom") << tr("Left") << tr("Right")); - m_positionComboxWidget->setCurrentText(g_positionMap.key(m_daemonDockInter->position())); - connect(m_positionComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) { - m_daemonDockInter->setPosition(g_positionMap.value(text)); - }); - connect(m_daemonDockInter, &DBusDock::PositionChanged, this, [ = ] (int position) { - Position pos = static_cast(position); - if (g_positionMap.key(pos) == m_positionComboxWidget->comboBox()->currentText()) - return; - - m_positionComboxWidget->setCurrentText(g_positionMap.key(pos)); - }); - layout->addSpacing(10); - layout->addWidget(m_positionComboxWidget); - m_dconfigWatcher->bind("dockLocation", m_positionComboxWidget); - } else { - m_positionComboxWidget->setVisible(false); - } - - // 状态 - if (Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "statusVisible", true).toBool()) { - static QMap g_stateMap = {{tr("Keep shown"), KeepShowing} - , {tr("Keep hidden"), KeepHidden} - , {tr("Smart hide"), SmartHide}}; - - //~ contents_path /personalization/Dock - //~ child_page Dock - m_stateComboxWidget->setTitle(tr("Status")); - m_stateComboxWidget->addBackground(); - m_stateComboxWidget->setComboxOption(QStringList() << tr("Keep shown") << tr("Keep hidden") << tr("Smart hide")); - m_stateComboxWidget->setCurrentText(g_stateMap.key(m_daemonDockInter->hideMode())); - connect(m_stateComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) { - m_daemonDockInter->setHideMode(g_stateMap.value(text)); - }); - connect(m_daemonDockInter, &DBusDock::HideModeChanged, this, [ = ] (int value) { - HideMode mode = static_cast(value); - if (g_stateMap.key(mode) == m_stateComboxWidget->comboBox()->currentText()) - return; - - m_stateComboxWidget->setCurrentText(g_stateMap.key(mode)); - }); - layout->addSpacing(10); - layout->addWidget(m_stateComboxWidget); - m_dconfigWatcher->bind("dockState", m_stateComboxWidget); - } else { - m_stateComboxWidget->setVisible(false); - } - - // 高度调整控件 - m_sizeSlider->addBackground(); - m_sizeSlider->slider()->setRange(40, 100); - QStringList ranges; - ranges << tr("Small") << "" << tr("Large"); - m_sizeSlider->setAnnotations(ranges); - connect(m_daemonDockInter, &DBusDock::DisplayModeChanged, this, &ModuleWidget::updateSliderValue); - connect(m_daemonDockInter, &DBusDock::WindowSizeFashionChanged, this, &ModuleWidget::updateSliderValue); - connect(m_daemonDockInter, &DBusDock::WindowSizeEfficientChanged, this, &ModuleWidget::updateSliderValue); - connect(m_sizeSlider->slider(), &DSlider::sliderMoved, m_sizeSlider->slider(), &DSlider::valueChanged); - connect(m_sizeSlider->slider(), &DSlider::valueChanged, this, [ = ] (int value) { - m_dockInter->resizeDock(value, true); - }); - connect(m_sizeSlider->slider(), &DSlider::sliderPressed, m_dockInter, [ = ] { - m_daemonDockInter->blockSignals(true); - m_sliderPressed = true; - }); - connect(m_sizeSlider->slider(), &DSlider::sliderReleased, m_dockInter, [ = ] { - m_daemonDockInter->blockSignals(false); - m_sliderPressed = false; - - // 松开手后通知dock拖拽状态接触 - QTimer::singleShot(0, this, [ = ] { - int offset = m_sizeSlider->slider()->value(); - m_dockInter->resizeDock(offset, false); - }); - }); - - updateSliderValue(); - m_dconfigWatcher->bind("dockSize", m_sizeSlider); - - layout->addSpacing(10); - layout->addWidget(m_sizeSlider); - - // 多屏显示设置 - if (QDBusConnection::sessionBus().interface()->isServiceRegistered("com.deepin.dde.Dock") - && QApplication::screens().size() > 1 - && !isCopyMode() - && Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "multiscreenVisible", true).toBool()) { - static QMap g_screenSettingMap = {{tr("On screen where the cursor is"), false} - , {tr("Only on main screen"), true}}; - - layout->addSpacing(10); - layout->addWidget(m_screenSettingTitle); - m_screenSettingComboxWidget->setTitle(tr("Show Dock")); - m_screenSettingComboxWidget->addBackground(); - m_screenSettingComboxWidget->setComboxOption(QStringList() << tr("On screen where the cursor is") << tr("Only on main screen")); - m_screenSettingComboxWidget->setCurrentText(g_screenSettingMap.key(m_dockInter->showInPrimary())); - connect(m_screenSettingComboxWidget, &ComboxWidget::onSelectChanged, this, [ = ] (const QString &text) { - m_dockInter->setShowInPrimary(g_screenSettingMap.value(text)); - }); - connect(qApp, &QApplication::screenAdded, this, [ = ] { - m_screenSettingTitle->setVisible(qApp->screens().count() > 1); - m_screenSettingComboxWidget->setVisible(qApp->screens().count() > 1); - }); - connect(qApp, &QApplication::screenRemoved, this, [ = ] { - m_screenSettingTitle->setVisible(qApp->screens().count() > 1); - m_screenSettingComboxWidget->setVisible(qApp->screens().count() > 1); - }); - - // 这里不会生效,但实际场景中也不存在有其他可配置的地方,可以不用处理 - connect(m_dockInter, &DBusInter::ShowInPrimaryChanged, this, [ = ] (bool showInPrimary) { - if (m_screenSettingComboxWidget->comboBox()->currentText() == g_screenSettingMap.key(showInPrimary)) - return; - - m_screenSettingComboxWidget->blockSignals(true); - m_screenSettingComboxWidget->setCurrentText(g_screenSettingMap.key(showInPrimary)); - m_screenSettingComboxWidget->blockSignals(false); - }); - layout->addSpacing(10); - layout->addWidget(m_screenSettingComboxWidget); - m_dconfigWatcher->bind("multiscreen", m_screenSettingTitle); - m_dconfigWatcher->bind("multiscreen", m_screenSettingComboxWidget); - } else { - m_screenSettingTitle->setVisible(false); - m_screenSettingComboxWidget->setVisible(false); - } - - // 插件区域 - QDBusPendingReply reply = m_dockInter->GetLoadedPlugins(); - QStringList plugins = reply.value(); - if (reply.error().type() != QDBusError::ErrorType::NoError - || !Utils::SettingValue("com.deepin.dde.dock.module.menu", QByteArray(), "hideVisible", true).toBool()) { - m_pluginAreaTitle->setVisible(false); - m_pluginTips->setVisible(false); - m_pluginView->setVisible(false); - qWarning() << "dbus call failed, method: 'GetLoadedPlugins()'"; - } else { - const QMap &pluginIconMap = {{"AiAssistant", "dcc_dock_assistant"} - , {"show-desktop", "dcc_dock_desktop"} - , {"onboard", "dcc_dock_keyboard"} - , {"notifications", "dcc_dock_notify"} - , {"shutdown", "dcc_dock_power"} - , {"multitasking", "dcc_dock_task"} - , {"datetime", "dcc_dock_time"} - , {"system-monitor", "dcc_dock_systemmonitor"} - , {"grand-search", "dcc_dock_grandsearch"} - , {"trash", "dcc_dock_trash"} - , {"shot-start-plugin", "shot-start-plugin"}}; - if (plugins.size() != 0) { - layout->addSpacing(20); - layout->addWidget(m_pluginAreaTitle); - m_dconfigWatcher->bind("dockPlugins", m_pluginAreaTitle); - - DFontSizeManager::instance()->bind(m_pluginTips, DFontSizeManager::T8); - m_pluginTips->adjustSize(); - m_pluginTips->setWordWrap(true); - m_pluginTips->setContentsMargins(10, 0, 10, 0); - m_pluginTips->setAlignment(Qt::AlignLeft); - layout->addSpacing(2); - layout->addWidget(m_pluginTips); - m_dconfigWatcher->bind("dockPlugins", m_pluginTips); - - m_pluginView->setAccessibleName("pluginList"); - m_pluginView->setBackgroundType(DStyledItemDelegate::BackgroundType::ClipCornerBackground); - m_pluginView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_pluginView->setSelectionMode(QListView::SelectionMode::NoSelection); - m_pluginView->setEditTriggers(DListView::NoEditTriggers); - m_pluginView->setFrameShape(DListView::NoFrame); - m_pluginView->setViewportMargins(0, 0, 0, 0); - m_pluginView->setItemSpacing(1); - - QMargins itemMargins(m_pluginView->itemMargins()); - itemMargins.setLeft(14); - m_pluginView->setItemMargins(itemMargins); - - m_pluginView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); - QScroller *scroller = QScroller::scroller(m_pluginView->viewport()); - QScrollerProperties sp; - sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff); - scroller->setScrollerProperties(sp); - - m_pluginView->setModel(m_pluginModel); - - layout->addSpacing(10); - layout->addWidget(m_pluginView); - m_dconfigWatcher->bind("dockPlugins", m_pluginView); - - for (auto name : plugins) { - DStandardItem *item = new DStandardItem(name); - item->setFontSize(DFontSizeManager::T8); - QSize size(16, 16); - - // 插件图标 - auto leftAction = new DViewItemAction(Qt::AlignVCenter, size, size, true); - - const QString pluginKey = m_dockInter->getPluginKey(name); - QIcon pluginIcon; - // 第三方插件通过pluginKey从系统中读取图标 - if (pluginIconMap.contains(pluginKey)) { - pluginIcon = QIcon::fromTheme(pluginIconMap.value(m_dockInter->getPluginKey(name))); - } else { - pluginIcon = QIcon::fromTheme(pluginKey); - } - - // 如果获取不到图标则使用默认图标 - if (pluginIcon.isNull()) { - pluginIcon = QIcon::fromTheme("dcc_dock_plug_in"); - } - - leftAction->setIcon(pluginIcon); - item->setActionList(Qt::Edge::LeftEdge, {leftAction}); - - auto rightAction = new DViewItemAction(Qt::AlignVCenter, size, size, true); - bool visible = m_dockInter->getPluginVisible(name); - auto checkstatus = visible ? DStyle::SP_IndicatorChecked : DStyle::SP_IndicatorUnchecked ; - auto checkIcon = qobject_cast(style())->standardIcon(checkstatus); - rightAction->setIcon(checkIcon); - item->setActionList(Qt::Edge::RightEdge, {rightAction}); - m_pluginModel->appendRow(item); - - connect(rightAction, &DViewItemAction::triggered, this, [ = ] { - bool checked = m_dockInter->getPluginVisible(name); - m_dockInter->setPluginVisible(name, !checked); - updateItemCheckStatus(name, !checked); - }); - } - // 固定大小,防止滚动 - int lineHeight = m_pluginView->visualRect(m_pluginView->indexAt(QPoint(0, 0))).height(); - m_pluginView->setMinimumHeight(lineHeight * plugins.size() + 10); - } else { - m_pluginAreaTitle->setVisible(false); - m_pluginTips->setVisible(false); - m_pluginView->setVisible(false); - } - } - - // 支持在触摸屏上滚动 - QScroller::grabGesture(this->viewport(), QScroller::LeftMouseButtonGesture); - QScroller *scroller = QScroller::scroller(this->window()); - QScrollerProperties sp; - sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff); - scroller->setScrollerProperties(sp); - - // 保持内容正常铺满 - layout->addStretch(); - - // 界面内容过多时可滚动查看 - QWidget *widget = new QWidget; - widget->setLayout(layout); - setWidget(widget); -} - -/**判断屏幕是否为复制模式的依据,第一个屏幕的X和Y值是否和其他的屏幕的X和Y值相等 - * 对于复制模式,这两个值肯定是相等的,如果不是复制模式,这两个值肯定不等,目前支持双屏 - * @brief DisplayManager::isCopyMode - * @return - */ -bool ModuleWidget::isCopyMode() -{ - QList screens = qApp->screens(); - if (screens.size() < 2) - return false; - - // 在多个屏幕的情况下,如果所有屏幕的位置的X和Y值都相等,则认为是复制模式 - QRect screenRect = screens[0]->availableGeometry(); - for (int i = 1; i < screens.size(); i++) { - QRect rect = screens[i]->availableGeometry(); - if (screenRect.x() != rect.x() || screenRect.y() != rect.y()) - return false; - } - - return true; -} - -void ModuleWidget::updateSliderValue() -{ - auto displayMode = m_daemonDockInter->displayMode(); - - m_sizeSlider->slider()->blockSignals(true); - if (displayMode == DisplayMode::Fashion) { - if (int(m_daemonDockInter->windowSizeFashion()) != m_sizeSlider->slider()->value()) - m_sizeSlider->slider()->setValue(int(m_daemonDockInter->windowSizeFashion())); - } else if (displayMode == DisplayMode::Efficient) { - if (int(m_daemonDockInter->windowSizeEfficient()) != m_sizeSlider->slider()->value()) - m_sizeSlider->slider()->setValue(int(m_daemonDockInter->windowSizeEfficient())); - } - m_sizeSlider->slider()->blockSignals(false); -} - -void ModuleWidget::updateItemCheckStatus(const QString &name, bool visible) -{ - for (int i = 0; i < m_pluginModel->rowCount(); ++i) { - auto item = static_cast(m_pluginModel->item(i)); - if (item->text() != name || item->actionList(Qt::Edge::RightEdge).size() < 1) - continue; - - auto action = item->actionList(Qt::Edge::RightEdge).first(); - auto checkstatus = visible ? DStyle::SP_IndicatorChecked : DStyle::SP_IndicatorUnchecked ; - auto icon = qobject_cast(style())->standardIcon(checkstatus); - action->setIcon(icon); - m_pluginView->update(item->index()); - break; - } -} diff --git a/plugins/dcc-dock-plugin/module_widget.h b/plugins/dcc-dock-plugin/module_widget.h deleted file mode 100644 index fea3d947b..000000000 --- a/plugins/dcc-dock-plugin/module_widget.h +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef MODULE_WIDGET_H -#define MODULE_WIDGET_H - -#include - -#include - -#include - -#include "com_deepin_dde_dock.h" -#include "config_watcher.h" - -namespace dcc { -namespace widgets { -class ComboxWidget; -class TitledSliderItem; -} -} - -DWIDGET_BEGIN_NAMESPACE -class DListView; -class DTipLabel; -DWIDGET_END_NAMESPACE - -class TitleLabel; -class QStandardItemModel; - -using namespace dcc::widgets; -using namespace dcc_dock_plugin; -using DBusDock = com::deepin::dde::daemon::Dock; -using DBusInter = com::deepin::dde::Dock; - -class ModuleWidget : public QScrollArea -{ - Q_OBJECT -public: - explicit ModuleWidget(QWidget *parent = nullptr); - ~ ModuleWidget(); - -private: - void initUI(); - bool isCopyMode(); - -private Q_SLOTS: - void updateSliderValue(); - void updateItemCheckStatus(const QString &name, bool visible); - -private: - ComboxWidget *m_modeComboxWidget; - ComboxWidget *m_positionComboxWidget; - ComboxWidget *m_stateComboxWidget; - - TitledSliderItem *m_sizeSlider; - - TitleLabel *m_screenSettingTitle; - ComboxWidget *m_screenSettingComboxWidget; - - TitleLabel *m_pluginAreaTitle; - DTK_WIDGET_NAMESPACE::DTipLabel *m_pluginTips; - DTK_WIDGET_NAMESPACE::DListView *m_pluginView; - QStandardItemModel *m_pluginModel; - - DBusDock *m_daemonDockInter; - DBusInter *m_dockInter; - ConfigWatcher *m_dconfigWatcher; - - bool m_sliderPressed; -}; - -#endif // MODULE_WIDGET_H diff --git a/plugins/dcc-dock-plugin/org.deepin.dde.dock.plugin.json b/plugins/dcc-dock-plugin/org.deepin.dde.dock.plugin.json deleted file mode 100644 index 565c10e2d..000000000 --- a/plugins/dcc-dock-plugin/org.deepin.dde.dock.plugin.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "magic":"dsg.config.meta", - "version":"1.0", - "contents":{ - "dockModel":{ - "value":"Enabled", - "serial":0, - "flags":[], - "name":"Model", - "name[zh_CN]":"模式", - "description[zh_CN]":"此配置为模式选择功能的是否启用,默认为启用;当配置为启用时,该设置项可以设置;当配置为禁用时,该设置项置灰;当配置为隐藏时,该设置项隐藏;", - "description":"", - "permissions":"readwrite", - "visibility":"private" - }, - "dockLocation":{ - "value":"Enabled", - "serial":0, - "flags":[], - "name":"Location", - "name[zh_CN]":"位置", - "description[zh_CN]":"此配置为位置选择功能的是否启用,默认为启用;当配置为启用时,该设置项可以设置;当配置为禁用时,该设置项置灰;当配置为隐藏时,该设置项隐藏;", - "description":"", - "permissions":"readwrite", - "visibility":"private" - }, - "dockState":{ - "value":"Enabled", - "serial":0, - "flags":[], - "name":"State", - "name[zh_CN]":"状态", - "description[zh_CN]":"此配置为状态选择功能的是否启用,默认为启用;当配置为启用时,该设置项可以设置;当配置为禁用时,该设置项置灰;当配置为隐藏时,该设置项隐藏;", - "description":"", - "permissions":"readwrite", - "visibility":"private" - }, - "dockSize":{ - "value":"Enabled", - "serial":0, - "flags":[], - "name":"Size", - "name[zh_CN]":"调整大小", - "description[zh_CN]":"此配置为调整大小功能的是否启用,默认为启用;当配置为启用时,该设置项可以设置;当配置为禁用时,该设置项置灰;当配置为隐藏时,该设置项隐藏;", - "description":"", - "permissions":"readwrite", - "visibility":"private" - }, - "multiscreen":{ - "value":"Enabled", - "serial":0, - "flags":[], - "name":"Multi-screen", - "name[zh_CN]":"多屏显示设置", - "description[zh_CN]":"此配置为多屏显示设置项功能的是否启用,默认为启用;当配置为启用时,该设置项可以设置;当配置为禁用时,该设置项置灰;当配置为隐藏时,该设置项隐藏;", - "description":"", - "permissions":"readwrite", - "visibility":"private" - }, - "dockPlugins":{ - "value":"Enabled", - "serial":0, - "flags":[], - "name":"Plugins", - "name[zh_CN]":"插件", - "description[zh_CN]":"此配置为插件显示功能的是否启用,默认为启用;当配置为启用时,该设置项可以设置;当配置为禁用时,该设置项置灰;当配置为隐藏时,该设置项隐藏;", - "description":"", - "permissions":"readwrite", - "visibility":"private" - } - } -} \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/resources.qrc b/plugins/dcc-dock-plugin/resources.qrc deleted file mode 100644 index 420796f2d..000000000 --- a/plugins/dcc-dock-plugin/resources.qrc +++ /dev/null @@ -1,42 +0,0 @@ - - - actions/icon_dock_32px.svg - texts/dcc_dock_time_16px.svg - texts/dcc_dock_assistant_16px.svg - texts/dcc_dock_desktop_16px.svg - texts/dcc_dock_keyboard_16px.svg - texts/dcc_dock_notify_16px.svg - texts/dcc_dock_plug_in_16px.svg - texts/dcc_dock_power_16px.svg - texts/dcc_dock_task_16px.svg - texts/dcc_dock_trash_16px.svg - texts/dcc_dock_grandsearch_16px.svg - texts/dcc_dock_systemmonitor_16px.svg - texts/shot-start-plugin_16px.svg - - - translations/dcc-dock-plugin.ts - translations/dcc-dock-plugin_bo.ts - translations/dcc-dock-plugin_az.ts - translations/dcc-dock-plugin_cs.ts - translations/dcc-dock-plugin_fi.ts - translations/dcc-dock-plugin_hu.ts - translations/dcc-dock-plugin_nl.ts - translations/dcc-dock-plugin_pt.ts - translations/dcc-dock-plugin_sq.ts - translations/dcc-dock-plugin_ug.ts - translations/dcc-dock-plugin_uk.ts - translations/dcc-dock-plugin_zh_CN.ts - translations/dcc-dock-plugin_zh_HK.ts - translations/dcc-dock-plugin_zh_TW.ts - translations/dcc-dock-plugin_de.ts - translations/dcc-dock-plugin_ca.ts - translations/dcc-dock-plugin_es.ts - translations/dcc-dock-plugin_hr.ts - translations/dcc-dock-plugin_it.ts - translations/dcc-dock-plugin_pl.ts - translations/dcc-dock-plugin_pt_BR.ts - translations/dcc-dock-plugin_ru.ts - translations/dcc-dock-plugin_en_US.ts - - diff --git a/plugins/dcc-dock-plugin/settings_module.cpp b/plugins/dcc-dock-plugin/settings_module.cpp deleted file mode 100644 index 6deca17c0..000000000 --- a/plugins/dcc-dock-plugin/settings_module.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "settings_module.h" -#include "module_widget.h" -#include "config_watcher.h" - -#include - -#include -#include - -DWIDGET_USE_NAMESPACE -DCORE_USE_NAMESPACE - -SettingsModule::SettingsModule() - : QObject() - , ModuleInterface() - , m_moduleWidget(nullptr) - , m_config(DConfig::create("org.deepin.dde.control-center", "org.deepin.dde.dock.plugin", QString(), this)) -{ - QTranslator *translator = new QTranslator(this); - translator->load(QString("/usr/share/dcc-dock-plugin/translations/dcc-dock-plugin_%1.qm").arg(QLocale::system().name())); - QCoreApplication::installTranslator(translator); -} - -SettingsModule::~SettingsModule() -{ - -} - -void SettingsModule::initialize() -{ - -} - -void SettingsModule::active() -{ - m_moduleWidget = new ModuleWidget; - - m_frameProxy->pushWidget(this, m_moduleWidget); - m_moduleWidget->setVisible(true); -} - -QStringList SettingsModule::availPage() const -{ - return QStringList() << "Dock"; -} - -const QString SettingsModule::displayName() const -{ - return tr("Dock"); -} - -QIcon SettingsModule::icon() const -{ - return QIcon::fromTheme("icon_dock"); -} - -QString SettingsModule::translationPath() const -{ - return QString(":/translations/dcc-dock-plugin_%1.ts"); -} - -QString SettingsModule::path() const -{ - return PERSONALIZATION; -} - -QString SettingsModule::follow() const -{ - return "10"; -} - -const QString SettingsModule::name() const -{ - return QStringLiteral("Dock"); -} - -void SettingsModule::showPage(const QString &pageName) -{ - Q_UNUSED(pageName); -} - -void SettingsModule::addChildPageTrans() const -{ - if (!m_frameProxy) - return; - - m_frameProxy->addChildPageTrans("Dock", tr("Dock")); -} - -void SettingsModule::initSearchData() -{ - onStatusChanged(); - - if (m_config->isValid()) - connect(m_config, &DConfig::valueChanged, this, &SettingsModule::onStatusChanged); -} - -void SettingsModule::preInitialize(bool sync, FrameProxyInterface::PushType) -{ - Q_UNUSED(sync); - addChildPageTrans(); - initSearchData(); -} - -void SettingsModule::onStatusChanged() -{ - if (!m_frameProxy) - return; - - // 模块名称 - const QString &module = m_frameProxy->moduleDisplayName(PERSONALIZATION); - - // 子模块名称 - const QString &dock = tr("Dock"); - - // 二级菜单显示状态设置 - m_frameProxy->setWidgetVisible(module, dock, true); - - auto visibleState = [ = ](const QString &key) { - return (!m_config || !m_config->isValid() || m_config->value(QString("%1").arg(key)).toString() == "Enabled"); - }; - - // 三级菜单显示状态设置 - m_frameProxy->setDetailVisible(module, dock, tr("Mode"), visibleState("dockModel")); - m_frameProxy->setDetailVisible(module, dock, tr("Location"), visibleState("dockLocation")); - m_frameProxy->setDetailVisible(module, dock, tr("Status"), visibleState("dockState")); - m_frameProxy->setDetailVisible(module, dock, tr("Size"), visibleState("dockSize")); - m_frameProxy->setDetailVisible(module, dock, tr("Show Dock"), visibleState("multiscreen")); - m_frameProxy->setDetailVisible(module, dock, tr("Plugin Area"), visibleState("dockPlugins")); - m_frameProxy->updateSearchData(module); -} diff --git a/plugins/dcc-dock-plugin/settings_module.h b/plugins/dcc-dock-plugin/settings_module.h deleted file mode 100644 index 6527991c2..000000000 --- a/plugins/dcc-dock-plugin/settings_module.h +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef SETTINGSMODULE_H -#define SETTINGSMODULE_H - -#include - -#include - -#include "interface/namespace.h" -#include "interface/moduleinterface.h" -#include "interface/frameproxyinterface.h" - -namespace DCC_NAMESPACE { - class ModuleInterface; - class FrameProxyInterface; -} - -using namespace DCC_NAMESPACE; - -DCORE_BEGIN_NAMESPACE -class DConfig; -DCORE_END_NAMESPACE - -class ModuleWidget; -class SettingsModule : public QObject, public ModuleInterface -{ - Q_OBJECT - - Q_PLUGIN_METADATA(IID ModuleInterface_iid FILE "dock_settings.json") - Q_INTERFACES(DCC_NAMESPACE::ModuleInterface) - -public: - explicit SettingsModule(); - - ~SettingsModule() Q_DECL_OVERRIDE; - - void initialize() Q_DECL_OVERRIDE; - - QStringList availPage() const Q_DECL_OVERRIDE; - - const QString displayName() const Q_DECL_OVERRIDE; - - QIcon icon() const Q_DECL_OVERRIDE; - - QString translationPath() const Q_DECL_OVERRIDE; - - QString path() const Q_DECL_OVERRIDE; - - QString follow() const Q_DECL_OVERRIDE; - - const QString name() const Q_DECL_OVERRIDE; - - void showPage(const QString &pageName) Q_DECL_OVERRIDE; - - void addChildPageTrans() const Q_DECL_OVERRIDE; - - void initSearchData() Q_DECL_OVERRIDE; - - void preInitialize(bool sync = false,FrameProxyInterface::PushType = FrameProxyInterface::PushType::Normal) Q_DECL_OVERRIDE; - -private: - void onStatusChanged(); - -public Q_SLOTS: - void active() Q_DECL_OVERRIDE; - -private: - ModuleWidget *m_moduleWidget; - DTK_CORE_NAMESPACE::DConfig *m_config; -}; - -#endif // SETTINGSMODULE_H diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_assistant_16px.svg b/plugins/dcc-dock-plugin/texts/dcc_dock_assistant_16px.svg deleted file mode 100644 index 7c2010bf1..000000000 --- a/plugins/dcc-dock-plugin/texts/dcc_dock_assistant_16px.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - icon/dock/assistant - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_desktop_16px.svg b/plugins/dcc-dock-plugin/texts/dcc_dock_desktop_16px.svg deleted file mode 100644 index c0fa9ab19..000000000 --- a/plugins/dcc-dock-plugin/texts/dcc_dock_desktop_16px.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - icon/dock/desktop - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_grandsearch_16px.svg b/plugins/dcc-dock-plugin/texts/dcc_dock_grandsearch_16px.svg deleted file mode 100644 index b1e0e65ba..000000000 --- a/plugins/dcc-dock-plugin/texts/dcc_dock_grandsearch_16px.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - icon/dock-set/search - - - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_notify_16px.svg b/plugins/dcc-dock-plugin/texts/dcc_dock_notify_16px.svg deleted file mode 100644 index fba759921..000000000 --- a/plugins/dcc-dock-plugin/texts/dcc_dock_notify_16px.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - icon/dock/notify - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_systemmonitor_16px.svg b/plugins/dcc-dock-plugin/texts/dcc_dock_systemmonitor_16px.svg deleted file mode 100644 index 50ee6bb28..000000000 --- a/plugins/dcc-dock-plugin/texts/dcc_dock_systemmonitor_16px.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - icon/dock-set/monitor - - - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_task_16px.svg b/plugins/dcc-dock-plugin/texts/dcc_dock_task_16px.svg deleted file mode 100644 index 0537c2347..000000000 --- a/plugins/dcc-dock-plugin/texts/dcc_dock_task_16px.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - icon/dock/task - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_time_16px.svg b/plugins/dcc-dock-plugin/texts/dcc_dock_time_16px.svg deleted file mode 100644 index da813d6f9..000000000 --- a/plugins/dcc-dock-plugin/texts/dcc_dock_time_16px.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - icon/dock/time - - - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/texts/shot-start-plugin_16px.svg b/plugins/dcc-dock-plugin/texts/shot-start-plugin_16px.svg deleted file mode 100644 index 367dd0180..000000000 --- a/plugins/dcc-dock-plugin/texts/shot-start-plugin_16px.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - 编组 3 - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translate_generation.sh b/plugins/dcc-dock-plugin/translate_generation.sh deleted file mode 100755 index c9080923b..000000000 --- a/plugins/dcc-dock-plugin/translate_generation.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# this file is used to auto-generate .qm file from .ts file. -# author: shibowen at linuxdeepin.com - -ts_list=(`ls translations/*.ts`) - -for ts in "${ts_list[@]}" -do - printf "\nprocess ${ts}\n" - lrelease "${ts}" -done diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin.ts deleted file mode 100644 index 378244be6..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin.ts +++ /dev/null @@ -1,776 +0,0 @@ - - - - - AbstractPluginsController - - - The plugin %1 is not compatible with the system. - - - - - AirplaneModeApplet - - - Airplane Mode - - - - - AirplaneModeItem - - - - Airplane mode enabled - - - - - Turn off - - - - - Turn on - - - - - Airplane Mode settings - - - - - Airplane mode disabled - - - - - AirplaneModePlugin - - - Airplane Mode - - - - - AppDragWidget - - - Remove - - - - - BluetoothApplet - - - Bluetooth settings - - - - - BluetoothItem - - - Turn off - - - - - Turn on - - - - - Bluetooth settings - - - - - %1 connected - - - - - Connecting... - - - - - Bluetooth - - - - - Turned off - - - - - BluetoothPlugin - - - Bluetooth - - - - - DBusAdaptors - - - Add keyboard layout - - - - - DatetimePlugin - - - Datetime - - - - - 12-hour time - - - - - 24-hour time - - - - - Time settings - - - - - DatetimeWidget - - - - Monday - - - - - Tuesday - - - - - Wednesday - - - - - Thursday - - - - - Friday - - - - - Saturday - - - - - Sunday - - - - - - monday - - - - - tuesday - - - - - wednesday - - - - - thursday - - - - - friday - - - - - saturday - - - - - sunday - - - - - %1year%2month%3day - - - - - DialogManager - - - Are you sure you want to empty %1 items? - - - - - Cancel - - - - - Delete - - - - - This action cannot be restored - - - - - DiskControlItem - - - Unknown device - - - - - Unknown volume - - - - - DiskMountPlugin - - - Disk - - - - - Open - - - - - Unmount all - - - - - LauncherItem - - - Launcher - - - - - MainWindow - - - Exit Safe Mode - - - - - Dock - Safe Mode - - - - - The Dock is in safe mode, please exit to show it properly - - - - - MenuWorker - - - Fashion Mode - - - - - Efficient Mode - - - - - Mode - Mode - - - - Top - Top - - - - Bottom - Bottom - - - - Left - Left - - - - Right - Right - - - - Location - Location - - - - Keep Shown - - - - - Keep Hidden - - - - - Smart Hide - - - - - Status - Status - - - - Dock settings - - - - - ModuleWidget - - - Size - Size - Dock - /personalization/Dock - - - - Multiple Displays - Multiple Displays - Dock - /personalization/Dock - - - - Plugin Area - Plugin Area - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Select which icons appear in the Dock - - - - - Fashion mode - Fashion mode - - - - - Efficient mode - Efficient mode - - - - Mode - Mode - Dock - /personalization/Dock - - - - - Top - Top - - - - - Bottom - Bottom - - - - - Left - Left - - - - - Right - Right - - - - Location - Location - Dock - /personalization/Dock - - - - - Keep shown - Keep shown - - - - - Keep hidden - Keep hidden - - - - - Smart hide - Smart hide - - - - Status - Status - Dock - /personalization/Dock - - - - Small - Small - - - - Large - Large - - - - - On screen where the cursor is - On screen where the cursor is - - - - - Only on main screen - Only on main screen - - - - Show Dock - Show Dock - - - - MultitaskingPlugin - - - - Multitasking View - - - - - Undock - - - - - OnboardPlugin - - - - Onboard - - - - - Settings - - - - - PowerPlugin - - - Power - - - - - Power settings - - - - - - Capacity %1 ... - - - - - Capacity %1 - - - - - Capacity %1, %2 min remaining - - - - - Capacity %1, %2 hr %3 min remaining - - - - - Capacity %1, fully charged - - - - - Charging %1 - - - - - Charging %1, %2 min until full - - - - - Charging %1, %2 hr %3 min until full - - - - - SettingsModule - - - - - Dock - Dock - - - - Mode - Mode - - - - Location - Location - - - - Status - Status - - - - Size - Size - - - - Show Dock - Show Dock - - - - Plugin Area - Plugin Area - - - - ShowDesktopPlugin - - - - Show Desktop - - - - - Undock - - - - - ShutdownPlugin - - - - Power - - - - - Shut down - - - - - Reboot - - - - - Suspend - - - - - Hibernate - - - - - Lock - - - - - Log out - - - - - Switch account - - - - - Power settings - - - - - SoundApplet - - - Volume - - - - - SoundItem - - - - Unmute - - - - - - Mute - - - - - Sound settings - - - - - No output devices - - - - - Volume %1 - - - - - SoundPlugin - - - Sound - - - - - TrashPlugin - - - Trash - - - - - Move to Trash - - - - - Trash - %1 file - - - - - Trash - %1 files - - - - - TrashWidget - - - Open - - - - - Empty - - - - diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_az.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_az.ts deleted file mode 100644 index bb5921a3e..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_az.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Ölçü - Dock - /personalization/Dock - - - - Multiple Displays - Çoxsaylı ekran - Dock - /personalization/Dock - - - - Plugin Area - Plaqin sahəsi - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Dok paneldə görünəcək nişanları seçin - - - - - Fashion mode - Müasir rejim - - - - - Efficient mode - Səmərəli rejim - - - - Mode - Rejim - Dock - /personalization/Dock - - - - - Top - Yuxarıda - - - - - Bottom - Aşağıda - - - - - Left - Sol - - - - - Right - Sağ - - - - Location - Yerləşmə - Dock - /personalization/Dock - - - - - Keep shown - Görünsün - - - - - Keep hidden - Gizli qalsın - - - - - Smart hide - Ağıllı gizlənmə - - - - Status - Vəziyyəti - Dock - /personalization/Dock - - - - Small - Kiçik - - - - Large - Geniş - - - - - On screen where the cursor is - Kursorun olduğu ekranda - - - - - Only on main screen - Yalnız əsas ekranda - - - - Show Dock - Dok paneli göstərmək - - - - SettingsModule - - - - - Dock - Dok panel - - - - Mode - Rejim - - - - Location - Yerləşmə - - - - Status - Vəziyyəti - - - - Size - Ölçü - - - - Show Dock - Dok paneli göstərmək - - - - Plugin Area - Plaqin sahəsi - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_bo.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_bo.ts deleted file mode 100644 index 86105e4c8..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_bo.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - ཆེ་ཆུང་། - Dock - /personalization/Dock - - - - Multiple Displays - བརྙན་མང་མངོན་སྟོན་སྒྲིག་འགོད། - Dock - /personalization/Dock - - - - Plugin Area - ལྷུ་ལག་ཁུལ་ཁོངས། - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - ལས་འགན་ཚན་བྱང་གི་ལྷུ་ལག་ཁུལ་དུ་མངོན་པའི་པར་རིས་འདེམས་པ། - - - - - Fashion mode - དར་སྲོལ་དཔེ་རྣམ། - - - - - Efficient mode - ལས་ཆོད་ཆེ་བའི་དཔེ་རྣམ། - - - - Mode - དཔེ་རྣམ། - Dock - /personalization/Dock - - - - - Top - གོང་། - - - - - Bottom - འོག - - - - - Left - གཡོན། - - - - - Right - གཡས། - - - - Location - གནས་ས། - Dock - /personalization/Dock - - - - - Keep shown - རྟག་ཏུ་མངོན་པ། - - - - - Keep hidden - རྟག་ཏུ་ཡིབ་པ། - - - - - Smart hide - རིག་ནུས་གབ་ཡིབ། - - - - Status - རྣམ་པ། - Dock - /personalization/Dock - - - - Small - ཆུང་ངུ། - - - - Large - ཆེ་བ། - - - - - On screen where the cursor is - ཙི་གུའི་གནས་ཡུལ་ལྟར་མངོན་པ། - - - - - Only on main screen - བརྙན་ཡོལ་ཨ་མ་ཁོ་ན་མངོན་པ། - - - - Show Dock - ལས་འགན་ཚན་བྱང་གི་གནས་ས། - - - - SettingsModule - - - - - Dock - ལས་འགན་ཚན་བྱང་། - - - - Mode - དཔེ་རྣམ། - - - - Location - གནས་ས། - - - - Status - རྣམ་པ། - - - - Size - ཆེ་ཆུང་། - - - - Show Dock - ལས་འགན་ཚན་བྱང་གི་གནས་ས། - - - - Plugin Area - ལྷུ་ལག་ཁུལ་ཁོངས། - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ca.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ca.ts deleted file mode 100644 index 14bee9c98..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ca.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Mida - Dock - /personalization/Dock - - - - Multiple Displays - Pantalles múltiples - Dock - /personalization/Dock - - - - Plugin Area - Àrea de connectors - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Seleccioneu quines icones apareixen a l'acoblador. - - - - - Fashion mode - Mode de moda - - - - - Efficient mode - Mode eficient - - - - Mode - Mode - Dock - /personalization/Dock - - - - - Top - Dalt - - - - - Bottom - A baix - - - - - Left - A l'esquerra - - - - - Right - A la dreta - - - - Location - Ubicació - Dock - /personalization/Dock - - - - - Keep shown - Mantén-lo visible - - - - - Keep hidden - Mantén-lo amagat - - - - - Smart hide - Ocultació intel·ligent - - - - Status - Estat - Dock - /personalization/Dock - - - - Small - petit - - - - Large - gros - - - - - On screen where the cursor is - A la pantalla el cursor és - - - - - Only on main screen - Només a la pantalla principal - - - - Show Dock - Mostra l'acoblador - - - - SettingsModule - - - - - Dock - Acoblador - - - - Mode - Mode - - - - Location - Ubicació - - - - Status - Estat - - - - Size - Mida - - - - Show Dock - Mostra l'acoblador - - - - Plugin Area - Àrea de connectors - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_cs.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_cs.ts deleted file mode 100644 index a85e3d002..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_cs.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Velikost - Dock - /personalization/Dock - - - - Multiple Displays - Více displejů - Dock - /personalization/Dock - - - - Plugin Area - Oblast pluginu - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Vyberte, které ikony se zobrazí v panelu - - - - - Fashion mode - Líbivý režim - - - - - Efficient mode - Nenáročný režim - - - - Mode - Režim - Dock - /personalization/Dock - - - - - Top - Nahoře - - - - - Bottom - Dole - - - - - Left - Vlevo - - - - - Right - Vpravo - - - - Location - Umístění - Dock - /personalization/Dock - - - - - Keep shown - Ponechat zobrazený - - - - - Keep hidden - Ponechat skrytý - - - - - Smart hide - Chytré skrývání - - - - Status - Stav - Dock - /personalization/Dock - - - - Small - Malý - - - - Large - Velký - - - - - On screen where the cursor is - Na obrazovce, na které se nachází ukazatel - - - - - Only on main screen - Pouze na hlavní obrazovce - - - - Show Dock - Zobrazit panel - - - - SettingsModule - - - - - Dock - Panel - - - - Mode - Režim - - - - Location - Umístění - - - - Status - Stav - - - - Size - Velikost - - - - Show Dock - Zobrazit panel - - - - Plugin Area - Oblast pluginu - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_de.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_de.ts deleted file mode 100644 index 957533edd..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_de.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Größe - Dock - /personalization/Dock - - - - Multiple Displays - Mehrfachbildschirm - Dock - /personalization/Dock - - - - Plugin Area - Pluginbereich - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Wählen Sie aus, welche Symbole im Dock erscheinen sollen - - - - - Fashion mode - Design-Modus - - - - - Efficient mode - Leistungs-Modus - - - - Mode - Modus - Dock - /personalization/Dock - - - - - Top - Oben - - - - - Bottom - Unten - - - - - Left - Links - - - - - Right - Rechts - - - - Location - Standort - Dock - /personalization/Dock - - - - - Keep shown - Angezeigt lassen - - - - - Keep hidden - Ausgeblendet lassen - - - - - Smart hide - Intelligentes Ausblenden - - - - Status - Status - Dock - /personalization/Dock - - - - Small - Klein - - - - Large - Groß - - - - - On screen where the cursor is - Auf dem Bildschirm, wo sich der Zeiger befindet - - - - - Only on main screen - Nur auf dem Hauptbildschirm - - - - Show Dock - Dock anzeigen - - - - SettingsModule - - - - - Dock - Dock - - - - Mode - Modus - - - - Location - Standort - - - - Status - Status - - - - Size - Größe - - - - Show Dock - Dock anzeigen - - - - Plugin Area - Pluginbereich - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_el.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_el.ts deleted file mode 100644 index c99a7eb0f..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_el.ts +++ /dev/null @@ -1,130 +0,0 @@ - - - ModuleWidget - - - Size - Μέγεθος - - - - Multiple Displays - Πολλαπλές Οθόνες - - - - Plugin Area - - - - - Select which icons appear in the Dock - - - - - - Fashion mode - Μοντέρνα λειτουργία - - - - - Efficient mode - Αποτελεσματική λειτουργία - - - - Mode - Λειτουργία - - - - - Top - Πάνω μέρος - - - - - Bottom - Κάτω μέρος - - - - - Left - Αριστερά - - - - - Right - Δεξιά - - - - Location - Τοποθεσία - - - - - Keep shown - - - - - - Keep hidden - Κρατήστε κρυφό - - - - - Smart hide - Έξυπνη απόκρυψη - - - - Status - Κατάσταση - - - - Small - Μικρό - - - - Large - Μεγάλο - - - - - On screen where the cursor is - Στην οθόνη όπου βρίσκεται ο κέρσορας - - - - - Only on main screen - Μόνο στην κύρια οθόνη - - - - Show Dock - - - - - SettingsModule - - - Dock - Προσθήκη στην γραμμή εργασιών - /personalization/Dock - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_en_US.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_en_US.ts deleted file mode 100644 index adf44cd9a..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_en_US.ts +++ /dev/null @@ -1,175 +0,0 @@ - - - - - ModuleWidget - - - Size - Size - Dock - /personalization/Dock - - - - Multiple Displays - Multiple Displays - Dock - /personalization/Dock - - - - Plugin Area - Plugin Area - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Select which icons appear in the Dock - - - - - Fashion mode - Fashion mode - - - - - Efficient mode - Efficient mode - - - - Mode - Mode - Dock - /personalization/Dock - - - - - Top - Top - - - - - Bottom - Bottom - - - - - Left - Left - - - - - Right - Right - - - - Location - Location - Dock - /personalization/Dock - - - - - Keep shown - Keep shown - - - - - Keep hidden - Keep hidden - - - - - Smart hide - Smart hide - - - - Status - Status - Dock - /personalization/Dock - - - - Small - Small - - - - Large - Large - - - - - On screen where the cursor is - On screen where the cursor is - - - - - Only on main screen - Only on main screen - - - - Show Dock - Show Dock - - - - SettingsModule - - - - - Dock - Dock - - - - Mode - Mode - - - - Location - Location - - - - Status - Status - - - - Size - Size - - - - Show Dock - Show Dock - - - - Plugin Area - Plugin Area - - - diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_es.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_es.ts deleted file mode 100644 index 5fd167187..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_es.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Tamaño - Dock - /personalization/Dock - - - - Multiple Displays - Múltiples pantallas - Dock - /personalization/Dock - - - - Plugin Area - Área de complementos - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Seleccionar los iconos que aparecen en el Dock - - - - - Fashion mode - Modo elegante - - - - - Efficient mode - Modo eficiente - - - - Mode - Modo - Dock - /personalization/Dock - - - - - Top - Arriba - - - - - Bottom - Abajo - - - - - Left - Izquierda - - - - - Right - Derecha - - - - Location - Ubicación - Dock - /personalization/Dock - - - - - Keep shown - Mantener visible - - - - - Keep hidden - Mantener oculto - - - - - Smart hide - Ocultar inteligentemente - - - - Status - Estado - Dock - /personalization/Dock - - - - Small - Pequeña - - - - Large - Grande - - - - - On screen where the cursor is - En la pantalla donde está el cursor - - - - - Only on main screen - Solo en la pantalla principal - - - - Show Dock - Mostrar el dock - - - - SettingsModule - - - - - Dock - Dock - - - - Mode - Modo - - - - Location - Ubicación - - - - Status - Estado - - - - Size - Tamaño - - - - Show Dock - Mostrar el dock - - - - Plugin Area - Área de complementos - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_fi.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_fi.ts deleted file mode 100644 index 5d5a9539f..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_fi.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Koko - Dock - /personalization/Dock - - - - Multiple Displays - Useita näyttöjä - Dock - /personalization/Dock - - - - Plugin Area - Laajennusalue - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Valitse mitkä kuvakkeet näkyvät telakassa - - - - - Fashion mode - Muodikas - - - - - Efficient mode - Tehokas - - - - Mode - Tila - Dock - /personalization/Dock - - - - - Top - Ylhäällä - - - - - Bottom - Alhaalla - - - - - Left - Vasen - - - - - Right - Oikea - - - - Location - Sijainti - Dock - /personalization/Dock - - - - - Keep shown - Näytä aina - - - - - Keep hidden - Pidä piilossa - - - - - Smart hide - Älykäs piilotus - - - - Status - Tila - Dock - /personalization/Dock - - - - Small - Pieni - - - - Large - Suuri - - - - - On screen where the cursor is - Näytöllä, jossa kohdistin on - - - - - Only on main screen - Vain päänäytöllä - - - - Show Dock - Näytä telakka - - - - SettingsModule - - - - - Dock - Telakka - - - - Mode - Tila - - - - Location - Sijainti - - - - Status - Tila - - - - Size - Koko - - - - Show Dock - Näytä telakka - - - - Plugin Area - Laajennusalue - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_fr.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_fr.ts deleted file mode 100644 index f37f7ad2e..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_fr.ts +++ /dev/null @@ -1,130 +0,0 @@ - - - ModuleWidget - - - Size - Taille - - - - Multiple Displays - Affichages multiples - - - - Plugin Area - - - - - Select which icons appear in the Dock - - - - - - Fashion mode - Mode dock - - - - - Efficient mode - Mode étendu - - - - Mode - Mode - - - - - Top - Haut - - - - - Bottom - Bas - - - - - Left - Gauche - - - - - Right - Droite - - - - Location - Emplacement - - - - - Keep shown - - - - - - Keep hidden - Maintenir caché - - - - - Smart hide - Masquer intelligemment - - - - Status - Statut - - - - Small - Petit - - - - Large - Grand - - - - - On screen where the cursor is - Sur l'écran où se trouve le curseur - - - - - Only on main screen - Uniquement sur l'écran principal - - - - Show Dock - - - - - SettingsModule - - - Dock - Dock - /personalization/Dock - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_hr.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_hr.ts deleted file mode 100644 index 6af61048f..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_hr.ts +++ /dev/null @@ -1,130 +0,0 @@ - - - ModuleWidget - - - Size - Veličina - - - - Multiple Displays - Višestruki zasloni - - - - Plugin Area - - - - - Select which icons appear in the Dock - - - - - - Fashion mode - Moderan način - - - - - Efficient mode - Učinkoviti način - - - - Mode - Način - - - - - Top - Gore - - - - - Bottom - Dolje - - - - - Left - Lijevo - - - - - Right - Desno - - - - Location - Lokacija - - - - - Keep shown - Drži prikazano - - - - - Keep hidden - Drži skriveno - - - - - Smart hide - Pametno skrivanje - - - - Status - Status - - - - Small - Maleno - - - - Large - Veliko - - - - - On screen where the cursor is - Na zaslon gdje je pokazivač - - - - - Only on main screen - Samo na glavni zaslon - - - - Show Dock - - - - - SettingsModule - - - Dock - - /personalization/Dock - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_hu.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_hu.ts deleted file mode 100644 index 8f902fda1..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_hu.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Méret - Dock - /personalization/Dock - - - - Multiple Displays - Többképernyős mód - Dock - /personalization/Dock - - - - Plugin Area - Bővítmény terület - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Válassza ki, hogy mely ikonok jelenjenek meg a dokkolóban - - - - - Fashion mode - Stílusos mód - - - - - Efficient mode - Hatékony mód - - - - Mode - Mód - Dock - /personalization/Dock - - - - - Top - Fent - - - - - Bottom - Lent - - - - - Left - Bal - - - - - Right - Jobb - - - - Location - Hely - Dock - /personalization/Dock - - - - - Keep shown - Megjelenítve tartás - - - - - Keep hidden - Maradjon rejtett - - - - - Smart hide - Intelligens elrejtés - - - - Status - Állapot - Dock - /personalization/Dock - - - - Small - Kicsi - - - - Large - Nagy - - - - - On screen where the cursor is - A képernyőn, ahol a kurzor található - - - - - Only on main screen - Csak a főképernyőn - - - - Show Dock - Dokkoló mutatása - - - - SettingsModule - - - - - Dock - Dokkoló - - - - Mode - Mód - - - - Location - Hely - - - - Status - Állapot - - - - Size - Méret - - - - Show Dock - Dokkoló mutatása - - - - Plugin Area - Bővítmény terület - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_it.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_it.ts deleted file mode 100644 index a0911d92d..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_it.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Dimensione - Dock - /personalization/Dock - - - - Multiple Displays - Display multipli - Dock - /personalization/Dock - - - - Plugin Area - Area plugin - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Seleziona quali icone appaiono nel Dock - - - - - Fashion mode - Modalità Fashion - - - - - Efficient mode - Modalità Efficient - - - - Mode - Modalità - Dock - /personalization/Dock - - - - - Top - Sopra - - - - - Bottom - Sotto - - - - - Left - Sinistra - - - - - Right - Destra - - - - Location - Posizione - Dock - /personalization/Dock - - - - - Keep shown - Mostra sempre - - - - - Keep hidden - Lascia nascosta - - - - - Smart hide - Nascondi automaticamente - - - - Status - Comportamento - Dock - /personalization/Dock - - - - Small - Piccolo - - - - Large - Grande - - - - - On screen where the cursor is - Sullo schermo dove è presente il cursore - - - - - Only on main screen - Solo sullo schermo principale - - - - Show Dock - Mostra la Dock - - - - SettingsModule - - - - - Dock - Dock - - - - Mode - Modalità - - - - Location - Posizione - - - - Status - Comportamento - - - - Size - Dimensioni - - - - Show Dock - Mostra la Dock - - - - Plugin Area - Area plugin - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ms.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ms.ts deleted file mode 100644 index ec70d1a43..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ms.ts +++ /dev/null @@ -1,130 +0,0 @@ - - - ModuleWidget - - - Size - Saiz - - - - Multiple Displays - Paparan Berbilang - - - - Plugin Area - - - - - Select which icons appear in the Dock - - - - - - Fashion mode - Mod fesyen - - - - - Efficient mode - Mod efisyen - - - - Mode - Mod - - - - - Top - Teratas - - - - - Bottom - Bawah - - - - - Left - Kiri - - - - - Right - Kanan - - - - Location - Lokasi - - - - - Keep shown - - - - - - Keep hidden - Kekal tersembunyi - - - - - Smart hide - Sembunyi pintar - - - - Status - Status - - - - Small - Kecil - - - - Large - Besar - - - - - On screen where the cursor is - Atas skrin yang mana kursor berada - - - - - Only on main screen - Hanya dalam skrin utama - - - - Show Dock - - - - - SettingsModule - - - Dock - Labuh - /personalization/Dock - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_nl.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_nl.ts deleted file mode 100644 index 2748b27c4..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_nl.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Grootte - Dock - /personalization/Dock - - - - Multiple Displays - Meerdere beeldschermen - Dock - /personalization/Dock - - - - Plugin Area - Invoegtoepassingsgebied - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Geef aan welke pictogrammen moeten worden getoond op het dock - - - - - Fashion mode - Moderne modus - - - - - Efficient mode - Efficiënte modus - - - - Mode - Modus - Dock - /personalization/Dock - - - - - Top - Bovenaan - - - - - Bottom - Onderaan - - - - - Left - Links - - - - - Right - Rechts - - - - Location - Locatie - Dock - /personalization/Dock - - - - - Keep shown - Altijd tonen - - - - - Keep hidden - Altijd verbergen - - - - - Smart hide - Slim verbergen - - - - Status - Status - Dock - /personalization/Dock - - - - Small - Klein - - - - Large - Groot - - - - - On screen where the cursor is - Op het scherm waar de cursor is - - - - - Only on main screen - Alleen op hoofdscherm - - - - Show Dock - Dock tonen - - - - SettingsModule - - - - - Dock - Vastmaken - - - - Mode - Modus - - - - Location - Locatie - - - - Status - Status - - - - Size - Grootte - - - - Show Dock - Dock tonen - - - - Plugin Area - Invoegtoepassingsgebied - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pl.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pl.ts deleted file mode 100644 index 0b2da01b6..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pl.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Rozmiar - Dock - /personalization/Dock - - - - Multiple Displays - Wiele ekranów - Dock - /personalization/Dock - - - - Plugin Area - Strefa wtyczek - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Wybierz, które wtyczki pojawią się w Doku - - - - - Fashion mode - Tryb modny - - - - - Efficient mode - Tryb wydajny - - - - Mode - Tryb - Dock - /personalization/Dock - - - - - Top - Góra - - - - - Bottom - Dół - - - - - Left - Lewo - - - - - Right - Prawo - - - - Location - Położenie - Dock - /personalization/Dock - - - - - Keep shown - Zawsze wyświetlaj - - - - - Keep hidden - Zawsze ukrywaj - - - - - Smart hide - Inteligentne ukrywanie - - - - Status - Status - Dock - /personalization/Dock - - - - Small - Mały - - - - Large - Ogromny - - - - - On screen where the cursor is - Na ekranie, tam gdzie jest kursor - - - - - Only on main screen - Tylko na ekranie głównym - - - - Show Dock - Pokaż dok - - - - SettingsModule - - - - - Dock - Dok - - - - Mode - Tryb - - - - Location - Położenie - - - - Status - Status - - - - Size - Rozmiar - - - - Show Dock - Pokaż dok - - - - Plugin Area - Strefa wtyczek - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pt.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pt.ts deleted file mode 100644 index ceb75afbb..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pt.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Tamanho - Dock - /personalization/Dock - - - - Multiple Displays - Vários ecrãs - Dock - /personalization/Dock - - - - Plugin Area - Área de plugins - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Selecione quais os ícones que aparecem na Doca - - - - - Fashion mode - Modo Elegante - - - - - Efficient mode - Modo eficiente - - - - Mode - Modo - Dock - /personalization/Dock - - - - - Top - Superior - - - - - Bottom - Inferior - - - - - Left - Esquerda - - - - - Right - Direita - - - - Location - Localização - Dock - /personalization/Dock - - - - - Keep shown - Manter visível - - - - - Keep hidden - Manter ocultada - - - - - Smart hide - Ocultação inteligente - - - - Status - Estado - Dock - /personalization/Dock - - - - Small - Pequeno - - - - Large - Grande - - - - - On screen where the cursor is - No ecrã onde se encontra o cursor - - - - - Only on main screen - Apenas no ecrã principal - - - - Show Dock - Mostrar Doca - - - - SettingsModule - - - - - Dock - Doca - - - - Mode - Modo - - - - Location - Localização - - - - Status - Estado - - - - Size - Tamanho - - - - Show Dock - Mostrar Doca - - - - Plugin Area - Área de plugins - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pt_BR.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pt_BR.ts deleted file mode 100644 index 5b39d544a..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_pt_BR.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Size - Dock - /personalization/Dock - - - - Multiple Displays - Multiple Displays - Dock - /personalization/Dock - - - - Plugin Area - Plugin Area - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Select which icons appear in the Dock - - - - - Fashion mode - Fashion mode - - - - - Efficient mode - Efficient mode - - - - Mode - Mode - Dock - /personalization/Dock - - - - - Top - Top - - - - - Bottom - Bottom - - - - - Left - Left - - - - - Right - Right - - - - Location - Location - Dock - /personalization/Dock - - - - - Keep shown - Keep shown - - - - - Keep hidden - Keep hidden - - - - - Smart hide - Smart hide - - - - Status - Status - Dock - /personalization/Dock - - - - Small - Small - - - - Large - Large - - - - - On screen where the cursor is - On screen where the cursor is - - - - - Only on main screen - Only on main screen - - - - Show Dock - Show Dock - - - - SettingsModule - - - - - Dock - Dock - - - - Mode - Mode - - - - Location - Location - - - - Status - Status - - - - Size - Tamanho - - - - Show Dock - Show Dock - - - - Plugin Area - Plugin Area - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ru.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ru.ts deleted file mode 100644 index 4f8e4f717..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ru.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Размер - Dock - /personalization/Dock - - - - Multiple Displays - Несколько Дисплеев - Dock - /personalization/Dock - - - - Plugin Area - Область Плагина - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Выбрать какие значки будут отображаться в Dock - - - - - Fashion mode - Стильный режим - - - - - Efficient mode - Эффективный режим - - - - Mode - Режим - Dock - /personalization/Dock - - - - - Top - На верху - - - - - Bottom - Внизу - - - - - Left - Слева - - - - - Right - Справа - - - - Location - Расположение - Dock - /personalization/Dock - - - - - Keep shown - Отображать - - - - - Keep hidden - Скрывать - - - - - Smart hide - Умное скрытие - - - - Status - Статус - Dock - /personalization/Dock - - - - Small - Маленький - - - - Large - Большой - - - - - On screen where the cursor is - На экране, где находится курсор - - - - - Only on main screen - Только на главном экране - - - - Show Dock - Показывать Dock - - - - SettingsModule - - - - - Dock - Dock - - - - Mode - Режим - - - - Location - Расположение - - - - Status - Статус - - - - Size - Размер - - - - Show Dock - Показывать Dock - - - - Plugin Area - Область Плагина - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_sq.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_sq.ts deleted file mode 100644 index cdd55f008..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_sq.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Madhësi - Dock - /personalization/Dock - - - - Multiple Displays - Shumë Ekrane - Dock - /personalization/Dock - - - - Plugin Area - Zonë Shtojcash - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Përzgjidhni cilat ikona shfaqen te Paneli - - - - - Fashion mode - Mënyra “Në modë” - - - - - Efficient mode - Mënyra efikasitet - - - - Mode - Mënyrë - Dock - /personalization/Dock - - - - - Top - Në Krye - - - - - Bottom - Në Fund - - - - - Left - Majtas - - - - - Right - Djathtas - - - - Location - Vendndodhje - Dock - /personalization/Dock - - - - - Keep shown - Mbaje të shfaqur - - - - - Keep hidden - Mbaje të fshehur - - - - - Smart hide - Fshehje e mençur - - - - Status - Gjendje - Dock - /personalization/Dock - - - - Small - I vogël - - - - Large - I madh - - - - - On screen where the cursor is - Në ekranin ku është kursori - - - - - Only on main screen - Vetëm në ekranin kryesor - - - - Show Dock - Shfaqe Panelin - - - - SettingsModule - - - - - Dock - Panel - - - - Mode - Mënyrë - - - - Location - Vendndodhje - - - - Status - Gjendje - - - - Size - Madhësi - - - - Show Dock - Shfaqe Panelin - - - - Plugin Area - Zonë Shtojcash - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_tr.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_tr.ts deleted file mode 100644 index 13821aac2..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_tr.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Boyut - Dock - /personalization/Dock - - - - Multiple Displays - Çoklu Ekran - Dock - /personalization/Dock - - - - Plugin Area - Eklenti Alanı - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Rıhtım'da hangi simgelerin görüneceğini seçin - - - - - Fashion mode - Moda Kip - - - - - Efficient mode - Verimli Kip - - - - Mode - Kip - Dock - /personalization/Dock - - - - - Top - Üst - - - - - Bottom - Alt - - - - - Left - Sol - - - - - Right - Sağ - - - - Location - Konum - Dock - /personalization/Dock - - - - - Keep shown - Gösterilmeyi sürdür - - - - - Keep hidden - Gizli tut - - - - - Smart hide - Akıll gizle - - - - Status - Durum - Dock - /personalization/Dock - - - - Small - Küçük - - - - Large - Büyük - - - - - On screen where the cursor is - İmlecin bulunduğu ekranda - - - - - Only on main screen - Sadece ana ekranda - - - - Show Dock - Rıhtımı Göster - - - - SettingsModule - - - - - Dock - Rıhtım - - - - Mode - Kip - - - - Location - Konum - - - - Status - Durum - - - - Size - Boyut - - - - Show Dock - Rıhtımı Göster - - - - Plugin Area - Eklenti Alanı - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ug.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ug.ts deleted file mode 100644 index 618b3b8e5..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_ug.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - چوڭلۇقى - Dock - /personalization/Dock - - - - Multiple Displays - كۆپ ئېكرانلىق كۆرسىتىش تەڭشىكى - Dock - /personalization/Dock - - - - Plugin Area - قىستۇرما رايونى - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - ۋەزىپە ئىستونى قىستۇرما رايونىدا كۆرسىتىلىدىغان سىنبەلگىنى تاللاڭ - - - - - Fashion mode - مودا ھالەت - - - - - Efficient mode - يۇقىرى ئۈنۈملۈك ھالەت - - - - Mode - ھالىتى - Dock - /personalization/Dock - - - - - Top - ئۈستى - - - - - Bottom - ئاستى - - - - - Left - سول - - - - - Right - ئوڭ - - - - Location - ئورنى - Dock - /personalization/Dock - - - - - Keep shown - داۋاملىق كۆرسىتىش - - - - - Keep hidden - داۋاملىق يوشۇرۇش - - - - - Smart hide - ئەقلىي يوشۇرۇش - - - - Status - ھالىتى - Dock - /personalization/Dock - - - - Small - كىچىك - - - - Large - چوڭ - - - - - On screen where the cursor is - مائۇسنىڭ ئورنىغا ئەگىشىپ كۆرۈنسۇن - - - - - Only on main screen - ئاساسىي ئېكراندىلا كۆرۈنسۇن - - - - Show Dock - ۋەزىپە ئىستونىنىڭ ئورنى - - - - SettingsModule - - - - - Dock - ۋەزىپە ئىستونى - - - - Mode - ھالىتى - - - - Location - ئورنى - - - - Status - ھالىتى - - - - Size - چوڭلۇقى - - - - Show Dock - ۋەزىپە ئىستونىنىڭ ئورنى - - - - Plugin Area - قىستۇرما رايونى - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_uk.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_uk.ts deleted file mode 100644 index b2dcd7e43..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_uk.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - Розмір - Dock - /personalization/Dock - - - - Multiple Displays - Кілька дисплеїв - Dock - /personalization/Dock - - - - Plugin Area - Область додатків - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - Виберіть, які піктограми буде показано на бічній панелі - - - - - Fashion mode - Модний режим - - - - - Efficient mode - Ефективний режим - - - - Mode - Режим - Dock - /personalization/Dock - - - - - Top - Вгорі - - - - - Bottom - Внизу - - - - - Left - Ліворуч - - - - - Right - Праворуч - - - - Location - Розташування - Dock - /personalization/Dock - - - - - Keep shown - Показувати постійно - - - - - Keep hidden - Залишати прихованим - - - - - Smart hide - Розумне приховування - - - - Status - Стан - Dock - /personalization/Dock - - - - Small - Малий - - - - Large - Великий - - - - - On screen where the cursor is - На екрані, де перебуває вказівник - - - - - Only on main screen - Лише на головному екрані - - - - Show Dock - Показувати панель - - - - SettingsModule - - - - - Dock - Панель - - - - Mode - Режим - - - - Location - Розташування - - - - Status - Стан - - - - Size - Розмір - - - - Show Dock - Показувати панель - - - - Plugin Area - Область додатків - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_CN.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_CN.ts deleted file mode 100644 index 66bcf32f8..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_CN.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - 大小 - Dock - /personalization/Dock - - - - Multiple Displays - 多屏显示设置 - Dock - /personalization/Dock - - - - Plugin Area - 插件区域 - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - 选择显示在任务栏插件区域的图标 - - - - - Fashion mode - 时尚模式 - - - - - Efficient mode - 高效模式 - - - - Mode - 模式 - Dock - /personalization/Dock - - - - - Top - - - - - - Bottom - - - - - - Left - - - - - - Right - - - - - Location - 位置 - Dock - /personalization/Dock - - - - - Keep shown - 一直显示 - - - - - Keep hidden - 一直隐藏 - - - - - Smart hide - 智能隐藏 - - - - Status - 状态 - Dock - /personalization/Dock - - - - Small - - - - - Large - - - - - - On screen where the cursor is - 跟随鼠标位置显示 - - - - - Only on main screen - 仅主屏显示 - - - - Show Dock - 任务栏位置 - - - - SettingsModule - - - - - Dock - 任务栏 - - - - Mode - 模式 - - - - Location - 位置 - - - - Status - 状态 - - - - Size - 大小 - - - - Show Dock - 任务栏位置 - - - - Plugin Area - 插件区域 - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_HK.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_HK.ts deleted file mode 100644 index 145c7c10f..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_HK.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - 大小 - Dock - /personalization/Dock - - - - Multiple Displays - 多屏顯示設置 - Dock - /personalization/Dock - - - - Plugin Area - 插件區域 - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - 選擇顯示在任務欄插件區域的圖標 - - - - - Fashion mode - 時尚模式 - - - - - Efficient mode - 高效模式 - - - - Mode - 模式 - Dock - /personalization/Dock - - - - - Top - - - - - - Bottom - - - - - - Left - - - - - - Right - - - - - Location - 位置 - Dock - /personalization/Dock - - - - - Keep shown - 一直顯示 - - - - - Keep hidden - 一直隱藏 - - - - - Smart hide - 智能隱藏 - - - - Status - 狀態 - Dock - /personalization/Dock - - - - Small - - - - - Large - - - - - - On screen where the cursor is - 跟隨鼠標位置顯示 - - - - - Only on main screen - 僅主屏顯示 - - - - Show Dock - 任務欄位置 - - - - SettingsModule - - - - - Dock - 任務欄 - - - - Mode - 模式 - - - - Location - 位置 - - - - Status - 狀態 - - - - Size - 大小 - - - - Show Dock - 任務欄位置 - - - - Plugin Area - 插件區域 - - - \ No newline at end of file diff --git a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_TW.ts b/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_TW.ts deleted file mode 100644 index 3aaf10bc5..000000000 --- a/plugins/dcc-dock-plugin/translations/dcc-dock-plugin_zh_TW.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - ModuleWidget - - - Size - 大小 - Dock - /personalization/Dock - - - - Multiple Displays - 多屏顯示設定 - Dock - /personalization/Dock - - - - Plugin Area - 外掛程式區域 - Dock - /personalization/Dock - - - - Select which icons appear in the Dock - 選擇顯示在任務欄外掛程式區域的圖示 - - - - - Fashion mode - 時尚模式 - - - - - Efficient mode - 高效模式 - - - - Mode - 模式 - Dock - /personalization/Dock - - - - - Top - 頂部 - - - - - Bottom - 底部 - - - - - Left - 左側 - - - - - Right - 右側 - - - - Location - 位置 - Dock - /personalization/Dock - - - - - Keep shown - 永遠顯示 - - - - - Keep hidden - 永遠隱藏 - - - - - Smart hide - 智慧隱藏 - - - - Status - 狀態 - Dock - /personalization/Dock - - - - Small - - - - - Large - - - - - - On screen where the cursor is - 跟隨滑鼠位置顯示 - - - - - Only on main screen - 僅主屏顯示 - - - - Show Dock - 任務欄位置 - - - - SettingsModule - - - - - Dock - 任務欄 - - - - Mode - 模式 - - - - Location - 位置 - - - - Status - 狀態 - - - - Size - 大小 - - - - Show Dock - 任務欄位置 - - - - Plugin Area - 外掛程式區域 - - - \ No newline at end of file diff --git a/plugins/disk-mount/CMakeLists.txt b/plugins/disk-mount/CMakeLists.txt deleted file mode 100644 index e9ec9bb55..000000000 --- a/plugins/disk-mount/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ - -set(PLUGIN_NAME "disk-mount") - -project(${PLUGIN_NAME}) - -# Sources files -file(GLOB SRCS "*.h" "*.cpp") - -find_package(PkgConfig REQUIRED) -find_package(Qt5Widgets REQUIRED) -find_package(Qt5Svg REQUIRED) -find_package(Qt5DBus REQUIRED) -find_package(DtkWidget REQUIRED) - -add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") -add_library(${PLUGIN_NAME} SHARED ${SRCS} resources.qrc) -set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../) -target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} ../../interfaces) -target_link_libraries(${PLUGIN_NAME} PRIVATE - ${DtkWidget_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Svg_LIBRARIES} - ${Qt5DBus_LIBRARIES} -) - -install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins) diff --git a/plugins/disk-mount/dbus/com.deepin.daemon.DiskMount.xml b/plugins/disk-mount/dbus/com.deepin.daemon.DiskMount.xml deleted file mode 100644 index f0ad16d00..000000000 --- a/plugins/disk-mount/dbus/com.deepin.daemon.DiskMount.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/disk-mount/dbus/dbusdiskmount.cpp b/plugins/disk-mount/dbus/dbusdiskmount.cpp deleted file mode 100644 index faa781e8f..000000000 --- a/plugins/disk-mount/dbus/dbusdiskmount.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusDiskMount -p dbusdiskmount com.deepin.daemon.DiskMount.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "dbusdiskmount.h" - -/* - * Implementation of interface class DBusDiskMount - */ - -DBusDiskMount::DBusDiskMount(QObject *parent) - : QDBusAbstractInterface("com.deepin.daemon.DiskMount", "/com/deepin/daemon/DiskMount", staticInterfaceName(), QDBusConnection::sessionBus(), parent) -{ - DiskInfo::registerMetaType(); - - QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); -} - -DBusDiskMount::~DBusDiskMount() -{ - QDBusConnection::sessionBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); -} - diff --git a/plugins/disk-mount/dbus/dbusdiskmount.h b/plugins/disk-mount/dbus/dbusdiskmount.h deleted file mode 100644 index 63c21d6c5..000000000 --- a/plugins/disk-mount/dbus/dbusdiskmount.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusDiskMount -p dbusdiskmount com.deepin.daemon.DiskMount.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ - -#ifndef DBUSDISKMOUNT_H_1468893654 -#define DBUSDISKMOUNT_H_1468893654 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "variant/diskinfo.h" - -/* - * Proxy class for interface com.deepin.daemon.DiskMount - */ -class DBusDiskMount: public QDBusAbstractInterface -{ - Q_OBJECT - - Q_SLOT void __propertyChanged__(const QDBusMessage& msg) - { - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.daemon.DiskMount") - return; - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - foreach(const QString &prop, changedProps.keys()) { - const QMetaObject* self = metaObject(); - for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { - QMetaProperty p = self->property(i); - if (p.name() == prop) { - Q_EMIT p.notifySignal().invoke(this); - } - } - } - } -public: - static inline const char *staticInterfaceName() - { return "com.deepin.daemon.DiskMount"; } - -public: - explicit DBusDiskMount(QObject *parent = 0); - - ~DBusDiskMount(); - - Q_PROPERTY(DiskInfoList DiskList READ diskList NOTIFY DiskListChanged) - inline DiskInfoList diskList() const - { return qvariant_cast< DiskInfoList >(property("DiskList")); } - -public Q_SLOTS: // METHODS - inline QDBusPendingReply<> Eject(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("Eject"), argumentList); - } - - inline QDBusPendingReply ListDisk() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("ListDisk"), argumentList); - } - - inline QDBusPendingReply<> Mount(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("Mount"), argumentList); - } - - inline QDBusPendingReply QueryDisk(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("QueryDisk"), argumentList); - } - - inline QDBusPendingReply<> Unmount(const QString &diskId) - { - QList argumentList; - argumentList << QVariant::fromValue(diskId); - return asyncCallWithArgumentList(QStringLiteral("Unmount"), argumentList); - } - -Q_SIGNALS: // SIGNALS - void Changed(int in0, const QString &in1); - void Error(const QString &uuid, const QString &info); -// begin property changed signals -void DiskListChanged(); -}; - -namespace com { - namespace deepin { - namespace daemon { - typedef ::DBusDiskMount DiskMount; - } - } -} -#endif diff --git a/plugins/disk-mount/dbus/variant/diskinfo.cpp b/plugins/disk-mount/dbus/variant/diskinfo.cpp deleted file mode 100644 index 0606d66b0..000000000 --- a/plugins/disk-mount/dbus/variant/diskinfo.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "diskinfo.h" - -DiskInfo::DiskInfo() -{ - -} - -void DiskInfo::registerMetaType() -{ - qRegisterMetaType("DiskInfo"); - qDBusRegisterMetaType(); - - qRegisterMetaType("DiskInfoList"); - qDBusRegisterMetaType(); -} - -QDebug operator<<(QDebug debug, const DiskInfo &info) -{ - debug << info.m_id << info.m_name << info.m_type << info.m_path << info.m_mountPoint << info.m_icon; - debug << '\t' << info.m_unmountable << '\t' << info.m_ejectable; - debug << '\t' << info.m_usedSize << '\t' << info.m_totalSize; - debug << endl; - - return debug; -} - -const QDataStream &operator>>(QDataStream &args, DiskInfo &info) -{ - args >> info.m_id >> info.m_name >> info.m_type >> info.m_path >> info.m_mountPoint >> info.m_icon; - args >> info.m_unmountable >> info.m_ejectable; - args >> info.m_usedSize >> info.m_totalSize; - - return args; -} - -const QDBusArgument &operator>>(const QDBusArgument &args, DiskInfo &info) -{ - args.beginStructure(); - args >> info.m_id >> info.m_name >> info.m_type >> info.m_path >> info.m_mountPoint >> info.m_icon; - args >> info.m_unmountable >> info.m_ejectable; - args >> info.m_usedSize >> info.m_totalSize; - args.endStructure(); - - return args; -} - -QDataStream &operator<<(QDataStream &args, const DiskInfo &info) -{ - args << info.m_id << info.m_name << info.m_type << info.m_path << info.m_mountPoint << info.m_icon; - args << info.m_unmountable << info.m_ejectable; - args << info.m_usedSize << info.m_totalSize; - - return args; -} - -QDBusArgument &operator<<(QDBusArgument &args, const DiskInfo &info) -{ - args.beginStructure(); - args << info.m_id << info.m_name << info.m_type << info.m_path << info.m_mountPoint << info.m_icon; - args << info.m_unmountable << info.m_ejectable; - args << info.m_usedSize << info.m_totalSize; - args.endStructure(); - - return args; -} diff --git a/plugins/disk-mount/dbus/variant/diskinfo.h b/plugins/disk-mount/dbus/variant/diskinfo.h deleted file mode 100644 index 9dd3f1dba..000000000 --- a/plugins/disk-mount/dbus/variant/diskinfo.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef DISKINFO_H -#define DISKINFO_H - -#include -#include -#include - -class DiskInfo -{ -public: - DiskInfo(); - static void registerMetaType(); - - friend QDebug operator<<(QDebug debug, const DiskInfo &info); - friend QDBusArgument &operator<<(QDBusArgument &args, const DiskInfo &info); - friend QDataStream &operator<<(QDataStream &args, const DiskInfo &info); - friend const QDBusArgument &operator>>(const QDBusArgument &args, DiskInfo &info); - friend const QDataStream &operator>>(QDataStream &args, DiskInfo &info); - -public: - QString m_id; - QString m_name; - QString m_type; - QString m_path; - QString m_mountPoint; - QString m_icon; - - bool m_unmountable; - bool m_ejectable; - - quint64 m_usedSize; - quint64 m_totalSize; -}; - -typedef QList DiskInfoList; - -Q_DECLARE_METATYPE(DiskInfo) -Q_DECLARE_METATYPE(DiskInfoList) - -#endif // DISKINFO_H diff --git a/plugins/disk-mount/disk-mount.json b/plugins/disk-mount/disk-mount.json deleted file mode 100644 index ad498eeb3..000000000 --- a/plugins/disk-mount/disk-mount.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "api": "1.1.1" -} diff --git a/plugins/disk-mount/diskcontrolitem.cpp b/plugins/disk-mount/diskcontrolitem.cpp deleted file mode 100644 index 9c21a887a..000000000 --- a/plugins/disk-mount/diskcontrolitem.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "diskcontrolitem.h" - -#include -#include - -DWIDGET_USE_NAMESPACE - -DiskControlItem::DiskControlItem(const DiskInfo &info, QWidget *parent) - : QFrame(parent), - - m_unknowIcon(":/icons/resources/unknown.svg"), - - m_diskIcon(new QLabel), - m_diskName(new QLabel), - m_diskCapacity(new QLabel), - m_capacityValueBar(new QProgressBar), - m_unmountButton(new DImageButton) -{ -// QIcon::setThemeName("deepin"); - - m_diskName->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - m_diskName->setStyleSheet("color:white;"); - - m_diskCapacity->setStyleSheet("color:rgba(255, 255, 255, .6);"); - - m_capacityValueBar->setTextVisible(false); - m_capacityValueBar->setFixedHeight(2); - m_capacityValueBar->setStyleSheet("QProgressBar {" - "border:none;" - "background-color:rgba(255, 255, 255, .1);" - "}" - "QProgressBar::chunk {" - "background-color:rgba(255, 255, 255, .8);" - "}"); - - m_unmountButton->setNormalPic(":/icons/resources/unmount-normal.png"); - m_unmountButton->setHoverPic(":/icons/resources/unmount-hover.png"); - m_unmountButton->setPressPic(":/icons/resources/unmount-press.png"); - m_unmountButton->setStyleSheet("margin-top:12px;"); - - QVBoxLayout *infoLayout = new QVBoxLayout; - infoLayout->addWidget(m_diskName); - infoLayout->addWidget(m_diskCapacity); - infoLayout->setSpacing(0); - infoLayout->setContentsMargins(3, 6, 0, 8); - - QHBoxLayout *unmountLayout = new QHBoxLayout; - unmountLayout->addLayout(infoLayout); - unmountLayout->addWidget(m_unmountButton); - unmountLayout->setSpacing(0); - unmountLayout->setMargin(0); - - QVBoxLayout *progressLayout = new QVBoxLayout; - progressLayout->addLayout(unmountLayout); - progressLayout->addWidget(m_capacityValueBar); - progressLayout->setSpacing(0); - progressLayout->setContentsMargins(10, 0, 0, 5); - - QHBoxLayout *centralLayout = new QHBoxLayout; - centralLayout->addWidget(m_diskIcon); - centralLayout->addLayout(progressLayout); - centralLayout->setSpacing(0); - centralLayout->setContentsMargins(0, 0, 5, 0); - - setLayout(centralLayout); - setObjectName("DiskItem"); - setStyleSheet("QFrame #DiskItem:hover {" - "background-color:rgba(255, 255, 255, .1);" - "border-radius:4px;" - "}"); - - connect(m_unmountButton, &DImageButton::clicked, [this] {emit requestUnmount(m_info.m_id);}); - - updateInfo(info); -} - -void DiskControlItem::updateInfo(const DiskInfo &info) -{ - m_info = info; - - m_diskIcon->setPixmap(QIcon::fromTheme(info.m_icon, m_unknowIcon).pixmap(48, 48)); - if (!info.m_name.isEmpty()) - m_diskName->setText(info.m_name); - else - m_diskName->setText(tr("Unknown device")); - if (info.m_totalSize) - m_diskCapacity->setText(QString("%1/%2").arg(formatDiskSize(info.m_usedSize)).arg(formatDiskSize(info.m_totalSize))); - else if (info.m_name.isEmpty()) - m_diskCapacity->clear(); - else - m_diskCapacity->setText(tr("Unknown volume")); - m_capacityValueBar->setMinimum(0); - m_capacityValueBar->setMaximum(std::max(1ull, info.m_totalSize)); - m_capacityValueBar->setValue(info.m_usedSize); -} - -const QString DiskControlItem::formatDiskSize(const quint64 size) const -{ - const quint64 mSize = 1000; - const quint64 gSize = mSize * 1000; - const quint64 tSize = gSize * 1000; - - if (size >= tSize) - return QString::number(double(size) / tSize, 'f', 2) + 'T'; - else if (size >= gSize) - return QString::number(double(size) / gSize, 'f', 2) + "G"; - else if (size >= mSize) - return QString::number(double(size) / mSize, 'f', 1) + "M"; - else - return QString::number(size) + "K"; -} diff --git a/plugins/disk-mount/diskcontrolitem.h b/plugins/disk-mount/diskcontrolitem.h deleted file mode 100644 index b3bd39b24..000000000 --- a/plugins/disk-mount/diskcontrolitem.h +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef DISKCONTROLITEM_H -#define DISKCONTROLITEM_H - -#include "dbus/dbusdiskmount.h" - -#include - -#include -#include -#include -#include - -class DiskControlItem : public QFrame -{ - Q_OBJECT - -public: - explicit DiskControlItem(const DiskInfo &info, QWidget *parent = 0); - -signals: - void requestUnmount(const QString &diskId) const; - -private slots: - void updateInfo(const DiskInfo &info); - const QString formatDiskSize(const quint64 size) const; - -private: - DiskInfo m_info; - QIcon m_unknowIcon; - - QLabel *m_diskIcon; - QLabel *m_diskName; - QLabel *m_diskCapacity; - QProgressBar *m_capacityValueBar; - Dtk::Widget::DImageButton *m_unmountButton; -}; - -#endif // DISKCONTROLITEM_H diff --git a/plugins/disk-mount/diskcontrolwidget.cpp b/plugins/disk-mount/diskcontrolwidget.cpp deleted file mode 100644 index 0aa0ec542..000000000 --- a/plugins/disk-mount/diskcontrolwidget.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "diskcontrolwidget.h" -#include "diskcontrolitem.h" - -#define WIDTH 300 - -DiskControlWidget::DiskControlWidget(QWidget *parent) - : QScrollArea(parent), - - m_centralLayout(new QVBoxLayout), - m_centralWidget(new QWidget), - - m_diskInter(new DBusDiskMount(this)) -{ - m_centralWidget->setLayout(m_centralLayout); - m_centralWidget->setFixedWidth(WIDTH); - - setWidget(m_centralWidget); - setFixedWidth(WIDTH); - setFrameStyle(QFrame::NoFrame); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setStyleSheet("background-color:transparent;"); - - connect(m_diskInter, &DBusDiskMount::DiskListChanged, this, &DiskControlWidget::diskListChanged); - connect(m_diskInter, &DBusDiskMount::Error, this, &DiskControlWidget::unmountFinished); - - QMetaObject::invokeMethod(this, "diskListChanged", Qt::QueuedConnection); -} - -void DiskControlWidget::unmountAll() -{ - for (auto disk : m_diskInfoList) - unmountDisk(disk.m_id); -} - -void DiskControlWidget::diskListChanged() -{ - DiskInfoList diskList = m_diskInter->diskList(); - - while (QLayoutItem *item = m_centralLayout->takeAt(0)) - { - delete item->widget(); - delete item; - } - - int mountedCount = 0; - for (auto info : diskList) - { - if (info.m_mountPoint.isEmpty()) - continue; - else - ++mountedCount; - - DiskControlItem *item = new DiskControlItem(info, this); - - connect(item, &DiskControlItem::requestUnmount, this, &DiskControlWidget::unmountDisk); - - m_centralLayout->addWidget(item); - m_diskInfoList.append(info); - } - - emit diskCountChanged(mountedCount); - - const int contentHeight = mountedCount * 70; - const int maxHeight = std::min(contentHeight, 70 * 6); - - m_centralWidget->setFixedHeight(contentHeight); - setFixedHeight(maxHeight); -} - -void DiskControlWidget::unmountDisk(const QString &diskId) const -{ - m_diskInter->Unmount(diskId); -} - -void DiskControlWidget::unmountFinished(const QString &uuid, const QString &info) -{ - qDebug() << uuid << info; -} diff --git a/plugins/disk-mount/diskcontrolwidget.h b/plugins/disk-mount/diskcontrolwidget.h deleted file mode 100644 index 5359aaa4a..000000000 --- a/plugins/disk-mount/diskcontrolwidget.h +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef DISKCONTROLWIDGET_H -#define DISKCONTROLWIDGET_H - -#include "dbus/dbusdiskmount.h" - -#include -#include - -class DiskControlWidget : public QScrollArea -{ - Q_OBJECT - -public: - explicit DiskControlWidget(QWidget *parent = 0); - - void unmountAll(); - -signals: - void diskCountChanged(const int count) const; - -private slots: - void diskListChanged(); - void unmountDisk(const QString &diskId) const; - void unmountFinished(const QString &uuid, const QString &info); - -private: - QVBoxLayout *m_centralLayout; - QWidget *m_centralWidget; - DBusDiskMount *m_diskInter; - - DiskInfoList m_diskInfoList; -}; - -#endif // DISKCONTROLWIDGET_H diff --git a/plugins/disk-mount/diskmountplugin.cpp b/plugins/disk-mount/diskmountplugin.cpp deleted file mode 100644 index 2e397bdae..000000000 --- a/plugins/disk-mount/diskmountplugin.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "diskmountplugin.h" - -#define OPEN "open" -#define UNMOUNT_ALL "unmount_all" - -DiskMountPlugin::DiskMountPlugin(QObject *parent) - : QObject(parent), - - m_pluginAdded(false), - - m_tipsLabel(new QLabel), - m_diskPluginItem(new DiskPluginItem), - m_diskControlApplet(nullptr) -{ - m_diskPluginItem->setVisible(false); - - m_tipsLabel->setObjectName("diskmount"); - m_tipsLabel->setVisible(false); - m_tipsLabel->setText(tr("Disk")); - m_tipsLabel->setStyleSheet("color:white;" - "padding:5px 10px;"); - - connect(m_diskPluginItem, &DiskPluginItem::requestContextMenu, [this] {m_proxyInter->requestContextMenu(this, QString());}); -} - -const QString DiskMountPlugin::pluginName() const -{ - return "disk-mount"; -} - -void DiskMountPlugin::init(PluginProxyInterface *proxyInter) -{ - m_proxyInter = proxyInter; - - initCompoments(); - m_diskPluginItem->setDockDisplayMode(displayMode()); -} - -QWidget *DiskMountPlugin::itemWidget(const QString &itemKey) -{ - Q_UNUSED(itemKey); - - return m_diskPluginItem; -} - -QWidget *DiskMountPlugin::itemTipsWidget(const QString &itemKey) -{ - Q_UNUSED(itemKey); - - return m_tipsLabel; -} - -QWidget *DiskMountPlugin::itemPopupApplet(const QString &itemKey) -{ - Q_UNUSED(itemKey); - - return m_diskControlApplet; -} - -const QString DiskMountPlugin::itemContextMenu(const QString &itemKey) -{ - Q_UNUSED(itemKey); - - QList items; - items.reserve(2); - - QMap open; - open["itemId"] = OPEN; - open["itemText"] = tr("Open"); - open["isActive"] = true; - items.push_back(open); - - QMap unmountAll; - unmountAll["itemId"] = UNMOUNT_ALL; - unmountAll["itemText"] = tr("Unmount all"); - unmountAll["isActive"] = true; - items.push_back(unmountAll); - - QMap menu; - menu["items"] = items; - menu["checkableMenu"] = false; - menu["singleCheck"] = false; - - return QJsonDocument::fromVariant(menu).toJson(); -} - -void DiskMountPlugin::invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) -{ - Q_UNUSED(itemKey) - Q_UNUSED(checked) - - if (menuId == OPEN) - QProcess::startDetached("gvfs-open", QStringList() << "computer://"); - else if (menuId == UNMOUNT_ALL) - m_diskControlApplet->unmountAll(); -} - -void DiskMountPlugin::initCompoments() -{ - m_diskControlApplet = new DiskControlWidget; - m_diskControlApplet->setObjectName("dist-mount"); - m_diskControlApplet->setVisible(false); - - connect(m_diskControlApplet, &DiskControlWidget::diskCountChanged, this, &DiskMountPlugin::diskCountChanged); -} - -void DiskMountPlugin::displayModeChanged(const Dock::DisplayMode mode) -{ - m_diskPluginItem->setDockDisplayMode(mode); -} - -void DiskMountPlugin::diskCountChanged(const int count) -{ - if (m_pluginAdded == bool(count)) - return; - - m_pluginAdded = bool(count); - - if (m_pluginAdded) - m_proxyInter->itemAdded(this, QString()); - else - m_proxyInter->itemRemoved(this, QString()); -} diff --git a/plugins/disk-mount/diskmountplugin.h b/plugins/disk-mount/diskmountplugin.h deleted file mode 100644 index ef3faad4f..000000000 --- a/plugins/disk-mount/diskmountplugin.h +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef DISKMOUNTPLUGIN_H -#define DISKMOUNTPLUGIN_H - -#include - -#include "pluginsiteminterface.h" -#include "diskcontrolwidget.h" -#include "diskpluginitem.h" - -class DiskMountPlugin : public QObject, PluginsItemInterface -{ - Q_OBJECT - Q_INTERFACES(PluginsItemInterface) - Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "disk-mount.json") - -public: - explicit DiskMountPlugin(QObject *parent = 0); - - const QString pluginName() const; - void init(PluginProxyInterface *proxyInter); - - QWidget *itemWidget(const QString &itemKey); - QWidget *itemTipsWidget(const QString &itemKey); - QWidget *itemPopupApplet(const QString &itemKey); - - const QString itemContextMenu(const QString &itemKey); - void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked); - -private: - void initCompoments(); - - void displayModeChanged(const Dock::DisplayMode mode); - -private slots: - void diskCountChanged(const int count); - -private: - bool m_pluginAdded; - - QLabel *m_tipsLabel; - DiskPluginItem *m_diskPluginItem; - DiskControlWidget *m_diskControlApplet; -}; - -#endif // DISKMOUNTPLUGIN_H diff --git a/plugins/disk-mount/diskpluginitem.cpp b/plugins/disk-mount/diskpluginitem.cpp deleted file mode 100644 index fbcfe230f..000000000 --- a/plugins/disk-mount/diskpluginitem.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "diskpluginitem.h" -#include "imageutil.h" - -#include -#include -#include -#include - -DiskPluginItem::DiskPluginItem(QWidget *parent) - : QWidget(parent), - m_displayMode(Dock::Efficient) -{ -// QIcon::setThemeName("deepin"); -} - -void DiskPluginItem::setDockDisplayMode(const Dock::DisplayMode mode) -{ - m_displayMode = mode; - - updateIcon(); -} - -void DiskPluginItem::paintEvent(QPaintEvent *e) -{ - QWidget::paintEvent(e); - - QPainter painter(this); - const QRectF &rf = QRectF(rect()); - const QRectF &rfp = QRectF(m_icon.rect()); - painter.drawPixmap(rf.center() - rfp.center(), m_icon); -} - -void DiskPluginItem::resizeEvent(QResizeEvent *e) -{ - QWidget::resizeEvent(e); - - updateIcon(); -} - -void DiskPluginItem::mousePressEvent(QMouseEvent *e) -{ - if (e->button() != Qt::RightButton) - return QWidget::mousePressEvent(e); - - const QPoint p(e->pos() - rect().center()); - if (p.manhattanLength() < std::min(width(), height()) * 0.8 * 0.5) - { - emit requestContextMenu(); - return; - } - - QWidget::mousePressEvent(e); -} - -QSize DiskPluginItem::sizeHint() const -{ - return QSize(26, 26); -} - -void DiskPluginItem::updateIcon() -{ - if (m_displayMode == Dock::Efficient) -// m_icon = ImageUtil::loadSvg(":/icons/resources/icon-small.svg", 16); - m_icon = QIcon::fromTheme("drive-removable-dock-symbolic").pixmap(16, 16); - else -// m_icon = ImageUtil::loadSvg(":/icons/resources/icon.svg", std::min(width(), height()) * 0.8); - m_icon = QIcon::fromTheme("drive-removable-dock").pixmap(std::min(width(), height()) * 0.8, std::min(width(), height()) * 0.8); - - update(); -} diff --git a/plugins/disk-mount/diskpluginitem.h b/plugins/disk-mount/diskpluginitem.h deleted file mode 100644 index c4d20bd4e..000000000 --- a/plugins/disk-mount/diskpluginitem.h +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef DISKPLUGINITEM_H -#define DISKPLUGINITEM_H - -#include "constants.h" - -#include -#include - -class DiskPluginItem : public QWidget -{ - Q_OBJECT - -public: - explicit DiskPluginItem(QWidget *parent = 0); - -signals: - void requestContextMenu() const; - -public slots: - void setDockDisplayMode(const Dock::DisplayMode mode); - -protected: - void paintEvent(QPaintEvent *e); - void resizeEvent(QResizeEvent *e); - void mousePressEvent(QMouseEvent *e); - QSize sizeHint() const; - -private: - void updateIcon(); - -private: - Dock::DisplayMode m_displayMode; - - QPixmap m_icon; -}; - -#endif // DISKPLUGINITEM_H diff --git a/plugins/disk-mount/imageutil.cpp b/plugins/disk-mount/imageutil.cpp deleted file mode 100644 index 58a3e60a3..000000000 --- a/plugins/disk-mount/imageutil.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "imageutil.h" - -#include - -const QPixmap ImageUtil::loadSvg(const QString &path, const int size) -{ - QPixmap pixmap(size, size); - QSvgRenderer renderer(path); - pixmap.fill(Qt::transparent); - - QPainter painter; - painter.begin(&pixmap); - renderer.render(&painter); - painter.end(); - - return pixmap; -} diff --git a/plugins/disk-mount/imageutil.h b/plugins/disk-mount/imageutil.h deleted file mode 100644 index 7abcea845..000000000 --- a/plugins/disk-mount/imageutil.h +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef IMAGEUTIL_H -#define IMAGEUTIL_H - -#include -#include - -class ImageUtil -{ -public: - static const QPixmap loadSvg(const QString &path, const int size); -}; - -#endif // IMAGEUTIL_H diff --git a/plugins/disk-mount/resources.qrc b/plugins/disk-mount/resources.qrc deleted file mode 100644 index f36bff8c2..000000000 --- a/plugins/disk-mount/resources.qrc +++ /dev/null @@ -1,10 +0,0 @@ - - - resources/icon-small.svg - resources/icon.svg - resources/unmount-press.png - resources/unmount-normal.png - resources/unmount-hover.png - resources/unknown.svg - - diff --git a/plugins/disk-mount/resources/icon-small.svg b/plugins/disk-mount/resources/icon-small.svg deleted file mode 100644 index 549ca8a0e..000000000 --- a/plugins/disk-mount/resources/icon-small.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - drive_harddisk_usb_symbolic_active_16px - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/plugins/disk-mount/resources/icon.svg b/plugins/disk-mount/resources/icon.svg deleted file mode 100644 index 952b644bf..000000000 --- a/plugins/disk-mount/resources/icon.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - 磁盘挂载-48px - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/disk-mount/resources/unknown.svg b/plugins/disk-mount/resources/unknown.svg deleted file mode 100644 index 8156620ab..000000000 --- a/plugins/disk-mount/resources/unknown.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - drive-unknown - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/disk-mount/resources/unmount-hover.png b/plugins/disk-mount/resources/unmount-hover.png deleted file mode 100644 index 863e17ac0..000000000 Binary files a/plugins/disk-mount/resources/unmount-hover.png and /dev/null differ diff --git a/plugins/disk-mount/resources/unmount-normal.png b/plugins/disk-mount/resources/unmount-normal.png deleted file mode 100644 index 77feec2ea..000000000 Binary files a/plugins/disk-mount/resources/unmount-normal.png and /dev/null differ diff --git a/plugins/disk-mount/resources/unmount-press.png b/plugins/disk-mount/resources/unmount-press.png deleted file mode 100644 index a3e0692cd..000000000 Binary files a/plugins/disk-mount/resources/unmount-press.png and /dev/null differ diff --git a/plugins/display/CMakeLists.txt b/plugins/display/CMakeLists.txt new file mode 100644 index 000000000..a727f2557 --- /dev/null +++ b/plugins/display/CMakeLists.txt @@ -0,0 +1,51 @@ + +set(PLUGIN_NAME "display") + +project(${PLUGIN_NAME}) + +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + +# Sources files +file(GLOB_RECURSE SRCS "*.h" "*.cpp" + "../../widgets/*.h" + "../../widgets/*.cpp" + "../../frame/util/imageutil.h" + "../../frame/util/imageutil.cpp" + "../../frame/util/statebutton.h" + "../../frame/util/statebutton.cpp" + "../../frame/util/horizontalseperator.h" + "../../frame/util/horizontalseperator.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp") + +find_package(PkgConfig REQUIRED) +find_package(Qt5Widgets REQUIRED) +find_package(Qt5Svg REQUIRED) +find_package(Qt5DBus REQUIRED) +find_package(DtkWidget REQUIRED) + +pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor) +pkg_check_modules(QGSettings REQUIRED gsettings-qt) + +add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") +add_library(${PLUGIN_NAME} SHARED ${SRCS} ./resource/display.qrc) +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../quick-trays) +target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ../../interfaces + ../../widgets + ../../frame + ../../frame/qtdbusextended + ./dbusinterface/generation_dbus_interface + componments) + +target_link_libraries(${PLUGIN_NAME} PRIVATE + ${XCB_EWMH_LIBRARIES} + ${DtkWidget_LIBRARIES} + ${QGSettings_LIBRARIES} + ${Qt5DBus_LIBRARIES} + ${Qt5Widgets_LIBRARIES} + ${Qt5Svg_LIBRARIES} +) + +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/quick-trays) diff --git a/plugins/display/brightnessadjwidget.cpp b/plugins/display/brightnessadjwidget.cpp new file mode 100644 index 000000000..f38f91688 --- /dev/null +++ b/plugins/display/brightnessadjwidget.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "brightnessadjwidget.h" +#include "brightnessmodel.h" +#include "slidercontainer.h" +#include "imageutil.h" + +#include + +const int ItemSpacing = 5; + +BrightnessAdjWidget::BrightnessAdjWidget(QWidget *parent) + : QWidget(parent) + , m_mainLayout(new QVBoxLayout(this)) + , m_brightnessModel(new BrightnessModel(this)) +{ + m_mainLayout->setMargin(0); + m_mainLayout->setSpacing(ItemSpacing); + + loadBrightnessItem(); +} + +void BrightnessAdjWidget::loadBrightnessItem() +{ + QList monitors = m_brightnessModel->monitors(); + int itemHeight = monitors.count() > 1 ? 56 : 30; + + for (BrightMonitor *monitor : monitors) { + SliderContainer *sliderContainer = new SliderContainer(this); + if (monitors.count() > 1) + sliderContainer->setTitle(monitor->name()); + + QPixmap leftPixmap = ImageUtil::loadSvg(":/icons/resources/brightnesslow", QSize(20, 20)); + QPixmap rightPixmap = ImageUtil::loadSvg(":/icons/resources/brightnesshigh", QSize(20, 20)); + sliderContainer->setIcon(SliderContainer::IconPosition::LeftIcon,leftPixmap, QSize(), 12); + sliderContainer->setIcon(SliderContainer::IconPosition::RightIcon, rightPixmap, QSize(), 12); + // 需求要求调节范围是10%-100%,且调节幅度为1% + sliderContainer->setRange(10, 100); + sliderContainer->setPageStep(1); + sliderContainer->setFixedWidth(310); + sliderContainer->setFixedHeight(itemHeight); + sliderContainer->updateSliderValue(monitor->brightness()); + + SliderProxyStyle *proxy = new SliderProxyStyle(SliderProxyStyle::Normal); + sliderContainer->setSliderProxyStyle(proxy); + m_mainLayout->addWidget(sliderContainer); + + connect(monitor, &BrightMonitor::brightnessChanged, sliderContainer, &SliderContainer::updateSliderValue); + connect(sliderContainer, &SliderContainer::sliderValueChanged, monitor, &BrightMonitor::setBrightness); + } + + QMargins margins = this->contentsMargins(); + setFixedHeight(margins.top() + margins.bottom() + monitors.count() * itemHeight + monitors.count() * ItemSpacing); +} + diff --git a/plugins/display/brightnessadjwidget.h b/plugins/display/brightnessadjwidget.h new file mode 100644 index 000000000..04c919d9b --- /dev/null +++ b/plugins/display/brightnessadjwidget.h @@ -0,0 +1,33 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef BRIGHTNESS_ADJUSTMENT_WIDGET_H +#define BRIGHTNESS_ADJUSTMENT_WIDGET_H + +#include + +class QVBoxLayout; +class BrightnessModel; + +/*! + * \brief The BrightnessAdjWidget class + * 显示器亮度调整页面 + */ +class BrightnessAdjWidget : public QWidget +{ + Q_OBJECT +public: + explicit BrightnessAdjWidget(QWidget *parent = nullptr); + +private: + void loadBrightnessItem(); + +private: + QVBoxLayout *m_mainLayout; + BrightnessModel *m_brightnessModel; +}; + + +#endif // BRIGHTNESS_ADJUSTMENT_WIDGET_H diff --git a/plugins/display/brightnessmodel.cpp b/plugins/display/brightnessmodel.cpp new file mode 100644 index 000000000..e430dfc37 --- /dev/null +++ b/plugins/display/brightnessmodel.cpp @@ -0,0 +1,211 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "brightnessmodel.h" + +#include +#include +#include +#include +#include +#include + +static const QString serviceName("org.deepin.dde.Display1"); +static const QString servicePath("/org/deepin/dde/Display1"); +static const QString serviceInterface("org.deepin.dde.Display1"); +static const QString propertiesInterface("org.freedesktop.DBus.Properties"); + +BrightnessModel::BrightnessModel(QObject *parent) + : QObject(parent) +{ + QDBusInterface dbusInter(serviceName, servicePath, serviceInterface, QDBusConnection::sessionBus()); + if (dbusInter.isValid()) { + // 读取所有的屏幕的信息 + m_primaryScreenName = dbusInter.property("Primary").value(); + m_monitor = readMonitors(dbusInter.property("Monitors").value>()); + + QDBusConnection::sessionBus().connect(serviceName, servicePath, propertiesInterface, + "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); + } +} + +BrightnessModel::~BrightnessModel() +{ +} + +QList BrightnessModel::monitors() +{ + return m_monitor; +} + +BrightMonitor *BrightnessModel::primaryMonitor() const +{ + for (BrightMonitor *monitor : m_monitor) { + if (monitor->isPrimary()) + return monitor; + } + + return nullptr; +} + +void BrightnessModel::primaryScreenChanged(QScreen *screen) +{ + BrightMonitor *defaultMonitor = nullptr; + for (BrightMonitor *monitor : m_monitor) { + monitor->setPrimary(monitor->name() == screen->name()); + if (monitor->isPrimary()) + defaultMonitor = monitor; + } + + if (defaultMonitor) + Q_EMIT primaryChanged(defaultMonitor); +} + +void BrightnessModel::onPropertyChanged(const QDBusMessage &msg) +{ + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName != serviceInterface) + return; + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + if (changedProps.contains("Primary")) { + m_primaryScreenName = changedProps.value("Primary").toString(); + BrightMonitor *defaultMonitor = nullptr; + for (BrightMonitor *monitor : m_monitor) { + monitor->setPrimary(monitor->name() == m_primaryScreenName); + if (monitor->isPrimary()) + defaultMonitor = monitor; + } + + if (defaultMonitor) + Q_EMIT primaryChanged(defaultMonitor); + } else if (changedProps.contains("Monitors")) { + int oldSize = m_monitor.size(); + qDeleteAll(m_monitor); + m_monitor = readMonitors(changedProps.value("Monitors").value>()); + if (oldSize == 1 && m_monitor.size() == 0) { + Q_EMIT screenVisibleChanged(false); + } else if (oldSize == 0 && m_monitor.size() == 1) { + Q_EMIT screenVisibleChanged(true); + } + } +} + +QList BrightnessModel::readMonitors(const QList &paths) +{ + QList monitors; + for (QDBusObjectPath path : paths) { + BrightMonitor *monitor = new BrightMonitor(path.path(), this); + monitor->setPrimary(m_primaryScreenName == monitor->name()); + monitors << monitor; + } + return monitors; +} + +/** + * @brief monitor + */ +BrightMonitor::BrightMonitor(QString path, QObject *parent) + : QObject(parent) + , m_path(path) + , m_brightness(100) + , m_enabled(false) + , m_isPrimary(false) +{ + QDBusInterface dbusInter(serviceName, path, serviceInterface + QString(".Monitor"), QDBusConnection::sessionBus()); + if (dbusInter.isValid()) { + // 读取所有的屏幕的信息 + m_name = dbusInter.property("Name").toString(); + m_brightness = static_cast(dbusInter.property("Brightness").toDouble() * 100); + m_enabled = dbusInter.property("Enabled").toBool(); + } + + QDBusConnection::sessionBus().connect(serviceName, path, propertiesInterface, + "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); +} + +BrightMonitor::~BrightMonitor() +{ +} + +void BrightMonitor::setPrimary(bool primary) +{ + m_isPrimary = primary; +} + +int BrightMonitor::brightness() +{ + return m_brightness; +} + +bool BrightMonitor::enabled() +{ + return m_enabled; +} + +QString BrightMonitor::name() +{ + return m_name; +} + +bool BrightMonitor::isPrimary() +{ + return m_isPrimary; +} + +void BrightMonitor::setBrightness(int value) +{ + callMethod("SetBrightness", { m_name, static_cast(value * 0.01) }); +} + +void BrightMonitor::onPropertyChanged(const QDBusMessage &msg) +{ + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName != QString("%1.Monitor").arg(serviceInterface)) + return; + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + if (changedProps.contains("Brightness")) { + int brightness = static_cast(changedProps.value("Brightness").value() * 100); + if (brightness != m_brightness) { + m_brightness = brightness; + Q_EMIT brightnessChanged(brightness); + } + } + if (changedProps.contains("Name")) { + QString name = changedProps.value("Name").value(); + if (name != m_name) { + m_name = name; + Q_EMIT nameChanged(name); + } + } + if (changedProps.contains("Enabled")) { + bool enabled = changedProps.value("Enabled").value(); + if (enabled != m_enabled) { + m_enabled = enabled; + Q_EMIT enabledChanged(enabled); + } + } +} + +QDBusMessage BrightMonitor::callMethod(const QString &methodName, const QList &argument) +{ + QDBusInterface dbusInter(serviceName, servicePath, serviceInterface, QDBusConnection::sessionBus()); + if (dbusInter.isValid()) { + QDBusPendingCall reply = dbusInter.asyncCallWithArgumentList(methodName, argument); + reply.waitForFinished(); + return reply.reply(); + } + + return QDBusMessage(); +} diff --git a/plugins/display/brightnessmodel.h b/plugins/display/brightnessmodel.h new file mode 100644 index 000000000..cf4423732 --- /dev/null +++ b/plugins/display/brightnessmodel.h @@ -0,0 +1,78 @@ +// Copyright (C) 2011 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef BRIGHTNESSMODEL_H +#define BRIGHTNESSMODEL_H + +#include +#include + +class BrightMonitor; +class QDBusMessage; +class QScreen; + +class BrightnessModel : public QObject +{ + Q_OBJECT + +public: + explicit BrightnessModel(QObject *parent = nullptr); + ~BrightnessModel(); + + QList monitors(); + BrightMonitor *primaryMonitor() const; + +Q_SIGNALS: + void primaryChanged(BrightMonitor *); + void screenVisibleChanged(bool); + +protected Q_SLOTS: + void primaryScreenChanged(QScreen *screen); + void onPropertyChanged(const QDBusMessage &msg); + +private: + QList readMonitors(const QList &paths); + +private: + QList m_monitor; + QString m_primaryScreenName; +}; + +class BrightMonitor : public QObject +{ + Q_OBJECT + +public: + explicit BrightMonitor(QString path, QObject *parent); + ~BrightMonitor(); + +Q_SIGNALS: + void brightnessChanged(int); + void nameChanged(QString); + void enabledChanged(bool); + +public: + void setPrimary(bool primary); + int brightness(); + bool enabled(); + QString name(); + bool isPrimary(); + +public slots: + void setBrightness(int value); + void onPropertyChanged(const QDBusMessage &msg); + +private: + QDBusMessage callMethod(const QString &methodName, const QList &argument); + +private: + QString m_path; + QString m_name; + int m_brightness; + bool m_enabled; + bool m_isPrimary; +}; + +#endif // DISPLAYMODEL_H diff --git a/plugins/display/brightnesswidget.cpp b/plugins/display/brightnesswidget.cpp new file mode 100644 index 000000000..428c97d0b --- /dev/null +++ b/plugins/display/brightnesswidget.cpp @@ -0,0 +1,104 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "brightnesswidget.h" +#include "brightnessmodel.h" +#include "imageutil.h" +#include "slidercontainer.h" + +#include + +#include +#include + +#define BACKSIZE 36 +#define IMAGESIZE 18 + +DGUI_USE_NAMESPACE + +BrightnessWidget::BrightnessWidget(BrightnessModel *model, QWidget *parent) + : QWidget(parent) + , m_sliderContainer(new SliderContainer(this)) + , m_model(model) +{ + initUi(); + initConnection(); +} + +BrightnessWidget::~BrightnessWidget() +{ +} + +void BrightnessWidget::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + + // 显示的时候更新一下slider的主屏幕亮度值 + updateSliderValue(); +} + +void BrightnessWidget::initUi() +{ + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(15, 0, 12, 0); + + onThemeTypeChanged(); + // 需求要求调节范围是10%-100%,且调节幅度为1% + m_sliderContainer->setRange(10, 100); + m_sliderContainer->setPageStep(1); + + SliderProxyStyle *style = new SliderProxyStyle; + m_sliderContainer->setSliderProxyStyle(style); + + mainLayout->addWidget(m_sliderContainer); +} + +void BrightnessWidget::initConnection() +{ + connect(m_sliderContainer, &SliderContainer::sliderValueChanged, this, [ this ](int value) { + BrightMonitor *monitor = m_model->primaryMonitor(); + if (monitor) + monitor->setBrightness(value); + }); + + connect(m_sliderContainer, &SliderContainer::iconClicked, this, [ this ](const SliderContainer::IconPosition &position) { + if (position == SliderContainer::IconPosition::RightIcon) + Q_EMIT brightClicked(); + }); + + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &BrightnessWidget::onThemeTypeChanged); + updateSliderValue(); +} + +void BrightnessWidget::updateSliderValue() +{ + BrightMonitor *monitor = m_model->primaryMonitor(); + if (monitor) { + m_sliderContainer->updateSliderValue(monitor->brightness()); + } +} + +void BrightnessWidget::convertThemePixmap(QPixmap &pixmap) +{ + // 图片是黑色的,如果当前主题为白色主题,则无需转换 + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::ColorType::LightType) + return; + + // 如果是黑色主题,则转换成白色图像 + QPainter painter(&pixmap); + painter.setCompositionMode(QPainter::CompositionMode_SourceIn); + painter.fillRect(pixmap.rect(), Qt::white); + painter.end(); +} + +void BrightnessWidget::onThemeTypeChanged() +{ + QPixmap leftPixmap = ImageUtil::loadSvg(":/brightness.svg", QSize(IMAGESIZE, IMAGESIZE)); + QPixmap rightPixmap = ImageUtil::loadSvg(":/ICON_Device_Laptop.svg", QSize(IMAGESIZE, IMAGESIZE)); + convertThemePixmap(leftPixmap); + convertThemePixmap(rightPixmap); + m_sliderContainer->setIcon(SliderContainer::IconPosition::LeftIcon, leftPixmap, QSize(), 10); + m_sliderContainer->setIcon(SliderContainer::IconPosition::RightIcon, rightPixmap, QSize(BACKSIZE, BACKSIZE), 12); +} diff --git a/plugins/display/brightnesswidget.h b/plugins/display/brightnesswidget.h new file mode 100644 index 000000000..f921eb94b --- /dev/null +++ b/plugins/display/brightnesswidget.h @@ -0,0 +1,45 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef BRIGHTNESSWIDGET_H +#define BRIGHTNESSWIDGET_H + +#include + +DWIDGET_USE_NAMESPACE + +class SliderContainer; +class BrightnessModel; +class BrightMonitor; + +class BrightnessWidget : public QWidget +{ + Q_OBJECT + +public: + explicit BrightnessWidget(BrightnessModel *model, QWidget *parent = nullptr); + ~BrightnessWidget() override; + +Q_SIGNALS: + void brightClicked(); + +protected: + void showEvent(QShowEvent *event) override; + +private: + void initUi(); + void initConnection(); + void updateSliderValue(); + void convertThemePixmap(QPixmap &pixmap); + +private Q_SLOTS: + void onThemeTypeChanged(); + +private: + SliderContainer *m_sliderContainer; + BrightnessModel *m_model; +}; + +#endif // LIGHTSETTINGWIDGET_H diff --git a/plugins/display/collaborationdevmodel.cpp b/plugins/display/collaborationdevmodel.cpp new file mode 100644 index 000000000..cf5c80e1e --- /dev/null +++ b/plugins/display/collaborationdevmodel.cpp @@ -0,0 +1,267 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "collaborationdevmodel.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +DGUI_USE_NAMESPACE +DCORE_USE_NAMESPACE + +static const QString CollaborationService = "org.deepin.dde.Cooperation1"; +static const QString CollaborationPath = "/org/deepin/dde/Cooperation1"; +static const QString CollaborationInterface = "org.deepin.dde.Cooperation1"; +static const QString ColPropertiesInterface = "org.freedesktop.DBus.Properties"; + +CollaborationDevModel::CollaborationDevModel(QObject *parent) + : QObject(parent) + , m_colDbusInter(new QDBusInterface(CollaborationService, CollaborationPath, CollaborationInterface, QDBusConnection::sessionBus(), this)) +{ + if (m_colDbusInter->isValid()) { + QList paths = m_colDbusInter->property("Machines").value>(); + for (const QDBusObjectPath& path : paths) { + CollaborationDevice *device = new CollaborationDevice(path.path(), this); + if (device->isValid()) + m_devices[path.path()] = device; + else + device->deleteLater(); + } + } else { + qWarning() << CollaborationService << " is invalid"; + } + + m_colDbusInter->connection().connect(CollaborationService, CollaborationPath, ColPropertiesInterface, + "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(QDBusMessage))); + + auto *dbusWatcher = new QDBusServiceWatcher(CollaborationService, m_colDbusInter->connection(), + QDBusServiceWatcher::WatchForUnregistration, this); + connect(dbusWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](){ + qWarning() << CollaborationService << "unregistered"; + clear(); + }); +} + +void CollaborationDevModel::checkServiceValid() +{ + if (!m_colDbusInter->isValid()) { + clear(); + } +} + +QList CollaborationDevModel::devices() const +{ + return m_devices.values(); +} + +void CollaborationDevModel::onPropertyChanged(const QDBusMessage &msg) +{ + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName != CollaborationInterface) + return; + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + if (changedProps.contains("Machines")) { + QList paths = m_colDbusInter->property("Machines").value>(); + QStringList devPaths; + for (const QDBusObjectPath& path : paths) { + devPaths << path.path(); + } + updateDevice(devPaths); + } +} + +void CollaborationDevModel::updateDevice(const QStringList &devPaths) +{ + if (devPaths.isEmpty()) { + qDeleteAll(m_devices); + m_devices.clear(); + } else { + // 清除已不存在的设备 + QMapIterator it(m_devices); + while (it.hasNext()) { + it.next(); + if (!devPaths.contains(it.key())) { + it.value()->deleteLater(); + m_devices.remove(it.key()); + } + } + + // 添加新增设备 + for (const QString &path : devPaths) { + if (!m_devices.contains(path)) { + CollaborationDevice *device = new CollaborationDevice(path, this); + if (device->isValid()) + m_devices[path] = device; + else + device->deleteLater(); + } + } + } + + emit devicesChanged(); +} + +void CollaborationDevModel::clear() +{ + for (CollaborationDevice *device : m_devices) { + device->deleteLater(); + } + m_devices.clear(); + + Q_EMIT devicesChanged(); +} + +CollaborationDevice *CollaborationDevModel::getDevice(const QString &machinePath) +{ + return m_devices.value(machinePath, nullptr); +} + +CollaborationDevice::CollaborationDevice(const QString &devPath, QObject *parent) + : QObject(parent) + , m_path(devPath) + , m_OS(-1) + , m_isConnected(false) + , m_isCooperated(false) + , m_isValid(false) + , m_isCooperating(false) + , m_devDbusInter(new QDBusInterface(CollaborationService, devPath, CollaborationInterface + QString(".Machine"), + QDBusConnection::sessionBus(), this)) +{ + if (m_devDbusInter->isValid()) { + m_name = m_devDbusInter->property("Name").toString(); + m_OS = m_devDbusInter->property("OS").toInt(); + m_isConnected = m_devDbusInter->property("Connected").toBool(); + m_isCooperated = m_devDbusInter->property("DeviceSharing").toBool(); + m_uuid = m_devDbusInter->property("UUID").toString(); + m_isValid = true; + } else { + qWarning() << "CollaborationDevice devPath:" << devPath << " is invalid and get properties failed"; + } + + m_devDbusInter->connection().connect(CollaborationService, m_path, ColPropertiesInterface, "PropertiesChanged", + this, SLOT(onPropertyChanged(QDBusMessage))); +} + +bool CollaborationDevice::isValid() const +{ + // not show android device + return m_isValid && m_OS != Android; +} + +QString CollaborationDevice::name() const +{ + return m_name; +} + +QString CollaborationDevice::uuid() const +{ + return m_uuid; +} + +QString CollaborationDevice::machinePath() const +{ + return m_path; +} + +QString CollaborationDevice::deviceIcon() const +{ + switch (m_OS) { + case DeviceType::Android: { + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) + return QString(":/ICON_Device_Headphone_dark.svg"); + + return QString(":/ICON_Device_Headphone.svg"); + } + default: { + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) + return QString(":/ICON_Device_Laptop_dark.svg"); + + return QString(":/ICON_Device_Laptop.svg"); + } + } +} + +bool CollaborationDevice::isConnected() const +{ + return m_isConnected; +} + +bool CollaborationDevice::isCooperated() const +{ + return m_isCooperated; +} + +void CollaborationDevice::setDeviceIsCooperating(bool isCooperating) +{ + m_isCooperating = isCooperating; +} + +void CollaborationDevice::onPropertyChanged(const QDBusMessage &msg) +{ + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName != QString("%1.Machine").arg(CollaborationInterface)) + return; + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + if (changedProps.contains("Connected")) { + bool isConnected = changedProps.value("Connected").value(); + m_isConnected = isConnected; + if (isConnected && m_isCooperating) { + // paired 成功之后再去请求cooperate + requestCooperate(); + } + + if (!isConnected){ + Q_EMIT pairedStateChanged(false); + } + } else if (changedProps.contains("DeviceSharing")) { + m_isCooperated = changedProps.value("DeviceSharing").value(); + + Q_EMIT pairedStateChanged(m_isCooperated); + } +} + +void CollaborationDevice::requestCooperate() const +{ + callMethod("RequestDeviceSharing"); +} + +void CollaborationDevice::disconnectDevice() const +{ + callMethod("Disconnect"); +} + +void CollaborationDevice::connect() const +{ + callMethod("Connect"); +} + +QDBusMessage CollaborationDevice::callMethod(const QString &methodName) const +{ + if (m_devDbusInter->isValid()) { + QDBusMessage msg = m_devDbusInter->call(methodName); + qInfo() << "CollaborationDevice callMethod:" << methodName << " " << msg.errorMessage(); + return msg; + } + + qWarning() << "CollaborationDevice callMethod: " << methodName << " failed"; + return QDBusMessage(); +} diff --git a/plugins/display/collaborationdevmodel.h b/plugins/display/collaborationdevmodel.h new file mode 100644 index 000000000..db9f4adb7 --- /dev/null +++ b/plugins/display/collaborationdevmodel.h @@ -0,0 +1,108 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef COLLABORATION_DEV_MODEL_H +#define COLLABORATION_DEV_MODEL_H + +#include +#include + +class QTimer; +class QDBusInterface; +class QDBusMessage; +class CollaborationDevice; + +/*! + * \brief The CollaborationDevModel class + * 协同设备model + */ +class CollaborationDevModel : public QObject +{ + Q_OBJECT +public: + explicit CollaborationDevModel(QObject *parent = nullptr); + +signals: + void devicesChanged(); + +public: + void checkServiceValid(); + + QList devices() const; + CollaborationDevice *getDevice(const QString &machinePath); + +private slots: + void onPropertyChanged(const QDBusMessage &msg); + +private: + void updateDevice(const QStringList &devPaths); + void clear(); + +private: + QDBusInterface *m_colDbusInter; + // machine path : device object + QMap m_devices; + +}; + +/*! + * \brief The CollaborationDevice class + * 协同设备类 + */ +class CollaborationDevice : public QObject +{ + Q_OBJECT +public: + explicit CollaborationDevice(const QString &devPath, QObject *parent = nullptr); + +signals: + void pairedStateChanged(bool); + +public: + bool isValid() const; + void connect() const; + void requestCooperate() const; + void disconnectDevice() const; + + QString name() const; + QString uuid() const; + QString machinePath() const; + QString deviceIcon() const; + bool isConnected() const; + bool isCooperated() const; + void setDeviceIsCooperating(bool isCooperating); + +private slots: + void onPropertyChanged(const QDBusMessage &msg); + +private: + QDBusMessage callMethod(const QString &methodName) const; + +private: + enum DeviceType { + Other = 0, + UOS, + Linux, + Windows, + MacOS, + Android + }; + + QString m_path; + QString m_name; + QString m_uuid; + int m_OS; + + bool m_isConnected; + bool m_isCooperated; + bool m_isValid; + + // 标记任务栏点击触发协同连接 + bool m_isCooperating; + + QDBusInterface *m_devDbusInter; +}; + +#endif // COLLABORATION_DEV_MODEL_H diff --git a/plugins/display/devcollaborationwidget.cpp b/plugins/display/devcollaborationwidget.cpp new file mode 100644 index 000000000..f75964ef1 --- /dev/null +++ b/plugins/display/devcollaborationwidget.cpp @@ -0,0 +1,241 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "devcollaborationwidget.h" +#include "collaborationdevmodel.h" +#include "devitemdelegate.h" + +#include + +#include +#include +#include +#include +#include + +#define TITLE_HEIGHT 16 +#define ITEM_WIDTH 310 +#define ITEM_HEIGHT 36 +#define LISTVIEW_ITEM_SPACE 5 +#define PER_DEGREE 14 + +DevCollaborationWidget::DevCollaborationWidget(QWidget *parent) + : QWidget(parent) + , m_deviceModel(new CollaborationDevModel(this)) + , m_deviceListView(new DListView(this)) + , m_viewItemModel(new QStandardItemModel(m_deviceListView)) + , m_refreshTimer(new QTimer(this)) +{ + initUI(); + loadDevice(); + + connect(m_deviceModel, &CollaborationDevModel::devicesChanged, this, &DevCollaborationWidget::loadDevice); + connect(m_deviceListView, &DListView::clicked, this, &DevCollaborationWidget::itemClicked); + connect(m_refreshTimer, &QTimer::timeout, this, &DevCollaborationWidget::refreshViewItem); +} + +void DevCollaborationWidget::showEvent(QShowEvent *event) +{ + m_deviceModel->checkServiceValid(); + + QWidget::showEvent(event); +} + +void DevCollaborationWidget::resizeEvent(QResizeEvent *event) +{ + Q_EMIT sizeChanged(); + + QWidget::resizeEvent(event); +} + +void DevCollaborationWidget::initUI() +{ + m_deviceListView->setModel(m_viewItemModel); + + QLabel *title = new QLabel(tr("PC collaboration"), this); + title->setFixedHeight(TITLE_HEIGHT); + + QHBoxLayout *hLayout = new QHBoxLayout(); + hLayout->setContentsMargins(10, 0, 0, 0); + hLayout->addWidget(title); + + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->setMargin(0); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + mainLayout->addLayout(hLayout); + mainLayout->addWidget(m_deviceListView); + + setLayout(mainLayout); + + m_deviceListView->setContentsMargins(0, 0, 0, 0); + m_deviceListView->setFrameShape(QFrame::NoFrame); + m_deviceListView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_deviceListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_deviceListView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + m_deviceListView->setResizeMode(QListView::Adjust); + m_deviceListView->setViewportMargins(0, 0, 0, 0); + m_deviceListView->setSpacing(LISTVIEW_ITEM_SPACE); + m_deviceListView->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_deviceListView->setItemDelegate(new DevItemDelegate(this)); +} + +void DevCollaborationWidget::loadDevice() +{ + if (!m_deviceListView->count()) { + for (CollaborationDevice *device : m_deviceModel->devices()) { + addItem(device); + } + } else { + updateDeviceListView(); + } + + if(!m_deviceListView->count()) { + m_deviceListView->hide(); + } else { + if (!m_deviceListView->isVisible()) + m_deviceListView->setVisible(true); + + m_deviceListView->setFixedSize(ITEM_WIDTH, m_deviceListView->count() * ITEM_HEIGHT + LISTVIEW_ITEM_SPACE * (m_deviceListView->count() * 2)); + } + + resetWidgetSize(); +} + +void DevCollaborationWidget::addItem(const CollaborationDevice *device) +{ + if (!device) + return; + + QStandardItem *item = new QStandardItem(); + DevItemDelegate::DevItemData data; + data.checkedIconPath = device->deviceIcon(); // TODO + data.text = device->name(); + data.iconPath = device->deviceIcon(); + int resultState = device->isCooperated() ? DevItemDelegate::Connected : DevItemDelegate::None; + + item->setData(QVariant::fromValue(data), DevItemDelegate::StaticDataRole); + item->setData(device->machinePath(), DevItemDelegate::MachinePathDataRole); + item->setData(0, DevItemDelegate::DegreeDataRole); + item->setData(resultState, DevItemDelegate::ResultDataRole); + + m_viewItemModel->appendRow(item); + m_deviceItemMap[device->machinePath()] = item; + + connect(device, &CollaborationDevice::pairedStateChanged, this, &DevCollaborationWidget::itemStatusChanged); +} + +void DevCollaborationWidget::updateDeviceListView() +{ + QList devices = m_deviceModel->devices(); + if (devices.isEmpty()) { + m_deviceListView->removeItems(0, m_deviceListView->count()); + m_deviceItemMap.clear(); + m_connectingDevices.clear(); + return; + } + + // 删除不存在设备 + for (int row = 0; row < m_deviceListView->count(); row++) { + QStandardItem *item = m_viewItemModel->item(row); + if (!item) + continue; + + QString machinePath = item->data(DevItemDelegate::MachinePathDataRole).toString(); + if (m_deviceModel->getDevice(machinePath)) + continue; + + m_deviceListView->removeItem(row); + + if (m_deviceItemMap.contains(machinePath)) { + m_deviceItemMap.remove(machinePath); + } + + if (m_connectingDevices.contains(machinePath)) { + m_connectingDevices.removeAll(machinePath); + } + } + + // 处理新增 + for (CollaborationDevice *device : devices) { + if (!m_deviceItemMap.contains(device->machinePath())) { + addItem(device); + } + } +} + +void DevCollaborationWidget::resetWidgetSize() +{ + int height = TITLE_HEIGHT + (m_deviceListView->count() ? m_deviceListView->height() : 0); + + setFixedSize(ITEM_WIDTH, height); +} + +void DevCollaborationWidget::itemClicked(const QModelIndex &index) +{ + QString machinePath = index.data(DevItemDelegate::MachinePathDataRole).toString(); + CollaborationDevice *device = m_deviceModel->getDevice(machinePath); + if (!device) + return; + + if (!device->isConnected()) { + device->setDeviceIsCooperating(true); + device->connect(); + if (!m_connectingDevices.contains(machinePath)) + m_connectingDevices.append(machinePath); + } else if (!device->isCooperated()) { + device->requestCooperate(); + if (!m_connectingDevices.contains(machinePath)) + m_connectingDevices.append(machinePath); + } else if (device->isCooperated()) { + device->disconnectDevice(); + if (m_connectingDevices.contains(machinePath)) + m_connectingDevices.removeOne(machinePath); + } + + if (!m_connectingDevices.isEmpty() && !m_refreshTimer->isActive()) + m_refreshTimer->start(80); +} + +void DevCollaborationWidget::itemStatusChanged() +{ + CollaborationDevice *device = qobject_cast(sender()); + if (!device) + return; + + device->setDeviceIsCooperating(false); + QString machinePath = device->machinePath(); + if (m_deviceItemMap.contains(machinePath) && m_deviceItemMap[machinePath]) { + // 更新item的连接状态 + int resultState = device->isCooperated() ? DevItemDelegate::Connected : DevItemDelegate::None; + m_deviceItemMap[machinePath]->setData(resultState, DevItemDelegate::ResultDataRole); + if (device->isCooperated() || !device->isConnected()) + m_deviceItemMap[machinePath]->setData(0, DevItemDelegate::DegreeDataRole); + + m_deviceListView->update(m_deviceItemMap[machinePath]->index()); + + if ((resultState == DevItemDelegate::Connected || !device->isConnected()) && m_connectingDevices.contains(machinePath)) { + m_connectingDevices.removeAll(machinePath); + } + } +} + +void DevCollaborationWidget::refreshViewItem() +{ + if (m_connectingDevices.isEmpty()) { + m_refreshTimer->stop(); + return; + } + + for (const QString &machinePath : m_connectingDevices) { + if (m_deviceItemMap.contains(machinePath) && m_deviceItemMap[machinePath]) { + int degree = m_deviceItemMap[machinePath]->data(DevItemDelegate::DegreeDataRole).toInt(); + degree += PER_DEGREE; // 递进值 + m_deviceItemMap[machinePath]->setData(DevItemDelegate::Connecting, DevItemDelegate::ResultDataRole); + m_deviceItemMap[machinePath]->setData(degree, DevItemDelegate::DegreeDataRole); + m_deviceListView->update(m_deviceItemMap[machinePath]->index()); + } + } +} diff --git a/plugins/display/devcollaborationwidget.h b/plugins/display/devcollaborationwidget.h new file mode 100644 index 000000000..6ec18eead --- /dev/null +++ b/plugins/display/devcollaborationwidget.h @@ -0,0 +1,57 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DEVICE_COLLABORATION_WIDGET_H +#define DEVICE_COLLABORATION_WIDGET_H + +#include +#include + +DWIDGET_USE_NAMESPACE + +class CollaborationDevice; +class CollaborationDevModel; + +/*! + * \brief The DevCollaborationWidget class + * 设备跨端协同子页面 + */ +class DevCollaborationWidget : public QWidget +{ + Q_OBJECT +public: + explicit DevCollaborationWidget(QWidget *parent = nullptr); + +signals: + void sizeChanged(); + +protected: + void showEvent(QShowEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private slots: + void loadDevice(); + void itemClicked(const QModelIndex &index); + void itemStatusChanged(); + void refreshViewItem(); + +private: + void initUI(); + void updateDeviceListView(); + + void addItem(const CollaborationDevice *device); + void resetWidgetSize(); + +private: + CollaborationDevModel *m_deviceModel; + DListView *m_deviceListView; + QStandardItemModel *m_viewItemModel; + QMap m_deviceItemMap; + QStringList m_connectingDevices; + + QTimer *m_refreshTimer; +}; + +#endif // DEVICE_COLLABORATION_WIDGET_H diff --git a/plugins/display/devitemdelegate.cpp b/plugins/display/devitemdelegate.cpp new file mode 100644 index 000000000..a77ce8e0d --- /dev/null +++ b/plugins/display/devitemdelegate.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "devitemdelegate.h" + +#include +#include +#include + +#include + +#define RADIUS_VALUE 10 +#define ITEM_SPACE 20 +#define ICON_WIDTH 16 +#define ICON_HEIGHT 16 +#define TEXT_RECT_HEIGHT 20 +#define ITEM_HEIGHT 36 +#define INDICATOR_SHADOW_OFFSET 10 + +DevItemDelegate::DevItemDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ + +} + +void DevItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (!index.isValid()) + return; + + painter->setRenderHint(QPainter::Antialiasing); + QVariant var = index.data(StaticDataRole); + DevItemData itemData = var.value(); + QRect rect = option.rect; + QPen pen; + pen.setWidth(2); + + // 鼠标悬停 + if (option.state.testFlag(QStyle::State_MouseOver)) { + pen.setColor(QColor("#EBECED")); + painter->setPen(pen); + painter->setBrush(QColor("#EBECED")); + painter->drawRoundedRect(rect, RADIUS_VALUE, RADIUS_VALUE); + } + + // 选中背景(连接上和选中) + int result = index.data(ResultDataRole).toInt(); + if (option.state.testFlag(QStyle::State_Selected) && result == Connected) { + pen.setColor(QColor("#0081FF")); + painter->setPen(pen); + painter->setBrush(QColor("#0081FF")); + painter->drawRoundedRect(rect, RADIUS_VALUE, RADIUS_VALUE); + } else { + // 绘制默认背景 + pen.setColor(QColor("#EBECED")); + painter->setPen(pen); + painter->setBrush(QColor("#EBECED")); + painter->drawRoundedRect(rect, RADIUS_VALUE, RADIUS_VALUE); + } + + bool selected = (option.state.testFlag(QStyle::State_Selected) && result == Connected); + + // 绘制Icon + QString imagePath = selected ? itemData.checkedIconPath : itemData.iconPath; + QRect iconRect = QRect(rect.left() + ITEM_SPACE, rect.top() + rect.height() / 2 - ICON_HEIGHT / 2, + ICON_WIDTH, ICON_HEIGHT); + painter->drawImage(iconRect, QImage(imagePath)); + + // 绘制text + QFont font = Dtk::Widget::DFontSizeManager::instance()->t4(); + painter->setFont(font); + pen.setColor(selected ? Qt::white : Qt::black); + painter->setPen(pen); + + int textRectWidth = rect.width() - ITEM_SPACE - iconRect.width() - iconRect.width() - ITEM_SPACE; + QRect textRect = QRect(iconRect.right() + ITEM_SPACE, rect.top() + 2, + textRectWidth, rect.height()); + + QFontMetrics fm(font); + QString itemText = fm.elidedText(itemData.text, Qt::ElideRight, textRectWidth); + painter->drawText(textRect, itemText); + + switch (result) { + case ResultState::Connected: + drawResultState(painter, rect); + break; + case ResultState::Connecting: + drawWaitingState(painter, rect, index.data(DegreeDataRole).toInt()); + break; + default: + break; + } +} + +QSize DevItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(index) + return QSize(option.rect.width(), ITEM_HEIGHT); +} + +void DevItemDelegate::drawWaitingState(QPainter *painter, const QRect &rect, int degree) const +{ + int left = rect.width() - ITEM_SPACE; + int top = rect.top() + rect.height() / 2 - ICON_HEIGHT / 2; + QRect newRect(left, top, ICON_WIDTH, ICON_HEIGHT); + + painter->setRenderHint(QPainter::Antialiasing, true); + QList> indicatorColors; + for (int i = 0; i < 3; i++) + indicatorColors << createDefaultIndicatorColorList(QColor("#0081FF")); + + double radius = 16 * 0.66; + auto center = QRectF(newRect).center(); + auto indicatorRadius = radius / 2 / 2 * 1.1; + auto indicatorDegreeDelta = 360 / indicatorColors.count(); + + for (int i = 0; i < indicatorColors.count(); ++i) { + QList colors = indicatorColors.value(i); + for (int j = 0; j < colors.count(); ++j) { + double degreeCurrent = degree - j * INDICATOR_SHADOW_OFFSET + indicatorDegreeDelta * i; + auto x = (radius - indicatorRadius) * qCos(qDegreesToRadians(degreeCurrent)); + auto y = (radius - indicatorRadius) * qSin(qDegreesToRadians(degreeCurrent)); + + x = center.x() + x; + y = center.y() + y; + auto tl = QPointF(x - 1 * indicatorRadius, y - 1 * indicatorRadius); + QRectF rf(tl.x(), tl.y(), indicatorRadius * 2, indicatorRadius * 2); + + QPainterPath path; + path.addEllipse(rf); + + painter->fillPath(path, colors.value(j)); + } + } +} + +void DevItemDelegate::drawResultState(QPainter *painter, const QRect &rect) const +{ + // 绘制对勾,14x12 + int left = rect.width() - ITEM_SPACE; + int top = rect.top() + rect.height() / 2 - 6; + + QPainterPath path; + path.moveTo(left, top + 6); + path.lineTo(left + 4, top + 11); + path.lineTo(left + 12, top + 1); + + painter->drawPath(path); +} + +QList DevItemDelegate::createDefaultIndicatorColorList(QColor color) const +{ + QList colors; + QList opacitys; + opacitys << 100 << 30 << 15 << 10 << 5 << 4 << 3 << 2 << 1; + for (int i = 0; i < opacitys.count(); ++i) { + color.setAlpha(255 * opacitys.value(i) / 100); + colors << color; + } + + return colors; +} diff --git a/plugins/display/devitemdelegate.h b/plugins/display/devitemdelegate.h new file mode 100644 index 000000000..4b043cc58 --- /dev/null +++ b/plugins/display/devitemdelegate.h @@ -0,0 +1,52 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DEVITEMDELEGATE_H +#define DEVITEMDELEGATE_H + +#include + +/*! + * \brief The DevItemDelegate class + */ +class DevItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + enum DevItemDataRole { + StaticDataRole = Qt::UserRole + 1, // 静态信息 + MachinePathDataRole = Qt::UserRole + 2, // machinePath, 可唯一代表一个设备 + DegreeDataRole = Qt::UserRole + 3, // degree 绘制waiting使用的参数 + ResultDataRole = Qt::UserRole + 4 // 连接结果 + }; + + enum ResultState { + None, + Connecting, + Connected + }; + + struct DevItemData { + QString checkedIconPath; + QString iconPath; + QString text; + }; + +public: + explicit DevItemDelegate(QObject *parent = nullptr); + +protected: + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; + +private: + void drawWaitingState(QPainter *painter, const QRect &rect, int degree) const; + void drawResultState(QPainter *painter, const QRect &rect) const; + QList createDefaultIndicatorColorList(QColor color) const; +}; + +Q_DECLARE_METATYPE(DevItemDelegate::DevItemData) + +#endif // DEVITEMDELEGATE_H diff --git a/plugins/display/display.json b/plugins/display/display.json new file mode 100644 index 000000000..73e8d1b67 --- /dev/null +++ b/plugins/display/display.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "order": 1 +} diff --git a/plugins/display/displayplugin.cpp b/plugins/display/displayplugin.cpp new file mode 100644 index 000000000..75f745e0d --- /dev/null +++ b/plugins/display/displayplugin.cpp @@ -0,0 +1,98 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "displayplugin.h" +#include "brightnesswidget.h" +#include "displaysettingwidget.h" +#include "brightnesswidget.h" +#include "brightnessmodel.h" + +#include "../../widgets/tipswidget.h" +#include "../../frame/util/utils.h" + +#include + +#include +#include + +#include + +using namespace Dock; +DisplayPlugin::DisplayPlugin(QObject *parent) + : QObject(parent) + , m_displayWidget(nullptr) + , m_displaySettingWidget(nullptr) + , m_displayTips(nullptr) + , m_model(nullptr) +{ +} + +const QString DisplayPlugin::pluginName() const +{ + return "display"; +} + +const QString DisplayPlugin::pluginDisplayName() const +{ + return "Brightness"; +} + +void DisplayPlugin::init(PluginProxyInterface *proxyInter) +{ + if (m_proxyInter == proxyInter) + return; + + m_proxyInter = proxyInter; + m_displayTips.reset(new TipsWidget); + m_model.reset(new BrightnessModel); + m_displayWidget.reset(new BrightnessWidget(m_model.data())); + m_displayWidget->setFixedHeight(60); + m_displaySettingWidget.reset(new DisplaySettingWidget); + + if (m_model->monitors().size() > 0) + m_proxyInter->itemAdded(this, pluginName()); + + connect(m_displayWidget.data(), &BrightnessWidget::brightClicked, this, [ this ] { + m_proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, true); + }); + connect(m_displaySettingWidget.data(), &DisplaySettingWidget::requestHide, this, [ this ] { + m_proxyInter->requestSetAppletVisible(this, QUICK_ITEM_KEY, false); + }); + connect(m_model.data(), &BrightnessModel::screenVisibleChanged, this, [ this ](bool visible) { + if (visible) + m_proxyInter->itemAdded(this, pluginName()); + else + m_proxyInter->itemRemoved(this, pluginName()); + }); +} + +QWidget *DisplayPlugin::itemWidget(const QString &itemKey) +{ + if (itemKey == QUICK_ITEM_KEY) { + return m_displayWidget.data(); + } + + return nullptr; +} + +QWidget *DisplayPlugin::itemTipsWidget(const QString &itemKey) +{ + Q_UNUSED(itemKey); + + return m_displayTips.data(); +} + +QWidget *DisplayPlugin::itemPopupApplet(const QString &itemKey) +{ + if (itemKey == QUICK_ITEM_KEY) + return m_displaySettingWidget.data(); + + return nullptr; +} + +PluginFlags DisplayPlugin::flags() const +{ + return PluginFlag::Type_Common | PluginFlag::Quick_Full; +} diff --git a/plugins/display/displayplugin.h b/plugins/display/displayplugin.h new file mode 100644 index 000000000..dddf7d366 --- /dev/null +++ b/plugins/display/displayplugin.h @@ -0,0 +1,49 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DISPLAYPLUGIN_H +#define DISPLAYPLUGIN_H + +#include "pluginsiteminterface.h" + +#include +#include +#include + +namespace Dock{ +class TipsWidget; +} + +class BrightnessWidget; +class BrightnessModel; +class DisplaySettingWidget; + +class DisplayPlugin : public QObject, PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "display.json") + +public: + explicit DisplayPlugin(QObject *parent = nullptr); + + const QString pluginName() const override; + const QString pluginDisplayName() const override; + void init(PluginProxyInterface *proxyInter) override; + + QWidget *itemWidget(const QString &itemKey) override; + QWidget *itemTipsWidget(const QString &itemKey) override; + QWidget *itemPopupApplet(const QString &itemKey) override; + + PluginFlags flags() const override; + +private: + QScopedPointer m_displayWidget; + QScopedPointer m_displaySettingWidget; + QScopedPointer m_displayTips; + QScopedPointer m_model; +}; + +#endif // DATETIMEPLUGIN_H diff --git a/plugins/display/displaysettingwidget.cpp b/plugins/display/displaysettingwidget.cpp new file mode 100644 index 000000000..67f3c1615 --- /dev/null +++ b/plugins/display/displaysettingwidget.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "displaysettingwidget.h" +#include "brightnessadjwidget.h" +#include "devcollaborationwidget.h" + +#include +#include + +#include + +const int ItemSpacing = 10; + +DisplaySettingWidget::DisplaySettingWidget(QWidget *parent) + : QWidget(parent) + , m_brightnessAdjWidget(new BrightnessAdjWidget(this)) + , m_collaborationWidget(new DevCollaborationWidget(this)) + , m_settingBtn(new QPushButton(tr("Multi-Screen Collaboration"), this)) +{ + initUI(); + + connect(m_settingBtn, &QPushButton::clicked, this, [ this ](){ + DDBusSender().service("org.deepin.dde.ControlCenter1") + .path("/org/deepin/dde/ControlCenter1") + .interface("org.deepin.dde.ControlCenter1") + .method("ShowPage").arg(QString("display")).call(); + Q_EMIT requestHide(); + }); +} + +void DisplaySettingWidget::initUI() +{ + setContentsMargins(0, 10, 0, 30); + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->setMargin(0); + mainLayout->setSpacing(ItemSpacing); + + mainLayout->addWidget(m_brightnessAdjWidget); + mainLayout->addWidget(m_collaborationWidget); + mainLayout->addWidget(m_settingBtn); + mainLayout->addStretch(); + + setLayout(mainLayout); + + resizeWidgetHeight(); + connect(m_collaborationWidget, &DevCollaborationWidget::sizeChanged, + this, &DisplaySettingWidget::resizeWidgetHeight); +} + +void DisplaySettingWidget::resizeWidgetHeight() +{ + QMargins margins = this->contentsMargins(); + setFixedHeight(margins.top() + margins.bottom() + m_brightnessAdjWidget->height() + + m_collaborationWidget->height() + m_settingBtn->height() + ItemSpacing * 2); +} diff --git a/plugins/display/displaysettingwidget.h b/plugins/display/displaysettingwidget.h new file mode 100644 index 000000000..705624779 --- /dev/null +++ b/plugins/display/displaysettingwidget.h @@ -0,0 +1,40 @@ +// Copyright (C) 2021 ~ 2022 Uniontech Software Technology Co.,Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DISPLAY_SETTING_WIDGET_H +#define DISPLAY_SETTING_WIDGET_H + +#include + +class QPushButton; +class BrightnessAdjWidget; +class DevCollaborationWidget; + +/*! + * \brief The DisplaySettingWidget class + * 显示设置页面,快捷设置面板-->亮度调节栏右边显示按钮-->此页面 + */ +class DisplaySettingWidget : public QWidget +{ + Q_OBJECT + +public: + explicit DisplaySettingWidget(QWidget *parent = nullptr); + +Q_SIGNALS: + void requestHide(); + +private: + void initUI(); + void resizeWidgetHeight(); + +private: + BrightnessAdjWidget *m_brightnessAdjWidget; // 亮度调整 + DevCollaborationWidget *m_collaborationWidget; // 跨端协同 + QPushButton *m_settingBtn; // 设置按钮 +}; + + +#endif // DISPLAY_SETTING_WIDGET_H diff --git a/plugins/display/resource/ICON_Device_Headphone.svg b/plugins/display/resource/ICON_Device_Headphone.svg new file mode 100644 index 000000000..c2aeaccf2 --- /dev/null +++ b/plugins/display/resource/ICON_Device_Headphone.svg @@ -0,0 +1,17 @@ + + + -mockplus- + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/display/resource/ICON_Device_Headphone_dark.svg b/plugins/display/resource/ICON_Device_Headphone_dark.svg new file mode 100644 index 000000000..7c797d1e1 --- /dev/null +++ b/plugins/display/resource/ICON_Device_Headphone_dark.svg @@ -0,0 +1,17 @@ + + + -mockplus- + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/display/resource/ICON_Device_Laptop.svg b/plugins/display/resource/ICON_Device_Laptop.svg new file mode 100644 index 000000000..115314c7c --- /dev/null +++ b/plugins/display/resource/ICON_Device_Laptop.svg @@ -0,0 +1,17 @@ + + + -mockplus- + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/display/resource/ICON_Device_Laptop_dark.svg b/plugins/display/resource/ICON_Device_Laptop_dark.svg new file mode 100644 index 000000000..3ba0d45f1 --- /dev/null +++ b/plugins/display/resource/ICON_Device_Laptop_dark.svg @@ -0,0 +1,17 @@ + + + -mockplus- + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/display/resource/brightness.svg b/plugins/display/resource/brightness.svg new file mode 100644 index 000000000..31d4f9830 --- /dev/null +++ b/plugins/display/resource/brightness.svg @@ -0,0 +1,15 @@ + + + ICON / MenuItem / Brightness+ + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/display/resource/brightnesshigh.svg b/plugins/display/resource/brightnesshigh.svg new file mode 100644 index 000000000..baeb9afcd --- /dev/null +++ b/plugins/display/resource/brightnesshigh.svg @@ -0,0 +1,3 @@ + + + diff --git a/plugins/display/resource/brightnesslow.svg b/plugins/display/resource/brightnesslow.svg new file mode 100644 index 000000000..c5a11a167 --- /dev/null +++ b/plugins/display/resource/brightnesslow.svg @@ -0,0 +1,3 @@ + + + diff --git a/plugins/display/resource/broadcast.svg b/plugins/display/resource/broadcast.svg new file mode 100644 index 000000000..f45b1ae57 --- /dev/null +++ b/plugins/display/resource/broadcast.svg @@ -0,0 +1,15 @@ + + + ICON / MenuItem / Broadcast + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/display/resource/display.qrc b/plugins/display/resource/display.qrc new file mode 100644 index 000000000..0994b934f --- /dev/null +++ b/plugins/display/resource/display.qrc @@ -0,0 +1,12 @@ + + + brightness.svg + brightnesshigh.svg + brightnesslow.svg + broadcast.svg + ICON_Device_Headphone_dark.svg + ICON_Device_Headphone.svg + ICON_Device_Laptop_dark.svg + ICON_Device_Laptop.svg + + diff --git a/plugins/keyboard-layout/CMakeLists.txt b/plugins/keyboard-layout/CMakeLists.txt index 7dbbb1171..a4433a0c5 100644 --- a/plugins/keyboard-layout/CMakeLists.txt +++ b/plugins/keyboard-layout/CMakeLists.txt @@ -3,44 +3,39 @@ set(PLUGIN_NAME "keyboard-layout") project(${PLUGIN_NAME}) +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + # Sources files -file(GLOB_RECURSE SRCS "*.h" "*.cpp") +file(GLOB_RECURSE SRCS "*.h" + "*.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) find_package(Qt5Svg REQUIRED) find_package(DtkWidget REQUIRED) find_package(Qt5DBus REQUIRED) -find_package(DFrameworkdbus REQUIRED) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) pkg_check_modules(QGSettings REQUIRED gsettings-qt) -set_source_files_properties( - org.fcitx.Fcitx.xml - PROPERTIES INCLUDE fcitxinputmethoditem.h - CLASSNAME FcitxInputMethodProxy -) - -qt5_add_dbus_interfaces(DBUS_INTERFACES - org.fcitx.Fcitx.xml -) - add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") -add_library(${PLUGIN_NAME} SHARED ${SRCS} ${DBUS_INTERFACES}) +add_library(${PLUGIN_NAME} SHARED ${SRCS}) set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../) target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} ${QGSettings_INCLUDE_DIRS} - ../../interfaces) + ../../interfaces + ./dbusinterface + ./dbusinterface/generation_dbus_interface + ../../frame/qtdbusextended) + target_link_libraries(${PLUGIN_NAME} PRIVATE ${DtkWidget_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} ${QGSettings_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Svg_LIBRARIES} ${Qt5DBus_LIBRARIES} ) -install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/system-trays/) +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/) install(FILES ./keybord_layout.json DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/dde-dock/indicator) diff --git a/plugins/keyboard-layout/dbusadaptors.cpp b/plugins/keyboard-layout/dbusadaptors.cpp index f8fea9c4c..8d2902e71 100644 --- a/plugins/keyboard-layout/dbusadaptors.cpp +++ b/plugins/keyboard-layout/dbusadaptors.cpp @@ -1,43 +1,27 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "utils.h" #include "dbusadaptors.h" -#include "fcitxinputmethoditem.h" #include -#include - #include -#include - -// switch kdb layout key in gsettings -const QString KDB_LAYOUT_KEYBINDING_KEY = "switchNextKbdLayout"; - -// dcc keyboard layout key in gsettings -const QString KDB_LAYOUT_DCC_NAME = "keyboardLayout"; - -// because not allowd to use libfcitx-qt, use org.fcitx.Fcitx to -// get fcitx status and data -const QString FCITX_ADDRESSS = "org.fcitx.Fcitx"; DBusAdaptors::DBusAdaptors(QObject *parent) - : QDBusAbstractAdaptor(parent), - m_keyboard(new Keyboard("com.deepin.daemon.InputDevices", - "/com/deepin/daemon/InputDevice/Keyboard", - QDBusConnection::sessionBus(), this)), - m_menu(new QMenu()), - m_gsettings(Utils::ModuleSettingsPtr("keyboard", QByteArray(), this)), - m_keybingEnabled(Utils::SettingsPtr("com.deepin.dde.keybinding.system.enable", QByteArray(), this)), - m_dccSettings(Utils::SettingsPtr("com.deepin.dde.control-center", QByteArray(), this)), - m_fcitxRunning(false), - m_inputmethod(nullptr) + : QDBusAbstractAdaptor(parent) + , m_keyboard(new Keyboard("org.deepin.dde.InputDevices1", + "/org/deepin/dde/InputDevice1/Keyboard", + QDBusConnection::sessionBus(), this)) + , m_menu(new QMenu) + , m_gsettings(Utils::ModuleSettingsPtr("keyboard", QByteArray(), this)) { m_keyboard->setSync(false); connect(m_keyboard, &Keyboard::CurrentLayoutChanged, this, &DBusAdaptors::onCurrentLayoutChanged); connect(m_keyboard, &Keyboard::UserLayoutListChanged, this, &DBusAdaptors::onUserLayoutListChanged); + connect(m_menu, &QMenu::triggered, this, &DBusAdaptors::handleActionTriggered); // init data @@ -47,16 +31,11 @@ DBusAdaptors::DBusAdaptors(QObject *parent) if (m_gsettings) connect(m_gsettings, &QGSettings::changed, this, &DBusAdaptors::onGSettingsChanged); - - // deepin show fcitx lang code,while fcitx is running - if (Dtk::Core::DSysInfo::isCommunityEdition()) { - initFcitxWatcher(); - } - } DBusAdaptors::~DBusAdaptors() { + delete m_menu; } QString DBusAdaptors::layout() const @@ -101,7 +80,7 @@ void DBusAdaptors::onClicked(int button, int x, int y) Q_UNUSED(button); - if (m_menu && m_userLayoutList.size() >= 2 && !m_fcitxRunning) { + if (m_menu && m_userLayoutList.size() >= 2) { m_menu->exec(QPoint(x, y)); } } @@ -182,12 +161,11 @@ void DBusAdaptors::handleActionTriggered(QAction *action) { if (action == m_addLayoutAction) { DDBusSender() - .service("com.deepin.dde.ControlCenter") - .interface("com.deepin.dde.ControlCenter") - .path("/com/deepin/dde/ControlCenter") + .service("org.deepin.dde.ControlCenter1") + .interface("org.deepin.dde.ControlCenter1") + .path("/org/deepin/dde/ControlCenter1") .method("ShowPage") - .arg(QString("keyboard")) - .arg(QString("Keyboard Layout/Add Keyboard Layout")) + .arg(QString("keyboard/keyboardGeneral/keyboardLayout")) .call(); } @@ -223,143 +201,3 @@ QString DBusAdaptors::duplicateCheck(const QString &kb) return kblayout + (list.count() > 1 ? QString::number(list.indexOf(kb) + 1) : ""); } - -void DBusAdaptors::onFcitxConnected(const QString &service) -{ - Q_UNUSED(service) - if (m_fcitxRunning) - return; - - // fcitx from closed to running - m_fcitxRunning = true; - setKeyboardLayoutGsettings(); - if (m_inputmethod) { - delete m_inputmethod; - m_inputmethod = nullptr; - } - // fcitx from off to on will create this, free it on fcitx closing. - m_inputmethod = new FcitxInputMethodProxy( - FCITX_ADDRESSS, - "/inputmethod", - QDBusConnection::sessionBus(), - this); - - if (QDBusConnection::sessionBus().connect(FCITX_ADDRESSS, "/inputmethod", - "org.freedesktop.DBus.Properties", "PropertiesChanged", this, - SLOT(onPropertyChanged(QString, QVariantMap, QStringList)))) { - } else { - qWarning() << "fcitx's PropertiesChanged signal connection was not successful"; - } - - Q_EMIT(fcitxStatusChanged(m_fcitxRunning)); - -} - -void DBusAdaptors::onFcitxDisconnected(const QString &service) -{ - Q_UNUSED(service) - if (!m_fcitxRunning) - return; - - // fcitx from running to close - m_fcitxRunning = false; - setKeyboardLayoutGsettings(); - QDBusConnection::sessionBus().disconnect(FCITX_ADDRESSS, "/inputmethod", - "org.freedesktop.DBus.Properties", "PropertiesChanged", this, - SLOT(onPropertyChanged(QString, QVariantMap, QStringList))); - // fcitx is closing, free it. - if (m_inputmethod) { - delete m_inputmethod; - m_inputmethod = nullptr; - } - - Q_EMIT(fcitxStatusChanged(m_fcitxRunning)); - -} - -void DBusAdaptors::onPropertyChanged(QString name, QVariantMap map, QStringList list) -{ - // fcitx uniquename start with fcitx-keyboard- which contains keyboard layout. - QString fcitxUniqueName("fcitx-keyboard-"); - qDebug() << QString("properties of interface %1 changed").arg(name); - - if (list.isEmpty() || "CurrentIM" != list[0]) - return; - - if (m_inputmethod == nullptr) - return; - - QString currentIM = m_inputmethod ->GetCurrentIM(); - if (currentIM.startsWith(fcitxUniqueName)) { - // fcitx uniquename contains keyboard layout, keyboard is after fcitx-keyboard- - // such as fcitx-keyboard-ara-uga, keyboard layout is ara;uga - // fcitx-keyboard-us keyboard is us; - // fcitx-keyboard-am-phonetic-alt keyboard layout is am;phonetic-alt - QString layout = currentIM.right(currentIM.size() - fcitxUniqueName.size()); - int splitLoc = layout.indexOf('-'); - if (splitLoc > 0) { - layout = layout.replace(splitLoc, 1, ';'); - } else { - layout.append(';'); - } - m_keyboard->setCurrentLayout(layout); - qDebug() << (m_keyboard->currentLayout() == layout); - } else { - // sunpinyin sogounpinyin uniquename not contains keyboard-layout. using lang code only for display. - FcitxQtInputMethodItemList lists = m_inputmethod -> iMList(); - for (FcitxQtInputMethodItem item : lists) { - if (currentIM == item.uniqueName()) { - // zh_CN display as cn - if (0 == QString::compare("zh_CN", item.langCode())) { - item.setLangCode("cn"); - } - QString layout = item.langCode(); - layout.append(';'); - m_keyboard->setCurrentLayout(layout); - qDebug() << (m_keyboard->currentLayout() == layout); - } - } - } - -} - -void DBusAdaptors::setKeyboardLayoutGsettings() -{ - // while fcitx is running, disable keyboard switch shortcut, enable it after fcitx stopped - if (m_keybingEnabled && m_keybingEnabled->keys().contains(KDB_LAYOUT_KEYBINDING_KEY)) { - m_keybingEnabled->set(KDB_LAYOUT_KEYBINDING_KEY, QVariant(!m_fcitxRunning)); - } - - // hide keyboard layout setttings in dde-control-center, resume it after fcitx stopped - if (m_dccSettings && m_dccSettings->keys().contains(KDB_LAYOUT_DCC_NAME)) { - m_dccSettings->set(KDB_LAYOUT_DCC_NAME, QVariant(!m_fcitxRunning)); - } -} - -bool DBusAdaptors::isFcitxRunning() const -{ - return m_fcitxRunning; -} - -void DBusAdaptors::initFcitxWatcher() -{ - qDebug() << "init fcitx status watcher"; - FcitxQtInputMethodItem::registerMetaType(); - // init dbusSewrviceWatcher to see fcitx status - m_fcitxWatcher = new QDBusServiceWatcher(this); - m_fcitxWatcher->setConnection(QDBusConnection::sessionBus()); - m_fcitxWatcher->addWatchedService(FCITX_ADDRESSS); - // send fcitx on or off signal, when fcitx is starting or closing. - connect(m_fcitxWatcher, SIGNAL(serviceRegistered(QString)), this, SLOT(onFcitxConnected(QString))); - connect(m_fcitxWatcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(onFcitxDisconnected(QString))); - - // get fcitx current status - QDBusReply registered = m_fcitxWatcher ->connection().interface()->isServiceRegistered(FCITX_ADDRESSS); - - if (registered.isValid() && registered.value()) { - // fcitx is alerdy running, - onFcitxConnected(QString()); - } - setKeyboardLayoutGsettings(); -} - diff --git a/plugins/keyboard-layout/dbusadaptors.h b/plugins/keyboard-layout/dbusadaptors.h index 164824103..c4e08c307 100644 --- a/plugins/keyboard-layout/dbusadaptors.h +++ b/plugins/keyboard-layout/dbusadaptors.h @@ -1,26 +1,24 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #ifndef DBUSADAPTORS_H #define DBUSADAPTORS_H -#include "fcitxinterface.h" - #include #include +#include "org_deepin_dde_inputdevice1_keyboard.h" -#include - -using Keyboard = com::deepin::daemon::inputdevice::Keyboard; +using Keyboard = org::deepin::dde::inputdevice1::Keyboard; class QGSettings; class DBusAdaptors : public QDBusAbstractAdaptor { Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "com.deepin.dde.Keyboard") + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Dock1.KeyboardLayout") // Q_CLASSINFO("D-Bus Introspection", "" -// " \n" +// " \n" // " \n" // " " // " " @@ -34,10 +32,8 @@ public: public: Q_PROPERTY(QString layout READ layout WRITE setLayout NOTIFY layoutChanged) - Q_PROPERTY(bool fcitxRunning READ isFcitxRunning NOTIFY fcitxStatusChanged) QString layout() const; void setLayout(const QString &str); - bool isFcitxRunning() const; Keyboard *getCurrentKeyboard(); @@ -46,7 +42,6 @@ public slots: signals: void layoutChanged(QString text); - void fcitxStatusChanged(bool running); private slots: void onCurrentLayoutChanged(const QString & value); @@ -58,22 +53,12 @@ private slots: private slots: void onGSettingsChanged(const QString &key); - void onFcitxConnected(const QString &service); - void onFcitxDisconnected(const QString &service); - void onPropertyChanged(QString name, QVariantMap map, QStringList list); private: QString duplicateCheck(const QString &kb); - void setKeyboardLayoutGsettings(); - void initFcitxWatcher(); private: Keyboard *m_keyboard; - bool m_fcitxRunning; - FcitxInputMethodProxy *m_inputmethod; - QDBusServiceWatcher *m_fcitxWatcher; - QGSettings *m_keybingEnabled; - QGSettings *m_dccSettings; QMenu *m_menu; QAction *m_addLayoutAction; diff --git a/plugins/keyboard-layout/dbusinterface/types/keyboardlayoutlist.cpp b/plugins/keyboard-layout/dbusinterface/types/keyboardlayoutlist.cpp new file mode 100644 index 000000000..d5a51a41e --- /dev/null +++ b/plugins/keyboard-layout/dbusinterface/types/keyboardlayoutlist.cpp @@ -0,0 +1,12 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "keyboardlayoutlist.h" + +void registerKeyboardLayoutListMetaType() +{ + qRegisterMetaType("KeyboardLayoutList"); + qDBusRegisterMetaType(); +} diff --git a/plugins/keyboard-layout/dbusinterface/types/keyboardlayoutlist.h b/plugins/keyboard-layout/dbusinterface/types/keyboardlayoutlist.h new file mode 100644 index 000000000..aa0c33aba --- /dev/null +++ b/plugins/keyboard-layout/dbusinterface/types/keyboardlayoutlist.h @@ -0,0 +1,18 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef KEYBOARDLAYOUTLIST_H +#define KEYBOARDLAYOUTLIST_H + +#include +#include +#include +#include + +typedef QMap KeyboardLayoutList; + +void registerKeyboardLayoutListMetaType(); + +#endif // KEYBOARDLAYOUTLIST_H diff --git a/plugins/keyboard-layout/dbusinterface/xml/org.deepin.dde.InputDevice1.Keyboard.xml b/plugins/keyboard-layout/dbusinterface/xml/org.deepin.dde.InputDevice1.Keyboard.xml new file mode 100644 index 000000000..63d0f886a --- /dev/null +++ b/plugins/keyboard-layout/dbusinterface/xml/org.deepin.dde.InputDevice1.Keyboard.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/keyboard-layout/fcitxinputmethoditem.cpp b/plugins/keyboard-layout/fcitxinputmethoditem.cpp deleted file mode 100644 index 417ea6e3e..000000000 --- a/plugins/keyboard-layout/fcitxinputmethoditem.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "fcitxinputmethoditem.h" - -#include -#include - -bool FcitxQtInputMethodItem::enabled() const -{ - return m_enabled; -} - -const QString& FcitxQtInputMethodItem::langCode() const -{ - return m_langCode; -} - -const QString& FcitxQtInputMethodItem::name() const -{ - return m_name; -} - -const QString& FcitxQtInputMethodItem::uniqueName() const -{ - return m_uniqueName; -} - -void FcitxQtInputMethodItem::setEnabled(bool enable) -{ - m_enabled = enable; -} - -void FcitxQtInputMethodItem::setLangCode(const QString& lang) -{ - m_langCode = lang; -} - -void FcitxQtInputMethodItem::setName(const QString& name) -{ - m_name = name; -} - -void FcitxQtInputMethodItem::setUniqueName(const QString& name) -{ - m_uniqueName = name; -} - -void FcitxQtInputMethodItem::registerMetaType() -{ - qRegisterMetaType("FcitxQtInputMethodItem"); - qDBusRegisterMetaType(); - qRegisterMetaType("FcitxQtInputMethodItemList"); - qDBusRegisterMetaType(); -} - -QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im) -{ - argument.beginStructure(); - argument << im.name(); - argument << im.uniqueName(); - argument << im.langCode(); - argument << im.enabled(); - argument.endStructure(); - return argument; -} - -const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im) -{ - QString name; - QString uniqueName; - QString langCode; - bool enabled; - argument.beginStructure(); - argument >> name >> uniqueName >> langCode >> enabled; - argument.endStructure(); - im.setName(name); - im.setUniqueName(uniqueName); - im.setLangCode(langCode); - im.setEnabled(enabled); - return argument; -} \ No newline at end of file diff --git a/plugins/keyboard-layout/fcitxinputmethoditem.h b/plugins/keyboard-layout/fcitxinputmethoditem.h deleted file mode 100644 index 17ba18802..000000000 --- a/plugins/keyboard-layout/fcitxinputmethoditem.h +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#ifndef FCITX_QT_INPUT_METHOD_ITEM_H -#define FCITX_QT_INPUT_METHOD_ITEM_H - -// Qt -#include -#include -#include - -class FcitxQtInputMethodItem -{ -public: - const QString& name() const; - const QString& uniqueName() const; - const QString& langCode() const; - bool enabled() const; - - void setName(const QString& name); - void setUniqueName(const QString& name); - void setLangCode(const QString& name); - void setEnabled(bool name); - static void registerMetaType(); - - inline bool operator < (const FcitxQtInputMethodItem& im) const { - return (m_enabled && !im.m_enabled); - } - -private: - QString m_name; - QString m_uniqueName; - QString m_langCode; - bool m_enabled; -}; - -typedef QList FcitxQtInputMethodItemList; - -QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im); -const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im); - -Q_DECLARE_METATYPE(FcitxQtInputMethodItem) -Q_DECLARE_METATYPE(FcitxQtInputMethodItemList) - -#endif diff --git a/plugins/keyboard-layout/keyboard.json b/plugins/keyboard-layout/keyboard.json index ad498eeb3..bec81f0da 100644 --- a/plugins/keyboard-layout/keyboard.json +++ b/plugins/keyboard-layout/keyboard.json @@ -1,3 +1,3 @@ { - "api": "1.1.1" + "api": "2.0.0" } diff --git a/plugins/keyboard-layout/keyboardplugin.cpp b/plugins/keyboard-layout/keyboardplugin.cpp index 2b65823e2..a4717ae9b 100644 --- a/plugins/keyboard-layout/keyboardplugin.cpp +++ b/plugins/keyboard-layout/keyboardplugin.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -29,7 +30,7 @@ void KeyboardPlugin::init(PluginProxyInterface *proxyInter) m_proxyInter = proxyInter; if (!m_dbusAdaptors) { - QString serverName = "com.deepin.daemon.InputDevices"; + QString serverName = "org.deepin.dde.InputDevices1"; QDBusConnectionInterface *ifc = QDBusConnection::sessionBus().interface(); if (!ifc->isServiceRegistered(serverName)) { @@ -45,8 +46,8 @@ void KeyboardPlugin::init(PluginProxyInterface *proxyInter) m_dbusAdaptors = new DBusAdaptors(this); } - QDBusConnection::sessionBus().registerService("com.deepin.dde.Keyboard"); - QDBusConnection::sessionBus().registerObject("/com/deepin/dde/Keyboard", "com.deepin.dde.Keyboard", this); + QDBusConnection::sessionBus().registerService("org.deepin.dde.Dock1.KeyboardLayout"); + QDBusConnection::sessionBus().registerObject("/org/deepin/dde/Dock1/KeyboardLayout", "org.deepin.dde.Dock1.KeyboardLayout", this); } } diff --git a/plugins/keyboard-layout/keyboardplugin.h b/plugins/keyboard-layout/keyboardplugin.h index 3a826389e..38288649b 100644 --- a/plugins/keyboard-layout/keyboardplugin.h +++ b/plugins/keyboard-layout/keyboardplugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/keyboard-layout/keybord_layout.json b/plugins/keyboard-layout/keybord_layout.json index ca5193e33..ade26475f 100644 --- a/plugins/keyboard-layout/keybord_layout.json +++ b/plugins/keyboard-layout/keybord_layout.json @@ -1,17 +1,17 @@ { "data": { "text": { - "dbus_service": "com.deepin.dde.Keyboard", - "dbus_path": "/com/deepin/dde/Keyboard", - "dbus_interface": "com.deepin.dde.Keyboard", + "dbus_service": "org.deepin.dde.Dock1.KeyboardLayout", + "dbus_path": "/org/deepin/dde/Dock1/KeyboardLayout", + "dbus_interface": "org.deepin.dde.Dock1.KeyboardLayout", "dbus_properties": "layout" } }, "action": { "trigger": { - "dbus_service": "com.deepin.dde.Keyboard", - "dbus_path": "/com/deepin/dde/Keyboard", - "dbus_interface": "com.deepin.dde.Keyboard", + "dbus_service": "org.deepin.dde.Dock1.KeyboardLayout", + "dbus_path": "/org/deepin/dde/Dock1/KeyboardLayout", + "dbus_interface": "org.deepin.dde.Dock1.KeyboardLayout", "dbus_method": "onClicked" } } diff --git a/plugins/keyboard-layout/org.fcitx.Fcitx.xml b/plugins/keyboard-layout/org.fcitx.Fcitx.xml deleted file mode 100644 index 89561efef..000000000 --- a/plugins/keyboard-layout/org.fcitx.Fcitx.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/media/CMakeLists.txt b/plugins/media/CMakeLists.txt new file mode 100644 index 000000000..792279e08 --- /dev/null +++ b/plugins/media/CMakeLists.txt @@ -0,0 +1,51 @@ + +set(PLUGIN_NAME "media") + +project(${PLUGIN_NAME}) + +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + +# Sources files +file(GLOB_RECURSE SRCS "*.h" "*.cpp" + "../../widgets/*.h" + "../../widgets/*.cpp" + "../../frame/util/imageutil.h" + "../../frame/util/imageutil.cpp" + "../../frame/util/statebutton.h" + "../../frame/util/statebutton.cpp" + "../../frame/util/horizontalseperator.h" + "../../frame/util/horizontalseperator.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp") + +find_package(PkgConfig REQUIRED) +find_package(Qt5Widgets REQUIRED) +find_package(Qt5Svg REQUIRED) +find_package(Qt5DBus REQUIRED) +find_package(DtkWidget REQUIRED) + +pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor) +pkg_check_modules(QGSettings REQUIRED gsettings-qt) + +add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") +add_library(${PLUGIN_NAME} SHARED ${SRCS}) +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../quick-trays) +target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ../../interfaces + ../../widgets + ../../frame + ../../frame/qtdbusextended + ./dbusinterface/generation_dbus_interface + componments) + +target_link_libraries(${PLUGIN_NAME} PRIVATE + ${XCB_EWMH_LIBRARIES} + ${DtkWidget_LIBRARIES} + ${QGSettings_LIBRARIES} + ${Qt5DBus_LIBRARIES} + ${Qt5Widgets_LIBRARIES} + ${Qt5Svg_LIBRARIES} +) + +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/quick-trays) diff --git a/plugins/media/media.json b/plugins/media/media.json new file mode 100644 index 000000000..2749bb47d --- /dev/null +++ b/plugins/media/media.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "order": 3 +} diff --git a/plugins/media/mediaplayermodel.cpp b/plugins/media/mediaplayermodel.cpp new file mode 100644 index 000000000..def2bdb54 --- /dev/null +++ b/plugins/media/mediaplayermodel.cpp @@ -0,0 +1,256 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "mediaplayermodel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MediaPlayerModel::MediaPlayerModel(QObject *parent) + : QObject(parent) + , m_isActived(false) + , m_mediaInter(nullptr) +{ + initMediaPlayer(); +} + +MediaPlayerModel::~MediaPlayerModel() +{ +} + +bool MediaPlayerModel::isActived() +{ + return m_isActived; +} + +bool MediaPlayerModel::canGoNext() +{ + return m_mediaInter ? m_mediaInter->canGoNext() : false; +} + +bool MediaPlayerModel::canGoPrevious() +{ + return m_mediaInter ? m_mediaInter->canGoPrevious() : false; +} + +bool MediaPlayerModel::canPause() +{ + return m_mediaInter ? m_mediaInter->canPause() : false; +} + +MediaPlayerModel::PlayStatus MediaPlayerModel::status() +{ + if (!m_isActived || !m_mediaInter) + return PlayStatus::Stop; + + return convertStatus(m_mediaInter->playbackStatus()); +} + +const QString MediaPlayerModel::name() +{ + if (m_mediaInter) { + Dict data = m_mediaInter->metadata(); + return data["xesam:title"].toString(); + } + + return QString(); +} + +const QString MediaPlayerModel::iconUrl() +{ + if (m_mediaInter) { + Dict data = m_mediaInter->metadata(); + return data["mpris:artUrl"].toString(); + } + + return QString(); +} + +const QString MediaPlayerModel::album() +{ + if (m_mediaInter) { + Dict data = m_mediaInter->metadata(); + return data["xesam:album"].toString(); + } + + return QString(); +} + +const QString MediaPlayerModel::artist() +{ + if (m_mediaInter) { + Dict data = m_mediaInter->metadata(); + return data["xesam:artist"].toString(); + } + + return QString(); +} + +void MediaPlayerModel::setStatus(const MediaPlayerModel::PlayStatus &stat) +{ + if (!m_mediaInter) + return; + + switch (stat) { + case MediaPlayerModel::PlayStatus::Play: { + m_mediaInter->Play(); + break; + } + case MediaPlayerModel::PlayStatus::Stop: { + m_mediaInter->Stop(); + break; + } + case MediaPlayerModel::PlayStatus::Pause: { + m_mediaInter->Pause(); + break; + } + default: break; + } +} + +void MediaPlayerModel::playNext() +{ + if (m_mediaInter) + m_mediaInter->Next(); +} + +void MediaPlayerModel::initMediaPlayer() +{ + QDBusInterface dbusInter("org.freedesktop.DBus", "/", "org.freedesktop.DBus", QDBusConnection::sessionBus(), this); + QDBusPendingCall call = dbusInter.asyncCall("ListNames"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + connect(watcher, &QDBusPendingCallWatcher::finished, [ = ] { + m_serviceName.clear(); + if (call.isError()) + return; + + QDBusReply reply = call.reply(); + const QStringList &serviceList = reply.value(); + + for (const QString &serv : serviceList) { + if (!serv.startsWith("org.mpris.MediaPlayer2")) + continue; + + QDBusInterface serviceInterface(serv, "/org/mpris/MediaPlayer2", + "org.mpris.MediaPlayer2.Player", QDBusConnection::sessionBus(), this); + // 如果开启了谷歌浏览器的后台服务(org.mpris.MediaPlayer2.chromium.instance17352) + // 也符合名称要求,但是它不是音乐服务,此时需要判断是否存在这个属性 + QVariant v = serviceInterface.property("CanPlay"); + if (!v.isValid() || !v.value()) + continue; + + m_serviceName = serv; + break; + } + + if (!m_serviceName.isEmpty()) { + m_isActived = true; + + m_mediaInter = new MediaPlayerInterface(m_serviceName, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this); + connect(m_mediaInter, &MediaPlayerInterface::PlaybackStatusChanged, this, [ this ] { + Q_EMIT statusChanged(convertStatus(m_mediaInter->playbackStatus())); + }); + connect(m_mediaInter, &MediaPlayerInterface::MetadataChanged, this, &MediaPlayerModel::metadataChanged); + Dict v = m_mediaInter->metadata(); + m_name = v.value("xesam:title").toString(); + m_icon = v.value("mpris:artUrl").toString(); + m_album = v.value("xesam:album").toString(); + m_artist = v.value("xesam:artist").toString(); + Q_EMIT startStop(m_isActived); + return; + } + + QDBusConnectionInterface *dbusInterface = QDBusConnection::sessionBus().interface(); + connect(dbusInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, + [ = ](const QString &name, const QString &, const QString &newOwner) { + if (name.startsWith("org.mpris.MediaPlayer2")) { + // 启动了音乐播放 + m_isActived = !newOwner.isEmpty(); + if (m_isActived) { + m_serviceName = name; + m_mediaInter = new MediaPlayerInterface(m_serviceName, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this); + connect(m_mediaInter, &MediaPlayerInterface::PlaybackStatusChanged, this, [ this ] { + Q_EMIT statusChanged(convertStatus(m_mediaInter->playbackStatus())); + }); + connect(m_mediaInter, &MediaPlayerInterface::MetadataChanged, this, &MediaPlayerModel::metadataChanged); + Dict v = m_mediaInter->metadata(); + m_name = v.value("xesam:title").toString(); + m_icon = v.value("mpris:artUrl").toString(); + m_album = v.value("xesam:album").toString(); + m_artist = v.value("xesam:artist").toString(); + } else { + if (!m_serviceName.isEmpty()) { + delete m_mediaInter; + m_mediaInter = nullptr; + } + m_serviceName.clear(); + } + Q_EMIT startStop(m_isActived); + } + }); + connect(dbusInterface, &QDBusConnectionInterface::serviceUnregistered, this, + [ = ](const QString &service) { + if (service.startsWith("org.mpris.MediaPlayer2")) { + // 启动了音乐播放 + m_serviceName.clear(); + m_isActived = false; + Q_EMIT startStop(m_isActived); + } + }); + }); + connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QDBusPendingCallWatcher::deleteLater); +} + +MediaPlayerModel::PlayStatus MediaPlayerModel::convertStatus(const QString &stat) +{ + if (stat == "Paused") + return PlayStatus::Pause; + if (stat == "Playing") + return PlayStatus::Play; + if (stat == "Stopped") + return PlayStatus::Stop; + + return PlayStatus::Unknow; +} + +MediaPlayerInterface::MediaPlayerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, "org.mpris.MediaPlayer2.Player", connection, parent) +{ + QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); +} + +MediaPlayerInterface::~MediaPlayerInterface() +{ + QDBusConnection::sessionBus().disconnect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &))); +} + +void MediaPlayerInterface::onPropertyChanged(const QDBusMessage &msg) +{ + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + + QString interfaceName = msg.arguments().at(0).toString(); + if (interfaceName !="org.mpris.MediaPlayer2.Player") + return; + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + QStringList keys = changedProps.keys(); + foreach(const QString &prop, keys) { + const QMetaObject* self = metaObject(); + for (int i = self->propertyOffset(); i < self->propertyCount(); ++i) { + QMetaProperty p = self->property(i); + if (p.name() == prop) { + Q_EMIT p.notifySignal().invoke(this); + } + } + } +} diff --git a/plugins/media/mediaplayermodel.h b/plugins/media/mediaplayermodel.h new file mode 100644 index 000000000..e3e682b68 --- /dev/null +++ b/plugins/media/mediaplayermodel.h @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef MEDIAPLAYERMODEL_H +#define MEDIAPLAYERMODEL_H + +#include +#include +#include + +typedef QMap Dict; +Q_DECLARE_METATYPE(Dict) + +class QDBusMessage; +class QDBusConnection; +class MediaPlayerInterface; + +class MediaPlayerModel : public QObject +{ + Q_OBJECT + +public: + enum PlayStatus { + Unknow = 0, + Play, + Pause, + Stop + }; + +public: + explicit MediaPlayerModel(QObject *parent = nullptr); + ~MediaPlayerModel(); + + bool isActived(); + bool canGoNext(); + bool canGoPrevious(); + bool canPause(); + + PlayStatus status(); + const QString name(); + const QString iconUrl(); + const QString album(); + const QString artist(); + + void setStatus(const PlayStatus &stat); + void playNext(); + +Q_SIGNALS: + void startStop(bool); + void statusChanged(const PlayStatus &); + void metadataChanged(); + +private: + void initMediaPlayer(); + PlayStatus convertStatus(const QString &stat); + +private: + bool m_isActived; + QString m_serviceName; + QString m_name; + QString m_icon; + QString m_album; + QString m_artist; + MediaPlayerInterface *m_mediaInter; +}; + +class MediaPlayerInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + MediaPlayerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + ~MediaPlayerInterface(); + +public: + inline QDBusPendingReply<> Play() { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Play"), argumentList); + } + + inline QDBusPendingReply<> Stop() { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Stop"), argumentList); + } + + inline QDBusPendingReply<> Pause() { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Pause"), argumentList); + } + + inline QDBusPendingReply<> Next() { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Next"), argumentList); + } + + Q_PROPERTY(Dict Metadata READ metadata NOTIFY MetadataChanged) + inline Dict metadata() const + { return qvariant_cast(property("Metadata")); } + + Q_PROPERTY(bool CanGoNext READ canGoNext NOTIFY CanGoNextChanged) + inline bool canGoNext() const + { return qvariant_cast< bool >(property("CanGoNext")); } + + Q_PROPERTY(bool CanGoPrevious READ canGoPrevious NOTIFY CanGoPreviousChanged) + inline bool canGoPrevious() const + { return qvariant_cast< bool >(property("CanGoPrevious")); } + + Q_PROPERTY(bool CanPause READ canPause NOTIFY CanPauseChanged) + inline bool canPause() const + { return qvariant_cast< bool >(property("CanPause")); } + + Q_PROPERTY(QString PlaybackStatus READ playbackStatus NOTIFY PlaybackStatusChanged) + inline QString playbackStatus() const + { return qvariant_cast< QString >(property("PlaybackStatus")); } + +Q_SIGNALS: + void MetadataChanged(); + void CanGoNextChanged(); + void CanGoPreviousChanged(); + void CanPauseChanged(); + void PlaybackStatusChanged(); + +private Q_SLOTS: + void onPropertyChanged(const QDBusMessage &msg); +}; + +#endif // MEDIAPLAYERLISTENER_H diff --git a/plugins/media/mediaplugin.cpp b/plugins/media/mediaplugin.cpp new file mode 100644 index 000000000..be5c046cd --- /dev/null +++ b/plugins/media/mediaplugin.cpp @@ -0,0 +1,71 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "mediaplugin.h" +#include "mediawidget.h" +#include "mediaplayermodel.h" + +MediaPlugin::MediaPlugin(QObject *parent) + : QObject(parent) + , m_mediaWidget(nullptr) + , m_model(nullptr) +{ +} + +const QString MediaPlugin::pluginName() const +{ + return "media"; +} + +const QString MediaPlugin::pluginDisplayName() const +{ + return "Media"; +} + +void MediaPlugin::init(PluginProxyInterface *proxyInter) +{ + if (m_proxyInter == proxyInter) + return; + + m_proxyInter = proxyInter; + + m_model.reset(new MediaPlayerModel); + m_mediaWidget.reset(new MediaWidget(m_model.data())); + m_mediaWidget->setFixedHeight(60); + m_mediaWidget->setVisible(m_model->isActived()); + + if (m_model->isActived()) + m_proxyInter->itemAdded(this, pluginName()); + + connect(m_model.data(), &MediaPlayerModel::startStop, this, [ this ](bool visible) { + if (visible) + m_proxyInter->itemAdded(this, pluginName()); + else + m_proxyInter->itemRemoved(this, pluginName()); + }); +} + +QWidget *MediaPlugin::itemWidget(const QString &itemKey) +{ + if (itemKey == QUICK_ITEM_KEY) + return m_mediaWidget.data(); + + return nullptr; +} + +QWidget *MediaPlugin::itemTipsWidget(const QString &itemKey) +{ + return nullptr; +} + +QWidget *MediaPlugin::itemPopupApplet(const QString &itemKey) +{ + return nullptr; +} + +PluginFlags MediaPlugin::flags() const +{ + return PluginFlag::Type_Common | PluginFlag::Quick_Full; +} diff --git a/plugins/media/mediaplugin.h b/plugins/media/mediaplugin.h new file mode 100644 index 000000000..bf1dee032 --- /dev/null +++ b/plugins/media/mediaplugin.h @@ -0,0 +1,41 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef MEDIAPLUGIN_H +#define MEDIAPLUGIN_H + +#include "pluginsiteminterface.h" + +namespace Dock{ +class TipsWidget; +} +class MediaWidget; +class MediaPlayerModel; + +class MediaPlugin : public QObject, PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "media.json") + +public: + explicit MediaPlugin(QObject *parent = nullptr); + + const QString pluginName() const override; + const QString pluginDisplayName() const override; + void init(PluginProxyInterface *proxyInter) override; + + QWidget *itemWidget(const QString &itemKey) override; + QWidget *itemTipsWidget(const QString &itemKey) override; + QWidget *itemPopupApplet(const QString &itemKey) override; + + PluginFlags flags() const override; + +private: + QScopedPointer m_mediaWidget; + QScopedPointer m_model; +}; + +#endif // DATETIMEPLUGIN_H diff --git a/plugins/media/mediawidget.cpp b/plugins/media/mediawidget.cpp new file mode 100644 index 000000000..055de43c5 --- /dev/null +++ b/plugins/media/mediawidget.cpp @@ -0,0 +1,191 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "mediawidget.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +DWIDGET_USE_NAMESPACE +DGUI_USE_NAMESPACE + +#define PAUSEHEIGHT 21 +#define PLAYHEIGHT 18 + +MediaWidget::MediaWidget(MediaPlayerModel *model, QWidget *parent) + : QWidget(parent) + , m_model(model) + , m_musicIcon(new QLabel(this)) + , m_musicName(new QLabel(this)) + , m_musicSinger(new QLabel(this)) + , m_pausePlayButton(new MusicButton(this)) + , m_nextButton(new MusicButton(this)) +{ + initUi(); + initConnection(); +} + +MediaWidget::~MediaWidget() +{ +} + +void MediaWidget::statusChanged(const MediaPlayerModel::PlayStatus &newStatus) +{ + switch (newStatus) { + case MediaPlayerModel::PlayStatus::Play: { + m_pausePlayButton->setButtonType(MusicButton::ButtonType::Pause); + break; + } + case MediaPlayerModel::PlayStatus::Stop: + case MediaPlayerModel::PlayStatus::Pause: { + m_pausePlayButton->setButtonType(MusicButton::ButtonType::Playing); + break; + } + default: break; + } +} + +void MediaWidget::onPlayClicked() +{ + // 设置当前的播放状态 + if (m_model->status() == MediaPlayerModel::PlayStatus::Play) + m_model->setStatus(MediaPlayerModel::PlayStatus::Pause); + else + m_model->setStatus(MediaPlayerModel::PlayStatus::Play); +} + +void MediaWidget::onNext() +{ + // 播放下一曲 + m_model->playNext(); +} + +void MediaWidget::initUi() +{ + m_pausePlayButton->setFixedWidth(20); + m_nextButton->setFixedWidth(20); + + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(20, 0, 20, 0); + mainLayout->addWidget(m_musicIcon); + + QWidget *infoWidget = new QWidget(this); + QVBoxLayout *infoLayout = new QVBoxLayout(infoWidget); + infoLayout->addWidget(m_musicName); + infoLayout->addWidget(m_musicSinger); + mainLayout->addWidget(infoWidget); + mainLayout->addStretch(); + mainLayout->addWidget(m_pausePlayButton); + mainLayout->addSpacing(25); + mainLayout->addWidget(m_nextButton); + + m_musicIcon->setFixedSize(32, 32); + m_musicName->setFont(DFontSizeManager::instance()->t8()); + m_musicSinger->setFont(DFontSizeManager::instance()->t10()); +} + +void MediaWidget::initConnection() +{ + connect(m_model, &MediaPlayerModel::startStop, this, [ this ](bool startOrStop) { + m_nextButton->setEnabled(m_model->canGoNext()); + onUpdateMediaInfo(); + statusChanged(m_model->status()); + }); + connect(m_model, &MediaPlayerModel::metadataChanged, this, &MediaWidget::onUpdateMediaInfo); + connect(m_model, &MediaPlayerModel::statusChanged, this, &MediaWidget::statusChanged); + connect(m_pausePlayButton, &MusicButton::clicked, this, &MediaWidget::onPlayClicked); + connect(m_nextButton, &MusicButton::clicked, this, &MediaWidget::onNext); + + m_pausePlayButton->setButtonType(m_model->status() == MediaPlayerModel::PlayStatus::Play ? + MusicButton::ButtonType::Pause : MusicButton::ButtonType::Playing); + m_nextButton->setButtonType(MusicButton::ButtonType::Next); +} + +void MediaWidget::onUpdateMediaInfo() +{ + m_musicName->setText(m_model->name()); + QString file = m_model->iconUrl(); + if (file.startsWith("file:///")) + file.replace("file:///", "/"); + m_musicIcon->setPixmap(QPixmap(file).scaled(m_musicIcon->size())); + m_musicSinger->setText(m_model->artist()); +} + +/** + * @brief 音乐播放的相关按钮 + * @param parent + */ + +MusicButton::MusicButton(QWidget *parent) + : QWidget(parent) +{ + installEventFilter(this); +} + +MusicButton::~MusicButton() +{ +} + +int MusicButton::getIconHeight() const +{ + switch (m_buttonType) { + case ButtonType::Pause: + return PAUSEHEIGHT; + case ButtonType::Next: + case ButtonType::Playing: + return PLAYHEIGHT; + } + + return PLAYHEIGHT; +} + +void MusicButton::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + +#define ICOMMARGIN 6 +#define ICONSPACE 2 + + int ctrlHeight = getIconHeight(); + + int width = this->width(); + int height = this->height(); + int startX = 2; + int startY = (height - ctrlHeight) / 2; + QColor color = DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::ColorType::LightType ? Qt::black : Qt::white; + QPainter painter(this); + painter.save(); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(color); + painter.setBrush(color); + if (m_buttonType == ButtonType::Pause) { + painter.drawRect(QRect(startX, startY, ICOMMARGIN, ctrlHeight)); + painter.drawRect(QRect(width - ICOMMARGIN - ICONSPACE, startY, ICOMMARGIN, ctrlHeight)); + } else { + QPainterPath trianglePath; + trianglePath.moveTo(startX, startY); + trianglePath.lineTo(width - ICOMMARGIN, height / 2); + trianglePath.lineTo(startX, startY + ctrlHeight); + trianglePath.lineTo(startX, startY); + painter.drawPath(trianglePath); + if (m_buttonType == ButtonType::Next) + painter.drawRect(width - ICOMMARGIN, startY, 2, ctrlHeight); + } + painter.restore(); +} + +void MusicButton::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + Q_EMIT clicked(); +} diff --git a/plugins/media/mediawidget.h b/plugins/media/mediawidget.h new file mode 100644 index 000000000..629a2d796 --- /dev/null +++ b/plugins/media/mediawidget.h @@ -0,0 +1,77 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef MEDIAWIDGET_H +#define MEDIAWIDGET_H + +#include "mediaplayermodel.h" + +#include + +class QLabel; +class MusicButton; +class MediaPlayerModel; + +DWIDGET_USE_NAMESPACE + +class MediaWidget : public QWidget +{ + Q_OBJECT + +public: + explicit MediaWidget(MediaPlayerModel *model, QWidget *parent = nullptr); + ~MediaWidget() override; + +private Q_SLOTS: + void statusChanged(const MediaPlayerModel::PlayStatus &newStatus); + void onPlayClicked(); + void onNext(); + void onUpdateMediaInfo(); + +private: + void initUi(); + void initConnection(); + +private: + MediaPlayerModel *m_model; + QLabel *m_musicIcon; + QLabel *m_musicName; + QLabel *m_musicSinger; + MusicButton *m_pausePlayButton; + MusicButton *m_nextButton; +}; + +// 音乐播放按钮 +class MusicButton : public QWidget +{ + Q_OBJECT + +Q_SIGNALS: + void clicked(); + +public: + enum ButtonType { Playing = 0, Pause, Next }; + +public: + MusicButton(QWidget *parent = Q_NULLPTR); + ~MusicButton() override; + + inline void setButtonType(const ButtonType &bt) { + m_buttonType = bt; + update(); + } + +protected: + void paintEvent(QPaintEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + +private: + int getIconHeight() const; + +private: + ButtonType m_buttonType; +}; + +#endif // MEDIAWIDGER_H diff --git a/plugins/multitasking/CMakeLists.txt b/plugins/multitasking/CMakeLists.txt index ec4feda4a..d02f5ab09 100644 --- a/plugins/multitasking/CMakeLists.txt +++ b/plugins/multitasking/CMakeLists.txt @@ -4,10 +4,8 @@ set(PLUGIN_NAME "multitasking") project(${PLUGIN_NAME}) # Sources files -file(GLOB SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp" - "../../frame/util/imageutil.h" - "../../frame/util/imageutil.cpp" - ) +file(GLOB SRCS "*.h" "*.cpp" "../../widgets/tipswidget.h" "../../widgets/tipswidget.cpp" +"../../frame/util/imageutil.h" "../../frame/util/imageutil.cpp") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) diff --git a/plugins/multitasking/multitasking.json b/plugins/multitasking/multitasking.json index fdabbaaaa..bec81f0da 100644 --- a/plugins/multitasking/multitasking.json +++ b/plugins/multitasking/multitasking.json @@ -1,3 +1,3 @@ { - "api": "1.2.2" + "api": "2.0.0" } diff --git a/plugins/multitasking/multitaskingplugin.cpp b/plugins/multitasking/multitaskingplugin.cpp index fba865a9a..46ff2e64b 100644 --- a/plugins/multitasking/multitaskingplugin.cpp +++ b/plugins/multitasking/multitaskingplugin.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -16,7 +17,6 @@ DGUI_USE_NAMESPACE using namespace Dock; MultitaskingPlugin::MultitaskingPlugin(QObject *parent) : QObject(parent) - , m_pluginLoaded(false) , m_multitaskingWidget(nullptr) , m_tipsLabel(new TipsWidget) { @@ -24,10 +24,10 @@ MultitaskingPlugin::MultitaskingPlugin(QObject *parent) m_tipsLabel->setObjectName("multitasking"); connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasCompositeChanged, this, [ = ] { - if (!m_proxyInter || !m_pluginLoaded) + if (!m_proxyInter) return; - if (DWindowManagerHelper::instance()->hasComposite() && !pluginIsDisable()) + if (DWindowManagerHelper::instance()->hasComposite()) m_proxyInter->itemAdded(this, PLUGIN_KEY); else m_proxyInter->itemRemoved(this, PLUGIN_KEY); @@ -63,24 +63,13 @@ QWidget *MultitaskingPlugin::itemTipsWidget(const QString &itemKey) void MultitaskingPlugin::init(PluginProxyInterface *proxyInter) { m_proxyInter = proxyInter; + m_multitaskingWidget.reset(new MultitaskingWidget); - if (!pluginIsDisable()) { - loadPlugin(); + if (DWindowManagerHelper::instance()->hasComposite()) { + m_proxyInter->itemAdded(this, pluginName()); } } -void MultitaskingPlugin::pluginStateSwitched() -{ - m_proxyInter->saveValue(this, PLUGIN_STATE_KEY, pluginIsDisable()); - - refreshPluginItemsVisible(); -} - -bool MultitaskingPlugin::pluginIsDisable() -{ - return !m_proxyInter->getValue(this, PLUGIN_STATE_KEY, true).toBool(); -} - const QString MultitaskingPlugin::itemCommand(const QString &itemKey) { if (itemKey == PLUGIN_KEY) @@ -157,49 +146,12 @@ void MultitaskingPlugin::setSortKey(const QString &itemKey, const int order) m_proxyInter->saveValue(this, key, order); } -void MultitaskingPlugin::pluginSettingsChanged() -{ - refreshPluginItemsVisible(); -} - PluginsItemInterface::PluginType MultitaskingPlugin::type() { return PluginType::Fixed; } -void MultitaskingPlugin::updateVisible() +PluginFlags MultitaskingPlugin::flags() const { - if (pluginIsDisable() || !DWindowManagerHelper::instance()->hasComposite()) { - m_proxyInter->itemRemoved(this, PLUGIN_KEY); - } else { - m_proxyInter->itemAdded(this, PLUGIN_KEY); - } -} - -void MultitaskingPlugin::loadPlugin() -{ - if (m_pluginLoaded) { - return; - } - - m_pluginLoaded = true; - - m_multitaskingWidget.reset(new MultitaskingWidget); - - m_proxyInter->itemAdded(this, pluginName()); - - updateVisible(); -} - -void MultitaskingPlugin::refreshPluginItemsVisible() -{ - if (pluginIsDisable()) { - m_proxyInter->itemRemoved(this, PLUGIN_KEY); - } else { - if (!m_pluginLoaded) { - loadPlugin(); - return; - } - updateVisible(); - } + return PluginFlag::Type_Fixed | PluginFlag::Attribute_ForceDock; } diff --git a/plugins/multitasking/multitaskingplugin.h b/plugins/multitasking/multitaskingplugin.h index 2853e51e0..2142cd3bf 100644 --- a/plugins/multitasking/multitaskingplugin.h +++ b/plugins/multitasking/multitaskingplugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -25,9 +26,7 @@ public: const QString pluginName() const override; const QString pluginDisplayName() const override; void init(PluginProxyInterface *proxyInter) override; - void pluginStateSwitched() override; bool pluginIsAllowDisable() override { return true; } - bool pluginIsDisable() override; QWidget *itemWidget(const QString &itemKey) override; QWidget *itemTipsWidget(const QString &itemKey) override; const QString itemCommand(const QString &itemKey) override; @@ -36,17 +35,10 @@ public: void refreshIcon(const QString &itemKey) override; int itemSortKey(const QString &itemKey) override; void setSortKey(const QString &itemKey, const int order) override; - void pluginSettingsChanged() override; PluginType type() override; + PluginFlags flags() const override; private: - void updateVisible(); - void loadPlugin(); - void refreshPluginItemsVisible(); - -private: - bool m_pluginLoaded; - QScopedPointer m_multitaskingWidget; QScopedPointer m_tipsLabel; }; diff --git a/plugins/multitasking/multitaskingwidget.cpp b/plugins/multitasking/multitaskingwidget.cpp index 577bee749..05466b5b5 100644 --- a/plugins/multitasking/multitaskingwidget.cpp +++ b/plugins/multitasking/multitaskingwidget.cpp @@ -1,14 +1,15 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "multitaskingwidget.h" #include "multitaskingplugin.h" -#include "imageutil.h" #include #include #include +#include MultitaskingWidget::MultitaskingWidget(QWidget *parent) : QWidget(parent) diff --git a/plugins/multitasking/multitaskingwidget.h b/plugins/multitasking/multitaskingwidget.h index bf45bc32a..af75fbd04 100644 --- a/plugins/multitasking/multitaskingwidget.h +++ b/plugins/multitasking/multitaskingwidget.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/onboard/CMakeLists.txt b/plugins/onboard/CMakeLists.txt index 46b95e2c7..11df5e04f 100644 --- a/plugins/onboard/CMakeLists.txt +++ b/plugins/onboard/CMakeLists.txt @@ -3,8 +3,15 @@ set(PLUGIN_NAME "onboard") project(${PLUGIN_NAME}) +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + # Sources files -file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp") +file(GLOB_RECURSE SRCS "*.h" + "*.cpp" + "../../widgets/tipswidget.h" + "../../widgets/tipswidget.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) @@ -15,15 +22,17 @@ find_package(DtkWidget REQUIRED) add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") add_library(${PLUGIN_NAME} SHARED ${SRCS} onboard.qrc) set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../) + target_include_directories(${PLUGIN_NAME} PUBLIC ${Qt5DBus_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} - ../../interfaces) + ../../interfaces + ../../frame/qtdbusextended + ./dbusinterface/generation_dbus_interface) + target_link_libraries(${PLUGIN_NAME} PRIVATE ${Qt5Widgets_LIBRARIES} ${Qt5DBus_LIBRARIES} ${DtkGui_LIBRARIES} ${DtkWidget_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} ) install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins) diff --git a/plugins/onboard/dbusinterface/types/arealist.cpp b/plugins/onboard/dbusinterface/types/arealist.cpp new file mode 100644 index 000000000..0b3ed4f15 --- /dev/null +++ b/plugins/onboard/dbusinterface/types/arealist.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "arealist.h" + +bool MonitRect::operator ==(const MonitRect &rect) +{ + return x1 == rect.x1 && y1 == rect.y1 && x2 == rect.x2 && y2 == rect.y2; +} + +QDBusArgument &operator<<(QDBusArgument &arg, const MonitRect &rect) +{ + arg.beginStructure(); + arg << rect.x1 << rect.y1 << rect.x2 << rect.y2; + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, MonitRect &rect) +{ + arg.beginStructure(); + arg >> rect.x1 >> rect.y1 >> rect.x2 >> rect.y2; + arg.endStructure(); + + return arg; +} + +void registerAreaListMetaType() +{ + qRegisterMetaType("MonitRect"); + qDBusRegisterMetaType(); + + qRegisterMetaType("AreaList"); + qDBusRegisterMetaType(); +} diff --git a/plugins/onboard/dbusinterface/types/arealist.h b/plugins/onboard/dbusinterface/types/arealist.h new file mode 100644 index 000000000..f75a0e53f --- /dev/null +++ b/plugins/onboard/dbusinterface/types/arealist.h @@ -0,0 +1,32 @@ +// Copyright (C) 2011 ~ 2017 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef AREALIST_H +#define AREALIST_H + +#include +#include +#include + +struct MonitRect { + int x1; + int y1; + int x2; + int y2; + + bool operator ==(const MonitRect& rect); +}; + +typedef QList AreaList; + +Q_DECLARE_METATYPE(MonitRect) +Q_DECLARE_METATYPE(AreaList) + +QDBusArgument &operator<<(QDBusArgument &arg, const MonitRect &rect); +const QDBusArgument &operator>>(const QDBusArgument &arg, MonitRect &rect); + +void registerAreaListMetaType(); + +#endif // AREALIST_H diff --git a/plugins/onboard/dbusinterface/xml/org.deepin.dde.daemon.Dock1.Entry.xml b/plugins/onboard/dbusinterface/xml/org.deepin.dde.daemon.Dock1.Entry.xml new file mode 100644 index 000000000..89b665e41 --- /dev/null +++ b/plugins/onboard/dbusinterface/xml/org.deepin.dde.daemon.Dock1.Entry.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/plugins/onboard/dbusinterface/xml/org.deepin.dde.daemon.Dock1.xml b/plugins/onboard/dbusinterface/xml/org.deepin.dde.daemon.Dock1.xml new file mode 100644 index 000000000..08573ed35 --- /dev/null +++ b/plugins/onboard/dbusinterface/xml/org.deepin.dde.daemon.Dock1.xml @@ -0,0 +1,3 @@ + + + diff --git a/plugins/dcc-dock-plugin/texts/dcc_dock_keyboard_16px.svg b/plugins/onboard/icon/dcc_keyboard.svg similarity index 100% rename from plugins/dcc-dock-plugin/texts/dcc_dock_keyboard_16px.svg rename to plugins/onboard/icon/dcc_keyboard.svg diff --git a/plugins/onboard/icon/deepin-virtualkeyboard.svg b/plugins/onboard/icon/deepin-virtualkeyboard.svg new file mode 100644 index 000000000..5916425fd --- /dev/null +++ b/plugins/onboard/icon/deepin-virtualkeyboard.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/onboard/icon/keyboard-symbolic-dark.svg b/plugins/onboard/icon/keyboard-symbolic-dark.svg deleted file mode 100644 index 55ef65718..000000000 --- a/plugins/onboard/icon/keyboard-symbolic-dark.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - keyboard-symbolic-dark - - - - - - \ No newline at end of file diff --git a/plugins/onboard/icon/keyboard-symbolic.svg b/plugins/onboard/icon/keyboard-symbolic.svg deleted file mode 100644 index 509a00539..000000000 --- a/plugins/onboard/icon/keyboard-symbolic.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - keyboard-symbolic - - - - - - \ No newline at end of file diff --git a/plugins/onboard/onboard.json b/plugins/onboard/onboard.json index ad498eeb3..bec81f0da 100644 --- a/plugins/onboard/onboard.json +++ b/plugins/onboard/onboard.json @@ -1,3 +1,3 @@ { - "api": "1.1.1" + "api": "2.0.0" } diff --git a/plugins/onboard/onboard.qrc b/plugins/onboard/onboard.qrc index 8747d5121..a067f2ebe 100644 --- a/plugins/onboard/onboard.qrc +++ b/plugins/onboard/onboard.qrc @@ -1,6 +1,6 @@ - icon/keyboard-symbolic-dark.svg - icon/keyboard-symbolic.svg + icon/deepin-virtualkeyboard.svg + icon/dcc_keyboard.svg diff --git a/plugins/onboard/onboarditem.cpp b/plugins/onboard/onboarditem.cpp index b9ae0fb49..c6d890ec3 100644 --- a/plugins/onboard/onboarditem.cpp +++ b/plugins/onboard/onboarditem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -26,20 +27,25 @@ OnboardItem::OnboardItem(QWidget *parent) connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [ = ] { update(); }); - m_icon = QIcon::fromTheme(":/icons/icon/keyboard-symbolic.svg"); + m_icon = QIcon::fromTheme(":/icons/icon/deepin-virtualkeyboard.svg"); +} + +QPixmap OnboardItem::iconPixmap(QSize size, DGuiApplicationHelper::ColorType themeType) const +{ + QString iconName = "deepin-virtualkeyboard"; + if (std::min(width(), height()) <= PLUGIN_BACKGROUND_MIN_SIZE + || themeType == DGuiApplicationHelper::LightType) + iconName.append(PLUGIN_MIN_ICON_NAME); + + return loadSvg(iconName, size); } void OnboardItem::paintEvent(QPaintEvent *e) { Q_UNUSED(e); - QPixmap pixmap; - QString iconName = "keyboard-symbolic"; - int iconSize = PLUGIN_ICON_MAX_SIZE; - QPainter painter(this); if (std::min(width(), height()) > PLUGIN_BACKGROUND_MIN_SIZE) { - QColor color; if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { color = Qt::black; @@ -78,12 +84,9 @@ void OnboardItem::paintEvent(QPaintEvent *e) path.addRoundedRect(rc, radius, radius); painter.fillPath(path, color); - } else if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { - iconName.append(PLUGIN_MIN_ICON_NAME); } - pixmap = loadSvg(iconName, QSize(iconSize, iconSize)); - + QPixmap pixmap = iconPixmap(QSize(PLUGIN_ICON_MAX_SIZE, PLUGIN_ICON_MAX_SIZE), DGuiApplicationHelper::instance()->themeType()); painter.setOpacity(1); const QRectF &rf = QRectF(rect()); const QRectF &rfp = QRectF(pixmap.rect()); @@ -94,10 +97,10 @@ const QPixmap OnboardItem::loadSvg(const QString &fileName, const QSize &size) c { const auto ratio = devicePixelRatioF(); - QPixmap pixmap; QSize pixmapSize = QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? size : (size * ratio); - pixmap = QIcon::fromTheme(fileName, m_icon).pixmap(pixmapSize); + QPixmap pixmap = QIcon::fromTheme(fileName, m_icon).pixmap(pixmapSize); pixmap.setDevicePixelRatio(ratio); + pixmap = pixmap.scaled(size * ratio); return pixmap; } diff --git a/plugins/onboard/onboarditem.h b/plugins/onboard/onboarditem.h index f62038958..c933d5c24 100644 --- a/plugins/onboard/onboarditem.h +++ b/plugins/onboard/onboarditem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,15 +8,20 @@ #include "constants.h" +#include + #include #include +DGUI_USE_NAMESPACE + class OnboardItem : public QWidget { Q_OBJECT public: explicit OnboardItem(QWidget *parent = nullptr); + QPixmap iconPixmap(QSize size, DGuiApplicationHelper::ColorType themeType) const; protected: void paintEvent(QPaintEvent *e) override; diff --git a/plugins/onboard/onboardplugin.cpp b/plugins/onboard/onboardplugin.cpp index 3de240456..c57b74e9d 100644 --- a/plugins/onboard/onboardplugin.cpp +++ b/plugins/onboard/onboardplugin.cpp @@ -1,17 +1,29 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "onboardplugin.h" #include "../widgets/tipswidget.h" +#include "org_deepin_dde_daemon_dock1.h" +#include "org_deepin_dde_daemon_dock1_entry.h" + +#include + #include #include +#include #define PLUGIN_STATE_KEY "enable" -using DBusDock = com::deepin::dde::daemon::Dock; -using DockEntryInter = com::deepin::dde::daemon::dock::Entry; +DGUI_USE_NAMESPACE + +using DBusDock = org::deepin::dde::daemon::Dock1; +using DockEntryInter = org::deepin::dde::daemon::dock1::Entry; + +static const QString serviceName = QString("org.deepin.dde.daemon.Dock1"); +static const QString servicePath = QString("/org/deepin/dde/daemon/Dock1"); using namespace Dock; OnboardPlugin::OnboardPlugin(QObject *parent) @@ -38,9 +50,10 @@ const QString OnboardPlugin::pluginDisplayName() const QWidget *OnboardPlugin::itemWidget(const QString &itemKey) { - Q_UNUSED(itemKey); + if (itemKey == pluginName()) + return m_onboardItem.data(); - return m_onboardItem.data(); + return nullptr; } QWidget *OnboardPlugin::itemTipsWidget(const QString &itemKey) @@ -68,7 +81,7 @@ void OnboardPlugin::pluginStateSwitched() bool OnboardPlugin::pluginIsDisable() { - return !(m_proxyInter->getValue(this, PLUGIN_STATE_KEY, false).toBool()); + return !(m_proxyInter->getValue(this, PLUGIN_STATE_KEY, true).toBool()); } const QString OnboardPlugin::itemCommand(const QString &itemKey) @@ -78,32 +91,14 @@ const QString OnboardPlugin::itemCommand(const QString &itemKey) return QString("dbus-send --print-reply --dest=org.onboard.Onboard /org/onboard/Onboard/Keyboard org.onboard.Onboard.Keyboard.ToggleVisible"); } -const QString OnboardPlugin::itemContextMenu(const QString &itemKey) -{ - Q_UNUSED(itemKey); - - QList items; - - QMap onboardSettings; - onboardSettings["itemId"] = "onboard-settings"; - onboardSettings["itemText"] = tr("Settings"); - onboardSettings["isActive"] = true; - items.push_back(onboardSettings); - - QMap menu; - menu["items"] = items; - menu["checkableMenu"] = false; - menu["singleCheck"] = false; - - return QJsonDocument::fromVariant(menu).toJson(); -} - void OnboardPlugin::invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) { Q_UNUSED(itemKey) Q_UNUSED(checked) - if (menuId != "onboard-settings") return; + if (menuId != "onboard-settings") + return; + if(!m_startupState) { QProcess *process = new QProcess; connect(process,&QProcess::started, this, [ = ] { @@ -119,17 +114,13 @@ void OnboardPlugin::invokedMenuItem(const QString &itemKey, const QString &menuI process->close(); process->deleteLater(); }); - process->start("onboard-settings"); + process->start("onboard-settings", QStringList()); } - DBusDock DockInter("com.deepin.dde.daemon.Dock", - "/com/deepin/dde/daemon/Dock", - QDBusConnection::sessionBus(), this); + DBusDock DockInter(serviceName, servicePath, QDBusConnection::sessionBus(), this); for (auto entry : DockInter.entries()) { - DockEntryInter AppInter("com.deepin.dde.daemon.Dock", - entry.path(), - QDBusConnection::sessionBus(), this); + DockEntryInter AppInter(serviceName, entry.path(), QDBusConnection::sessionBus(), this); if(AppInter.name() == "Onboard-Settings" && !AppInter.isActive()) { AppInter.Activate(0); break; @@ -163,6 +154,35 @@ void OnboardPlugin::pluginSettingsChanged() refreshPluginItemsVisible(); } +QIcon OnboardPlugin::icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) +{ + if (dockPart == DockPart::DCCSetting) { + if (themeType == DGuiApplicationHelper::ColorType::LightType) + return QIcon(":/icons/icon/dcc_keyboard.svg"); + + QPixmap pixmap(":/icons/icon/dcc_keyboard.svg"); + QPainter pa(&pixmap); + pa.setCompositionMode(QPainter::CompositionMode_SourceIn); + pa.fillRect(pixmap.rect(), Qt::white); + return pixmap; + } + + if (dockPart == DockPart::QuickPanel) + return m_onboardItem->iconPixmap(QSize(24, 24), themeType); + + return m_onboardItem->iconPixmap(QSize(18, 16), themeType); +} + +PluginsItemInterface::PluginMode OnboardPlugin::status() const +{ + return PluginsItemInterface::PluginMode::Active; +} + +QString OnboardPlugin::description() const +{ + return pluginDisplayName(); +} + void OnboardPlugin::loadPlugin() { if (m_pluginLoaded) { @@ -180,7 +200,8 @@ void OnboardPlugin::loadPlugin() void OnboardPlugin::refreshPluginItemsVisible() { - if (pluginIsDisable()) { + if (pluginIsDisable()) + { m_proxyInter->itemRemoved(this, pluginName()); } else { if (!m_pluginLoaded) { diff --git a/plugins/onboard/onboardplugin.h b/plugins/onboard/onboardplugin.h index 80a7c9370..f21abe29c 100644 --- a/plugins/onboard/onboardplugin.h +++ b/plugins/onboard/onboardplugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -11,9 +12,6 @@ #include #include -#include -#include - namespace Dock { class TipsWidget; } @@ -37,7 +35,6 @@ public: QWidget *itemWidget(const QString &itemKey) override; QWidget *itemTipsWidget(const QString &itemKey) override; const QString itemCommand(const QString &itemKey) override; - const QString itemContextMenu(const QString &itemKey) override; void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) override; void displayModeChanged(const Dock::DisplayMode displayMode) override; @@ -45,6 +42,9 @@ public: void setSortKey(const QString &itemKey, const int order) override; void pluginSettingsChanged() override; + QIcon icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) override; + PluginMode status() const override; + QString description() const override; private: void loadPlugin(); diff --git a/plugins/overlay-warning/CMakeLists.txt b/plugins/overlay-warning/CMakeLists.txt index 3a07bf4b2..7f0d65ad7 100644 --- a/plugins/overlay-warning/CMakeLists.txt +++ b/plugins/overlay-warning/CMakeLists.txt @@ -4,7 +4,7 @@ set(PLUGIN_NAME "overlay-warning") project(${PLUGIN_NAME}) # Sources files -file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp") +file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../../widgets/tipswidget.h" "../../widgets/tipswidget.cpp") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) @@ -28,5 +28,5 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins) # policy kit -install(FILES com.deepin.dde.dock.overlay.policy +install(FILES org.deepin.dde.dock.overlay.policy DESTINATION share/polkit-1/actions/) diff --git a/plugins/overlay-warning/com.deepin.dde.dock.overlay.policy b/plugins/overlay-warning/org.deepin.dde.dock.overlay.policy similarity index 100% rename from plugins/overlay-warning/com.deepin.dde.dock.overlay.policy rename to plugins/overlay-warning/org.deepin.dde.dock.overlay.policy diff --git a/plugins/overlay-warning/overlay-warning-plugin.cpp b/plugins/overlay-warning/overlay-warning-plugin.cpp index 470bac30d..66d8f3978 100644 --- a/plugins/overlay-warning/overlay-warning-plugin.cpp +++ b/plugins/overlay-warning/overlay-warning-plugin.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,7 +14,7 @@ #define PLUGIN_STATE_KEY "enable" #define OverlayFileSystemType "overlay" -#define AuthAgentDbusService "com.deepin.Polkit1AuthAgent" +#define AuthAgentDbusService "org.deepin.dde.Polkit1.AuthAgent" DWIDGET_USE_NAMESPACE @@ -114,6 +115,11 @@ void OverlayWarningPlugin::setSortKey(const QString &itemKey, const int order) m_proxyInter->saveValue(this, key, order); } +PluginFlags OverlayWarningPlugin::flags() const +{ + return PluginFlag::Type_NoneFlag; +} + void OverlayWarningPlugin::loadPlugin() { if (m_pluginLoaded) { @@ -174,9 +180,9 @@ void OverlayWarningPlugin::showCloseOverlayDialogPre() void OverlayWarningPlugin::showCloseOverlayDialog() { qDebug() << "start disable overlayroot process"; - const int result = QProcess::execute("/usr/bin/pkexec /usr/sbin/overlayroot-disable"); + const int result = QProcess::execute("/usr/bin/pkexec /usr/sbin/overlayroot-disable", QStringList()); if (result == 0) { - QProcess::startDetached("reboot"); + QProcess::startDetached("reboot", QStringList()); } else { qDebug() << "disable overlayroot failed, the return code is" << result; } diff --git a/plugins/overlay-warning/overlay-warning-plugin.h b/plugins/overlay-warning/overlay-warning-plugin.h index 9d29afa3b..eb8955b68 100644 --- a/plugins/overlay-warning/overlay-warning-plugin.h +++ b/plugins/overlay-warning/overlay-warning-plugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -41,6 +42,7 @@ public: int itemSortKey(const QString &itemKey) override; void setSortKey(const QString &itemKey, const int order) override; + PluginFlags flags() const override; private: void loadPlugin(); diff --git a/plugins/overlay-warning/overlay-warning.json b/plugins/overlay-warning/overlay-warning.json index ad498eeb3..bec81f0da 100644 --- a/plugins/overlay-warning/overlay-warning.json +++ b/plugins/overlay-warning/overlay-warning.json @@ -1,3 +1,3 @@ { - "api": "1.1.1" + "api": "2.0.0" } diff --git a/plugins/overlay-warning/overlaywarningwidget.cpp b/plugins/overlay-warning/overlaywarningwidget.cpp index e14440775..df431049a 100644 --- a/plugins/overlay-warning/overlaywarningwidget.cpp +++ b/plugins/overlay-warning/overlaywarningwidget.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -49,9 +50,8 @@ const QPixmap OverlayWarningWidget::loadSvg(const QString &fileName, const QSize { const auto ratio = devicePixelRatioF(); - QPixmap pixmap; QSize pixmapSize = QCoreApplication::testAttribute(Qt::AA_UseHighDpiPixmaps) ? size : (size * ratio); - pixmap = QIcon::fromTheme(fileName).pixmap(pixmapSize); + QPixmap pixmap = QIcon::fromTheme(fileName).pixmap(pixmapSize); pixmap.setDevicePixelRatio(ratio); return pixmap; diff --git a/plugins/overlay-warning/overlaywarningwidget.h b/plugins/overlay-warning/overlaywarningwidget.h index 1071f9118..d6f21b0a0 100644 --- a/plugins/overlay-warning/overlaywarningwidget.h +++ b/plugins/overlay-warning/overlaywarningwidget.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/plugin-guide/home_monitor/home_monitor.json b/plugins/plugin-guide/home_monitor/home_monitor.json index 86b33bb4a..031bf0ec8 100644 --- a/plugins/plugin-guide/home_monitor/home_monitor.json +++ b/plugins/plugin-guide/home_monitor/home_monitor.json @@ -1,3 +1,3 @@ { - "api": "1.1.1" + "api": "2.0.0" } diff --git a/plugins/plugin-guide/home_monitor/homemonitorplugin.cpp b/plugins/plugin-guide/home_monitor/homemonitorplugin.cpp index 1848c4e53..1107f97b5 100644 --- a/plugins/plugin-guide/home_monitor/homemonitorplugin.cpp +++ b/plugins/plugin-guide/home_monitor/homemonitorplugin.cpp @@ -1,9 +1,11 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "homemonitorplugin.h" +#include + HomeMonitorPlugin::HomeMonitorPlugin(QObject *parent) : QObject(parent) { @@ -137,3 +139,56 @@ void HomeMonitorPlugin::invokedMenuItem(const QString &itemKey, const QString &m QProcess::startDetached("gparted"); } } + +QIcon HomeMonitorPlugin::icon(const DockPart &) +{ + QIcon pixMapIcon; + QPixmap pixmap; + QPainter painter(&pixmap); + painter.begin(&pixmap); + QFont font; + font.setPixelSize(10); + painter.setFont(font); + painter.drawText(QPoint(0, 0), m_pluginWidget->textContent()); + painter.end(); + pixMapIcon.addPixmap(pixmap); + return pixMapIcon; +} + +PluginsItemInterface::PluginMode HomeMonitorPlugin::status() const +{ + return PluginMode::Active; +} + +QString HomeMonitorPlugin::description() const +{ + // 当isPrimary()返回值为true的时候,这个值用于返回在大图标下面的状态信息, + // 例如,如果当前图标是网络图标,下面则显示连接的网络信息,或者如果是其他的图标,下面显示连接的 + // 状态等(开启或者关闭) + if (status() == PluginMode::Active) + return tr("Enabled"); + + return tr("Disabled"); +} + +QIcon HomeMonitorPlugin::icon(const DockPart &dockPart, int themeType) +{ + if (dockPart == DockPart::QuickShow) { + QIcon icon; + return icon; + } + + return QIcon(); +} + +PluginFlags HomeMonitorPlugin::flags() const +{ + // 返回的插件为Type_Common-快捷区域插件, Quick_Multi快捷插件显示两列的那种,例如网络和蓝牙 + // Attribute_CanDrag该插件在任务栏上支持拖动,Attribute_CanInsert该插件支持在其前面插入其他的图标 + // Attribute_CanSetting该插件支持在控制中心设置显示或隐藏 + return PluginFlags::Type_Common + | PluginFlags::Quick_Multi + | PluginFlags::Attribute_CanDrag + | PluginFlags::Attribute_CanInsert + | PluginFlags::Attribute_CanSetting; +} diff --git a/plugins/plugin-guide/home_monitor/homemonitorplugin.h b/plugins/plugin-guide/home_monitor/homemonitorplugin.h index 602d1a9d5..c052e5962 100644 --- a/plugins/plugin-guide/home_monitor/homemonitorplugin.h +++ b/plugins/plugin-guide/home_monitor/homemonitorplugin.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -35,6 +35,13 @@ public: const QString itemContextMenu(const QString &itemKey) override; void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) override; + QIcon icon(const DockPart &) override; + PluginMode status() const override; + QString description() const override; + + QIcon icon(const DockPart &dockPart, int themeType) override; + PluginFlags flags() const override; + private: InformationWidget *m_pluginWidget; QLabel *m_tipsWidget; diff --git a/plugins/plugin-guide/home_monitor/informationwidget.cpp b/plugins/plugin-guide/home_monitor/informationwidget.cpp index f94ec1e0d..287c48540 100644 --- a/plugins/plugin-guide/home_monitor/informationwidget.cpp +++ b/plugins/plugin-guide/home_monitor/informationwidget.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -37,7 +37,7 @@ InformationWidget::InformationWidget(QWidget *parent) refreshInfo(); } -void InformationWidget::refreshInfo() +const QString InformationWidget::textContent() const { // 获取分区总容量 const double total = m_storageInfo->bytesTotal(); @@ -45,7 +45,11 @@ void InformationWidget::refreshInfo() const double available = m_storageInfo->bytesAvailable(); // 得到可用百分比 const int percent = qRound(available / total * 100); - - // 更新内容 - m_infoLabel->setText(QString("Home:\n%1\%").arg(percent)); + return QString("Home:\n%1\%").arg(percent); +} + +void InformationWidget::refreshInfo() +{ + // 更新内容 + m_infoLabel->setText(textContent()); } diff --git a/plugins/plugin-guide/home_monitor/informationwidget.h b/plugins/plugin-guide/home_monitor/informationwidget.h index d86b01014..33b264942 100644 --- a/plugins/plugin-guide/home_monitor/informationwidget.h +++ b/plugins/plugin-guide/home_monitor/informationwidget.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -18,6 +18,7 @@ public: explicit InformationWidget(QWidget *parent = nullptr); inline QStorageInfo * storageInfo() { return m_storageInfo; } + const QString textContent() const; private slots: // 用于更新数据的槽函数 diff --git a/plugins/plugin-guide/plugins-developer-guide.md b/plugins/plugin-guide/plugins-developer-guide.md index d93c91136..fde7dbce7 100644 --- a/plugins/plugin-guide/plugins-developer-guide.md +++ b/plugins/plugin-guide/plugins-developer-guide.md @@ -27,6 +27,8 @@ dde-dock 插件是根据 Qt 插件标准所开发的共享库文件(`so`),通 PluginsItemInterface 中定义的接口除了displayMode 和 position(历史遗留),从插件的角度来看都是被动的,只能等待被任务栏的插件机制调用。 +另外定义了DockPart枚举,用于表示返回图标的位置,分别有快捷插件显示区域,快捷图标区域和系统插件显示区域,主要用于区域插件在不同的位置的显示。 + |名称|简介| |-|-| |pluginName | 返回插件名称,用于在 dde-dock 内部管理插件时使用 `必须实现`| @@ -51,6 +53,10 @@ PluginsItemInterface 中定义的接口除了displayMode 和 position(历史 |refreshIcon | 当插件控件的图标需要更新时此接口被调用| |displayMode | 用于插件主动获取 dde-dock 当前的显示模式| |position | 用于插件主动获取 dde-dock 当前的位置| +|icon | 用于返回当前插件在快捷设置面板、快捷设置图标区域,系统插件显示区域等和不同的系统主题(主题黑色,主题白色)的图标,正常状态下显示的图标即可 | +|status | 用于返回当前快捷设置插件的状态,激活状态还是禁用状态 | +|description | 用于返回插件的描述(快捷设置面板中isPrimary为true的时候有用) | +|flags | 用于返回插件的属性,例如插件显示的位置,插件占几列,插件是否支持拖动等 | ### PluginProxyInterface @@ -61,6 +67,7 @@ PluginsItemInterface 中定义的接口除了displayMode 和 position(历史 |itemAdded | 向 dde-dock 添加新的主控件(一个插件可以添加多个主控件它们之间使用`ItemKey`区分)| |itemUpdate | 通知 dde-dock 有主控件需要更新| |itemRemoved | 从 dde-dock 移除主控件| +|updateDockInfo | 当插件图标发生变化的时候,响应该函数 | |requestWindowAutoHide | 设置 dde-dock 是否允许隐藏,通常被用在任务栏被设置为智能隐藏或始终隐藏而插件又需要让 dde-dock 保持显示状态来显示一些重要信息的场景下| |requestRefreshWindowVisible | 通知 dde-dock 更新隐藏状态| |requestSetAppletVisible | 通知 dde-dock 显示或隐藏插件的弹出面板(鼠标左键点击后弹出的控件)| @@ -219,19 +226,31 @@ install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins) ``` json { - "api": "1.2" + "api": "2.0.0" } ``` -另外(可选的)还支持指定一个 dbus 服务,dock 在加载插件时会检查此插件所依赖的 dbus 服务,如果服务没有启动则不会初始化这个插件,直到服务启动,如下表示依赖 dbus 地址为 "com.deepin.daemon.Network" 的 dbus 服务。 +另外(可选的)还支持指定一个 dbus 服务,dock 在加载插件时会检查此插件所依赖的 dbus 服务,如果服务没有启动则不会初始化这个插件,直到服务启动,如下表示依赖 dbus 地址为 "org.deepin.dde.Network1" 的 dbus 服务。 ``` json { - "api": "1.2", - "depends-daemon-dbus-service": "com.deepin.daemon.Network" + "api": "2.0.0", + "depends-daemon-dbus-service": "org.deepin.dde.Network1" } ``` +当插件在快捷面板中展示的时候,不同的插件之间支持按照一定的顺序进行排序,dock在加载该插件的时候会检查该插件的元数据文件中是否存在order字段,如果存在该字段,就会按照该字段指定的顺序进行排序,如果不存在该字段,那么该插件就会插入到已经指定该字段的插件的后面,同时按照加载的先后顺序进行排序 + +```json +{ + "api": "2.0.0", + "order": 1, + "depends-daemon-dbus-service": "org.deepin.dde.Audio1" +} +``` + + + ### 插件核心类 `homemonitorplugin.h` 声明了类 `HomeMonitorPlugin`,它继承(实现)了前面提到的 `PluginItemInterface`,这代表了它是一个实现了 dde-dock 接口的插件。 @@ -265,6 +284,11 @@ public: // 返回插件的 widget QWidget *itemWidget(const QString &itemKey) override; + PluginMode status() const override; + QString description() const override; + + QIcon icon(const DockPart &dockPart, int themeType) override; + PluginFlags flags() const override; }; #endif // HOMEMONITORPLUGIN_H @@ -299,6 +323,29 @@ QWidget *HomeMonitorPlugin::itemWidget(const QString &itemKey) // 但是不会有任何东西被添加到 dde-dock 上 return nullptr; } + + +QIcon HomeMonitorPlugin::icon(const DockPart &dockPart, int themeType) +{ + if (dockPart == DockPart::QuickShow) { + QIcon icon; + return icon; + } + + return QIcon(); +} + +PluginFlags HomeMonitorPlugin::flags() const +{ + // 返回的插件为Type_Common-快捷区域插件, Quick_Multi快捷插件显示两列的那种,例如网络和蓝牙 + // Attribute_CanDrag该插件在任务栏上支持拖动,Attribute_CanInsert该插件支持在其前面插入其他的图标 + // Attribute_CanSetting该插件支持在控制中心设置显示或隐藏 + return PluginFlags::Type_Common + | PluginFlags::Quick_Multi + | PluginFlags::Attribute_CanDrag + | PluginFlags::Attribute_CanInsert + | PluginFlags::Attribute_CanSetting; +} ``` ## 测试插件加载 @@ -499,20 +546,55 @@ void HomeMonitorPlugin::init(PluginProxyInterface *proxyInter) } ``` -在调用 `itemAdded` 之后,dde-dock 会在合适的时机调用插件的`itemWidget`接口以获取需要显示的控件。如果插件提供了多个主控件到 dde-dock 上,那么插件核心类应该在 itemWidget 接口中分析参数 itemKey,并返回与之对应的控件对象,当插件只有一个可显示项目时,itemKey 可以忽略 (但不建议忽略)。 +在调用 `itemAdded` 之后,dde-dock 会将该控件在任务栏插件区域显示出来,在展开快捷面板的时候,会将该插件的大图标显示在快捷面板上,快捷面板上显示的内容可以通过如下两种方式来显示 + +1、调用插件类的icon方法、status方法、description方法来获取插件的显示的图标、文本描述和状态等 + +```c++ +QIcon icon(const DockPart &dockPart, int themeType); +// 其中,判断dockPart==DockPart::QuickPanel,此时显示在快捷面板上面的图标,themeType表示主题类型,对应于dtk中的DGuiApplicationHelper::ColorType类型的枚举值,分别表示黑色或白色的主题,根据不同的主题返回不同的图标 +PluginMode status() const; +// 插件当前的状态,返回值为激活、禁用和没有激活状态,任务栏会根据这个值将图标自动变成不同的颜色 +QString description() const; +// 插件的描述,这个一般是在插件区域显示的文本,例如网络插件,这个返回当前连接的网络的名称等 + +// 在点击快捷面板的这个插件的图标的时候,会自动执行插件返回的命令字符串,见以下函数 +const QString itemCommand(const QString &itemKey); + +// 在插件需要改变图标或文字的时候,请调用PluginProxyInterface类的updateDockInfo方法,第一个参数传入this即可,如下 +void updateDockInfo(PluginsItemInterface *const, const DockPart &); +// updateDockInfo为代理类PluginProxyInterface的方法DockPart为需要刷新的位置 +``` + +2、第一个方法的灵活性不是太好,因此建议使用第二种方法 ``` c++ QWidget *HomeMonitorPlugin::itemWidget(const QString &itemKey) { - Q_UNUSED(itemKey); - - return m_pluginWidget; + if (itemKey == QUICK_ITEM_KEY) + return m_pluginWidget; + + return nullptr; } +判断itemKey == QUICK_ITEM_KEY(QUICK_ITEM_KEY为插件基类中定义的一个宏),返回在快捷面板区域的展示。一般在该插件需要在快捷面板区域响应复杂的操作,例如蓝牙插件或网络插件需要通过该面板进行开关等操作,此时建议用这种方法 ``` -现在再根据“测试插件加载”一节中的步骤,编译、安装、重启 dde-dock,就可以看到主控件在 dde-dock 面板上出现了,如下图所示: +任务栏使用哪种显示方式的逻辑是,先通过第一种方法中的获取图标的接口,判断是否存在图标,如果存在图标,就用第一种方法来显示,如果不存在,就用第二种方法来显示 -![central-widget](images/central-widget.png) +任务栏插件 图标的显示 + +在任务栏上不同的插件都会有自己的图标,在不同的主题下显示的图标也不相同,不同的位置显示的图标也会有所区别,因此我们需要实现如下的接口 + +```c++ +QIcon icon(const DockPart &dockPart, int themeType); +其中dockPart表示该插件图标所在的位置,有如下取值 +enum class DockPart { + QuickShow = 0, // 快捷插件显示区域 + QuickPanel, // 快捷面板的图标 + SystemPanel, // 系统插件显示区域(例如电源插件) + DCCSetting // 显示在控制中心个性化设置的图标 +}; +``` ## 支持禁用插件 @@ -578,12 +660,6 @@ void HomeMonitorPlugin::init(PluginProxyInterface *proxyInter) } ``` -重新编译、安装、重启 dde-dock,然后 dde-dock 面板上点击鼠标右键查看“插件”子菜单就会看到空白项,点击它将禁用插件,再次点击则启用插件。 - -不过为什么是空白项呢?是因为有一个接口还没有实现:pluginDisplayName - -在相应文件中分别添加如下内容,来修复这个问题: - ``` c++ // homemonitorplugin.h @@ -661,8 +737,6 @@ QWidget *HomeMonitorPlugin::itemTipsWidget(const QString &itemKey) dde-dock 在发现鼠标悬停在插件的控件上时就会调用这个接口拿到相应的控件并显示出来。 -![tips-widget](images/tips-widget.png) - ## 支持 applet 上面的 tips 显示的控件在鼠标移开之后就会消失,如果插件需要长时间显示一个窗体及时鼠标离开也会保持显示状态来做一些提示或功能的话那就需要使用 applet,applet 控件在左键点击后显示,点击控件以外的其他地方后消失。 @@ -699,6 +773,13 @@ void HomeMonitorPlugin::init(PluginProxyInterface *proxyInter) } ``` +如果需要点击快捷面板中的图标弹出applet,需要调用一下接口 + +```c++ +void requestSetAppletVisible(PluginsItemInterface * const itemInter, const QString &itemKey, const bool visible); +// 其中,itemInter传入this, itemKey在此处传入一个制定的字符串,那么在下方的itemPopupApplet接口的方法中就需要根据这个指定的itemKey返回对应的QWidget来显示,visible传true +``` + 接着实现 applet 相关的接口 itemPopupApplet: ``` c++ @@ -727,9 +808,7 @@ QWidget *HomeMonitorPlugin::itemPopupApplet(const QString &itemKey) } ``` -编译,安装,重启 dde-dock 之后点击主控件即可看到弹出的 applet 控件。 -![applet-widget](images/applet-widget.png) ## 支持右键菜单 @@ -790,6 +869,37 @@ void HomeMonitorPlugin::invokedMenuItem(const QString &itemKey, const QString &m 编译,安装,重启 dde-dock 之后右键点击主控件即可看到弹出右键菜单。 -![context-menu](images/context-menu.png) +## 插件类型和属性 + +在flag接口中返回当前插件的位置和属性的信息,实现如下接口 + +```c++ +PluginFlags HomeMonitorPlugin::flags() const; +{ + return PluginFlag::Type_Common + | Quick_Multi + | Attribute_CanDrag + | Attribute_CanInsert + | Attribute_CanSetting; +} +// 返回值有如下 +enum PluginFlag { + Type_NoneFlag = 0x1, // 插件类型-没有任何的属性,不在任何地方显示 + Type_Common = 0x2, // 插件类型-快捷插件区 + Type_Tool = 0x4, // 插件类型-工具插件,例如回收站 + Type_System = 0x8, // 插件类型-系统插件,例如关机插件 + Type_Tray = 0x10, // 插件类型-托盘区,例如U盘插件 + Type_Fixed = 0x20, // 插件类型-固定区域,例如多任务视图和显示桌面 + Quick_Single = 0x40, // 当插件类型为Common时,快捷插件区域只有一列的那种插件 + Quick_Multi = 0x80, // 当插件类型为Common时,快捷插件区占两列的那种插件 + Quick_Full = 0x100, // 当插件类型为Common时,快捷插件区占用4列的那种插件,例如声音、亮度设置和音乐等 + Attribute_CanDrag = 0x200, // 插件属性-是否支持拖动 + Attribute_CanInsert = 0x400, // 插件属性-是否支持在其前面插入其他的插件,普通的快捷插件是支持的 + Attribute_CanSetting = 0x800, // 插件属性-是否可以在控制中心设置显示或隐藏 + + FlagMask = 0xffffffff // 掩码 +}; +// 在此根据自己插件的类型返回相应的属性,这里可以是组合,但是插件类型的组合只能是其中的一种,快捷插件区域的显示列也只能是其中一种,插件的属性可以混合显示 +``` 至此,一个包含基本功能的插件就完成了。 diff --git a/plugins/pluginmanager/CMakeLists.txt b/plugins/pluginmanager/CMakeLists.txt new file mode 100644 index 000000000..1a7d5ab00 --- /dev/null +++ b/plugins/pluginmanager/CMakeLists.txt @@ -0,0 +1,45 @@ + +set(PLUGIN_NAME "pluginmanager") + +project(${PLUGIN_NAME}) + +# Sources files +file(GLOB_RECURSE SRCS "*.h" "*.cpp" "*.qrc" "../../frame/drag/quickdragcore.h" "../../frame/drag/quickdragcore.cpp" +"../../frame/util/settingconfig.h" "../../frame/util/settingconfig.cpp" +"../../frame/util/pluginloader.h" "../../frame/util/pluginloader.cpp" +"../../frame/dbus/dockinterface.h" "../../frame/dbus/dockinterface.cpp" +"../../frame/dbusinterface/generation_dbus_interface/org_deepin_dde_daemon_dock1.h" +"../../frame/dbusinterface/generation_dbus_interface/org_deepin_dde_daemon_dock1.cpp" +"../../frame/dbusinterface/types/dockrect.h" +"../../frame/dbusinterface/types/dockrect.cpp" +"../../interfaces/pluginmanagerinterface.h" +) + +find_package(PkgConfig REQUIRED) +find_package(Qt5Widgets REQUIRED) +find_package(Qt5Svg REQUIRED) +find_package(Qt5DBus REQUIRED) +find_package(DtkWidget REQUIRED) +pkg_check_modules(QGSettings REQUIRED gsettings-qt) + +add_library(${PLUGIN_NAME} SHARED ${SRCS}) +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../loader/) +target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} + ${Qt5DBus_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ./pluginadapter + ../../frame/drag + ../../frame/dbusinterface + ../../frame/dbusinterface/generation_dbus_interface/ + ../../interfaces + ) + +target_link_libraries(${PLUGIN_NAME} PRIVATE + ${DtkWidget_LIBRARIES} + ${Qt5Widgets_LIBRARIES} + ${Qt5Svg_LIBRARIES} + ${Qt5DBus_LIBRARIES} + ${QGSettings_LIBRARIES} +) + +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/loader) diff --git a/plugins/pluginmanager/dockplugincontroller.cpp b/plugins/pluginmanager/dockplugincontroller.cpp new file mode 100644 index 000000000..0c62c776c --- /dev/null +++ b/plugins/pluginmanager/dockplugincontroller.cpp @@ -0,0 +1,711 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dockplugincontroller.h" +#include "pluginsiteminterface.h" +#include "pluginsiteminterface_v20.h" +#include "pluginadapter.h" +#include "utils.h" +#include "settingconfig.h" + +#include +#include + +#include +#include +#include +#include + +#define PLUGININFO "pluginInfo" +#define DOCK_QUICK_PLUGINS "Dock_Quick_Plugins" + +static const QStringList CompatiblePluginApiList { + "1.1.1", + "1.2", + "1.2.1", + "1.2.2", + DOCK_PLUGIN_API_VERSION +}; + +class PluginInfo : public QObject +{ +public: + PluginInfo() : QObject(nullptr), m_loaded(false), m_visible(false) {} + bool m_loaded; + bool m_visible; + QString m_itemKey; +}; + +DockPluginController::DockPluginController(PluginProxyInterface *proxyInter, QObject *parent) + : QObject(parent) + , m_dbusDaemonInterface(QDBusConnection::sessionBus().interface()) + , m_dockDaemonInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this)) + , m_proxyInter(proxyInter) +{ + qApp->installEventFilter(this); + + refreshPluginSettings(); + + connect(SETTINGCONFIG, &SettingConfig::valueChanged, this, &DockPluginController::onConfigChanged); + connect(m_dockDaemonInter, &DockInter::PluginSettingsSynced, this, &DockPluginController::refreshPluginSettings, Qt::QueuedConnection); +} + +DockPluginController::~DockPluginController() +{ + for (auto inter : m_pluginsMap.keys()) { + delete m_pluginsMap.value(inter).value("pluginloader"); + m_pluginsMap[inter]["pluginloader"] = nullptr; + if (m_pluginsMap[inter].contains(PLUGININFO)) + m_pluginsMap[inter][PLUGININFO]->deleteLater(); + m_pluginsMap.remove(inter); + delete inter; + inter = nullptr; + } +} + +QList DockPluginController::plugins() const +{ + return m_pluginsMap.keys(); +} + +QList DockPluginController::pluginsInSetting() const +{ + // 插件有三种状态 + // 1、所有的插件,不管这个插件是否调用itemAdded方法,只要是通过dock加载的插件(换句话说,也就是在/lib/dde-dock/plugins目录下的插件) + // 2、在1的基础上,插件自身调用了itemAdded方法的插件,例如机器上没有蓝牙设备,那么蓝牙插件就不会调用itemAdded方法,这时候就不算 + // 3、在2的基础上,由控制中心来决定那些插件是否在任务栏显示的插件 + // 此处返回的是第二种插件 + QList settingPlugins; + QMap pluginSort; + for (auto it = m_pluginsMap.begin(); it != m_pluginsMap.end(); it++) { + PluginsItemInterface *plugin = it.key(); + qInfo() << plugin->pluginName(); + if (plugin->pluginDisplayName().isEmpty()) + continue; + + QMap pluginMap = it.value(); + // 如果不包含PLUGININFO这个key值,肯定是未加载 + if (!pluginMap.contains(PLUGININFO)) + continue; + + PluginInfo *pluginInfo = static_cast(pluginMap[PLUGININFO]); + if (!pluginInfo->m_loaded) + continue; + + // 这里只需要返回插件为可以在控制中心设置的插件 + if (!(plugin->flags() & PluginFlag::Attribute_CanSetting)) + continue; + + settingPlugins << plugin; + pluginSort[plugin] = plugin->itemSortKey(pluginInfo->m_itemKey); + } + + std::sort(settingPlugins.begin(), settingPlugins.end(), [ pluginSort ](PluginsItemInterface *plugin1, PluginsItemInterface *plugin2) { + return pluginSort[plugin1] < pluginSort[plugin2]; + }); + + return settingPlugins; +} + +QList DockPluginController::currentPlugins() const +{ + QList loadedPlugins; + + QMap pluginSortMap; + for (auto it = m_pluginsMap.begin(); it != m_pluginsMap.end(); it++) { + QMap objectMap = it.value(); + if (!objectMap.contains(PLUGININFO)) + continue; + + PluginInfo *pluginInfo = static_cast(objectMap[PLUGININFO]); + if (!pluginInfo->m_loaded) + continue; + + PluginsItemInterface *plugin = it.key(); + loadedPlugins << plugin; + pluginSortMap[plugin] = plugin->itemSortKey(pluginInfo->m_itemKey); + } + + std::sort(loadedPlugins.begin(), loadedPlugins.end(), [ pluginSortMap ](PluginsItemInterface *pluginItem1, PluginsItemInterface *pluginItem2) { + return pluginSortMap.value(pluginItem1) < pluginSortMap.value(pluginItem2); + }); + return loadedPlugins; +} + +void DockPluginController::saveValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant &value) +{ + savePluginValue(getPluginInterface(itemInter), key, value); +} + +const QVariant DockPluginController::getValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant &fallback) +{ + return getPluginValue(getPluginInterface(itemInter), key, fallback); +} + +void DockPluginController::removeValue(PluginsItemInterface *const itemInter, const QStringList &keyList) +{ + removePluginValue(getPluginInterface(itemInter), keyList); +} + +void DockPluginController::itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) +{ + PluginsItemInterface *pluginItem = getPluginInterface(itemInter); + + PluginAdapter *pluginAdapter = dynamic_cast(pluginItem); + if (pluginAdapter) { + // 如果该插件可以正常转换为PluginAdapter插件,表示当前插件是v20插件,为了兼容v20插件 + // 中获取ICON,因此,使用调用插件的itemWidget来截图的方式返回QIcon,所以此处传入itemKey + pluginAdapter->setItemKey(itemKey); + } + + // 如果是通过插件来调用m_proxyInter的 + PluginInfo *pluginInfo = nullptr; + QMap &interfaceData = m_pluginsMap[pluginItem]; + if (interfaceData.contains(PLUGININFO)) { + pluginInfo = static_cast(interfaceData[PLUGININFO]); + // 如果插件已经加载,则无需再次加载(此处保证插件出现重复调用itemAdded的情况) + if (pluginInfo->m_loaded) + return; + } else { + pluginInfo = new PluginInfo; + interfaceData[PLUGININFO] = pluginInfo; + } + pluginInfo->m_itemKey = itemKey; + pluginInfo->m_loaded = true; + + if (pluginCanDock(pluginItem)) + addPluginItem(pluginItem, itemKey); + + Q_EMIT pluginInserted(pluginItem, itemKey); +} + +void DockPluginController::itemUpdate(PluginsItemInterface * const itemInter, const QString &itemKey) +{ + m_proxyInter->itemUpdate(getPluginInterface(itemInter), itemKey); +} + +void DockPluginController::itemRemoved(PluginsItemInterface * const itemInter, const QString &itemKey) +{ + PluginsItemInterface *pluginInter = getPluginInterface(itemInter); + // 更新字段中的isLoaded字段,表示当前没有加载 + QMap &interfaceData = m_pluginsMap[pluginInter]; + if (interfaceData.contains(PLUGININFO)) { + PluginInfo *pluginInfo = static_cast(interfaceData[PLUGININFO]); + // 将是否加载的标记修改为未加载 + pluginInfo->m_loaded = false; + } + + removePluginItem(pluginInter, itemKey); + Q_EMIT pluginRemoved(pluginInter); +} + +void DockPluginController::requestWindowAutoHide(PluginsItemInterface * const itemInter, const QString &itemKey, const bool autoHide) +{ + m_proxyInter->requestWindowAutoHide(getPluginInterface(itemInter), itemKey, autoHide); +} + +void DockPluginController::requestRefreshWindowVisible(PluginsItemInterface * const itemInter, const QString &itemKey) +{ + m_proxyInter->requestRefreshWindowVisible(getPluginInterface(itemInter), itemKey); +} + +// 请求页面显示或者隐藏,由插件内部来调用,例如在移除蓝牙插件后,如果已经弹出了蓝牙插件的面板,则隐藏面板 +void DockPluginController::requestSetAppletVisible(PluginsItemInterface * const itemInter, const QString &itemKey, const bool visible) +{ + PluginsItemInterface *pluginInter = getPluginInterface(itemInter); + Q_EMIT requestAppletVisible(pluginInter, itemKey, visible); + m_proxyInter->requestSetAppletVisible(pluginInter, itemKey, visible); +} + +PluginsItemInterface *DockPluginController::getPluginInterface(PluginsItemInterface * const itemInter) +{ + // 先从事先定义好的map中查找,如果没有找到,就是v23插件,直接返回当前插件的指针 + qulonglong pluginAddr = (qulonglong)itemInter; + if (m_pluginAdapterMap.contains(pluginAddr)) + return m_pluginAdapterMap[pluginAddr]; + + return itemInter; +} + +void DockPluginController::addPluginItem(PluginsItemInterface * const itemInter, const QString &itemKey) +{ + // 如果这个插件都没有加载,那么此处肯定是无需新增 + if (!m_pluginsMap.contains(itemInter)) + return; + + PluginInfo *pluginInfo = nullptr; + QMap &interfaceData = m_pluginsMap[itemInter]; + // 此处的PLUGININFO的数据已经在前面调用的地方给填充了数据,如果没有获取到这个数据,则无需新增 + if (!interfaceData.contains(PLUGININFO)) + return; + + pluginInfo = static_cast(interfaceData[PLUGININFO]); + pluginInfo->m_visible = true; + + m_proxyInter->itemAdded(itemInter, itemKey); +} + +void DockPluginController::removePluginItem(PluginsItemInterface * const itemInter, const QString &itemKey) +{ + if (!m_pluginsMap.contains(itemInter)) + return; + + // 更新字段中的isLoaded字段,表示当前没有加载 + QMap &interfaceData = m_pluginsMap[itemInter]; + if (!interfaceData.contains(PLUGININFO)) + return; + + PluginInfo *pluginInfo = static_cast(interfaceData[PLUGININFO]); + // 将是否在任务栏显示的标记改为不显示 + pluginInfo->m_visible = false; + m_proxyInter->itemRemoved(itemInter, itemKey); +} + +QString DockPluginController::itemKey(PluginsItemInterface *itemInter) const +{ + if (!m_pluginsMap.contains(itemInter)) + return QString(); + + QMap interfaceData = m_pluginsMap[itemInter]; + if (!interfaceData.contains(PLUGININFO)) + return QString(); + + PluginInfo *pluginInfo = static_cast(interfaceData[PLUGININFO]); + return pluginInfo->m_itemKey; +} + +QJsonObject DockPluginController::metaData(PluginsItemInterface *pluginItem) +{ + if (!m_pluginsMap.contains(pluginItem)) + return QJsonObject(); + + QPluginLoader *pluginLoader = qobject_cast(m_pluginsMap[pluginItem].value("pluginloader")); + + if (!pluginLoader) + return QJsonObject(); + + return pluginLoader->metaData().value("MetaData").toObject(); +} + +void DockPluginController::savePluginValue(PluginsItemInterface * const itemInter, const QString &key, const QVariant &value) +{ + // is it necessary? + // refreshPluginSettings(); + + // save to local cache + QJsonObject localObject = m_pluginSettingsObject.value(itemInter->pluginName()).toObject(); + localObject.insert(key, QJsonValue::fromVariant(value)); //Note: QVariant::toJsonValue() not work in Qt 5.7 + + // save to daemon + QJsonObject remoteObject, remoteObjectInter; + remoteObjectInter.insert(key, QJsonValue::fromVariant(value)); //Note: QVariant::toJsonValue() not work in Qt 5.7 + remoteObject.insert(itemInter->pluginName(), remoteObjectInter); + + if (itemInter->type() == PluginsItemInterface::Fixed && key == "enable" && !value.toBool()) { + int fixedPluginCount = 0; + // 遍历FixPlugin插件个数 + for (auto it(m_pluginsMap.begin()); it != m_pluginsMap.end();) { + if (it.key()->type() == PluginsItemInterface::Fixed) { + fixedPluginCount++; + } + ++it; + } + // 修改插件的order值,位置为队尾 + QString name = localObject.keys().last(); + // 此次做一下判断,有可能初始数据不存在pos_*字段,会导致enable字段被修改。或者此处可以循环所有字段是否存在pos_开头的字段? + if (name != key) { + localObject.insert(name, QJsonValue::fromVariant(fixedPluginCount)); //Note: QVariant::toJsonValue() not work in Qt 5.7 + // daemon中同样修改 + remoteObjectInter.insert(name, QJsonValue::fromVariant(fixedPluginCount)); //Note: QVariant::toJsonValue() not work in Qt 5.7 + remoteObject.insert(itemInter->pluginName(), remoteObjectInter); + } + } + + m_pluginSettingsObject.insert(itemInter->pluginName(), localObject); + m_dockDaemonInter->MergePluginSettings(QJsonDocument(remoteObject).toJson(QJsonDocument::JsonFormat::Compact)); +} + +const QVariant DockPluginController::getPluginValue(PluginsItemInterface * const itemInter, const QString &key, const QVariant &fallback) +{ + // load from local cache + QVariant v = m_pluginSettingsObject.value(itemInter->pluginName()).toObject().value(key).toVariant(); + if (v.isNull() || !v.isValid()) { + v = fallback; + } + + return v; +} + +void DockPluginController::removePluginValue(PluginsItemInterface * const itemInter, const QStringList &keyList) +{ + if (keyList.isEmpty()) { + m_pluginSettingsObject.remove(itemInter->pluginName()); + } else { + QJsonObject localObject = m_pluginSettingsObject.value(itemInter->pluginName()).toObject(); + for (auto key : keyList) { + localObject.remove(key); + } + m_pluginSettingsObject.insert(itemInter->pluginName(), localObject); + } + + m_dockDaemonInter->RemovePluginSettings(itemInter->pluginName(), keyList); +} + +void DockPluginController::startLoadPlugin(const QStringList &dirs) +{ + QDir dir; + for (const QString &path : dirs) { + if (!dir.exists(path)) + continue; + + startLoader(new PluginLoader(path, this)); + } +} + +bool DockPluginController::isPluginLoaded(PluginsItemInterface *itemInter) +{ + if (!m_pluginsMap.contains(itemInter)) + return false; + + QMap pluginObject = m_pluginsMap.value(itemInter); + if (!pluginObject.contains(PLUGININFO)) + return false; + + PluginInfo *pluginInfo = static_cast(pluginObject.value(PLUGININFO)); + return pluginInfo->m_visible; +} + +QObject *DockPluginController::pluginItemAt(PluginsItemInterface *const itemInter, const QString &itemKey) const +{ + if (!m_pluginsMap.contains(itemInter)) + return nullptr; + + return m_pluginsMap[itemInter][itemKey]; +} + +PluginsItemInterface *DockPluginController::pluginInterAt(const QString &itemKey) +{ + QMapIterator> it(m_pluginsMap); + while (it.hasNext()) { + it.next(); + if (it.value().keys().contains(itemKey)) { + return it.key(); + } + } + + return nullptr; +} + +PluginsItemInterface *DockPluginController::pluginInterAt(QObject *destItem) +{ + QMapIterator> it(m_pluginsMap); + while (it.hasNext()) { + it.next(); + if (it.value().values().contains(destItem)) { + return it.key(); + } + } + + return nullptr; +} + +void DockPluginController::startLoader(PluginLoader *loader) +{ + connect(loader, &PluginLoader::finished, loader, &PluginLoader::deleteLater, Qt::QueuedConnection); + connect(loader, &PluginLoader::pluginFounded, this, [ = ](const QString &pluginFile) { + QPair pair; + pair.first = pluginFile; + pair.second = nullptr; + m_pluginLoadMap.insert(pair, false); + }); + connect(loader, &PluginLoader::pluginFounded, this, &DockPluginController::loadPlugin, Qt::QueuedConnection); + + int delay = Utils::SettingValue("com.deepin.dde.dock", "/com/deepin/dde/dock/", "delay-plugins-time", 0).toInt(); + QTimer::singleShot(delay, loader, [ = ] { loader->start(QThread::LowestPriority); }); +} + +void DockPluginController::displayModeChanged() +{ + const Dock::DisplayMode displayMode = qApp->property(PROP_DISPLAY_MODE).value(); + const auto inters = m_pluginsMap.keys(); + + for (auto inter : inters) + inter->displayModeChanged(displayMode); +} + +void DockPluginController::positionChanged() +{ + const Dock::Position position = qApp->property(PROP_POSITION).value(); + const auto inters = m_pluginsMap.keys(); + + for (auto inter : inters) + inter->positionChanged(position); +} + +void DockPluginController::loadPlugin(const QString &pluginFile) +{ + QPluginLoader *pluginLoader = new QPluginLoader(pluginFile, this); + const QJsonObject &meta = pluginLoader->metaData().value("MetaData").toObject(); + const QString &pluginApi = meta.value("api").toString(); + bool pluginIsValid = true; + if (pluginApi.isEmpty() || !CompatiblePluginApiList.contains(pluginApi)) { + qDebug() << objectName() + << "plugin api version not matched! expect versions:" << CompatiblePluginApiList + << ", got version:" << pluginApi + << ", the plugin file is:" << pluginFile; + + pluginIsValid = false; + } + + PluginsItemInterface *interface = qobject_cast(pluginLoader->instance()); + if (!interface) { + // 如果识别当前插件失败,就认为这个插件是v20的插件,将其转换为v20插件接口 + PluginsItemInterface_V20 *interface_v20 = qobject_cast(pluginLoader->instance()); + if (interface_v20) { + // 将v20插件接口通过适配器转换成v23的接口,方便在后面识别 + PluginAdapter *pluginAdapter = new PluginAdapter(interface_v20, pluginLoader); + // 将适配器的地址保存到map列表中,因为适配器自己会调用itemAdded方法,转换成PluginsItemInterface类,但是实际上它 + // 对应的是PluginAdapter类,因此,这个map用于在后面的itemAdded方法中用来查找 + m_pluginAdapterMap[(qulonglong)(interface_v20)] = pluginAdapter; + interface = pluginAdapter; + } + } + + if (!interface) { + qDebug() << objectName() << "load plugin failed!!!" << pluginLoader->errorString() << pluginFile; + + pluginLoader->unload(); + pluginLoader->deleteLater(); + + pluginIsValid = false; + } + + if (!pluginIsValid) { + for (auto &pair : m_pluginLoadMap.keys()) { + if (pair.first == pluginFile) { + m_pluginLoadMap.remove(pair); + } + } + QString notifyMessage(tr("The plugin %1 is not compatible with the system.")); + Dtk::Core::DUtil::DNotifySender(notifyMessage.arg(QFileInfo(pluginFile).fileName())).appIcon("dialog-warning").call(); + return; + } + + if (interface->pluginName() == "multitasking" && (Utils::IS_WAYLAND_DISPLAY || Dtk::Core::DSysInfo::deepinType() == Dtk::Core::DSysInfo::DeepinServer)) { + for (auto &pair : m_pluginLoadMap.keys()) { + if (pair.first == pluginFile) { + m_pluginLoadMap.remove(pair); + } + } + return; + } + + QMapIterator, bool> it(m_pluginLoadMap); + while (it.hasNext()) { + it.next(); + if (it.key().first == pluginFile) { + m_pluginLoadMap.remove(it.key()); + QPair newPair; + newPair.first = pluginFile; + newPair.second = interface; + m_pluginLoadMap.insert(newPair, false); + break; + } + } + + // 保存 PluginLoader 对象指针 + QMap interfaceData; + interfaceData["pluginloader"] = pluginLoader; + m_pluginsMap.insert(interface, interfaceData); + QString dbusService = meta.value("depends-daemon-dbus-service").toString(); + if (!dbusService.isEmpty() && !m_dbusDaemonInterface->isServiceRegistered(dbusService).value()) { + qDebug() << objectName() << dbusService << "daemon has not started, waiting for signal"; + connect(m_dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, + [ = ](const QString & name, const QString & oldOwner, const QString & newOwner) { + Q_UNUSED(oldOwner); + if (name == dbusService && !newOwner.isEmpty()) { + qDebug() << objectName() << dbusService << "daemon started, init plugin and disconnect"; + initPlugin(interface); + disconnect(m_dbusDaemonInterface); + } + } + ); + return; + } + + // NOTE(justforlxz): 插件的所有初始化工作都在init函数中进行, + // loadPlugin函数是按队列执行的,initPlugin函数会有可能导致 + // 函数执行被阻塞。 + QTimer::singleShot(1, this, [ = ] { + initPlugin(interface); + }); +} + +void DockPluginController::initPlugin(PluginsItemInterface *interface) +{ + if (!interface) + return; + + qDebug() << objectName() << "init plugin: " << interface->pluginName(); + interface->init(this); + + for (const auto &pair : m_pluginLoadMap.keys()) { + if (pair.second == interface) + m_pluginLoadMap.insert(pair, true); + } + + bool loaded = true; + for (int i = 0; i < m_pluginLoadMap.keys().size(); ++i) { + if (!m_pluginLoadMap.values()[i]) { + loaded = false; + break; + } + } + + // 插件全部加载完成 + if (loaded) { + emit pluginLoadFinished(); + } + qDebug() << objectName() << "init plugin finished: " << interface->pluginName(); +} + +void DockPluginController::refreshPluginSettings() +{ + const QString &pluginSettings = m_dockDaemonInter->GetPluginSettings().value(); + if (pluginSettings.isEmpty()) { + qDebug() << "Error! get plugin settings from dbus failed!"; + return; + } + + const QJsonObject &pluginSettingsObject = QJsonDocument::fromJson(pluginSettings.toLocal8Bit()).object(); + if (pluginSettingsObject.isEmpty()) { + return; + } + + // nothing changed + if (pluginSettingsObject == m_pluginSettingsObject) { + return; + } + + for (auto pluginsIt = pluginSettingsObject.constBegin(); pluginsIt != pluginSettingsObject.constEnd(); ++pluginsIt) { + const QString &pluginName = pluginsIt.key(); + const QJsonObject &settingsObject = pluginsIt.value().toObject(); + QJsonObject newSettingsObject = m_pluginSettingsObject.value(pluginName).toObject(); + for (auto settingsIt = settingsObject.constBegin(); settingsIt != settingsObject.constEnd(); ++settingsIt) { + newSettingsObject.insert(settingsIt.key(), settingsIt.value()); + } + // TODO: remove not exists key-values + m_pluginSettingsObject.insert(pluginName, newSettingsObject); + } + + // not notify plugins to refresh settings if this update is not emit by dock daemon + if (sender() != m_dockDaemonInter) { + return; + } + + // notify all plugins to reload plugin settings + for (PluginsItemInterface *pluginInter : m_pluginsMap.keys()) { + pluginInter->pluginSettingsChanged(); + } + + // reload all plugin items for sort order or container + QMap> pluginsMapTemp = m_pluginsMap; + for (auto it = pluginsMapTemp.constBegin(); it != pluginsMapTemp.constEnd(); ++it) { + const QList &itemKeyList = it.value().keys(); + for (auto key : itemKeyList) { + if (key != "pluginloader") { + itemRemoved(it.key(), key); + } + } + for (auto key : itemKeyList) { + if (key != "pluginloader") { + itemAdded(it.key(), key); + } + } + } +} + +bool DockPluginController::eventFilter(QObject *object, QEvent *event) +{ + if (object != qApp || event->type() != QEvent::DynamicPropertyChange) + return false; + + QDynamicPropertyChangeEvent *const dpce = static_cast(event); + const QString propertyName = dpce->propertyName(); + + if (propertyName == PROP_POSITION) + positionChanged(); + else if (propertyName == PROP_DISPLAY_MODE) + displayModeChanged(); + + return false; +} + +bool DockPluginController::pluginCanDock(PluginsItemInterface *plugin) const +{ + const QStringList configPlugins = SETTINGCONFIG->value(DOCK_QUICK_PLUGINS).toStringList(); + return pluginCanDock(configPlugins, plugin); +} + +bool DockPluginController::pluginCanDock(const QStringList &config, PluginsItemInterface *plugin) const +{ + // 1、如果插件是强制驻留任务栏,则始终显示 + // 2、如果插件是托盘插件,例如U盘插件,则始终显示 + if ((plugin->flags() & PluginFlag::Attribute_ForceDock) + || (plugin->flags() & PluginFlag::Type_Tray)) + return true; + + // 3、如果该插件并未加载(未调用itemAdde或已经调用itemRemoved),则该插件不显示 + if (!m_pluginsMap.contains(plugin)) + return false; + + const QMap &pluginMap = m_pluginsMap[plugin]; + // 如果不包含PLUGININFO,说明该插件从未调用itemAdded方法,无需加载 + if (!pluginMap.contains(PLUGININFO)) + return false; + + // 如果该插件信息的m_loaded为true,说明已经调用过itemAdded方法,并且之后又调用了itemRemoved方法,则插件也无需加载 + PluginInfo *pluginInfo = static_cast(pluginMap[PLUGININFO]); + if (!pluginInfo->m_loaded) + return false; + + // 4、插件已经驻留在任务栏,则始终显示 + return config.contains(plugin->pluginName()); +} + +void DockPluginController::updateDockInfo(PluginsItemInterface * const itemInter, const DockPart &part) +{ + m_proxyInter->updateDockInfo(itemInter, part); + Q_EMIT pluginUpdated(itemInter, part); +} + +void DockPluginController::onConfigChanged(const QString &key, const QVariant &value) +{ + if (key != DOCK_QUICK_PLUGINS) + return; + + QStringList pluginNames = value.toStringList(); + // 这里只处理工具插件(回收站)和系统插件(电源插件) + for (PluginsItemInterface *plugin : plugins()) { + QString itemKey = this->itemKey(plugin); + bool canDock = pluginCanDock(pluginNames, plugin); + if (!canDock && isPluginLoaded(plugin)) { + // 如果当前配置中不包含当前插件,但是当前插件已经加载,那么就移除该插件 + removePluginItem(plugin, itemKey); + QWidget *itemWidget = plugin->itemWidget(itemKey); + if (itemWidget) + itemWidget->setVisible(false); + } else if (canDock && !isPluginLoaded(plugin)) { + // 如果当前配置中包含当前插件,但是当前插件并未加载,那么就加载该插件 + addPluginItem(plugin, itemKey); + // 只有工具插件是通过QWidget的方式进行显示的,因此,这里只处理工具插件 + if (plugin->flags() & PluginFlag::Type_Tool) { + QWidget *itemWidget = plugin->itemWidget(itemKey); + if (itemWidget) + itemWidget->setVisible(true); + } + } + } +} diff --git a/plugins/pluginmanager/dockplugincontroller.h b/plugins/pluginmanager/dockplugincontroller.h new file mode 100644 index 000000000..d0e4bb3b2 --- /dev/null +++ b/plugins/pluginmanager/dockplugincontroller.h @@ -0,0 +1,101 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DOCKPLUGINCONTROLLER_H +#define DOCKPLUGINCONTROLLER_H + +#include "pluginproxyinterface.h" +#include "pluginloader.h" +#include "dbusutil.h" + +#include +#include +#include + +class PluginsItemInterface; +class PluginAdapter; + +class DockPluginController : public QObject, protected PluginProxyInterface +{ + Q_OBJECT + +public: + explicit DockPluginController(PluginProxyInterface *proxyInter, QObject *parent = Q_NULLPTR); + ~ DockPluginController() override; + + QList plugins() const; // 所有的插件 + QList pluginsInSetting() const; // 控制中心用于可以设置是否显示或隐藏的插件 + QList currentPlugins() const; // 当前使用的插件 + + QString itemKey(PluginsItemInterface *itemInter) const; + QJsonObject metaData(PluginsItemInterface *pluginItem); + + virtual void savePluginValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant &value); + virtual const QVariant getPluginValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant& fallback = QVariant()); + virtual void removePluginValue(PluginsItemInterface * const itemInter, const QStringList &keyList); + void startLoadPlugin(const QStringList &dirs); + +Q_SIGNALS: + void pluginLoadFinished(); + void pluginInserted(PluginsItemInterface *itemInter, QString); + void pluginRemoved(PluginsItemInterface *itemInter); + void pluginUpdated(PluginsItemInterface *, const DockPart); + void requestAppletVisible(PluginsItemInterface *, const QString &, bool); + +protected: + bool isPluginLoaded(PluginsItemInterface *itemInter); + + QObject *pluginItemAt(PluginsItemInterface * const itemInter, const QString &itemKey) const; + PluginsItemInterface *pluginInterAt(const QString &itemKey); + PluginsItemInterface *pluginInterAt(QObject *destItem); + bool eventFilter(QObject *object, QEvent *event) override; + + bool pluginCanDock(PluginsItemInterface *plugin) const; + bool pluginCanDock(const QStringList &config, PluginsItemInterface *plugin) const; + void updateDockInfo(PluginsItemInterface * const itemInter, const DockPart &part) override; + +private: + // implements PluginProxyInterface + void saveValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant &value) override; + const QVariant getValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant& fallback = QVariant()) override; + void removeValue(PluginsItemInterface * const itemInter, const QStringList &keyList) override; + + void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override; + void itemUpdate(PluginsItemInterface * const itemInter, const QString &itemKey) override; + void itemRemoved(PluginsItemInterface * const itemInter, const QString &itemKey) override; + void requestWindowAutoHide(PluginsItemInterface * const itemInter, const QString &itemKey, const bool autoHide) override; + void requestRefreshWindowVisible(PluginsItemInterface * const itemInter, const QString &itemKey) override; + void requestSetAppletVisible(PluginsItemInterface * const itemInter, const QString &itemKey, const bool visible) override; + PluginsItemInterface *getPluginInterface(PluginsItemInterface * const itemInter); + + void addPluginItem(PluginsItemInterface * const itemInter, const QString &itemKey); + void removePluginItem(PluginsItemInterface * const itemInter, const QString &itemKey); + +private Q_SLOTS: + void startLoader(PluginLoader *loader); + void displayModeChanged(); + void positionChanged(); + void loadPlugin(const QString &pluginFile); + void initPlugin(PluginsItemInterface *interface); + void refreshPluginSettings(); + void onConfigChanged(const QString &key, const QVariant &value); + +private: + QDBusConnectionInterface *m_dbusDaemonInterface; + DockInter *m_dockDaemonInter; + + // interface, "pluginloader", PluginLoader指针对象 + QMap> m_pluginsMap; + + // filepath, interface, loaded + QMap, bool> m_pluginLoadMap; + + QJsonObject m_pluginSettingsObject; + QMap m_pluginAdapterMap; + + PluginProxyInterface *m_proxyInter; +}; + +#endif // ABSTRACTPLUGINSCONTROLLER_H diff --git a/plugins/pluginmanager/iconmanager.cpp b/plugins/pluginmanager/iconmanager.cpp new file mode 100644 index 000000000..50871a2e3 --- /dev/null +++ b/plugins/pluginmanager/iconmanager.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2023 ~ 2023 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "iconmanager.h" +#include "dockplugincontroller.h" +#include "pluginsiteminterface.h" + +#include +#include +#include +#include + +#include +#include + +#define ITEMSPACE 6 +#define IMAGESIZE 12 +#define ITEMSIZE 18 +#define MINISIZE 1 +#define STARTPOS 2 + +DGUI_USE_NAMESPACE + +IconManager::IconManager(DockPluginController *pluginController, QObject *parent) + : QObject{parent} + , m_pluginController(pluginController) + , m_position(Dock::Position::Bottom) + , m_displayMode(Dock::DisplayMode::Efficient) +{ +} + +void IconManager::setPosition(Dock::Position position) +{ + m_position = position; +} + +void IconManager::setDisplayMode(Dock::DisplayMode displayMode) +{ + m_displayMode = displayMode; +} + +QPixmap IconManager::pixmap(DGuiApplicationHelper::ColorType colorType) const +{ + // 缺省图标 + QPixmap pixmap = QIcon::fromTheme("dock-control-panel").pixmap(ITEMSIZE, ITEMSIZE); + QColor foreColor = (colorType == DGuiApplicationHelper::ColorType::DarkType ? Qt::white : Qt::black); + foreColor.setAlphaF(0.8); + QPainter pa(&pixmap); + pa.setCompositionMode(QPainter::CompositionMode_SourceIn); + pa.fillRect(pixmap.rect(), foreColor); + return pixmap.scaled(pixmap.size() / qApp->devicePixelRatio()); +} + +PluginsItemInterface *IconManager::findPlugin(const QString &pluginName) const +{ + QList plugins = m_pluginController->currentPlugins(); + for (PluginsItemInterface *plugin : plugins) { + if (plugin->pluginName() == pluginName) + return plugin; + } + + return nullptr; +} diff --git a/plugins/pluginmanager/iconmanager.h b/plugins/pluginmanager/iconmanager.h new file mode 100644 index 000000000..1d7b6d286 --- /dev/null +++ b/plugins/pluginmanager/iconmanager.h @@ -0,0 +1,36 @@ +// Copyright (C) 2023 ~ 2023 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef ICONMANAGER_H +#define ICONMANAGER_H + +#include "pluginsiteminterface.h" + +#include +#include + +class DockPluginController; +class PluginsItemInterface; + +class IconManager : public QObject +{ + Q_OBJECT + +public: + explicit IconManager(DockPluginController *pluginController, QObject *parent = nullptr); + void setPosition(Dock::Position position); + void setDisplayMode(Dock::DisplayMode displayMode); + QPixmap pixmap(DGuiApplicationHelper::ColorType colorType) const; + +private: + PluginsItemInterface *findPlugin(const QString &pluginName) const; + +private: + DockPluginController *m_pluginController; + Dock::Position m_position; + Dock::DisplayMode m_displayMode; +}; + +#endif // ICONMANAGER_H diff --git a/plugins/pluginmanager/largerquickitem.cpp b/plugins/pluginmanager/largerquickitem.cpp new file mode 100644 index 000000000..97550c9f6 --- /dev/null +++ b/plugins/pluginmanager/largerquickitem.cpp @@ -0,0 +1,298 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "largerquickitem.h" +#include "pluginsiteminterface.h" + +#include +#include +#include + +#include +#include +#include + +#define BGSIZE 36 +#define ICONWIDTH 24 +#define ICONHEIGHT 24 + +DWIDGET_USE_NAMESPACE + +static QSize expandSize = QSize(20, 20); + +LargerQuickItem::LargerQuickItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent) + : QuickSettingItem(pluginInter, itemKey, parent) + , m_iconWidget(nullptr) + , m_nameLabel(nullptr) + , m_stateLabel(nullptr) + , m_itemWidgetParent(nullptr) +{ + initUi(); +} + +LargerQuickItem::~LargerQuickItem() +{ + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (itemWidget) + itemWidget->setParent(nullptr); +} + +void LargerQuickItem::doUpdate() +{ + if (m_iconWidget && m_nameLabel && m_stateLabel) { + m_iconWidget->update(); + m_nameLabel->setText(QFontMetrics(m_nameLabel->font()).elidedText(pluginItem()->pluginDisplayName(), Qt::TextElideMode::ElideRight, m_nameLabel->width())); + m_stateLabel->setText(QFontMetrics(m_stateLabel->font()).elidedText(pluginItem()->description(), Qt::TextElideMode::ElideRight, m_stateLabel->width())); + } else { + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (itemWidget) { + // 如果插件没有返回图标的显示,则获取插件的itemWidget + itemWidget->update(); + } + } +} + +void LargerQuickItem::detachPlugin() +{ + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (itemWidget && itemWidget->parentWidget() == this) + itemWidget->setParent(m_itemWidgetParent); +} + +QuickSettingItem::QuickItemStyle LargerQuickItem::type() const +{ + return QuickSettingItem::QuickItemStyle::Larger; +} + +bool LargerQuickItem::eventFilter(QObject *obj, QEvent *event) +{ + if (!m_iconWidget) + return QuickSettingItem::eventFilter(obj, event); + + switch (event->type()) { + case QEvent::MouseButtonRelease: { + if (obj->objectName() == "expandLabel") { + // 如果是鼠标的按下事件 + QWidget *widget = pluginItem()->itemPopupApplet(QUICK_ITEM_KEY); + if (widget) + Q_EMIT requestShowChildWidget(widget); + break; + } + if (obj == this) { + QStringList commandArgumend = pluginItem()->itemCommand(itemKey()).split(" "); + if (commandArgumend.size() == 0) + break; + + QString command = commandArgumend.first(); + commandArgumend.removeFirst(); + QProcess::startDetached(command, commandArgumend); + } + break; + } + case QEvent::Resize: { + QLabel *labelWidget = qobject_cast(obj); + if (!labelWidget) + break; + + if (labelWidget == m_nameLabel) { + labelWidget->setText(QFontMetrics(labelWidget->font()).elidedText(pluginItem()->pluginDisplayName(), Qt::TextElideMode::ElideRight, labelWidget->width())); + break; + } + if (labelWidget == m_stateLabel) { + labelWidget->setText(QFontMetrics(labelWidget->font()).elidedText(pluginItem()->description(), Qt::TextElideMode::ElideRight, labelWidget->width())); + } + break; + } + default: + break; + } + + return QuickSettingItem::eventFilter(obj, event); +} + +void LargerQuickItem::showEvent(QShowEvent *event) +{ + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (pluginItem()->icon(DockPart::QuickPanel).isNull() && itemWidget) { + itemWidget->setParent(this); + itemWidget->setVisible(true); + } +} + +void LargerQuickItem::resizeEvent(QResizeEvent *event) +{ + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (pluginItem()->icon(DockPart::QuickPanel).isNull() && itemWidget) { + itemWidget->setFixedSize(size()); + } + + QuickSettingItem::resizeEvent(event); +} + +void LargerQuickItem::initUi() +{ + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (pluginItem()->icon(DockPart::QuickPanel).isNull() && itemWidget) { + m_itemWidgetParent = itemWidget->parentWidget(); + // 如果插件没有返回图标的显示,则获取插件的itemWidget + QHBoxLayout *mainLayout = new QHBoxLayout(this); + itemWidget->setParent(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addWidget(itemWidget); + itemWidget->setVisible(true); + } else { + // 如果插件获取到插件区域的图标,则让其按照图标来组合显示 + // 如果是占用两排的插件,则用横向Layout + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(10, 0, 10, 0); + mainLayout->setSpacing(0); + mainLayout->addStretch(10); + mainLayout->setAlignment(Qt::AlignCenter); + + // 添加图标 + QWidget *iconWidgetParent = new QWidget(this); + QVBoxLayout *iconLayout = new QVBoxLayout(iconWidgetParent); + iconLayout->setContentsMargins(0, 0, 0, 0); + iconLayout->setSpacing(0); + iconLayout->setAlignment(Qt::AlignCenter); + + m_iconWidget = new QuickIconWidget(pluginItem(), itemKey(), iconWidgetParent); + m_iconWidget->setFixedSize(BGSIZE, BGSIZE); + iconLayout->addWidget(m_iconWidget); + mainLayout->addWidget(iconWidgetParent); + mainLayout->addSpacing(10); + + // 添加中间的名称部分 + QWidget *textWidget = new QWidget(this); + m_nameLabel = new QLabel(textWidget); + m_stateLabel = new QLabel(textWidget); + m_nameLabel->setObjectName("nameLabel"); + m_stateLabel->setObjectName("stateLabel"); + + // 设置图标和文字的属性 + QFont nameFont = DFontSizeManager::instance()->t6(); + nameFont.setBold(true); + QPalette pe; + pe.setColor(QPalette::WindowText, Qt::black); + m_nameLabel->setPalette(pe); + m_stateLabel->setPalette(pe); + m_nameLabel->setFont(nameFont); + m_stateLabel->setFont(DFontSizeManager::instance()->t10()); + m_nameLabel->setText(pluginItem()->pluginDisplayName()); + m_stateLabel->setText(pluginItem()->description()); + m_nameLabel->installEventFilter(this); + m_stateLabel->installEventFilter(this); + + QVBoxLayout *textLayout = new QVBoxLayout(textWidget); + textLayout->setContentsMargins(0, 0, 0, 0); + textLayout->setSpacing(0); + textLayout->addWidget(m_nameLabel); + textLayout->addWidget(m_stateLabel); + textLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + mainLayout->addWidget(textWidget); + + // 添加右侧的展开按钮 + QWidget *expandWidgetParent = new QWidget(this); + QVBoxLayout *expandLayout = new QVBoxLayout(expandWidgetParent); + expandLayout->setSpacing(0); + QLabel *expandLabel = new QLabel(expandWidgetParent); + expandLabel->setObjectName("expandLabel"); + expandLabel->setPixmap(QPixmap(expandFileName())); + expandLabel->setFixedSize(expandSize); + expandLabel->setAutoFillBackground(true); + expandLabel->installEventFilter(this); + expandLayout->addWidget(expandLabel); + pe.setBrush(QPalette::Window, Qt::transparent); + expandLabel->setPalette(pe); + mainLayout->addWidget(expandWidgetParent); + } +} + +QString LargerQuickItem::expandFileName() const +{ + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) + return QString(":/icons/resources/arrow-right-dark.svg"); + + return QString(":/icons/resources/arrow-right.svg"); +} + +/** + * @brief QuickIconWidget::QuickIconWidget + * @param pluginInter + * @param parent + * 图标的widget + */ +QuickIconWidget::QuickIconWidget(PluginsItemInterface *pluginInter, const QString &itemKey, QWidget *parent) + : QWidget(parent) + , m_pluginInter(pluginInter) + , m_itemKey(itemKey) +{ +} + +void QuickIconWidget::paintEvent(QPaintEvent *event) +{ + QPixmap pixmapIcon = pluginIcon(); + if (pixmapIcon.isNull()) + return QWidget::paintEvent(event); + + pixmapIcon = pluginIcon(true); + QPainter painter(this); + painter.setRenderHint(QPainter::RenderHint::Antialiasing); + painter.setPen(foregroundColor()); + + DPalette dpa = DPaletteHelper::instance()->palette(this); + QPainter pa(&pixmapIcon); + pa.setCompositionMode(QPainter::CompositionMode_SourceIn); + pa.fillRect(pixmapIcon.rect(), painter.pen().brush()); + // 如果是主图标,则显示阴影背景 + painter.save(); + painter.setPen(Qt::NoPen); + painter.setBrush(dpa.brush(DPalette::ColorRole::Midlight)); + painter.drawEllipse(rect()); + painter.restore(); + QRect rctIcon((rect().width() - pixmapIcon.width()) / 2, (rect().height() - pixmapIcon.height()) / 2, pixmapIcon.width(), pixmapIcon.height()); + painter.drawPixmap(rctIcon, pixmapIcon); +} + +QColor QuickIconWidget::foregroundColor() const +{ + DPalette dpa = DPaletteHelper::instance()->palette(this); + // TODO 此处的颜色是临时获取的,后期需要和设计师确认,改成正规的颜色 + if (m_pluginInter->status() == PluginsItemInterface::PluginMode::Active) + return dpa.color(DPalette::ColorGroup::Active, DPalette::ColorRole::Text); + + if (m_pluginInter->status() == PluginsItemInterface::PluginMode::Deactive) + return dpa.color(DPalette::ColorGroup::Disabled, DPalette::ColorRole::Text); + + return dpa.color(DPalette::ColorGroup::Normal, DPalette::ColorRole::Text); +} + +QPixmap QuickIconWidget::pluginIcon(bool contailGrab) const +{ + QIcon icon = m_pluginInter->icon(DockPart::QuickPanel); + if (icon.isNull() && contailGrab) { + // 如果图标为空,就使用itemWidget的截图作为它的图标,这种一般是适用于老版本插件或者没有实现v23接口的插件 + QWidget *itemWidget = m_pluginInter->itemWidget(m_itemKey); + if (itemWidget) { + itemWidget->setFixedSize(ICONWIDTH, ICONHEIGHT); + return itemWidget->grab(); + } + return QPixmap(); + } + + // 获取icon接口返回的图标 + int pixmapWidth = width(); + int pixmapHeight = height(); + QList iconSizes = icon.availableSizes(); + if (iconSizes.size() > 0) { + QSize size = iconSizes[0]; + if (size.isValid() && !size.isEmpty() && !size.isNull()) { + pixmapWidth = size.width(); + pixmapHeight = size.height(); + } + } + + return icon.pixmap(pixmapWidth, pixmapHeight); +} diff --git a/plugins/pluginmanager/largerquickitem.h b/plugins/pluginmanager/largerquickitem.h new file mode 100644 index 000000000..c99dc8b30 --- /dev/null +++ b/plugins/pluginmanager/largerquickitem.h @@ -0,0 +1,67 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef LARGERQUICKITEM_H +#define LARGERQUICKITEM_H + +#include + +class QuickIconWidget; +class QWidget; +class QLabel; + +// 插件在快捷面板中的展示样式,这个为大图标,展示为两列的那种,例如网络和蓝牙 +class LargerQuickItem : public QuickSettingItem +{ + Q_OBJECT + +public: + LargerQuickItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent = nullptr); + ~LargerQuickItem() override; + void doUpdate() override; + void detachPlugin() override; + + QuickItemStyle type() const override; + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + void showEvent(QShowEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private: + void initUi(); + QString expandFileName() const; + +private: + QuickIconWidget *m_iconWidget; + QLabel *m_nameLabel; + QLabel *m_stateLabel; + QWidget *m_itemWidgetParent; +}; + +/** + * @brief The QuickIconWidget class + * 图标的Widget + */ +class QuickIconWidget : public QWidget +{ + Q_OBJECT + +public: + explicit QuickIconWidget(PluginsItemInterface *pluginInter, const QString &itemKey, QWidget *parent = Q_NULLPTR); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QColor foregroundColor() const; + QPixmap pluginIcon(bool contailGrab = false) const; + +private: + PluginsItemInterface *m_pluginInter; + QString m_itemKey; +}; + +#endif // MULTIQUICKITEM_H diff --git a/plugins/pluginmanager/linequickitem.cpp b/plugins/pluginmanager/linequickitem.cpp new file mode 100644 index 000000000..a538ce6c0 --- /dev/null +++ b/plugins/pluginmanager/linequickitem.cpp @@ -0,0 +1,101 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "linequickitem.h" +#include "pluginsiteminterface.h" + +#include + +#include + +DWIDGET_USE_NAMESPACE + +LineQuickItem::LineQuickItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent) + : QuickSettingItem(pluginInter, itemKey, parent) + , m_centerWidget(pluginInter->itemWidget(QUICK_ITEM_KEY)) + , m_centerParentWidget(nullptr) + , m_effectWidget(new DBlurEffectWidget(this)) +{ + initUi(); + initConnection(); + QMetaObject::invokeMethod(this, &LineQuickItem::resizeSelf, Qt::QueuedConnection); +} + +LineQuickItem::~LineQuickItem() +{ + if (m_centerWidget) + m_centerWidget->setParent(nullptr); +} + +void LineQuickItem::doUpdate() +{ + if (m_centerWidget) + m_centerWidget->update(); +} + +void LineQuickItem::detachPlugin() +{ + if (m_centerWidget) + m_centerWidget->setParent(m_centerParentWidget); +} + +QuickSettingItem::QuickItemStyle LineQuickItem::type() const +{ + return QuickSettingItem::QuickItemStyle::Line; +} + +bool LineQuickItem::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_centerWidget && event->type() == QEvent::Resize) + resizeSelf(); + + return QuickSettingItem::eventFilter(obj, event); +} + +void LineQuickItem::initUi() +{ + m_effectWidget->setBlurRectXRadius(8); + m_effectWidget->setBlurRectYRadius(8); + onThemeTypeChanged(DGuiApplicationHelper::instance()->themeType()); + + // 如果图标不为空 + if (!m_centerWidget) + return; + + m_centerWidget->setVisible(true); + m_centerParentWidget = m_centerWidget->parentWidget(); + + QHBoxLayout *layout = new QHBoxLayout(m_effectWidget); + layout->setContentsMargins(0, 0, 0, 0); + layout->setAlignment(Qt::AlignHCenter); + layout->addWidget(m_centerWidget); + + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addWidget(m_effectWidget); + + m_centerWidget->installEventFilter(this); +} + +void LineQuickItem::initConnection() +{ + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &LineQuickItem::onThemeTypeChanged); +} + +void LineQuickItem::resizeSelf() +{ + if (!m_centerWidget) + return; + + m_effectWidget->setFixedHeight(m_centerWidget->height()); + setFixedHeight(m_centerWidget->height()); +} + +void LineQuickItem::onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType) +{ + QColor maskColor = themeType == DGuiApplicationHelper::ColorType::LightType ? Qt::white : Qt::black; + maskColor.setAlphaF(themeType == DGuiApplicationHelper::ColorType::LightType ? 0.8 : 0.5); + m_effectWidget->setMaskColor(maskColor); +} diff --git a/plugins/pluginmanager/linequickitem.h b/plugins/pluginmanager/linequickitem.h new file mode 100644 index 000000000..c37b978e2 --- /dev/null +++ b/plugins/pluginmanager/linequickitem.h @@ -0,0 +1,51 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef LINEQUICKITEM_H +#define LINEQUICKITEM_H + +#include "quicksettingitem.h" + +#include + +namespace Dtk { +namespace Widget { +class DBlurEffectWidget; +} +} + +DGUI_USE_NAMESPACE + +// 插件在快捷面板中的展示的样式,这个为整行显示的插件,例如声音,亮度调整和音乐播放等 +class LineQuickItem : public QuickSettingItem +{ + Q_OBJECT + +public: + LineQuickItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent = nullptr); + ~LineQuickItem() override; + void doUpdate() override; + void detachPlugin() override; + + QuickItemStyle type() const override; + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +private: + void initUi(); + void initConnection(); + void resizeSelf(); + +private Q_SLOTS: + void onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType); + +private: + QWidget *m_centerWidget; + QWidget *m_centerParentWidget; + Dtk::Widget::DBlurEffectWidget *m_effectWidget; +}; + +#endif // FULLQUICKITEM_H diff --git a/plugins/pluginmanager/pluginadapter/pluginadapter.cpp b/plugins/pluginmanager/pluginadapter/pluginadapter.cpp new file mode 100644 index 000000000..a6505f324 --- /dev/null +++ b/plugins/pluginmanager/pluginadapter/pluginadapter.cpp @@ -0,0 +1,194 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "pluginadapter.h" + +#include + +#define ICONWIDTH 24 +#define ICONHEIGHT 24 + +PluginAdapter::PluginAdapter(PluginsItemInterface_V20 *pluginInter, QPluginLoader *pluginLoader) + : m_pluginInter(pluginInter) + , m_pluginLoader(pluginLoader) +{ +} + +PluginAdapter::~PluginAdapter() +{ + delete m_pluginInter; +} + +const QString PluginAdapter::pluginName() const +{ + return m_pluginInter->pluginName(); +} + +const QString PluginAdapter::pluginDisplayName() const +{ + return m_pluginInter->pluginDisplayName(); +} + +void PluginAdapter::init(PluginProxyInterface *proxyInter) +{ + m_pluginInter->init(proxyInter); +} + +QWidget *PluginAdapter::itemWidget(const QString &itemKey) +{ + return m_pluginInter->itemWidget(itemKey); +} + +QWidget *PluginAdapter::itemTipsWidget(const QString &itemKey) +{ + return m_pluginInter->itemTipsWidget(itemKey); +} + +QWidget *PluginAdapter::itemPopupApplet(const QString &itemKey) +{ + return m_pluginInter->itemPopupApplet(itemKey); +} + +const QString PluginAdapter::itemCommand(const QString &itemKey) +{ + return m_pluginInter->itemCommand(itemKey); +} + +const QString PluginAdapter::itemContextMenu(const QString &itemKey) +{ + return m_pluginInter->itemContextMenu(itemKey); +} + +void PluginAdapter::invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) +{ + m_pluginInter->invokedMenuItem(itemKey, menuId, checked); +} + +int PluginAdapter::itemSortKey(const QString &itemKey) +{ + return m_pluginInter->itemSortKey(itemKey); +} + +void PluginAdapter::setSortKey(const QString &itemKey, const int order) +{ + m_pluginInter->setSortKey(itemKey, order); +} + +bool PluginAdapter::itemAllowContainer(const QString &itemKey) +{ + return m_pluginInter->itemAllowContainer(itemKey); +} + +bool PluginAdapter::itemIsInContainer(const QString &itemKey) +{ + return m_pluginInter->itemIsInContainer(itemKey); +} + +void PluginAdapter::setItemIsInContainer(const QString &itemKey, const bool container) +{ + m_pluginInter->setItemIsInContainer(itemKey, container); +} + +bool PluginAdapter::pluginIsAllowDisable() +{ + return m_pluginInter->pluginIsAllowDisable(); +} + +bool PluginAdapter::pluginIsDisable() +{ + return m_pluginInter->pluginIsDisable(); +} + +void PluginAdapter::pluginStateSwitched() +{ + m_pluginInter->pluginStateSwitched(); +} + +void PluginAdapter::displayModeChanged(const Dock::DisplayMode displayMode) +{ + m_pluginInter->displayModeChanged(displayMode); +} + +void PluginAdapter::positionChanged(const Dock::Position position) +{ + m_pluginInter->positionChanged(position); +} + +void PluginAdapter::refreshIcon(const QString &itemKey) +{ + m_pluginInter->refreshIcon(itemKey); +} + +void PluginAdapter::pluginSettingsChanged() +{ + m_pluginInter->pluginSettingsChanged(); +} + +PluginsItemInterface::PluginType PluginAdapter::type() +{ + switch (m_pluginInter->type()) { + case PluginsItemInterface_V20::PluginType::Fixed: + return PluginsItemInterface::PluginType::Fixed; + case PluginsItemInterface_V20::PluginType::Normal: + return PluginsItemInterface::PluginType::Normal; + } + return PluginsItemInterface::PluginType::Normal; +} + +PluginsItemInterface::PluginSizePolicy PluginAdapter::pluginSizePolicy() const +{ + switch (m_pluginInter->pluginSizePolicy()) { + case PluginsItemInterface_V20::PluginSizePolicy::Custom: + return PluginsItemInterface::PluginSizePolicy::Custom; + case PluginsItemInterface_V20::PluginSizePolicy::System: + return PluginsItemInterface::PluginSizePolicy::System; + } + return PluginsItemInterface::PluginSizePolicy::Custom; +} + +QIcon PluginAdapter::icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) +{ + QWidget *itemWidget = m_pluginInter->itemWidget(m_itemKey); + if (!itemWidget) + return QIcon(); + + switch (dockPart) { + case DockPart::QuickPanel: + case DockPart::SystemPanel: { + // 如果图标为空,就使用itemWidget的截图作为它的图标,这种一般是适用于老版本插件或者没有实现v23接口的插件 + QSize oldSize = itemWidget->size(); + itemWidget->setFixedSize(ICONWIDTH, ICONHEIGHT); + QPixmap pixmap = itemWidget->grab(); + itemWidget->setFixedSize(oldSize); + return pixmap; + } + default: break; + } + + return QIcon(); +} + +PluginsItemInterface::PluginMode PluginAdapter::status() const +{ + return PluginMode::Active; +} + +QString PluginAdapter::description() const +{ + return m_pluginInter->pluginDisplayName(); +} + +PluginFlags PluginAdapter::flags() const +{ + if (m_pluginLoader->fileName().contains(TRAY_PATH)) + return PluginFlag::Type_Tray | PluginFlag::Attribute_CanDrag | PluginFlag::Attribute_CanInsert; + + return PluginsItemInterface::flags(); +} + +void PluginAdapter::setItemKey(const QString &itemKey) +{ + m_itemKey = itemKey; +} diff --git a/plugins/pluginmanager/pluginadapter/pluginadapter.h b/plugins/pluginmanager/pluginadapter/pluginadapter.h new file mode 100644 index 000000000..4279cc4ab --- /dev/null +++ b/plugins/pluginmanager/pluginadapter/pluginadapter.h @@ -0,0 +1,66 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef PLUGINADAPTER_H +#define PLUGINADAPTER_H + +#include "pluginsiteminterface.h" +#include "pluginsiteminterface_v20.h" + +#include + +/** 适配器,当加载到v20插件的时候,通过该接口来转成v23接口的插件 + * @brief The PluginAdapter class + */ + +class PluginAdapter : public QObject, public PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + +public: + PluginAdapter(PluginsItemInterface_V20 *pluginInter, QPluginLoader *pluginLoader); + ~PluginAdapter(); + + const QString pluginName() const override; + const QString pluginDisplayName() const override; + void init(PluginProxyInterface *proxyInter) override; + QWidget *itemWidget(const QString &itemKey) override; + + QWidget *itemTipsWidget(const QString &itemKey) override; + QWidget *itemPopupApplet(const QString &itemKey) override; + const QString itemCommand(const QString &itemKey) override; + const QString itemContextMenu(const QString &itemKey) override; + void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) override; + int itemSortKey(const QString &itemKey) override; + void setSortKey(const QString &itemKey, const int order) override; + bool itemAllowContainer(const QString &itemKey) override; + bool itemIsInContainer(const QString &itemKey) override; + void setItemIsInContainer(const QString &itemKey, const bool container) override; + + bool pluginIsAllowDisable() override; + bool pluginIsDisable() override; + void pluginStateSwitched() override; + void displayModeChanged(const Dock::DisplayMode displayMode) override; + void positionChanged(const Dock::Position position) override; + void refreshIcon(const QString &itemKey) override; + void pluginSettingsChanged() override; + PluginType type() override; + PluginSizePolicy pluginSizePolicy() const override; + + QIcon icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType = DGuiApplicationHelper::instance()->themeType()) override; + PluginMode status() const override; + QString description() const override; + PluginFlags flags() const override; + + void setItemKey(const QString &itemKey); + +private: + PluginsItemInterface_V20 *m_pluginInter; + QString m_itemKey; + QPluginLoader *m_pluginLoader; +}; + +#endif // PLUGINADAPTER_H diff --git a/plugins/pluginmanager/pluginadapter/pluginsiteminterface_v20.h b/plugins/pluginmanager/pluginadapter/pluginsiteminterface_v20.h new file mode 100644 index 000000000..885f826e4 --- /dev/null +++ b/plugins/pluginmanager/pluginadapter/pluginsiteminterface_v20.h @@ -0,0 +1,245 @@ +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef PLUGINSITEMINTERFACE_V20_H +#define PLUGINSITEMINTERFACE_V20_H + +#include "pluginproxyinterface.h" + +#include +#include + +/// +/// \brief The PluginsItemInterface_V20 class +/// the dock plugins item interface, all dock plugins should +/// inheirt this class and override all pure virtual function. +/// +class PluginsItemInterface_V20 +{ +public: + enum PluginType { + Normal, + Fixed + }; + + /** + * @brief Plugin size policy + */ + enum PluginSizePolicy { + System = 1 << 0, // Follow the system + Custom = 1 << 1 // The custom + }; + + /// + /// \brief ~PluginsItemInterface_V20 + /// DON'T try to delete m_proxyInter. + /// + virtual ~PluginsItemInterface_V20() {} + + /// + /// \brief pluginName + /// tell dock the unique plugin id + /// \return + /// + virtual const QString pluginName() const = 0; + virtual const QString pluginDisplayName() const { return QString(); } + + /// + /// \brief init + /// init your plugins, you need to save proxyInter to m_proxyInter + /// member variable. but you shouldn't free this pointer. + /// \param proxyInter + /// DON'T try to delete this pointer. + /// + virtual void init(PluginProxyInterface *proxyInter) = 0; + /// + /// \brief itemWidget + /// your plugin item widget, each item should have a unique key. + /// \param itemKey + /// your widget' unqiue key. + /// \return + /// + virtual QWidget *itemWidget(const QString &itemKey) = 0; + + /// + /// \brief itemTipsWidget + /// override this function if your item want to have a tips. + /// the tips will shown when user hover your item. + /// nullptr will be ignored. + /// \param itemKey + /// \return + /// + virtual QWidget *itemTipsWidget(const QString &itemKey) {Q_UNUSED(itemKey); return nullptr;} + /// + /// \brief itemPopupApplet + /// override this function if your item wants to have an popup applet. + /// the popup applet will shown when user click your item. + /// + /// Tips: + /// dock should receive mouse press/release event to check user mouse operate, + /// if your item filter mouse event, this function will not be called. + /// so if you override mouse event and want to use popup applet, you + /// should pass event to your parent use QWidget::someEvent(e); + /// \param itemKey + /// \return + /// + virtual QWidget *itemPopupApplet(const QString &itemKey) {Q_UNUSED(itemKey); return nullptr;} + /// + /// \brief itemCommand + /// execute spec command when user clicked your item. + /// ensure your command do not get user input. + /// + /// empty string will be ignored. + /// \param itemKey + /// \return + /// + virtual const QString itemCommand(const QString &itemKey) {Q_UNUSED(itemKey); return QString();} + + /// + /// \brief itemContextMenu + /// context menu is shown when RequestPopupMenu called. + /// \param itemKey + /// \return + /// + virtual const QString itemContextMenu(const QString &itemKey) {Q_UNUSED(itemKey); return QString();} + /// + /// \brief invokedMenuItem + /// call if context menu item is clicked + /// \param itemKey + /// \param itemId + /// menu item id + /// \param checked + /// + virtual void invokedMenuItem(const QString &itemKey, const QString &menuId, const bool checked) {Q_UNUSED(itemKey); Q_UNUSED(menuId); Q_UNUSED(checked);} + + /// + /// \brief itemSortKey + /// tell dock where your item wants to put on. + /// + /// this index is start from 1 and + /// 0 for left side + /// -1 for right side + /// \param itemKey + /// \return + /// + virtual int itemSortKey(const QString &itemKey) {Q_UNUSED(itemKey); return 1;} + /// + /// \brief setSortKey + /// save your item new position + /// sort key will be changed when plugins order + /// changed(by user drag-drop) + /// \param itemKey + /// \param order + /// + virtual void setSortKey(const QString &itemKey, const int order) {Q_UNUSED(itemKey); Q_UNUSED(order);} + + /// + /// \brief itemAllowContainer + /// tell dock is your item allow to move into container + /// + /// if your item placed into container, popup tips and popup + /// applet will be disabled. + /// \param itemKey + /// \return + /// + virtual bool itemAllowContainer(const QString &itemKey) {Q_UNUSED(itemKey); return false;} + /// + /// \brief itemIsInContainer + /// tell dock your item is in container, this function + /// called at item init and if your item enable container. + /// \param itemKey + /// \return + /// + virtual bool itemIsInContainer(const QString &itemKey) {Q_UNUSED(itemKey); return false;} + /// + /// \brief setItemIsInContainer + /// save your item new state. + /// this function called when user drag out your item from + /// container or user drop item into container(if your item + /// allow drop into container). + /// \param itemKey + /// \param container + /// + virtual void setItemIsInContainer(const QString &itemKey, const bool container) {Q_UNUSED(itemKey); Q_UNUSED(container);} + + virtual bool pluginIsAllowDisable() { return false; } + virtual bool pluginIsDisable() { return false; } + virtual void pluginStateSwitched() {} + + /// + /// \brief displayModeChanged + /// override this function to receive display mode changed signal + /// \param displayMode + /// + virtual void displayModeChanged(const Dock::DisplayMode displayMode) {Q_UNUSED(displayMode);} + /// + /// \brief positionChanged + /// override this function to receive dock position changed signal + /// \param position + /// + virtual void positionChanged(const Dock::Position position) {Q_UNUSED(position);} + + /// + /// \brief refreshIcon + /// refresh item icon, its triggered when system icon theme changed. + /// \param itemKey + /// item key + /// + virtual void refreshIcon(const QString &itemKey) { Q_UNUSED(itemKey); } + + /// + /// \brief displayMode + /// get current dock display mode + /// \return + /// + inline Dock::DisplayMode displayMode() const + { + return qApp->property(PROP_DISPLAY_MODE).value(); + } + + /// + /// \brief position + /// get current dock position + /// \return + /// + inline Dock::Position position() const + { + return qApp->property(PROP_POSITION).value(); + } + + /// + /// \brief settingsChanged + /// override this function to receive plugin settings changed signal(DeepinSync) + /// + virtual void pluginSettingsChanged() {} + + /// + /// \brief type + /// default plugin add dock right,fixed plugin add to dock fixed area + /// + virtual PluginType type() { return Normal; } + + /// + /// \brief plugin size policy + /// default plugin size policy + /// + virtual PluginSizePolicy pluginSizePolicy() const { return System; } + +protected: + /// + /// \brief m_proxyInter + /// NEVER delete this object. + /// + PluginProxyInterface *m_proxyInter = nullptr; +}; + +QT_BEGIN_NAMESPACE + +#define ModuleInterfaceV20_iid "com.deepin.dock.PluginsItemInterface" + +Q_DECLARE_INTERFACE(PluginsItemInterface_V20, ModuleInterfaceV20_iid) +QT_END_NAMESPACE + +#endif // PLUGINSITEMINTERFACE_H diff --git a/plugins/pluginmanager/pluginchildpage.cpp b/plugins/pluginmanager/pluginchildpage.cpp new file mode 100644 index 000000000..65d7f84a2 --- /dev/null +++ b/plugins/pluginmanager/pluginchildpage.cpp @@ -0,0 +1,131 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "pluginchildpage.h" + +#include +#include + +#include +#include +#include +#include +#include + +DWIDGET_USE_NAMESPACE +DGUI_USE_NAMESPACE + +PluginChildPage::PluginChildPage(QWidget *parent) + : QWidget(parent) + , m_headerWidget(new QWidget(this)) + , m_back(new QPushButton(m_headerWidget)) + , m_title(new QLabel(m_headerWidget)) + , m_container(new QWidget(this)) + , m_topWidget(nullptr) + , m_containerLayout(new QVBoxLayout(m_container)) +{ + initUi(); + initConnection(); +} + +PluginChildPage::~PluginChildPage() +{ +} + +void PluginChildPage::pushWidget(QWidget *widget) +{ + // 首先将界面其他的窗体移除 + for (int i = m_containerLayout->count() - 1; i >= 0; i--) { + QLayoutItem *item = m_containerLayout->itemAt(i); + item->widget()->removeEventFilter(this); + item->widget()->hide(); + m_containerLayout->removeItem(item); + } + m_topWidget = widget; + if (widget) { + widget->installEventFilter(this); + m_containerLayout->addWidget(widget); + widget->show(); + } + QMetaObject::invokeMethod(this, &PluginChildPage::resetHeight, Qt::QueuedConnection); +} + +void PluginChildPage::setTitle(const QString &text) +{ + m_title->setText(text); +} + +void PluginChildPage::initUi() +{ + m_back->setIcon(backPixmap()); + m_back->setFixedWidth(24); + m_back->setFlat(true); + m_title->setAlignment(Qt::AlignCenter); + QHBoxLayout *headerLayout = new QHBoxLayout(m_headerWidget); + headerLayout->setContentsMargins(11, 12, 24 + 11, 12); + headerLayout->setSpacing(0); + headerLayout->addWidget(m_back); + headerLayout->addWidget(m_title); + m_headerWidget->setFixedHeight(48); + + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + + mainLayout->addWidget(m_headerWidget); + mainLayout->addWidget(m_container); + m_containerLayout->setContentsMargins(11, 0, 11, 0); + m_containerLayout->setSpacing(0); +} + +void PluginChildPage::initConnection() +{ + connect(m_back, &QPushButton::clicked, this, &PluginChildPage::back); +} + +bool PluginChildPage::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_topWidget && event->type() == QEvent::Resize) { + resetHeight(); + } + return QWidget::eventFilter(watched, event); +} + +void PluginChildPage::resetHeight() +{ + QMargins m = m_containerLayout->contentsMargins(); + m_container->setFixedHeight(m.top() + m.bottom() + (m_topWidget ? m_topWidget->height() : 0)); + setFixedHeight(m_headerWidget->height() + m_container->height()); +} + +QPixmap PluginChildPage::backPixmap() const +{ + QPixmap pixmap(16, 16); + pixmap.fill(Qt::transparent); + + // 设置背景色 + QColor backColor; + if (DGuiApplicationHelper::ColorType::DarkType == DGuiApplicationHelper::instance()->themeType()) { + backColor = Qt::black; + backColor.setAlphaF(0.05); + } else { + backColor = Qt::white; + backColor.setAlphaF(0.2); + } + QPainter painter(&pixmap); + painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); + painter.setPen(Qt::NoPen); + QPainterPath path; + path.addEllipse(pixmap.rect()); + painter.fillPath(path, backColor); + QSize arrowSize(10, 10); + QPixmap arrowPixmap = DStyle::standardIcon(style(), DStyle::SP_ArrowLeave).pixmap(arrowSize); + // 让其居中显示 + QSize backSize = pixmap.size(); + painter.drawPixmap((backSize.width() - arrowSize.width()) / 2, (backSize.height() - arrowSize.height()) / 2, + arrowSize.width(), arrowSize.height(), arrowPixmap); + painter.end(); + return pixmap; +} diff --git a/plugins/pluginmanager/pluginchildpage.h b/plugins/pluginmanager/pluginchildpage.h new file mode 100644 index 000000000..7c67f6b74 --- /dev/null +++ b/plugins/pluginmanager/pluginchildpage.h @@ -0,0 +1,46 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef PLUGINCHILDPAGE_H +#define PLUGINCHILDPAGE_H + +#include + +class QPushButton; +class QLabel; +class QVBoxLayout; + +class PluginChildPage : public QWidget +{ + Q_OBJECT + +public: + explicit PluginChildPage(QWidget *parent); + ~PluginChildPage() override; + void pushWidget(QWidget *widget); + void setTitle(const QString &text); + +Q_SIGNALS: + void back(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + void initUi(); + void initConnection(); + void resetHeight(); + QPixmap backPixmap() const; + +private: + QWidget *m_headerWidget; + QPushButton *m_back; + QLabel *m_title; + QWidget *m_container; + QWidget *m_topWidget; + QVBoxLayout *m_containerLayout; +}; + +#endif // PLUGINCHILDPAGE_H diff --git a/plugins/pluginmanager/pluginmanager.cpp b/plugins/pluginmanager/pluginmanager.cpp new file mode 100644 index 000000000..e2b509c36 --- /dev/null +++ b/plugins/pluginmanager/pluginmanager.cpp @@ -0,0 +1,163 @@ +// Copyright (C) 2023 ~ 2023 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "pluginmanager.h" +#include "dockplugincontroller.h" +#include "quicksettingcontainer.h" +#include "iconmanager.h" + +#include + +PluginManager::PluginManager(QObject *parent) + : m_dockController(nullptr) + , m_iconManager(nullptr) +{ +} + +const QString PluginManager::pluginName() const +{ + return "pluginManager"; +} + +const QString PluginManager::pluginDisplayName() const +{ + return "pluginManager"; +} + +void PluginManager::init(PluginProxyInterface *proxyInter) +{ + if (m_proxyInter == proxyInter) + return; + + m_proxyInter = proxyInter; + + m_dockController.reset(new DockPluginController(proxyInter)); + m_quickContainer.reset(new QuickSettingContainer(m_dockController.data())); + m_iconManager.reset(new IconManager(m_dockController.data())); + m_iconManager->setPosition(position()); + m_iconManager->setDisplayMode(displayMode()); + + connect(m_dockController.data(), &DockPluginController::requestAppletVisible, this, [ this ](PluginsItemInterface *itemInter, const QString &itemKey, bool visible) { + if (visible) { + QWidget *appletWidget = itemInter->itemPopupApplet(itemKey); + if (appletWidget) + m_quickContainer->showPage(appletWidget, itemInter); + } else { + // 显示主面板 + m_quickContainer->topLevelWidget()->hide(); + } + }); + connect(m_dockController.data(), &DockPluginController::pluginLoadFinished, this, &PluginManager::pluginLoadFinished); + + // 开始加载插件 + m_dockController->startLoadPlugin(getPluginPaths()); + + m_proxyInter->itemAdded(this, pluginName()); +} + +QWidget *PluginManager::itemWidget(const QString &itemKey) +{ + Q_UNUSED(itemKey); + return nullptr; +} + +QWidget *PluginManager::itemPopupApplet(const QString &itemKey) +{ + if (itemKey == QUICK_ITEM_KEY) { + // 返回快捷面板 + return m_quickContainer.data(); + } + + return nullptr; +} + +QIcon PluginManager::icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) +{ + if (dockPart == DockPart::QuickShow) { + return m_iconManager->pixmap(themeType); + } + + return QIcon(); +} + +PluginFlags PluginManager::flags() const +{ + // 当前快捷插件组合区域只支持在快捷区域显示 + return PluginFlag::Type_Common | PluginFlag::Attribute_ForceDock; +} + +PluginsItemInterface::PluginSizePolicy PluginManager::pluginSizePolicy() const +{ + return PluginSizePolicy::Custom; +} + +void PluginManager::positionChanged(const Dock::Position position) +{ + m_iconManager->setPosition(position); + m_proxyInter->itemUpdate(this, pluginName()); +} + +void PluginManager::displayModeChanged(const Dock::DisplayMode displayMode) +{ + m_iconManager->setDisplayMode(displayMode); + m_proxyInter->itemUpdate(this, pluginName()); +} + +QList PluginManager::plugins() const +{ + return m_dockController->plugins(); +} + +QList PluginManager::pluginsInSetting() const +{ + return m_dockController->pluginsInSetting(); +} + +QList PluginManager::currentPlugins() const +{ + return m_dockController->currentPlugins(); +} + +QString PluginManager::itemKey(PluginsItemInterface *itemInter) const +{ + return m_dockController->itemKey(itemInter); +} + +QJsonObject PluginManager::metaData(PluginsItemInterface *itemInter) const +{ + return m_dockController->metaData(itemInter); +} + +#ifndef QT_DEBUG +static QStringList getPathFromConf(const QString &key) { + QSettings set("/etc/deepin/dde-dock.conf", QSettings::IniFormat); + auto value = set.value(key).toString(); + if (!value.isEmpty()) { + return value.split(':'); + } + + return QStringList(); +} +#endif + +QStringList PluginManager::getPluginPaths() const +{ + QStringList pluginPaths; +#ifdef QT_DEBUG + pluginPaths << QString("%1/..%2").arg(qApp->applicationDirPath()).arg(QUICK_PATH) + << QString("%1/..%2").arg(qApp->applicationDirPath()).arg(PLUGIN_PATH) + << QString("%1/..%2").arg(qApp->applicationDirPath()).arg(TRAY_PATH); +#else + pluginPaths << QString("/usr/lib/dde-dock%1").arg(QUICK_PATH) + << QString("/usr/lib/dde-dock%1").arg(PLUGIN_PATH) + << QString("/usr/lib/dde-dock%1").arg(TRAY_PATH); + + const QStringList pluginsDirs = (getPathFromConf("PATH") << getPathFromConf("SYSTEM_TRAY_PATH")); + if (!pluginsDirs.isEmpty()) + pluginPaths << pluginsDirs; +#endif + + return pluginPaths; +} diff --git a/plugins/pluginmanager/pluginmanager.h b/plugins/pluginmanager/pluginmanager.h new file mode 100644 index 000000000..5e649f033 --- /dev/null +++ b/plugins/pluginmanager/pluginmanager.h @@ -0,0 +1,57 @@ +// Copyright (C) 2023 ~ 2023 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef PLUGINMANAGER_H +#define PLUGINMANAGER_H + +#include "pluginsiteminterface.h" +#include "pluginmanagerinterface.h" + +#include + +class DockPluginController; +class QuickSettingContainer; +class IconManager; + +class PluginManager : public PluginManagerInterface, public PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "pluginmanager.json") + +public: + explicit PluginManager(QObject *parent = nullptr); + + const QString pluginName() const override; + const QString pluginDisplayName() const override; + void init(PluginProxyInterface *proxyInter) override; + QWidget *itemWidget(const QString &itemKey) override; + QWidget *itemPopupApplet(const QString &itemKey) override; + QIcon icon(const DockPart &dockPart, DGuiApplicationHelper::ColorType themeType) override; + PluginFlags flags() const override; + PluginSizePolicy pluginSizePolicy() const override; + +protected: + void positionChanged(const Dock::Position position) override; + void displayModeChanged(const Dock::DisplayMode displayMode) override; + +protected: + // 实现PluginManagerInterface接口,用于向dock提供所有已经加载的插件 + QList plugins() const override; + QList pluginsInSetting() const override; + QList currentPlugins() const override; + QString itemKey(PluginsItemInterface *itemInter) const override; + QJsonObject metaData(PluginsItemInterface *itemInter) const override; + +private: + QStringList getPluginPaths() const; + +private: + QSharedPointer m_dockController; + QSharedPointer m_quickContainer; + QSharedPointer m_iconManager; +}; + +#endif // PLUGINMANAGER_H diff --git a/plugins/pluginmanager/pluginmanager.json b/plugins/pluginmanager/pluginmanager.json new file mode 100644 index 000000000..b8397f765 --- /dev/null +++ b/plugins/pluginmanager/pluginmanager.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "order":0 +} diff --git a/plugins/pluginmanager/quicksettingcontainer.cpp b/plugins/pluginmanager/quicksettingcontainer.cpp new file mode 100644 index 000000000..4e1215c32 --- /dev/null +++ b/plugins/pluginmanager/quicksettingcontainer.cpp @@ -0,0 +1,407 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "quicksettingcontainer.h" +#include "dockplugincontroller.h" +#include "pluginsiteminterface.h" +#include "quicksettingitem.h" +#include "pluginchildpage.h" +#include "utils.h" +#include "quickdragcore.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +DWIDGET_USE_NAMESPACE + +struct QuickDragInfo { + QPoint dragPosition; + QWidget *dragItem = nullptr; + PluginsItemInterface *pluginInter = nullptr; + void reset() { + dragPosition.setX(0); + dragPosition.setY(0); + dragItem = nullptr; + pluginInter = nullptr; + } + bool isNull() { + return !dragItem; + } +} QuickDragInfo; + +#define ITEMWIDTH 70 +#define ITEMHEIGHT 60 +#define ITEMSPACE 10 +#define COLUMNCOUNT 4 + +QuickSettingContainer::QuickSettingContainer(DockPluginController *pluginController, QWidget *parent) + : QWidget(parent) + , m_switchLayout(new QStackedLayout(this)) + , m_mainWidget(new QWidget(this)) + , m_pluginWidget(new QWidget(m_mainWidget)) + , m_pluginLayout(new QGridLayout(m_pluginWidget)) + , m_componentWidget(new QWidget(m_mainWidget)) + , m_mainlayout(new QVBoxLayout(m_mainWidget)) + , m_pluginController(pluginController) + , m_childPage(new PluginChildPage(this)) + , m_dragInfo(new struct QuickDragInfo) + , m_childShowPlugin(nullptr) +{ + initUi(); + initConnection(); + m_childPage->installEventFilter(this); + setMouseTracking(true); +} + +QuickSettingContainer::~QuickSettingContainer() +{ + delete m_dragInfo; +} + +void QuickSettingContainer::showPage(QWidget *widget, PluginsItemInterface *pluginInter) +{ + if (widget && pluginInter && widget != m_mainWidget) { + m_childShowPlugin = pluginInter; + m_childPage->setTitle(pluginInter->pluginDisplayName()); + m_childPage->pushWidget(widget); + m_switchLayout->setCurrentWidget(m_childPage); + } else { + m_childShowPlugin = nullptr; + m_switchLayout->setCurrentIndex(0); + } + + onResizeView(); +} + +bool QuickSettingContainer::eventFilter(QObject *watched, QEvent *event) +{ + switch (event->type()) { + case QEvent::Resize: { + onResizeView(); + break; + } + case QEvent::MouseButtonPress: { + QMouseEvent *mouseEvent = static_cast(event); + QuickSettingItem *item = qobject_cast(watched); + if (item && item->pluginItem()->flags() & PluginFlag::Attribute_CanDrag) { + m_dragInfo->dragPosition = mouseEvent->pos(); + m_dragInfo->dragItem = item; + m_dragInfo->pluginInter = item->pluginItem(); + } + break; + } + case QEvent::MouseButtonRelease: { + m_dragInfo->reset(); + break; + } + default: + break; + } + + return QWidget::eventFilter(watched, event); +} + +void QuickSettingContainer::showEvent(QShowEvent *event) +{ + // 当面板显示的时候,直接默认显示快捷面板的窗口 + QWidget::showEvent(event); + if (m_switchLayout->currentWidget() != m_mainWidget) { + m_childPage->pushWidget(nullptr); + m_switchLayout->setCurrentWidget(m_mainWidget); + onResizeView(); + } +} + +void QuickSettingContainer::appendPlugin(PluginsItemInterface *itemInter, QString itemKey, bool needLayout) +{ + QuickSettingItem *quickItem = QuickSettingFactory::createQuickWidget(itemInter, itemKey); + if (!quickItem) + return; + + quickItem->setParent(m_pluginWidget); + quickItem->setMouseTracking(true); + quickItem->installEventFilter(this); + connect(quickItem, &QuickSettingItem::requestShowChildWidget, this, &QuickSettingContainer::onShowChildWidget); + m_quickSettings << quickItem; + if (quickItem->type() == QuickSettingItem::QuickItemStyle::Line) { + // 插件位置占据整行,例如声音、亮度和音乐等 + m_componentWidget->layout()->addWidget(quickItem); + updateFullItemLayout(); + } else if (needLayout) { + // 插件占据两行或者一行 + updateItemLayout(); + } + + onResizeView(); +} + +void QuickSettingContainer::onPluginRemove(PluginsItemInterface *itemInter) +{ + QList::Iterator removeItemIter = std::find_if(m_quickSettings.begin(), m_quickSettings.end(), [ = ](QuickSettingItem *item)->bool { + return item->pluginItem() == itemInter; + }); + + if (removeItemIter == m_quickSettings.end()) + return; + + QuickSettingItem *removeItem = *removeItemIter; + removeItem->detachPlugin(); + + if (removeItem->type() == QuickSettingItem::QuickItemStyle::Line) + m_componentWidget->layout()->removeWidget(removeItem); + else + m_pluginLayout->removeWidget(removeItem); + + m_quickSettings.removeOne(removeItem); + removeItem->deleteLater(); + if (m_childShowPlugin == itemInter) + showPage(nullptr); + + updateItemLayout(); + updateFullItemLayout(); + onResizeView(); +} + +void QuickSettingContainer::onShowChildWidget(QWidget *childWidget) +{ + QuickSettingItem *quickWidget = qobject_cast(sender()); + if (!quickWidget) + return; + + showPage(childWidget, quickWidget->pluginItem()); +} + +void QuickSettingContainer::mouseMoveEvent(QMouseEvent *event) +{ + if (m_dragInfo->isNull()) + return; + + QPoint pointCurrent = event->pos(); + if (qAbs(m_dragInfo->dragPosition.x() - pointCurrent.x()) > 5 + || qAbs(m_dragInfo->dragPosition.y() - pointCurrent.y()) > 5) { + QuickSettingItem *moveItem = qobject_cast(m_dragInfo->dragItem); + QuickIconDrag *drag = new QuickIconDrag(this, moveItem->dragPixmap()); + QuickPluginMimeData *mimedata = new QuickPluginMimeData(m_dragInfo->pluginInter, drag); + drag->setMimeData(mimedata); + drag->setDragHotPot(m_dragInfo->dragPosition); + + m_dragInfo->reset(); + drag->exec(Qt::CopyAction); + } +} + +void QuickSettingContainer::updateItemLayout() +{ + // 清空之前的控件,重新添加 + while (m_pluginLayout->count() > 0) + m_pluginLayout->takeAt(0); + + // 将插件按照两列和一列的顺序来进行排序 + QMap> quickSettings; + QMap> orderQuickSettings; + for (QuickSettingItem *item : m_quickSettings) { + QuickSettingItem::QuickItemStyle type = item->type(); + if (type == QuickSettingItem::QuickItemStyle::Line) + continue; + + QJsonObject metaData = m_pluginController->metaData(item->pluginItem()); + if (metaData.contains("order")) + orderQuickSettings[type][item] = metaData.value("order").toInt(); + else + quickSettings[type] << item; + } + // 将需要排序的插件按照顺序插入到原来的数组中 + for (auto itQuick = orderQuickSettings.begin(); itQuick != orderQuickSettings.end(); itQuick++) { + QuickSettingItem::QuickItemStyle type = itQuick.key(); + QMap &orderQuicks = itQuick.value(); + for (auto it = orderQuicks.begin(); it != orderQuicks.end(); it++) { + int index = it.value(); + if (index >= 0 && index < quickSettings[type].size()) + quickSettings[type][index] = it.key(); + else + quickSettings[type] << it.key(); + } + } + auto insertQuickSetting = [ quickSettings, this ](QuickSettingItem::QuickItemStyle type, int &row, int &column) { + if (!quickSettings.contains(type)) + return; + + int usedColumn = (type == QuickSettingItem::QuickItemStyle::Larger ? 2 : 1); + QList quickPlugins = quickSettings[type]; + for (QuickSettingItem *quickItem : quickPlugins) { + quickItem->setVisible(true); + m_pluginLayout->addWidget(quickItem, row, column, 1, usedColumn); + column += usedColumn; + if (column >= COLUMNCOUNT) { + row++; + column = 0; + } + } + }; + + int row = 0; + int column = 0; + insertQuickSetting(QuickSettingItem::QuickItemStyle::Larger, row, column); + insertQuickSetting(QuickSettingItem::QuickItemStyle::Standard, row, column); +} + +void QuickSettingContainer::updateFullItemLayout() +{ + while (m_componentWidget->layout()->count() > 0) + m_componentWidget->layout()->takeAt(0); + + QList fullItems; + QMap fullItemOrder; + for (QuickSettingItem *item : m_quickSettings) { + if (item->type() != QuickSettingItem::QuickItemStyle::Line) + continue; + + fullItems << item; + int order = -1; + QJsonObject metaData = m_pluginController->metaData(item->pluginItem()); + if (metaData.contains("order")) + order = metaData.value("order").toInt(); + + fullItemOrder[item] = order; + } + + std::sort(fullItems.begin(), fullItems.end(), [ fullItemOrder, fullItems ](QuickSettingItem *item1, QuickSettingItem *item2) { + int order1 = fullItemOrder.value(item1, -1); + int order2 = fullItemOrder.value(item2, -1); + if (order1 == order2) { + // 如果两个值相等,就根据他们的加载顺序进行排序 + return fullItems.indexOf(item1) < fullItems.indexOf(item2); + } + if (order1 == -1) + return false; + if (order2 == -1) + return true; + + return order1 < order2; + }); + + for (QuickSettingItem *item : fullItems) { + item->setVisible(true); + m_componentWidget->layout()->addWidget(item); + } +} + +void QuickSettingContainer::initUi() +{ + m_mainlayout->setSpacing(ITEMSPACE); + m_mainlayout->setContentsMargins(ITEMSPACE, ITEMSPACE, ITEMSPACE, ITEMSPACE); + + m_pluginLayout->setContentsMargins(0, 0, 0, 0); + m_pluginLayout->setSpacing(ITEMSPACE); + m_pluginLayout->setAlignment(Qt::AlignLeft); + for (int i = 0; i < COLUMNCOUNT; i++) + m_pluginLayout->setColumnMinimumWidth(i, ITEMWIDTH); + + m_pluginWidget->setLayout(m_pluginLayout); + m_mainlayout->addWidget(m_pluginWidget); + + QVBoxLayout *ctrlLayout = new QVBoxLayout(m_componentWidget); + ctrlLayout->setContentsMargins(0, 0, 0, 0); + ctrlLayout->setSpacing(ITEMSPACE); + ctrlLayout->setDirection(QBoxLayout::BottomToTop); + + m_mainlayout->addWidget(m_componentWidget); + // 加载所有的可以在快捷面板显示的插件 + QList plugins = m_pluginController->currentPlugins(); + for (PluginsItemInterface *plugin : plugins) { + appendPlugin(plugin, m_pluginController->itemKey(plugin), false); + } + + m_switchLayout->addWidget(m_mainWidget); + m_switchLayout->addWidget(m_childPage); + + setMouseTracking(true); + setAcceptDrops(true); + + QMetaObject::invokeMethod(this, [ = ] { + if (plugins.size() > 0) { + updateItemLayout(); + updateFullItemLayout(); + } + // 设置当前窗口的大小 + onResizeView(); + setFixedWidth(ITEMWIDTH * 4 + (ITEMSPACE * 5)); + }, Qt::QueuedConnection); +} + +void QuickSettingContainer::initConnection() +{ + connect(m_pluginController, &DockPluginController::pluginInserted, this, [ = ](PluginsItemInterface *itemInter, QString itemKey) { + appendPlugin(itemInter, itemKey); + }); + connect(m_pluginController, &DockPluginController::pluginRemoved, this, &QuickSettingContainer::onPluginRemove); + connect(m_pluginController, &DockPluginController::pluginUpdated, this, &QuickSettingContainer::onPluginUpdated); + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &QuickSettingContainer::onThemeTypeChanged); + + connect(m_childPage, &PluginChildPage::back, this, [ this ] { + showPage(m_mainWidget); + }); +} + +// 调整尺寸 +void QuickSettingContainer::onResizeView() +{ + if (m_switchLayout->currentWidget() == m_mainWidget) { + int selfPluginCount = 0; + int fullItemHeight = 0; + int widgetCount = 0; + for (QuickSettingItem *item : m_quickSettings) { + item->setFixedHeight(ITEMHEIGHT); + if (item->type() == QuickSettingItem::QuickItemStyle::Line) { + fullItemHeight += item->height(); + widgetCount++; + continue; + } + // 如果是置顶的插件,则认为它占用两个普通插件的位置 + int increCount = (item->type() == QuickSettingItem::QuickItemStyle::Larger ? 2 : 1); + selfPluginCount += increCount; + } + + int rowCount = selfPluginCount / COLUMNCOUNT; + if (selfPluginCount % COLUMNCOUNT > 0) + rowCount++; + + m_pluginWidget->setFixedHeight(ITEMHEIGHT * rowCount + ITEMSPACE * (rowCount - 1)); + m_componentWidget->setFixedHeight(fullItemHeight + (widgetCount - 1) * ITEMSPACE); + + setFixedHeight(ITEMSPACE * 3 + m_pluginWidget->height() + m_componentWidget->height()); + } else if (m_switchLayout->currentWidget() == m_childPage) { + setFixedHeight(m_childPage->height()); + } +} + +void QuickSettingContainer::onPluginUpdated(PluginsItemInterface *itemInter, const DockPart dockPart) +{ + if (dockPart != DockPart::QuickPanel) + return; + + for (QuickSettingItem *settingItem : m_quickSettings) { + if (settingItem->pluginItem() != itemInter) + continue; + + settingItem->doUpdate(); + break; + } +} + +void QuickSettingContainer::onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType) +{ + for (QuickSettingItem *settingItem : m_quickSettings) + settingItem->doUpdate(); +} diff --git a/plugins/pluginmanager/quicksettingcontainer.h b/plugins/pluginmanager/quicksettingcontainer.h new file mode 100644 index 000000000..e4cd2ad46 --- /dev/null +++ b/plugins/pluginmanager/quicksettingcontainer.h @@ -0,0 +1,81 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef QUICKSETTINGCONTAINER_H +#define QUICKSETTINGCONTAINER_H + +#include "pluginproxyinterface.h" + +#include "dtkwidget_global.h" + +#include +#include + +#include + +class DockItem; +class QVBoxLayout; +class DockPluginController; +class BrightnessModel; +class BrightnessWidget; +class QuickSettingItem; +class QStackedLayout; +class VolumeDevicesWidget; +class QLabel; +class PluginChildPage; +class QGridLayout; +class DisplaySettingWidget; +struct QuickDragInfo; + +DWIDGET_USE_NAMESPACE + +class QuickSettingContainer : public QWidget +{ + Q_OBJECT + +public: + void showPage(QWidget *widget, PluginsItemInterface *pluginInter = nullptr); + explicit QuickSettingContainer(DockPluginController *pluginController, QWidget *parent = nullptr); + ~QuickSettingContainer() override; + +protected: + void mouseMoveEvent(QMouseEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event) override; + void showEvent(QShowEvent *event) override; + +private Q_SLOTS: + void onPluginRemove(PluginsItemInterface *itemInter); + void onShowChildWidget(QWidget *childWidget); + void onResizeView(); + void onPluginUpdated(PluginsItemInterface *itemInter, const DockPart dockPart); + void onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType); + +private: + // 加载UI + void initUi(); + // 初始化槽函数 + void initConnection(); + // 调整控件位置 + void updateItemLayout(); + // 调整全列插件的位置 + void updateFullItemLayout(); + // 插入插件 + void appendPlugin(PluginsItemInterface *itemInter, QString itemKey, bool needLayout = true); + +private: + QStackedLayout *m_switchLayout; + QWidget *m_mainWidget; + QWidget *m_pluginWidget; + QGridLayout *m_pluginLayout; + QWidget *m_componentWidget; + QVBoxLayout *m_mainlayout; + DockPluginController *m_pluginController; + PluginChildPage *m_childPage; + QuickDragInfo *m_dragInfo; + QList m_quickSettings; + PluginsItemInterface *m_childShowPlugin; +}; + +#endif // PLUGINCONTAINER_H diff --git a/plugins/pluginmanager/quicksettingitem.cpp b/plugins/pluginmanager/quicksettingitem.cpp new file mode 100644 index 000000000..550e1b558 --- /dev/null +++ b/plugins/pluginmanager/quicksettingitem.cpp @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 + * 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 . + */ +#include "quicksettingitem.h" +#include "pluginsiteminterface.h" +#include "imageutil.h" +#include "largerquickitem.h" +#include "standardquickitem.h" +#include "linequickitem.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ICONWIDTH 24 +#define ICONHEIGHT 24 +#define ICONSPACE 10 +#define RADIUS 8 +#define FONTSIZE 10 + +#define BGWIDTH 128 +#define BGSIZE 36 +#define MARGINLEFTSPACE 10 +#define OPENICONSIZE 12 +#define MARGINRIGHTSPACE 9 + +DWIDGET_USE_NAMESPACE + +QuickSettingItem::QuickSettingItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent) + : QWidget(parent) + , m_pluginInter(pluginInter) + , m_itemKey(itemKey) +{ + setAcceptDrops(true); + this->installEventFilter(this); +} + +QuickSettingItem::~QuickSettingItem() +{ +} + +PluginsItemInterface *QuickSettingItem::pluginItem() const +{ + return m_pluginInter; +} + +const QPixmap QuickSettingItem::dragPixmap() +{ + return grab(); +} + +const QString QuickSettingItem::itemKey() const +{ + return m_itemKey; +} + +void QuickSettingItem::paintEvent(QPaintEvent *e) +{ + QWidget::paintEvent(e); + QPainter painter(this); + painter.setRenderHint(QPainter::RenderHint::Antialiasing); + painter.setPen(foregroundColor()); + QPainterPath path; + path.addRoundedRect(rect(), RADIUS, RADIUS); + painter.setClipPath(path); + // 绘制背景色 + QColor backColor(Qt::white); + if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::ColorType::DarkType) { + backColor = Qt::black; + backColor.setAlphaF(0.5); + } + DPalette dpa = DPaletteHelper::instance()->palette(this); + painter.fillRect(rect(), backColor); +} + +QColor QuickSettingItem::foregroundColor() const +{ + DPalette dpa = DPaletteHelper::instance()->palette(this); + // TODO: 此处的颜色是临时获取的,后期需要和设计师确认,改成正规的颜色 + if (m_pluginInter->status() == PluginsItemInterface::PluginMode::Active) + return dpa.color(DPalette::ColorGroup::Active, DPalette::ColorRole::Text); + + if (m_pluginInter->status() == PluginsItemInterface::PluginMode::Deactive) + return dpa.color(DPalette::ColorGroup::Disabled, DPalette::ColorRole::Text); + + return dpa.color(DPalette::ColorGroup::Normal, DPalette::ColorRole::Text); +} + +QuickSettingItem *QuickSettingFactory::createQuickWidget(PluginsItemInterface * const pluginInter, const QString &itemKey) +{ + // 如果显示在面板的图标或者Widget为空,则不让显示(例如电池插件) + if (!(pluginInter->flags() & PluginFlag::Type_Common)) + return nullptr; + + if (pluginInter->flags() & PluginFlag::Quick_Multi) + return new LargerQuickItem(pluginInter, itemKey); + + if (pluginInter->flags() & PluginFlag::Quick_Full) + return new LineQuickItem(pluginInter, itemKey); + + if (pluginInter->flags() & PluginFlag::Quick_Single) + return new StandardQuickItem(pluginInter, itemKey); + + return nullptr; +} diff --git a/plugins/pluginmanager/quicksettingitem.h b/plugins/pluginmanager/quicksettingitem.h new file mode 100644 index 000000000..57e41fe7f --- /dev/null +++ b/plugins/pluginmanager/quicksettingitem.h @@ -0,0 +1,54 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef QUICKSETTINGITEM_H +#define QUICKSETTINGITEM_H + +#include + +class PluginsItemInterface; +class QuickIconWidget; + +class QuickSettingItem : public QWidget +{ + Q_OBJECT + +public: + enum class QuickItemStyle { + Standard = 1, // 插件的UI显示单列 + Larger, // 插件的UI显示双列,例如网络和蓝牙等 + Line // 插件的UI整行显示,例如声音,亮度、音乐播放等 + }; + +public: + QuickSettingItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent = nullptr); + ~QuickSettingItem() override; + PluginsItemInterface *pluginItem() const; + virtual const QPixmap dragPixmap(); + virtual void doUpdate() {} + virtual void detachPlugin() {} + const QString itemKey() const; + + virtual QuickItemStyle type() const = 0; + +Q_SIGNALS: + void requestShowChildWidget(QWidget *); + +protected: + void paintEvent(QPaintEvent *e) override; + QColor foregroundColor() const; + +private: + PluginsItemInterface *m_pluginInter; + QString m_itemKey; +}; + +class QuickSettingFactory +{ +public: + static QuickSettingItem *createQuickWidget(PluginsItemInterface *const pluginInter, const QString &itemKey); +}; + +#endif // QUICKSETTINGITEM_H diff --git a/plugins/pluginmanager/resources/built-in-icons/dock-control-panel.dci b/plugins/pluginmanager/resources/built-in-icons/dock-control-panel.dci new file mode 100644 index 000000000..7fe619708 Binary files /dev/null and b/plugins/pluginmanager/resources/built-in-icons/dock-control-panel.dci differ diff --git a/plugins/pluginmanager/resources/built-in-icons/dock-control-panel.dci.license b/plugins/pluginmanager/resources/built-in-icons/dock-control-panel.dci.license new file mode 100644 index 000000000..c0469f3bd --- /dev/null +++ b/plugins/pluginmanager/resources/built-in-icons/dock-control-panel.dci.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. + +SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/pluginmanager/resources/pluginmanager.qrc b/plugins/pluginmanager/resources/pluginmanager.qrc new file mode 100644 index 000000000..760cabc9d --- /dev/null +++ b/plugins/pluginmanager/resources/pluginmanager.qrc @@ -0,0 +1,5 @@ + + + built-in-icons/dock-control-panel.dci + + diff --git a/plugins/pluginmanager/standardquickitem.cpp b/plugins/pluginmanager/standardquickitem.cpp new file mode 100644 index 000000000..b96590a7a --- /dev/null +++ b/plugins/pluginmanager/standardquickitem.cpp @@ -0,0 +1,185 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "standardquickitem.h" +#include "pluginsiteminterface.h" + +#include +#include + +#include +#include +#include + +#define ICONHEIGHT 24 +#define ICONWIDTH 24 +#define TEXTHEIGHT 11 + +DWIDGET_USE_NAMESPACE + +StandardQuickItem::StandardQuickItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent) + : QuickSettingItem(pluginInter, itemKey, parent) + , m_itemParentWidget(nullptr) + , m_needPaint(true) +{ + initUi(); +} + +StandardQuickItem::~StandardQuickItem() +{ +} + +QuickSettingItem::QuickItemStyle StandardQuickItem::type() const +{ + return QuickSettingItem::QuickItemStyle::Standard; +} + +void StandardQuickItem::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + QStringList commandArgument = pluginItem()->itemCommand(itemKey()).split(" "); + if (commandArgument.size() > 0) { + QString command = commandArgument.first(); + commandArgument.removeFirst(); + QProcess::startDetached(command, commandArgument); + } +} + +void StandardQuickItem::resizeEvent(QResizeEvent *event) +{ + doUpdate(); + QuickSettingItem::resizeEvent(event); +} + +void StandardQuickItem::initUi() +{ + QWidget *topWidget = iconWidget(this); + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(topWidget); + installEventFilter(this); +} + +QWidget *StandardQuickItem::iconWidget(QWidget *parent) +{ + // 显示图标的窗体 + QWidget *widget = new QWidget(parent); + m_needPaint = true; + QIcon icon = pluginItem()->icon(DockPart::QuickPanel); + if (icon.isNull()) { + // 如果图标为空,则将获取itemWidget作为它的显示 + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (itemWidget) { + m_itemParentWidget = itemWidget->parentWidget(); + QHBoxLayout *layout = new QHBoxLayout(widget); + layout->setContentsMargins(0, 0, 0 ,0); + itemWidget->setParent(widget); + layout->addWidget(itemWidget); + itemWidget->setVisible(true); + m_needPaint = false; + } + } + + if (m_needPaint) { + // 如果没有子窗体,则需要添加下方的文字 + QVBoxLayout *layout = new QVBoxLayout(widget); + layout->setAlignment(Qt::AlignVCenter); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + QLabel *imageLabel = new QLabel(widget); + imageLabel->setObjectName("imageLabel"); + imageLabel->setFixedHeight(ICONHEIGHT); + imageLabel->setAlignment(Qt::AlignCenter); + + QLabel *labelText = new QLabel(widget); + labelText->setObjectName("textLabel"); + labelText->setFixedHeight(TEXTHEIGHT); + updatePluginName(labelText); + labelText->setAlignment(Qt::AlignCenter); + labelText->setFont(DFontSizeManager::instance()->t10()); + layout->addWidget(imageLabel); + layout->addSpacing(7); + layout->addWidget(labelText); + } + + return widget; +} + +QPixmap StandardQuickItem::pixmap() const +{ + // 如果快捷面板区域的图标为空,那么就获取itemWidget的截图 + QIcon icon = pluginItem()->icon(DockPart::QuickPanel); + if (icon.isNull()) + return QPixmap(); + + int pixmapWidth = ICONWIDTH; + int pixmapHeight = ICONHEIGHT; + QList iconSizes = icon.availableSizes(); + if (iconSizes.size() > 0) { + QSize size = iconSizes[0]; + if (size.isValid() && !size.isEmpty() && !size.isNull()) { + pixmapWidth = size.width(); + pixmapHeight = size.height(); + } + } + + return icon.pixmap(pixmapWidth / qApp->devicePixelRatio(), pixmapHeight / qApp->devicePixelRatio()); +} + +QLabel *StandardQuickItem::findChildLabel(QWidget *parent, const QString &childObjectName) const +{ + QList childrends = parent->children(); + for (QObject *child : childrends) { + QWidget *widget = qobject_cast(child); + if (!widget) + continue; + + QLabel *label = qobject_cast(child); + if (label && widget->objectName() == childObjectName) + return label; + + label = findChildLabel(widget, childObjectName); + if (label) + return label; + } + + return nullptr; +} + +void StandardQuickItem::updatePluginName(QLabel *textLabel) +{ + if (!textLabel) + return; + + QString text = pluginItem()->description(); + if (text.isEmpty()) + text = pluginItem()->pluginDisplayName(); + QFontMetrics ftm(textLabel->font()); + text = ftm.elidedText(text, Qt::TextElideMode::ElideRight, textLabel->width()); + textLabel->setText(text); +} + +void StandardQuickItem::doUpdate() +{ + if (m_needPaint) { + QLabel *imageLabel = findChildLabel(this, "imageLabel"); + if (imageLabel) { + // 更新图像 + imageLabel->setPixmap(pixmap()); + } + updatePluginName(findChildLabel(this, "textLabel")); + } else { + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (itemWidget) + itemWidget->update(); + } +} + +void StandardQuickItem::detachPlugin() +{ + QWidget *itemWidget = pluginItem()->itemWidget(QUICK_ITEM_KEY); + if (itemWidget && !m_needPaint) + itemWidget->setParent(m_itemParentWidget); +} diff --git a/plugins/pluginmanager/standardquickitem.h b/plugins/pluginmanager/standardquickitem.h new file mode 100644 index 000000000..8a73755f1 --- /dev/null +++ b/plugins/pluginmanager/standardquickitem.h @@ -0,0 +1,42 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef STANDARDQUICKITEM_H +#define STANDARDQUICKITEM_H + +#include "quicksettingitem.h" + +class QLabel; + +// 插件在快捷面板中展示的样式,这个为默认,展示一行一列的那种 +class StandardQuickItem : public QuickSettingItem +{ + Q_OBJECT + +public: + StandardQuickItem(PluginsItemInterface *const pluginInter, const QString &itemKey, QWidget *parent = nullptr); + ~StandardQuickItem() override; + + QuickItemStyle type() const override; + void doUpdate() override; + void detachPlugin() override; + +protected: + void mouseReleaseEvent(QMouseEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private: + void initUi(); + QWidget *iconWidget(QWidget *parent); + QPixmap pixmap() const; + QLabel *findChildLabel(QWidget *parent, const QString &childObjectName) const; + void updatePluginName(QLabel *textLabel); + +private: + QWidget *m_itemParentWidget; + bool m_needPaint; +}; + +#endif // SINGLEQUICKITEM_H diff --git a/plugins/power/CMakeLists.txt b/plugins/power/CMakeLists.txt index 4c369d75d..3016ac120 100644 --- a/plugins/power/CMakeLists.txt +++ b/plugins/power/CMakeLists.txt @@ -3,8 +3,15 @@ set(PLUGIN_NAME "power") project(${PLUGIN_NAME}) +generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface) + # Sources files -file(GLOB_RECURSE SRCS "*.h" "*.cpp" "../../widgets/*.h" "../../widgets/*.cpp") +file(GLOB_RECURSE SRCS "*.h" + "*.cpp" + "../../widgets/tipswidget.h" + "../../widgets/tipswidget.cpp" + "../../frame/qtdbusextended/*.h" + "../../frame/qtdbusextended/*.cpp") find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) @@ -12,26 +19,24 @@ find_package(Qt5Svg REQUIRED) find_package(Qt5DBus REQUIRED) find_package(DtkWidget REQUIRED) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) pkg_check_modules(QGSettings REQUIRED gsettings-qt) add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") add_library(${PLUGIN_NAME} SHARED ${SRCS} power.qrc) -set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../system-trays) +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../quick-trays) target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} ${QGSettings_INCLUDE_DIRS} - ../../interfaces) + ../../interfaces + ../../frame/qtdbusextended + ./dbusinterface/generation_dbus_interface) + target_link_libraries(${PLUGIN_NAME} PRIVATE ${DtkWidget_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Svg_LIBRARIES} ${Qt5DBus_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} ${QGSettings_LIBRARIES} ) -install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/system-trays) - -dconfig_meta_files(APPID org.deepin.dde.dock FILES ../../configs/org.deepin.dde.dock.plugin.power.json) +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/quick-trays) diff --git a/plugins/power/dbus/dbusaccount.cpp b/plugins/power/dbus/dbusaccount.cpp index 69726ec21..d8be6aece 100644 --- a/plugins/power/dbus/dbusaccount.cpp +++ b/plugins/power/dbus/dbusaccount.cpp @@ -1,7 +1,19 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c DBusAccount -p dbusaccount org.deepin.dde.Accounts1.xml + * + * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + #include "dbusaccount.h" /* @@ -18,4 +30,3 @@ DBusAccount::~DBusAccount() { QDBusConnection::systemBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); } - diff --git a/plugins/power/dbus/dbusaccount.h b/plugins/power/dbus/dbusaccount.h index e9a2cb50c..754bc3ffe 100644 --- a/plugins/power/dbus/dbusaccount.h +++ b/plugins/power/dbus/dbusaccount.h @@ -1,7 +1,18 @@ -// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c DBusAccount -p dbusaccount org.deepin.dde.Accounts1.xml + * + * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + #ifndef DBUSACCOUNT_H_1439464396 #define DBUSACCOUNT_H_1439464396 @@ -15,7 +26,7 @@ #include /* - * Proxy class for interface com.deepin.daemon.Accounts + * Proxy class for interface org.deepin.dde.Accounts1 */ class DBusAccount: public QDBusAbstractInterface { @@ -28,7 +39,7 @@ class DBusAccount: public QDBusAbstractInterface return; } QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName != "com.deepin.daemon.Accounts") { + if (interfaceName != "org.deepin.dde.Accounts1") { return; } QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); @@ -45,11 +56,11 @@ class DBusAccount: public QDBusAbstractInterface } public: static inline const char *staticService() - { return "com.deepin.daemon.Accounts"; } + { return "org.deepin.dde.Accounts1"; } static inline const char *staticInterfacePath() - { return "/com/deepin/daemon/Accounts"; } + { return "/org/deepin/dde/Accounts1"; } static inline const char *staticInterfaceName() - { return "com.deepin.daemon.Accounts"; } + { return "org.deepin.dde.Accounts1"; } public: explicit DBusAccount(QObject *parent = 0); @@ -63,7 +74,7 @@ public: //namespace com { // namespace deepin { -// namespace daemon { +// namespace dde { // typedef ::DBusAccount Accounts; // } // } diff --git a/plugins/power/dbus/dbuspower.cpp b/plugins/power/dbus/dbuspower.cpp index 29cdedac3..ababc6e45 100644 --- a/plugins/power/dbus/dbuspower.cpp +++ b/plugins/power/dbus/dbuspower.cpp @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusPower -p dbuspower com.deepin.daemon.Power.xml + * Command line was: qdbusxml2cpp -c DBusPower -p dbuspower org.deepin.dde.Power1.xml * * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). * @@ -16,7 +16,7 @@ */ DBusPower::DBusPower(QObject *parent) - : QDBusAbstractInterface("com.deepin.daemon.Power", "/com/deepin/daemon/Power", staticInterfaceName(), QDBusConnection::sessionBus(), parent) + : QDBusAbstractInterface("org.deepin.dde.Power1", "/org/deepin/dde/Power1", staticInterfaceName(), QDBusConnection::sessionBus(), parent) { qRegisterMetaType("BatteryStateMap"); qDBusRegisterMetaType(); diff --git a/plugins/power/dbus/dbuspower.h b/plugins/power/dbus/dbuspower.h index 47225849b..1f0417b1f 100644 --- a/plugins/power/dbus/dbuspower.h +++ b/plugins/power/dbus/dbuspower.h @@ -1,6 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusPower -p dbuspower com.deepin.daemon.Power.xml + * Command line was: qdbusxml2cpp -c DBusPower -p dbuspower org.deepin.dde.Power1.xml * * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). * @@ -26,7 +26,7 @@ Q_DECLARE_METATYPE(BatteryPercentageMap) Q_DECLARE_METATYPE(BatteryStateMap) /* - * Proxy class for interface com.deepin.daemon.Power + * Proxy class for interface org.deepin.dde.Power1 */ class DBusPower: public QDBusAbstractInterface { @@ -38,7 +38,7 @@ class DBusPower: public QDBusAbstractInterface if (3 != arguments.count()) return; QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.daemon.Power") + if (interfaceName !="org.deepin.dde.Power1") return; QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); foreach(const QString &prop, changedProps.keys()) { @@ -53,7 +53,7 @@ class DBusPower: public QDBusAbstractInterface } public: static inline const char *staticInterfaceName() - { return "com.deepin.daemon.Power"; } + { return "org.deepin.dde.Power1"; } public: explicit DBusPower(QObject *parent = 0); @@ -80,10 +80,10 @@ void BatteryPercentageChanged(); void BatteryStateChanged(); }; -namespace com { +namespace org { namespace deepin { - namespace daemon { - typedef ::DBusPower Power; + namespace dde { + typedef ::DBusPower SessionPower1; } } } diff --git a/plugins/power/dbus/com.deepin.daemon.Power.xml b/plugins/power/dbus/org.deepin.dde.Power1.xml similarity index 96% rename from plugins/power/dbus/com.deepin.daemon.Power.xml rename to plugins/power/dbus/org.deepin.dde.Power1.xml index af034c1f2..9589fe74c 100644 --- a/plugins/power/dbus/com.deepin.daemon.Power.xml +++ b/plugins/power/dbus/org.deepin.dde.Power1.xml @@ -1,4 +1,4 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tray/fashiontray/containers/abstractcontainer.cpp b/plugins/tray/fashiontray/containers/abstractcontainer.cpp index 465b97322..57bd56d38 100644 --- a/plugins/tray/fashiontray/containers/abstractcontainer.cpp +++ b/plugins/tray/fashiontray/containers/abstractcontainer.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/abstractcontainer.h b/plugins/tray/fashiontray/containers/abstractcontainer.h index 625fa781f..a699c89a3 100644 --- a/plugins/tray/fashiontray/containers/abstractcontainer.h +++ b/plugins/tray/fashiontray/containers/abstractcontainer.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/attentioncontainer.cpp b/plugins/tray/fashiontray/containers/attentioncontainer.cpp index 62f459c35..70e6555ce 100644 --- a/plugins/tray/fashiontray/containers/attentioncontainer.cpp +++ b/plugins/tray/fashiontray/containers/attentioncontainer.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/attentioncontainer.h b/plugins/tray/fashiontray/containers/attentioncontainer.h index dea276e4c..f6b8fcfd9 100644 --- a/plugins/tray/fashiontray/containers/attentioncontainer.h +++ b/plugins/tray/fashiontray/containers/attentioncontainer.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/holdcontainer.cpp b/plugins/tray/fashiontray/containers/holdcontainer.cpp index 3ca5e7e72..3aa66e41b 100644 --- a/plugins/tray/fashiontray/containers/holdcontainer.cpp +++ b/plugins/tray/fashiontray/containers/holdcontainer.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/holdcontainer.h b/plugins/tray/fashiontray/containers/holdcontainer.h index 90982b417..1e427d612 100644 --- a/plugins/tray/fashiontray/containers/holdcontainer.h +++ b/plugins/tray/fashiontray/containers/holdcontainer.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/normalcontainer.cpp b/plugins/tray/fashiontray/containers/normalcontainer.cpp index aa96ef5e8..0a3085df3 100644 --- a/plugins/tray/fashiontray/containers/normalcontainer.cpp +++ b/plugins/tray/fashiontray/containers/normalcontainer.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -175,7 +176,7 @@ int NormalContainer::whereToInsert(FashionTrayWidgetWrapper *wrapper) int NormalContainer::whereToInsertByDefault(FashionTrayWidgetWrapper *wrapper) const { int index = 0; - switch (wrapper->absTrayWidget()->trayType()) { + switch (wrapper->absTrayWidget()->trayTyep()) { case AbstractTrayWidget::TrayType::ApplicationTray: index = whereToInsertAppTrayByDefault(wrapper); break; @@ -191,13 +192,13 @@ int NormalContainer::whereToInsertByDefault(FashionTrayWidgetWrapper *wrapper) c int NormalContainer::whereToInsertAppTrayByDefault(FashionTrayWidgetWrapper *wrapper) const { - if (wrapperList().isEmpty() || wrapper->absTrayWidget()->trayType() != AbstractTrayWidget::TrayType::ApplicationTray) { + if (wrapperList().isEmpty() || wrapper->absTrayWidget()->trayTyep() != AbstractTrayWidget::TrayType::ApplicationTray) { return 0; } int lastAppTrayIndex = -1; for (int i = 0; i < wrapperList().size(); ++i) { - if (wrapperList().at(i)->absTrayWidget()->trayType() == AbstractTrayWidget::TrayType::ApplicationTray) { + if (wrapperList().at(i)->absTrayWidget()->trayTyep() == AbstractTrayWidget::TrayType::ApplicationTray) { lastAppTrayIndex = i; continue; } @@ -208,7 +209,7 @@ int NormalContainer::whereToInsertAppTrayByDefault(FashionTrayWidgetWrapper *wra return 0; } // the inserting tray is not a AppTray - if (wrapper->absTrayWidget()->trayType() != AbstractTrayWidget::TrayType::ApplicationTray) { + if (wrapper->absTrayWidget()->trayTyep() != AbstractTrayWidget::TrayType::ApplicationTray) { return lastAppTrayIndex + 1; } @@ -218,7 +219,7 @@ int NormalContainer::whereToInsertAppTrayByDefault(FashionTrayWidgetWrapper *wra return 0; } for (int i = 0; i < wrapperList().size(); ++i) { - if (wrapperList().at(i)->absTrayWidget()->trayType() != AbstractTrayWidget::TrayType::ApplicationTray) { + if (wrapperList().at(i)->absTrayWidget()->trayTyep() != AbstractTrayWidget::TrayType::ApplicationTray) { insertIndex = i; break; } @@ -243,7 +244,7 @@ int NormalContainer::whereToInsertSystemTrayByDefault(FashionTrayWidgetWrapper * int firstSystemTrayIndex = -1; for (int i = 0; i < wrapperList().size(); ++i) { - if (wrapperList().at(i)->absTrayWidget()->trayType() == AbstractTrayWidget::TrayType::SystemTray) { + if (wrapperList().at(i)->absTrayWidget()->trayTyep() == AbstractTrayWidget::TrayType::SystemTray) { firstSystemTrayIndex = i; break; } @@ -253,7 +254,7 @@ int NormalContainer::whereToInsertSystemTrayByDefault(FashionTrayWidgetWrapper * return wrapperList().size(); } // the inserting tray is not a SystemTray - if (wrapper->absTrayWidget()->trayType() != AbstractTrayWidget::TrayType::SystemTray) { + if (wrapper->absTrayWidget()->trayTyep() != AbstractTrayWidget::TrayType::SystemTray) { return firstSystemTrayIndex; } @@ -263,7 +264,7 @@ int NormalContainer::whereToInsertSystemTrayByDefault(FashionTrayWidgetWrapper * return firstSystemTrayIndex; } for (int i = 0; i < wrapperList().size(); ++i) { - if (wrapperList().at(i)->absTrayWidget()->trayType() != AbstractTrayWidget::TrayType::SystemTray) { + if (wrapperList().at(i)->absTrayWidget()->trayTyep() != AbstractTrayWidget::TrayType::SystemTray) { continue; } if (insertIndex > trayPlugin()->itemSortKey(wrapperList().at(i)->itemKey())) { diff --git a/plugins/tray/fashiontray/containers/normalcontainer.h b/plugins/tray/fashiontray/containers/normalcontainer.h index 0158af784..6d953be3a 100644 --- a/plugins/tray/fashiontray/containers/normalcontainer.h +++ b/plugins/tray/fashiontray/containers/normalcontainer.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/spliteranimated.cpp b/plugins/tray/fashiontray/containers/spliteranimated.cpp index 9f0450780..71a04ca1e 100644 --- a/plugins/tray/fashiontray/containers/spliteranimated.cpp +++ b/plugins/tray/fashiontray/containers/spliteranimated.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/containers/spliteranimated.h b/plugins/tray/fashiontray/containers/spliteranimated.h index 14c51d732..f64624ae0 100644 --- a/plugins/tray/fashiontray/containers/spliteranimated.h +++ b/plugins/tray/fashiontray/containers/spliteranimated.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/fashiontrayconstants.h b/plugins/tray/fashiontray/fashiontrayconstants.h index 103df7522..f0a68af91 100644 --- a/plugins/tray/fashiontray/fashiontrayconstants.h +++ b/plugins/tray/fashiontray/fashiontrayconstants.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/fashiontraycontrolwidget.cpp b/plugins/tray/fashiontray/fashiontraycontrolwidget.cpp index 148cd7ed2..35e8e847c 100644 --- a/plugins/tray/fashiontray/fashiontraycontrolwidget.cpp +++ b/plugins/tray/fashiontray/fashiontraycontrolwidget.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/fashiontraycontrolwidget.h b/plugins/tray/fashiontray/fashiontraycontrolwidget.h index 68f2a4c41..a706111a0 100644 --- a/plugins/tray/fashiontray/fashiontraycontrolwidget.h +++ b/plugins/tray/fashiontray/fashiontraycontrolwidget.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/fashiontrayitem.cpp b/plugins/tray/fashiontray/fashiontrayitem.cpp index dc105bc77..6ae0a8d67 100644 --- a/plugins/tray/fashiontray/fashiontrayitem.cpp +++ b/plugins/tray/fashiontray/fashiontrayitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/fashiontrayitem.h b/plugins/tray/fashiontray/fashiontrayitem.h index 74bfb3af0..15fa0bd8d 100644 --- a/plugins/tray/fashiontray/fashiontrayitem.h +++ b/plugins/tray/fashiontray/fashiontrayitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/fashiontraywidgetwrapper.cpp b/plugins/tray/fashiontray/fashiontraywidgetwrapper.cpp index 13297cb9b..592f2bea1 100644 --- a/plugins/tray/fashiontray/fashiontraywidgetwrapper.cpp +++ b/plugins/tray/fashiontray/fashiontraywidgetwrapper.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/fashiontray/fashiontraywidgetwrapper.h b/plugins/tray/fashiontray/fashiontraywidgetwrapper.h index c22bb4def..d24ea6c24 100644 --- a/plugins/tray/fashiontray/fashiontraywidgetwrapper.h +++ b/plugins/tray/fashiontray/fashiontraywidgetwrapper.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,13 +8,13 @@ #include "../abstracttraywidget.h" +#include "org_deepin_dde_gesture1.h" + #include #include #include -#include - -using Gesture = com::deepin::daemon::Gesture; +using Gesture = org::deepin::dde::Gesture1; #define TRAY_ITEM_DRAG_MIMEDATA "TrayItemDragDrop" diff --git a/plugins/tray/indicatortray.cpp b/plugins/tray/indicatortray.cpp index ad7237db5..62cb7ced0 100644 --- a/plugins/tray/indicatortray.cpp +++ b/plugins/tray/indicatortray.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/indicatortray.h b/plugins/tray/indicatortray.h index 65b02db30..a9bd01358 100644 --- a/plugins/tray/indicatortray.h +++ b/plugins/tray/indicatortray.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/indicatortraywidget.cpp b/plugins/tray/indicatortraywidget.cpp index 9cfcf7961..7f8907662 100644 --- a/plugins/tray/indicatortraywidget.cpp +++ b/plugins/tray/indicatortraywidget.cpp @@ -1,19 +1,16 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "indicatortraywidget.h" -#include "constants.h" #include "util/utils.h" #include #include -#include #include #include -#include -DGUI_USE_NAMESPACE IndicatorTrayWidget::IndicatorTrayWidget(const QString &indicatorName, QWidget *parent, Qt::WindowFlags f) : AbstractTrayWidget(parent, f) @@ -26,14 +23,20 @@ IndicatorTrayWidget::IndicatorTrayWidget(const QString &indicatorName, QWidget * auto layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); m_label = new QLabel(this); + + QPalette p = m_label->palette(); + p.setColor(QPalette::Foreground, Qt::white); + p.setColor(QPalette::Background, Qt::transparent); + m_label->setPalette(p); + m_label->setAttribute(Qt::WA_TranslucentBackground); layout->addWidget(m_label, 0, Qt::AlignCenter); setLayout(layout); // register dbus - auto path = QString("/com/deepin/dde/Dock/Indicator/") + m_indicatorName; - auto interface = QString("com.deepin.dde.Dock.Indicator.") + m_indicatorName; + auto path = QString("/org/deepin/dde/Dock1/Indicator/") + m_indicatorName; + auto interface = QString("org.deepin.dde.Dock1.Indicator.") + m_indicatorName; auto sessionBus = QDBusConnection::sessionBus(); sessionBus.registerObject(path, interface, @@ -47,9 +50,6 @@ IndicatorTrayWidget::IndicatorTrayWidget(const QString &indicatorName, QWidget * connect(m_gsettings, &QGSettings::changed, this, &IndicatorTrayWidget::onGSettingsChanged); } - - updateLabelColor(); - connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &IndicatorTrayWidget::updateLabelColor); } IndicatorTrayWidget::~IndicatorTrayWidget() @@ -73,33 +73,29 @@ void IndicatorTrayWidget::sendClick(uint8_t buttonIndex, int x, int y) } void IndicatorTrayWidget::enableLabel(bool enable) -{ - m_enableClick = enable; - m_label->setEnabled(enable); - updateLabelColor(); -} - -void IndicatorTrayWidget::resizeEvent(QResizeEvent *event) -{ - QWidget::resizeEvent(event); - - if (event->size().height() <= PLUGIN_BACKGROUND_MIN_SIZE || event->oldSize().height() <= PLUGIN_BACKGROUND_MIN_SIZE) - updateLabelColor(); -} - -void IndicatorTrayWidget::updateLabelColor() { QPalette p = m_label->palette(); - p.setColor(QPalette::Foreground, m_label->isEnabled() ? Qt::white : Qt::lightGray); - - if (height() <= PLUGIN_BACKGROUND_MIN_SIZE && DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) { - p.setColor(QPalette::Foreground, m_label->isEnabled() ? Qt::black : Qt::darkGray); + if (!enable) { + m_enableClick = false; + p.setColor(QPalette::Disabled, QPalette::Foreground, Qt::lightGray); + p.setColor(QPalette::Disabled, QPalette::Background, Qt::transparent); + m_label->setEnabled(enable); + } else { + m_enableClick = true; + p.setColor(QPalette::Normal, QPalette::BrightText, Qt::white); + p.setColor(QPalette::Normal, QPalette::Background, Qt::transparent); + m_label->setEnabled(enable); } m_label->setPalette(p); m_label->update(); } +void IndicatorTrayWidget::resizeEvent(QResizeEvent *event) +{ + return QWidget::resizeEvent(event); +} + void IndicatorTrayWidget::setPixmapData(const QByteArray &data) { auto rawPixmap = QPixmap::fromImage(QImage::fromData(data)); diff --git a/plugins/tray/indicatortraywidget.h b/plugins/tray/indicatortraywidget.h index 8f1e6cd31..489a7af70 100644 --- a/plugins/tray/indicatortraywidget.h +++ b/plugins/tray/indicatortraywidget.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -27,7 +28,6 @@ public: protected: void resizeEvent(QResizeEvent *event) override; - void updateLabelColor(); public Q_SLOTS: Q_SCRIPTABLE void setPixmapData(const QByteArray &data); diff --git a/plugins/tray/snitraywidget.cpp b/plugins/tray/snitraywidget.cpp index cb919691a..9036d051d 100644 --- a/plugins/tray/snitraywidget.cpp +++ b/plugins/tray/snitraywidget.cpp @@ -1,9 +1,11 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "snitraywidget.h" #include "util/themeappicon.h" +#include "util/utils.h" #include "../../widgets/tipswidget.h" #include @@ -28,10 +30,10 @@ QPointer SNITrayWidget::PopupWindow = nullptr; Dock::Position SNITrayWidget::DockPosition = Dock::Position::Top; using namespace Dock; SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent) - : AbstractTrayWidget(parent) - , m_dbusMenuImporter(nullptr) - , m_menu(nullptr) - , m_updateIconTimer(new QTimer(this)) + : AbstractTrayWidget(parent), + m_dbusMenuImporter(nullptr), + m_menu(nullptr), + m_updateIconTimer(new QTimer(this)) , m_updateOverlayIconTimer(new QTimer(this)) , m_updateAttentionIconTimer(new QTimer(this)) , m_sniServicePath(sniServicePath) @@ -56,6 +58,10 @@ SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent) arrowRectangle->setArrowWidth(18); arrowRectangle->setArrowHeight(10); arrowRectangle->setObjectName("snitraypopup"); + if (Utils::IS_WAYLAND_DISPLAY) { + Qt::WindowFlags flags = arrowRectangle->windowFlags() | Qt::FramelessWindowHint; + arrowRectangle->setWindowFlags(flags); + } PopupWindow = arrowRectangle; connect(qApp, &QApplication::aboutToQuit, PopupWindow, &DockPopupWindow::deleteLater); } @@ -108,8 +114,6 @@ SNITrayWidget::SNITrayWidget(const QString &sniServicePath, QWidget *parent) connect(m_sniInter, &StatusNotifierItem::OverlayIconPixmapChanged, this, &SNITrayWidget::onSNIOverlayIconPixmapChanged); connect(m_sniInter, &StatusNotifierItem::StatusChanged, this, &SNITrayWidget::onSNIStatusChanged); - connect(this, &SNITrayWidget::requestShowMenu, this, &SNITrayWidget::showContextMenu); - // the following signals can be emit automatically // need refresh cached properties in these slots connect(m_sniInter, &StatusNotifierItem::NewIcon, [ = ] { @@ -153,8 +157,7 @@ void SNITrayWidget::updateIcon() void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y) { switch (mouseButton) { - case XCB_BUTTON_INDEX_1: - { + case XCB_BUTTON_INDEX_1: { QFuture future = QtConcurrent::run([ = ] { StatusNotifierItem inter(m_dbusService, m_dbusPath, QDBusConnection::sessionBus()); QDBusPendingReply<> reply = inter.Activate(x, y); @@ -162,7 +165,7 @@ void SNITrayWidget::sendClick(uint8_t mouseButton, int x, int y) // primarily work for apps using libappindicator. reply.waitForFinished(); if (reply.isError()) { - Q_EMIT requestShowMenu(x, y); + showContextMenu(x,y); } }); } @@ -273,8 +276,6 @@ void SNITrayWidget::initMenu() qDebug() << "generate the sni menu object"; m_menu = m_dbusMenuImporter->menu(); - if (m_menu && !m_menu->parentWidget()) - m_menu->setParent(topLevelWidget(), Qt::Popup); qDebug() << "the sni menu obect is:" << m_menu; } @@ -598,7 +599,7 @@ void SNITrayWidget::handleMouseRelease() Q_ASSERT(sender() == m_handleMouseReleaseTimer); // do not dealwith all mouse event of SystemTray, class SystemTrayItem will handle it - if (trayType() == SystemTray) + if (trayTyep() == SystemTray) return; const QPoint point(m_lastMouseReleaseData.first - rect().center()); diff --git a/plugins/tray/snitraywidget.h b/plugins/tray/snitraywidget.h index d4f6b5b88..7c8f57570 100644 --- a/plugins/tray/snitraywidget.h +++ b/plugins/tray/snitraywidget.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -9,7 +10,7 @@ #include "abstracttraywidget.h" #include "util/dockpopupwindow.h" -#include +#include "org_kde_statusnotifieritem.h" #include #include @@ -19,7 +20,7 @@ class DBusMenuImporter; namespace Dock { class TipsWidget; } -//using namespace com::deepin::dde; + using namespace org::kde; /** @@ -60,7 +61,6 @@ public: Q_SIGNALS: void statusChanged(SNITrayWidget::ItemStatus status); - void requestShowMenu(int x, int y); private Q_SLOTS: void initSNIPropertys(); diff --git a/plugins/tray/system-trays/systemtrayitem.cpp b/plugins/tray/system-trays/systemtrayitem.cpp index 9ff1387cc..8608c5aea 100644 --- a/plugins/tray/system-trays/systemtrayitem.cpp +++ b/plugins/tray/system-trays/systemtrayitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -7,6 +8,7 @@ #include #include +#include #include @@ -17,6 +19,7 @@ SystemTrayItem::SystemTrayItem(PluginsItemInterface *const pluginInter, const QS : AbstractTrayWidget(parent) , m_popupShown(false) , m_tapAndHold(false) + , m_contextMenu(new QMenu) // 此处设置parent有问题,会导致当前菜单显示透明,因此设置parent为nullptr,在析构函数中释放 , m_pluginInter(pluginInter) , m_centralWidget(m_pluginInter->itemWidget(itemKey)) , m_popupTipsDelayTimer(new QTimer(this)) @@ -48,10 +51,18 @@ SystemTrayItem::SystemTrayItem(PluginsItemInterface *const pluginInter, const QS arrowRectangle->setArrowWidth(18); arrowRectangle->setArrowHeight(10); arrowRectangle->setObjectName("systemtraypopup"); + if (Utils::IS_WAYLAND_DISPLAY) { + Qt::WindowFlags flags = arrowRectangle->windowFlags() | Qt::FramelessWindowHint; + arrowRectangle->setWindowFlags(flags); + } PopupWindow = arrowRectangle; connect(qApp, &QApplication::aboutToQuit, PopupWindow, &DockPopupWindow::deleteLater); } + if (Utils::IS_WAYLAND_DISPLAY) { + Qt::WindowFlags flags = m_contextMenu->windowFlags() | Qt::FramelessWindowHint; + m_contextMenu->setWindowFlags(flags); + } // 必须初始化父窗口,否则当主题切换之后再设置父窗口的时候palette会更改为主题切换前的palette if (QWidget *w = m_pluginInter->itemPopupApplet(m_itemKey)) { w->setParent(PopupWindow.data()); @@ -66,7 +77,7 @@ SystemTrayItem::SystemTrayItem(PluginsItemInterface *const pluginInter, const QS connect(m_popupTipsDelayTimer, &QTimer::timeout, this, &SystemTrayItem::showHoverTips); connect(m_popupAdjustDelayTimer, &QTimer::timeout, this, &SystemTrayItem::updatePopupPosition, Qt::QueuedConnection); - connect(&m_contextMenu, &QMenu::triggered, this, &SystemTrayItem::menuActionClicked); + connect(m_contextMenu, &QMenu::triggered, this, &SystemTrayItem::menuActionClicked); if (m_gsettings) connect(m_gsettings, &QGSettings::changed, this, &SystemTrayItem::onGSettingsChanged); @@ -76,6 +87,7 @@ SystemTrayItem::SystemTrayItem(PluginsItemInterface *const pluginInter, const QS SystemTrayItem::~SystemTrayItem() { + m_contextMenu->deleteLater(); if (m_popupShown) popupWindowAccept(); } @@ -418,7 +430,7 @@ void SystemTrayItem::showContextMenu() QJsonObject jsonMenu = jsonDocument.object(); - qDeleteAll(m_contextMenu.actions()); + qDeleteAll(m_contextMenu->actions()); QJsonArray jsonMenuItems = jsonMenu.value("items").toArray(); for (auto item : jsonMenuItems) { @@ -428,16 +440,13 @@ void SystemTrayItem::showContextMenu() action->setChecked(itemObj.value("checked").toBool()); action->setData(itemObj.value("itemId").toString()); action->setEnabled(itemObj.value("isActive").toBool()); - m_contextMenu.addAction(action); + m_contextMenu->addAction(action); } hidePopup(); emit requestWindowAutoHide(false); - if (!m_contextMenu.parentWidget()) - m_contextMenu.setParent(topLevelWidget(), Qt::Popup); - - m_contextMenu.exec(QCursor::pos()); + m_contextMenu->exec(QCursor::pos()); onContextMenuAccepted(); } diff --git a/plugins/tray/system-trays/systemtrayitem.h b/plugins/tray/system-trays/systemtrayitem.h index 08c136d82..09a5eaa8d 100644 --- a/plugins/tray/system-trays/systemtrayitem.h +++ b/plugins/tray/system-trays/systemtrayitem.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -11,10 +12,10 @@ #include "pluginsiteminterface.h" #include -#include class QGSettings; -class Menu; +class QMenu; + class SystemTrayItem : public AbstractTrayWidget { Q_OBJECT @@ -27,7 +28,7 @@ public: QString itemKeyForConfig() override; void updateIcon() override; void sendClick(uint8_t mouseButton, int x, int y) override; - inline TrayType trayType() const override { return TrayType::SystemTray; } + inline TrayType trayTyep() const override { return TrayType::SystemTray; } QWidget *trayTipsWidget(); QWidget *trayPopupApplet(); @@ -80,7 +81,7 @@ private: private: bool m_popupShown; bool m_tapAndHold; - QMenu m_contextMenu; + QMenu *m_contextMenu; PluginsItemInterface* m_pluginInter; QWidget *m_centralWidget; diff --git a/plugins/tray/system-trays/systemtrayscontroller.cpp b/plugins/tray/system-trays/systemtrayscontroller.cpp index 311cfaedf..200bf8ff2 100644 --- a/plugins/tray/system-trays/systemtrayscontroller.cpp +++ b/plugins/tray/system-trays/systemtrayscontroller.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "systemtrayscontroller.h" #include "pluginsiteminterface.h" #include "utils.h" +#include "proxyplugincontroller.h" #include #include @@ -13,6 +15,22 @@ SystemTraysController::SystemTraysController(QObject *parent) : AbstractPluginsController(parent) { setObjectName("SystemTray"); + + // 将当前对象添加进代理对象列表中,代理对象在加载插件成功后,会调用列表中所有对象的itemAdded方法来添加插件 + ProxyPluginController::instance(PluginType::QuickPlugin)->addProxyInterface(this); + ProxyPluginController::instance(PluginType::SystemTrays)->addProxyInterface(this); + + QMetaObject::invokeMethod(this, [ this ] { + // 在加载当前的tray插件之前,所有的插件已经加载,因此此处需要获取代理中已经加载过的插件来加载到当前布局中 + loadPlugins(ProxyPluginController::instance(PluginType::QuickPlugin)); + loadPlugins(ProxyPluginController::instance(PluginType::SystemTrays)); + }, Qt::QueuedConnection); +} + +SystemTraysController::~SystemTraysController() +{ + ProxyPluginController::instance(PluginType::QuickPlugin)->removeProxyInterface(this); + ProxyPluginController::instance(PluginType::SystemTrays)->removeProxyInterface(this); } void SystemTraysController::itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) @@ -28,11 +46,10 @@ void SystemTraysController::itemAdded(PluginsItemInterface * const itemInter, co connect(item, &SystemTrayItem::itemVisibleChanged, this, [=] (bool visible){ if (visible) { emit pluginItemAdded(itemKey, item); - } - else { + } else { emit pluginItemRemoved(itemKey, item); } - }); + }, Qt::QueuedConnection); mPluginsMap[itemInter][itemKey] = item; @@ -69,10 +86,7 @@ void SystemTraysController::itemRemoved(PluginsItemInterface * const itemInter, item->centralWidget()->setParent(nullptr); // just delete our wrapper object(PluginsItem) - // 直接删除,item被用到的地方太多,且很多地方没判断是否为空,不应该用deleteLater - // item->deleteLater(); - delete item; - item = nullptr; + item->deleteLater(); } void SystemTraysController::requestWindowAutoHide(PluginsItemInterface * const itemInter, const QString &itemKey, const bool autoHide) @@ -100,21 +114,6 @@ void SystemTraysController::requestSetAppletVisible(PluginsItemInterface * const return; if (visible) { - // 在弹出界面前先隐藏其他插件的tips - QMap> &mPluginsMap = pluginsMap(); - foreach (auto interface, mPluginsMap.keys()) { - if (interface != itemInter) { - foreach (auto oldItemKey, mPluginsMap[interface].keys()) { - if (oldItemKey != "pluginloader") { - SystemTrayItem *oldItem = qobject_cast(pluginItemAt(interface, oldItemKey)); - if (oldItem) { - oldItem->hidePopup(); - } - } - } - } - } - item->showPopupApplet(itemInter->itemPopupApplet(itemKey)); } else { item->hidePopup(); @@ -125,9 +124,8 @@ int SystemTraysController::systemTrayItemSortKey(const QString &itemKey) { auto inter = pluginInterAt(itemKey); - if (!inter) { + if (!inter) return -1; - } return inter->itemSortKey(itemKey); } @@ -136,9 +134,8 @@ void SystemTraysController::setSystemTrayItemSortKey(const QString &itemKey, con { auto inter = pluginInterAt(itemKey); - if (!inter) { + if (!inter) return; - } inter->setSortKey(itemKey, order); } @@ -147,9 +144,8 @@ const QVariant SystemTraysController::getValueSystemTrayItem(const QString &item { auto inter = pluginInterAt(itemKey); - if (!inter) { + if (!inter) return QVariant(); - } return getValue(inter, key, fallback); } @@ -158,20 +154,16 @@ void SystemTraysController::saveValueSystemTrayItem(const QString &itemKey, cons { auto inter = pluginInterAt(itemKey); - if (!inter) { + if (!inter) return; - } saveValue(inter, key, value); } -void SystemTraysController::startLoader() +void SystemTraysController::loadPlugins(ProxyPluginController *proxyController) { - QString pluginsDir("../plugins/system-trays"); - if (!QDir(pluginsDir).exists()) { - pluginsDir = "/usr/lib/dde-dock/plugins/system-trays"; - } - qDebug() << "using system tray plugins dir:" << pluginsDir; - - AbstractPluginsController::startLoader(new PluginLoader(pluginsDir, this)); + // 加载已有插件,并将其添加到当前的插件中 + const QList &pluginsItems = proxyController->pluginsItems(); + for (PluginsItemInterface *itemInter : pluginsItems) + itemAdded(itemInter, proxyController->itemKey(itemInter)); } diff --git a/plugins/tray/system-trays/systemtrayscontroller.h b/plugins/tray/system-trays/systemtrayscontroller.h index 25305de68..2c0aabbc6 100644 --- a/plugins/tray/system-trays/systemtrayscontroller.h +++ b/plugins/tray/system-trays/systemtrayscontroller.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -9,20 +10,21 @@ #include "pluginproxyinterface.h" #include "util/abstractpluginscontroller.h" -#include - #include #include #include #include class PluginsItemInterface; +class ProxyPluginController; + class SystemTraysController : public AbstractPluginsController { Q_OBJECT public: explicit SystemTraysController(QObject *parent = nullptr); + ~SystemTraysController() override; // implements PluginProxyInterface void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override; @@ -38,12 +40,13 @@ public: const QVariant getValueSystemTrayItem(const QString &itemKey, const QString &key, const QVariant& fallback = QVariant()); void saveValueSystemTrayItem(const QString &itemKey, const QString &key, const QVariant &value); - void startLoader(); - signals: void pluginItemAdded(const QString &itemKey, AbstractTrayWidget *pluginItem) const; void pluginItemRemoved(const QString &itemKey, AbstractTrayWidget *pluginItem) const; void pluginItemUpdated(const QString &itemKey, AbstractTrayWidget *pluginItem) const; + +private: + void loadPlugins(ProxyPluginController *proxyController); }; #endif // SYSTEMTRAYSCONTROLLER_H diff --git a/plugins/tray/tray.json b/plugins/tray/tray.json index 40c82cea6..051df050f 100644 --- a/plugins/tray/tray.json +++ b/plugins/tray/tray.json @@ -1,4 +1,4 @@ { - "api": "1.1.1", - "depends-daemon-dbus-service": "com.deepin.dde.TrayManager" + "api": "2.0.0", + "depends-daemon-dbus-service": "org.deepin.dde.TrayManager1" } diff --git a/plugins/tray/trayplugin.cpp b/plugins/tray/trayplugin.cpp index c27bcedab..f751ca444 100644 --- a/plugins/tray/trayplugin.cpp +++ b/plugins/tray/trayplugin.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -94,7 +95,6 @@ void TrayPlugin::init(PluginProxyInterface *proxyInter) // 加载sni,xem,自定义indicator协议以及其他托盘插件 QTimer::singleShot(0, this, &TrayPlugin::loadIndicator); - QTimer::singleShot(0, m_systemTraysController, &SystemTraysController::startLoader); QTimer::singleShot(0, this, &TrayPlugin::initSNI); QTimer::singleShot(0, this, &TrayPlugin::initXEmbed); } @@ -260,7 +260,7 @@ bool TrayPlugin::isSystemTrayItem(const QString &itemKey) { AbstractTrayWidget *const trayWidget = m_trayMap.value(itemKey, nullptr); - if (trayWidget && trayWidget->trayType() == AbstractTrayWidget::TrayType::SystemTray) { + if (trayWidget && trayWidget->trayTyep() == AbstractTrayWidget::TrayType::SystemTray) { return true; } @@ -376,7 +376,7 @@ void TrayPlugin::addTrayWidget(const QString &itemKey, AbstractTrayWidget *trayW return; } - if (m_trayMap.values().contains(trayWidget)) { + if (m_trayMap.contains(itemKey) || m_trayMap.values().contains(trayWidget)) { return; } @@ -420,17 +420,13 @@ void TrayPlugin::traySNIAdded(const QString &itemKey, const QString &sniServiceP return; } - std::lock_guard lock(m_sniMutex); - if (m_trayMap.contains(itemKey) || m_passiveSNITrayMap.contains(itemKey)) { - return; - } - SNITrayWidget *trayWidget = new SNITrayWidget(sniServicePath); // TODO(lxz): 在future里已经对dbus进行过检查了,这里应该不需要再次检查。 if (!trayWidget->isValid()) return; + std::lock_guard lock(m_sniMutex); if (trayWidget->status() == SNITrayWidget::ItemStatus::Passive) { m_passiveSNITrayMap.insert(itemKey, trayWidget); } else { @@ -533,11 +529,10 @@ void TrayPlugin::trayRemoved(const QString &itemKey, const bool deleteObject) // only delete tray object when it is a tray of applications // set the parent of the tray object to avoid be deconstructed by parent(DockItem/PluginsItem/TrayPluginsItem) - if (widget->trayType() == AbstractTrayWidget::TrayType::SystemTray) { + if (widget->trayTyep() == AbstractTrayWidget::TrayType::SystemTray) { widget->setParent(nullptr); } else if (deleteObject) { widget->deleteLater(); - widget = nullptr; } } diff --git a/plugins/tray/trayplugin.h b/plugins/tray/trayplugin.h index e25a3c172..71e413c2a 100644 --- a/plugins/tray/trayplugin.h +++ b/plugins/tray/trayplugin.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/plugins/tray/xembedtraywidget.cpp b/plugins/tray/xembedtraywidget.cpp index 7f00bab89..07a4be5ad 100644 --- a/plugins/tray/xembedtraywidget.cpp +++ b/plugins/tray/xembedtraywidget.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -11,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +31,7 @@ #define WINE_WINDOW_PROP_NAME "__wine_prefix" #define IS_WINE_WINDOW_BY_WM_CLASS "explorer.exe" -static const uint16_t iconDefaultSize = PLUGIN_ICON_MAX_SIZE; +static const qreal iconSize = PLUGIN_ICON_MAX_SIZE; // this static var hold all suffix of tray widget keys. // that is in order to fix can not show multiple trays provide by one application, @@ -71,7 +71,6 @@ XEmbedTrayWidget::XEmbedTrayWidget(quint32 winId, xcb_connection_t *cnn, Display , m_valid(true) , m_xcbCnn(cnn) , m_display(disp) - , m_injectMode(Direct) { wrapWindow(); setOwnerPID(getWindowPID(winId)); @@ -172,16 +171,15 @@ void XEmbedTrayWidget::wrapWindow() } auto cookie = xcb_get_geometry(c, m_windowId); - QScopedPointer clientGeom(xcb_get_geometry_reply(c, cookie, nullptr)); + xcb_get_geometry_reply_t *clientGeom(xcb_get_geometry_reply(c, cookie, Q_NULLPTR)); if (!clientGeom) { m_valid = false; return; } + free(clientGeom); //create a container window - //创建托盘window,并使背景透明化 const auto ratio = devicePixelRatioF(); - uint16_t iconSize = iconDefaultSize * ratio; auto screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; m_containerWid = xcb_generate_id(c); uint32_t values[2]; @@ -193,7 +191,7 @@ void XEmbedTrayWidget::wrapWindow() m_containerWid, /* window Id */ screen->root, /* parent window */ 0, 0, /* x, y */ - iconSize, iconSize, /* width, height */ + iconSize * ratio, iconSize * ratio, /* width, height */ 0, /* border_width */ XCB_WINDOW_CLASS_INPUT_OUTPUT,/* class */ screen->root_visual, /* visual */ @@ -256,45 +254,31 @@ void XEmbedTrayWidget::wrapWindow() // xembed_message_send(m_windowId, XEMBED_EMBEDDED_NOTIFY, m_containerWid, 0, 0); //move window we're embedding + /* const uint32_t windowMoveConfigVals[2] = { 0, 0 }; xcb_configure_window(c, m_windowId, - XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, windowMoveConfigVals); + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, + windowMoveCentially quitting the application. Returns onfigVals); + */ - // 判断托盘的大小是否超出iconSize - QSize clientWindowSize; - if (clientGeom) { - clientWindowSize = QSize(clientGeom->width, clientGeom->height); - } - - if (clientWindowSize.isEmpty() || clientWindowSize.width() > iconSize || clientWindowSize.height() > iconSize ) { - - uint16_t widthNormalized = std::min(clientGeom->width, iconSize); - uint16_t heighNormalized = std::min(clientGeom->height, iconSize); - - const uint32_t windowSizeConfigVals[2] = {widthNormalized, heighNormalized}; - xcb_configure_window(c, m_windowId, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, windowSizeConfigVals); - - xcb_flush(c); - clientWindowSize = QSize(iconSize, iconSize); + //if the window is a clearly stupid size resize to be something sensible + //this is needed as chormium and such when resized just fill the icon with transparent space and only draw in the middle + //however spotify does need this as by default the window size is 900px wide. + //use an artbitrary heuristic to make sure icons are always sensible +// if (clientGeom->width > iconSize || clientGeom->height > iconSize ) + { + const uint32_t windowMoveConfigVals[2] = { uint32_t(iconSize * ratio), uint32_t(iconSize * ratio) }; + xcb_configure_window(c, m_windowId, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + windowMoveConfigVals); } //show the embedded window otherwise nothing happens xcb_map_window(c, m_windowId); - xcb_clear_area(c, 0, m_windowId, 0, 0, clientWindowSize.width(), clientWindowSize.height()); - // xcb_clear_area(c, 0, m_windowId, 0, 0, qMin(clientGeom->width, iconSize), qMin(clientGeom->height, iconSize)); xcb_flush(c); - - // 通过xcb获取window属性,判断该window是否处理button press事件 - // 当window不关注button press等事件时,使用xtest extension - auto windowAttributesCookie = xcb_get_window_attributes(c, m_windowId); - QScopedPointer windowAttributes(xcb_get_window_attributes_reply(c, windowAttributesCookie, nullptr)); - if (windowAttributes && !(windowAttributes->all_event_masks & XCB_EVENT_MASK_BUTTON_PRESS)) { - m_injectMode = XTest; - } - // setWindowOnTop(false); setWindowOnTop(true); setX11PassMouseEvent(true); @@ -306,33 +290,15 @@ void XEmbedTrayWidget::sendHoverEvent() return; } + // fake enter event const QPoint p(rawXPosition(QCursor::pos())); configContainerPosition(); setX11PassMouseEvent(false); setWindowOnTop(true); Display *display = IS_WAYLAND_DISPLAY ? m_display : QX11Info::display(); if (display) { - if (m_injectMode == XTest || IS_WAYLAND_DISPLAY) { - // fake enter event - XTestFakeMotionEvent(display, 0, p.x(), p.y(), CurrentTime); - XFlush(display); - } else { - // 发送 montion notify event到client,实现hover事件 - auto c = QX11Info::connection(); - xcb_motion_notify_event_t* event = new xcb_motion_notify_event_t; - memset(event, 0x00, sizeof(xcb_motion_notify_event_t)); - event->response_type = XCB_MOTION_NOTIFY; - event->event = m_windowId; - event->same_screen = 1; - event->root = QX11Info::appRootWindow(); - event->time = 0; - event->root_x = p.x(); - event->root_y = p.y(); - event->child = 0; - event->state = 0; - xcb_send_event(c, false, m_windowId, XCB_EVENT_MASK_POINTER_MOTION, (char*)event); - delete event; - } + XTestFakeMotionEvent(display, 0, p.x(), p.y(), CurrentTime); + XFlush(display); } QTimer::singleShot(100, this, [=] { setX11PassMouseEvent(true); }); @@ -367,59 +333,19 @@ void XEmbedTrayWidget::sendClick(uint8_t mouseButton, int x, int y) return; m_sendHoverEvent->stop(); - auto c = QX11Info::connection(); - if (!c) { - qWarning() << "QX11Info::connection() is " << c; - return; - } + const QPoint p(rawXPosition(QPoint(x, y))); configContainerPosition(); setX11PassMouseEvent(false); setWindowOnTop(true); Display *display = IS_WAYLAND_DISPLAY ? m_display : QX11Info::display(); - - if (m_injectMode == XTest) { - XTestFakeMotionEvent(display, 0, p.x(), p.y(), CurrentTime); - XFlush(display); - XTestFakeButtonEvent(display, mouseButton, true, CurrentTime); - XFlush(display); - XTestFakeButtonEvent(display, mouseButton, false, CurrentTime); - XFlush(display); - } else { - // press event - xcb_button_press_event_t *pressEvent = new xcb_button_press_event_t; - memset(pressEvent, 0x00, sizeof(xcb_button_press_event_t)); - pressEvent->response_type = XCB_BUTTON_PRESS; - pressEvent->event = m_windowId; - pressEvent->same_screen = 1; - pressEvent->root = QX11Info::appRootWindow(); - pressEvent->time = 0; - pressEvent->root_x = p.x(); - pressEvent->root_y = p.y(); - pressEvent->child = 0; - pressEvent->state = 0; - pressEvent->detail = mouseButton; - xcb_send_event(c, false, m_windowId, XCB_EVENT_MASK_BUTTON_PRESS, (char*)pressEvent); - delete pressEvent; - - // release event - xcb_button_release_event_t *releaseEvent = new xcb_button_release_event_t; - memset(releaseEvent, 0x00, sizeof(xcb_button_release_event_t)); - releaseEvent->response_type = XCB_BUTTON_RELEASE; - releaseEvent->event = m_windowId; - releaseEvent->same_screen = 1; - releaseEvent->root = QX11Info::appRootWindow(); - releaseEvent->time = QX11Info::getTimestamp(); - releaseEvent->root_x = p.x(); - releaseEvent->root_y = p.y(); - releaseEvent->child = 0; - releaseEvent->state = 0; - releaseEvent->detail = mouseButton; - xcb_send_event(c, false, m_windowId, XCB_EVENT_MASK_BUTTON_RELEASE, (char*)releaseEvent); - delete releaseEvent; - } - + XTestFakeMotionEvent(display, 0, p.x(), p.y(), CurrentTime); + XFlush(display); + XTestFakeButtonEvent(display, mouseButton, true, CurrentTime); + XFlush(display); + XTestFakeButtonEvent(display, mouseButton, false, CurrentTime); + XFlush(display); QTimer::singleShot(100, this, [=] { setX11PassMouseEvent(true); }); } @@ -492,8 +418,8 @@ void XEmbedTrayWidget::refershIconImage() expose.window = m_containerWid; expose.x = 0; expose.y = 0; - expose.width = iconDefaultSize * ratio; - expose.height = iconDefaultSize * ratio; + expose.width = iconSize * ratio; + expose.height = iconSize * ratio; xcb_send_event_checked(c, false, m_containerWid, XCB_EVENT_MASK_VISIBILITY_CHANGE, reinterpret_cast(&expose)); xcb_flush(c); @@ -509,7 +435,7 @@ void XEmbedTrayWidget::refershIconImage() return; } - m_image = qimage.scaled(iconDefaultSize * ratio, iconDefaultSize * ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation); + m_image = qimage.scaled(iconSize * ratio, iconSize * ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation); m_image.setDevicePixelRatio(ratio); update(); diff --git a/plugins/tray/xembedtraywidget.h b/plugins/tray/xembedtraywidget.h index 12973b8ff..9e27c65ea 100644 --- a/plugins/tray/xembedtraywidget.h +++ b/plugins/tray/xembedtraywidget.h @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -50,13 +51,6 @@ private slots: bool isBadWindow(); private: - // Direct client关注xevent,使用xevent来处理button事件等 - // XTest client不关注xevent,使用xtest extension处理 - enum InjectMode { - Direct, - XTest, - }; - bool m_active = false; WId m_windowId; WId m_containerWid; @@ -68,7 +62,6 @@ private: bool m_valid; xcb_connection_t *m_xcbCnn; Display* m_display; - InjectMode m_injectMode; }; #endif // XEMBEDTRAYWIDGET_H diff --git a/rpm/dde-dock.spec b/rpm/dde-dock.spec index 942299ade..1eaa1ec01 100644 --- a/rpm/dde-dock.spec +++ b/rpm/dde-dock.spec @@ -4,13 +4,14 @@ Name: dde-dock Version: 5.4.9 Release: 1 Summary: Deepin desktop-environment - Dock module -License: LGPL-3.0-or-later +License: GPLv3 URL: http://shuttle.corp.deepin.com/cache/repos/eagle/release-candidate/RERFNS4wLjAuNjU3NQ/pool/main/d/dde-dock/ Source0: %{name}-%{version}.orig.tar.xz BuildRequires: cmake BuildRequires: gcc-c++ BuildRequires: pkgconfig(dbusmenu-qt5) +BuildRequires: pkgconfig(dde-network-utils) BuildRequires: dtkwidget-devel >= 5.1 BuildRequires: dtkcore-devel >= 5.1 BuildRequires: pkgconfig(dframeworkdbus) >= 2.0 @@ -32,6 +33,7 @@ BuildRequires: qt5-linguist BuildRequires: gtest-devel BuildRequires: gmock-devel Requires: dbusmenu-qt5 +Requires: dde-network-utils Requires: dde-qt-dbus-factory Requires: xcb-util-wm Requires: xcb-util-image @@ -86,7 +88,7 @@ export PATH=%{_qt5_bindir}:$PATH %{_bindir}/%{name} %{_libdir}/%{name}/ %{_datarootdir}/glib-2.0/schemas/com.deepin.dde.dock.module.gschema.xml -%{_datarootdir}/polkit-1/actions/com.deepin.dde.dock.overlay.policy +%{_datarootdir}/polkit-1/actions/org.deepin.dde.dock.overlay.policy %files devel %{_includedir}/%{name}/ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 45994a1c4..86b83aa63 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,19 +14,22 @@ file(GLOB_RECURSE SRCS "../widgets/*.h" "../widgets/*.cpp") +list(REMOVE_ITEM SRCS "plugins/dcc-dock-settings-plugin/*.cpp") + # Sources files file(GLOB_RECURSE PLUGIN_SRCS "../plugins/bluetooth/*.h" "../plugins/bluetooth/*.cpp" "../plugins/bluetooth/componments/*.h" "../plugins/bluetooth/componments/*.cpp" - "../plugins/dcc-dock-plugin/*.h" - "../plugins/dcc-dock-plugin/*.cpp" + #"../plugins/dcc-dock-plugin/*.h" + #"../plugins/dcc-dock-plugin/*.cpp" "../frame/util/horizontalseperator.h" "../frame/util/horizontalseperator.cpp") + # 其包含的"interface/moduleinterface.h"文件中定义了ModuleInterface_iid,任务栏插件框架的interface文件中也有定义 -list(FILTER PLUGIN_SRCS EXCLUDE REGEX "../plugins/dcc-dock-plugin/settings_module.*") +#list(FILTER PLUGIN_SRCS EXCLUDE REGEX "../plugins/dcc-dock-plugin/settings_module.*") # 用于测试覆盖率的编译条件 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -lgcov") @@ -48,13 +51,14 @@ find_package(Qt5DBus REQUIRED) find_package(DtkWidget REQUIRED) find_package(Qt5Svg REQUIRED) find_package(Qt5 COMPONENTS Test REQUIRED) -find_package(DdeControlCenter REQUIRED) +#find_package(DdeControlCenter REQUIRED) find_package(GTest REQUIRED) find_package(GMock REQUIRED) +find_package(dbusmenu-qt5 REQUIRED) pkg_check_modules(QGSettings REQUIRED gsettings-qt) pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) -pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor) +pkg_check_modules(XCB_EWMH REQUIRED xcb-image xcb-composite xtst xcb-ewmh xext dbusmenu-qt5 x11 xcursor) # 添加执行文件信息 add_executable(${BIN_NAME} @@ -72,12 +76,12 @@ target_include_directories(${BIN_NAME} PUBLIC ${DFrameworkDBus_INCLUDE_DIRS} ${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${QGSettings_INCLUDE_DIRS} - ${DdeControlCenter_INCLUDE_DIR} + #${DdeControlCenter_INCLUDE_DIR} ../interfaces fakedbus ../plugins/bluetooth ../plugins/bluetooth/componments - ../plugins/dcc-dock-plugin + #../plugins/dcc-dock-plugin ) # 链接库 @@ -92,7 +96,7 @@ target_link_libraries(${BIN_NAME} PRIVATE ${Qt5DBus_LIBRARIES} ${QGSettings_LIBRARIES} ${Qt5Svg_LIBRARIES} - ${DdeControlCenter_LIBRARIES} + #${DdeControlCenter_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} -lpthread diff --git a/tests/controller/ut_dockitemmanager.cpp b/tests/controller/ut_dockitemmanager.cpp index db62eb77f..fdcff2294 100644 --- a/tests/controller/ut_dockitemmanager.cpp +++ b/tests/controller/ut_dockitemmanager.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/controller/ut_dockplugincontroller.cpp b/tests/controller/ut_dockplugincontroller.cpp index 71d1f0a81..1e16dc43f 100644 --- a/tests/controller/ut_dockplugincontroller.cpp +++ b/tests/controller/ut_dockplugincontroller.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/display/ut_displaymanager.cpp b/tests/display/ut_displaymanager.cpp index 4a9bb9e35..260fae8f2 100644 --- a/tests/display/ut_displaymanager.cpp +++ b/tests/display/ut_displaymanager.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/components/ut_appdrag.cpp b/tests/item/components/ut_appdrag.cpp index f9dc567a4..0740cebd9 100644 --- a/tests/item/components/ut_appdrag.cpp +++ b/tests/item/components/ut_appdrag.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/components/ut_appdragwidget.cpp b/tests/item/components/ut_appdragwidget.cpp index 745b4c66e..4f2d1bb94 100644 --- a/tests/item/components/ut_appdragwidget.cpp +++ b/tests/item/components/ut_appdragwidget.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/components/ut_appsnapshot.cpp b/tests/item/components/ut_appsnapshot.cpp index 0e0c3a4f6..d661cd603 100644 --- a/tests/item/components/ut_appsnapshot.cpp +++ b/tests/item/components/ut_appsnapshot.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/components/ut_floatingpreview.cpp b/tests/item/components/ut_floatingpreview.cpp index faab8fee7..7b8db9faa 100644 --- a/tests/item/components/ut_floatingpreview.cpp +++ b/tests/item/components/ut_floatingpreview.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/components/ut_previewcontainer.cpp b/tests/item/components/ut_previewcontainer.cpp index 475b8d64d..dea560310 100644 --- a/tests/item/components/ut_previewcontainer.cpp +++ b/tests/item/components/ut_previewcontainer.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/testplugin.cpp b/tests/item/testplugin.cpp index 26afcd581..78ebf9819 100644 --- a/tests/item/testplugin.cpp +++ b/tests/item/testplugin.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/testplugin.h b/tests/item/testplugin.h index 64b4c4a54..2bc0f747c 100644 --- a/tests/item/testplugin.h +++ b/tests/item/testplugin.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/ut_appitem.cpp b/tests/item/ut_appitem.cpp index ad7cefc7b..6b7bdbfa4 100644 --- a/tests/item/ut_appitem.cpp +++ b/tests/item/ut_appitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -31,7 +32,7 @@ void Test_AppItem::SetUp() activeSettings = Utils::ModuleSettingsPtr("activeapp"); dockedSettings = Utils::ModuleSettingsPtr("dockapp"); - appItem = new AppItem(appSettings, activeSettings, dockedSettings, QDBusObjectPath("/com/deepin/dde/daemon/Dock/entries/e0T6045b766")); + appItem = new AppItem(appSettings, activeSettings, dockedSettings, QDBusObjectPath("/org/deepin/dde/daemon/Dock1/entries/e0T6045b766")); } void Test_AppItem::TearDown() @@ -93,6 +94,7 @@ TEST_F(Test_AppItem, coverage_test) appItem->checkGSettingsControl(); appItem->showHoverTips(); appItem->popupTips(); + appItem->startDrag(); appItem->playSwingEffect(); appItem->invokedMenuItem("invalid", true); appItem->contextMenu(); diff --git a/tests/item/ut_dockitem.cpp b/tests/item/ut_dockitem.cpp index 2a3e4551a..9e0c05dda 100644 --- a/tests/item/ut_dockitem.cpp +++ b/tests/item/ut_dockitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/ut_launcheritem.cpp b/tests/item/ut_launcheritem.cpp index a9f033bb0..a536813f1 100644 --- a/tests/item/ut_launcheritem.cpp +++ b/tests/item/ut_launcheritem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/ut_placeholderitem.cpp b/tests/item/ut_placeholderitem.cpp index 74244fe21..cbc3f85d1 100644 --- a/tests/item/ut_placeholderitem.cpp +++ b/tests/item/ut_placeholderitem.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/ut_pluginsitem.cpp b/tests/item/ut_pluginsitem.cpp index b11fcde8a..9f8268274 100644 --- a/tests/item/ut_pluginsitem.cpp +++ b/tests/item/ut_pluginsitem.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/item/ut_traypluginitem.cpp b/tests/item/ut_traypluginitem.cpp index 178056000..511050e6a 100644 --- a/tests/item/ut_traypluginitem.cpp +++ b/tests/item/ut_traypluginitem.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/main.cpp b/tests/main.cpp index 7d3c342e2..ab0a620ab 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -20,7 +21,6 @@ int main(int argc, char **argv) DockApplication app(argc, argv); // 设置应用名为dde-dock,否则dconfig相关的配置就读不到了 - // TODO dtk已经有相关接口,待下次修改 app.setApplicationName("dde-dock"); qApp->setProperty("CANSHOW", true); diff --git a/tests/plugins/dcc-dock-settings-plugin/ut_gsettings_watcher.cpp b/tests/plugins/dcc-dock-settings-plugin/ut_gsettings_watcher.cpp index 23817db64..a04f4e34c 100644 --- a/tests/plugins/dcc-dock-settings-plugin/ut_gsettings_watcher.cpp +++ b/tests/plugins/dcc-dock-settings-plugin/ut_gsettings_watcher.cpp @@ -1,53 +1,49 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later -#include "config_watcher.h" +//#include "config_watcher.h" #include -#include #include -using namespace dcc_dock_plugin; +//using namespace dcc_dock_plugin; class Test_GSettingWatcher : public QObject, public ::testing::Test {}; TEST_F(Test_GSettingWatcher, bind) { - const QString &appName = qApp->applicationName(); - qApp->setApplicationName("dde-dock"); - ConfigWatcher watcher("org.deepin.dde.control-center", "org.deepin.dde.dock.plugin"); +/* ConfigWatcher watcher("dde.dock.plugin.dconfig"); QWidget widget; - watcher.bind("dockPlugins", &widget); - watcher.bind("dockPlugins", nullptr); + watcher.bind("Control-Center_Dock_Plugins", &widget); + watcher.bind("Control-Center_Dock_Plugins", nullptr); watcher.bind("invalid", &widget); watcher.bind("", &widget); watcher.bind("", nullptr); - qApp->setApplicationName(appName); + */ } TEST_F(Test_GSettingWatcher, setStatus) { - const QString &appName = qApp->applicationName(); - qApp->setApplicationName("dde-control-center"); - ConfigWatcher watcher("org.deepin.dde.control-center", "org.deepin.dde.dock.plugin"); +/* ConfigWatcher watcher("dde.dock.plugin.dconfig"); QWidget widget; - watcher.bind("dockPlugins", &widget); - watcher.setStatus("dockPlugins", &widget); - qApp->setApplicationName(appName); + watcher.bind("Control-Center_Dock_Plugins", &widget); + watcher.setStatus("Control-Center_Dock_Plugins", &widget); + */ } TEST_F(Test_GSettingWatcher, onStatusModeChanged) { - ConfigWatcher watcher("org.deepin.dde.control-center", "org.deepin.dde.dock.plugin"); +/* ConfigWatcher watcher("dde.dock.plugin.dconfig"); QWidget widget; - watcher.bind("dockPlugins", &widget); - watcher.onStatusModeChanged("dockPlugins"); + watcher.bind("Control-Center_Dock_Plugins", &widget); + watcher.onStatusModeChanged("Control-Center_Dock_Plugins"); watcher.onStatusModeChanged("invalid"); watcher.onStatusModeChanged(""); + */ } diff --git a/tests/plugins/dcc-dock-settings-plugin/ut_module_widget.cpp b/tests/plugins/dcc-dock-settings-plugin/ut_module_widget.cpp index 12cd90c11..88f913854 100644 --- a/tests/plugins/dcc-dock-settings-plugin/ut_module_widget.cpp +++ b/tests/plugins/dcc-dock-settings-plugin/ut_module_widget.cpp @@ -1,8 +1,8 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later -#include "module_widget.h" +//#include "module_widget.h" #include @@ -13,7 +13,7 @@ class Test_ModuleWidget : public QObject, public ::testing::Test TEST_F(Test_ModuleWidget, updateSliderValue) { - ModuleWidget widget; + //ModuleWidget widget; - widget.updateSliderValue(); + //widget.updateSliderValue(); } diff --git a/tests/util/ut_dockapplication.cpp b/tests/util/ut_dockapplication.cpp index 33a1d29e4..093cc7377 100644 --- a/tests/util/ut_dockapplication.cpp +++ b/tests/util/ut_dockapplication.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/util/ut_dockpopupwindow.cpp b/tests/util/ut_dockpopupwindow.cpp index 4f75160e8..058dc18dd 100644 --- a/tests/util/ut_dockpopupwindow.cpp +++ b/tests/util/ut_dockpopupwindow.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -13,7 +14,7 @@ #include -DGUI_USE_NAMESPACE +DWIDGET_USE_NAMESPACE class Test_DockPopupWindow : public QObject, public ::testing::Test { diff --git a/tests/util/ut_horizontalseperator.cpp b/tests/util/ut_horizontalseperator.cpp index 7ff56e552..906ccb40b 100644 --- a/tests/util/ut_horizontalseperator.cpp +++ b/tests/util/ut_horizontalseperator.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/util/ut_imageutil.cpp b/tests/util/ut_imageutil.cpp index f142c9eb7..f55a84cd8 100644 --- a/tests/util/ut_imageutil.cpp +++ b/tests/util/ut_imageutil.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/util/ut_menuworker.cpp b/tests/util/ut_menuworker.cpp index d5054bb9f..191eb66b7 100644 --- a/tests/util/ut_menuworker.cpp +++ b/tests/util/ut_menuworker.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -17,7 +18,7 @@ class Test_MenuWorker : public ::testing::Test TEST_F(Test_MenuWorker, coverage_test) { - MenuWorker *worker = new MenuWorker(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus())); + MenuWorker *worker = new MenuWorker(new DBusDock("org.deepin.dde.daemon.Dock1", "/org/deepin/dde/daemon/Dock1", QDBusConnection::sessionBus())); DockItemManager::instance()->m_pluginsInter->m_pluginsMap.clear(); QMenu *menu = new QMenu(); menu = worker->createMenu(menu); @@ -31,7 +32,7 @@ TEST_F(Test_MenuWorker, coverage_test) TEST_F(Test_MenuWorker, setAutoHide) { - MenuWorker *worker = new MenuWorker(new DBusDock("com.deepin.dde.daemon.Dock", "/com/deepin/dde/daemon/Dock", QDBusConnection::sessionBus())); + MenuWorker *worker = new MenuWorker(new DBusDock("org.deepin.dde.daemon.Dock1", "/org/deepin/dde/daemon/Dock1", QDBusConnection::sessionBus())); ASSERT_TRUE(worker->m_autoHide); worker->setAutoHide(false); diff --git a/tests/util/ut_multiscreenworker.cpp b/tests/util/ut_multiscreenworker.cpp index 45d368bc2..2de3a990d 100644 --- a/tests/util/ut_multiscreenworker.cpp +++ b/tests/util/ut_multiscreenworker.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -19,7 +20,7 @@ class Test_MultiScreenWorker : public ::testing::Test TEST_F(Test_MultiScreenWorker, coverage_test) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); qDebug() << worker->dockRect("test screen"); @@ -30,7 +31,7 @@ TEST_F(Test_MultiScreenWorker, coverage_test) worker->updateDaemonDockSize(20); QDBusMessage msg; - worker->handleDBusSignal(msg); + worker->handleDbusSignal(msg); worker->onRegionMonitorChanged(0, 0, worker->m_registerKey); @@ -42,6 +43,7 @@ TEST_F(Test_MultiScreenWorker, coverage_test) worker->checkXEventMonitorService(); worker->showAniFinished(); worker->hideAniFinished(); + worker->primaryScreenChanged(); worker->onRequestUpdateFrontendGeometry(); worker->isCopyMode(); worker->onRequestUpdatePosition(Dock::Position::Top, Dock::Position::Bottom); @@ -56,7 +58,7 @@ TEST_F(Test_MultiScreenWorker, coverage_test) TEST_F(Test_MultiScreenWorker, onDisplayModeChanged) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->onDisplayModeChanged(static_cast(0)); worker->m_hideMode = HideMode::KeepShowing; @@ -81,7 +83,7 @@ TEST_F(Test_MultiScreenWorker, onDisplayModeChanged) TEST_F(Test_MultiScreenWorker, displayAnimation_onRequestUpdateRegionMonitor) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->m_position = Dock::Position::Left; worker->displayAnimation("primary", MultiScreenWorker::AniAction::Show); @@ -120,7 +122,7 @@ TEST_F(Test_MultiScreenWorker, displayAnimation_onRequestUpdateRegionMonitor) TEST_F(Test_MultiScreenWorker, onTouchPress_onTouchRelease) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); QPoint p(0, 0); worker->rawXPosition(p); @@ -156,7 +158,7 @@ TEST_F(Test_MultiScreenWorker, onTouchPress_onTouchRelease) TEST_F(Test_MultiScreenWorker, onDelayAutoHideChanged) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->m_hideMode = HideMode::SmartHide; worker->m_hideState = HideState::Show; @@ -177,7 +179,7 @@ TEST_F(Test_MultiScreenWorker, onDelayAutoHideChanged) TEST_F(Test_MultiScreenWorker, onPositionChanged) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->m_hideMode = HideMode::KeepHidden; worker->onPositionChanged(static_cast(0)); @@ -202,7 +204,7 @@ TEST_F(Test_MultiScreenWorker, onPositionChanged) TEST_F(Test_MultiScreenWorker, reInitDisplayData) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->reInitDisplayData(); @@ -213,7 +215,7 @@ TEST_F(Test_MultiScreenWorker, reInitDisplayData) TEST_F(Test_MultiScreenWorker, onRequestUpdateMonitorInfo) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->onRequestUpdateMonitorInfo(); @@ -224,7 +226,7 @@ TEST_F(Test_MultiScreenWorker, onRequestUpdateMonitorInfo) TEST_F(Test_MultiScreenWorker, updateParentGeometry) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->updateParentGeometry(QRect(0, 0, 10, 10), Position::Top); worker->updateParentGeometry(QRect(0, 0, 10, 10), Position::Bottom); @@ -238,7 +240,7 @@ TEST_F(Test_MultiScreenWorker, updateParentGeometry) TEST_F(Test_MultiScreenWorker, onWindowSizeChanged) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->onWindowSizeChanged(-1); @@ -249,7 +251,7 @@ TEST_F(Test_MultiScreenWorker, onWindowSizeChanged) TEST_F(Test_MultiScreenWorker, updateDisplay) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->updateDisplay(); @@ -260,7 +262,7 @@ TEST_F(Test_MultiScreenWorker, updateDisplay) TEST_F(Test_MultiScreenWorker, onExtralRegionMonitorChanged) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->onExtralRegionMonitorChanged(0, 0, "test"); @@ -282,7 +284,7 @@ TEST_F(Test_MultiScreenWorker, onExtralRegionMonitorChanged) TEST_F(Test_MultiScreenWorker, onRegionMonitorChanged) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->onRegionMonitorChanged(0, 0, "test"); @@ -307,7 +309,7 @@ TEST_F(Test_MultiScreenWorker, dockScreen) TEST_F(Test_MultiScreenWorker, screenworker_test3) { MainWindow window; - MultiScreenWorker *worker = new MultiScreenWorker(&window); + MultiScreenWorker *worker = new MultiScreenWorker(&window, DWindowManagerHelper::instance()); worker->resetDockScreen(); diff --git a/tests/util/ut_pluginloader.cpp b/tests/util/ut_pluginloader.cpp index b5e6dfa67..ffe058486 100644 --- a/tests/util/ut_pluginloader.cpp +++ b/tests/util/ut_pluginloader.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/util/ut_themeappicon.cpp b/tests/util/ut_themeappicon.cpp index 518f93461..39c222445 100644 --- a/tests/util/ut_themeappicon.cpp +++ b/tests/util/ut_themeappicon.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/util/ut_touchsignalmanager.cpp b/tests/util/ut_touchsignalmanager.cpp index 1ea02417b..c9fcd5773 100644 --- a/tests/util/ut_touchsignalmanager.cpp +++ b/tests/util/ut_touchsignalmanager.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/util/ut_utils.cpp b/tests/util/ut_utils.cpp index 8fe947d14..f68e18928 100644 --- a/tests/util/ut_utils.cpp +++ b/tests/util/ut_utils.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/widgets/ut_tipswidget.cpp b/tests/widgets/ut_tipswidget.cpp index edc378b44..c7b04a716 100644 --- a/tests/widgets/ut_tipswidget.cpp +++ b/tests/widgets/ut_tipswidget.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/window/ut_mainpanelcontrol.cpp b/tests/window/ut_mainpanelcontrol.cpp index efeca35f8..ad9bb29f5 100644 --- a/tests/window/ut_mainpanelcontrol.cpp +++ b/tests/window/ut_mainpanelcontrol.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/tests/window/ut_mainwindow.cpp b/tests/window/ut_mainwindow.cpp index dab72ed81..63207d49c 100644 --- a/tests/window/ut_mainwindow.cpp +++ b/tests/window/ut_mainwindow.cpp @@ -1,4 +1,5 @@ -// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// Copyright (C) 2018 ~ 2020 Uniontech Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/translations/dde-dock.ts b/translations/dde-dock.ts index 72b323953..cccc01236 100644 --- a/translations/dde-dock.ts +++ b/translations/dde-dock.ts @@ -1,4 +1,6 @@ - + + + AbstractPluginsController @@ -44,10 +46,21 @@ - AppDragWidget + AppMultiItem - Remove - Remove + Open + Open + + + + BloothAdapterWidget + + My Devices + My Devices + + + Other Devices + Other Devices @@ -88,12 +101,35 @@ Turned off + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Turn on + + + Turn off + Turn off + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Turn on + + + Turn off + Turn off + DBusAdaptors @@ -102,6 +138,21 @@ Add keyboard layout + + DateTimeDisplayer + + 12-hour time + 12-hour time + + + 24-hour time + 24-hour time + + + Time settings + Time settings + + DatetimePlugin @@ -122,66 +173,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Monday - - - Tuesday - Tuesday - - - Wednesday - Wednesday - - - Thursday - Thursday - - - Friday - Friday - - - Saturday - Saturday - - - Sunday - Sunday - - - monday - monday - - - tuesday - tuesday - - - wednesday - wednesday - - - thursday - thursday - - - friday - friday - - - saturday - saturday - - - sunday - sunday - - - %1year%2month%3day - %1year%2month%3day + PC collaboration + PC collaboration @@ -204,29 +199,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Unknown device - - - Unknown volume - Unknown volume + Multi-Screen Collaboration + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + The plugin %1 is not compatible with the system. + + + + HomeMonitorPlugin + + Enabled + Enabled - Open - Open - - - Unmount all - Unmount all + Disabled + Disabled @@ -236,21 +230,6 @@ Launcher - - MainWindow - - Exit Safe Mode - Exit Safe Mode - - - Dock - Safe Mode - Dock - Safe Mode - - - The Dock is in safe mode, please exit to show it properly - The Dock is in safe mode, please exit to show it properly - - MenuWorker @@ -306,105 +285,6 @@ Dock settings - - ModuleWidget - - Size - Size - Dock - /personalization/Dock - - - Multiple Displays - Multiple Displays - Dock - /personalization/Dock - - - Plugin Area - Plugin Area - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Select which icons appear in the Dock - - - Fashion mode - Fashion mode - - - Efficient mode - Efficient mode - - - Mode - Mode - Dock - /personalization/Dock - - - Top - Top - - - Bottom - Bottom - - - Left - Left - - - Right - Right - - - Location - Location - Dock - /personalization/Dock - - - Keep shown - Keep shown - - - Keep hidden - Keep hidden - - - Smart hide - Smart hide - - - Status - Status - Dock - /personalization/Dock - - - Small - Small - - - Large - Large - - - Show Dock - Show Dock - - - On screen where the cursor is - On screen where the cursor is - - - Only on main screen - Only on main screen - - MultitaskingPlugin @@ -422,21 +302,9 @@ Onboard Onboard - - Settings - Settings - PowerPlugin - - Power - Power - - - Power settings - Power settings - Capacity %1, %2 min remaining Capacity %1, %2 min remaining @@ -469,36 +337,9 @@ Capacity %1, fully charged Capacity %1, fully charged - - - SettingsModule - Dock - Dock - - - Mode - Mode - - - Location - Location - - - Status - Status - - - Size - Size - - - Show Dock - Show Dock - - - Plugin Area - Plugin Area + Battery + @@ -514,10 +355,6 @@ ShutdownPlugin - - Power - Power - Shut down Shut down @@ -550,12 +387,27 @@ Reboot Reboot + + Power + Power + SoundApplet - Volume - Volume + Device + Device + + + + SoundDevicesWidget + + Output Device + Output Device + + + Sound settings + Sound settings @@ -576,10 +428,6 @@ Volume %1 Volume %1 - - No output devices - No output devices - SoundPlugin @@ -618,4 +466,19 @@ Empty - \ No newline at end of file + + WindowManager + + Exit Safe Mode + Exit Safe Mode + + + Dock - Safe Mode + Dock - Safe Mode + + + The Dock is in safe mode, please exit to show it properly + The Dock is in safe mode, please exit to show it properly + + + diff --git a/translations/dde-dock_ady.ts b/translations/dde-dock_ady.ts new file mode 100644 index 000000000..4a94e6c3c --- /dev/null +++ b/translations/dde-dock_ady.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_af.ts b/translations/dde-dock_af.ts index 910dec54f..d018401ac 100644 --- a/translations/dde-dock_af.ts +++ b/translations/dde-dock_af.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Oop + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bloutand + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bloutand + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bloutand + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - Skyf - - - Open - Oop - - - Unmount all + The plugin %1 is not compatible with the system. - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Deaktiveerd + + + + LauncherItem + + Launcher + Lanseerder + + + + MenuWorker Fashion Mode @@ -143,17 +279,10 @@ - Plugins + Dock settings - - LauncherItem - - Launcher - Lanseerder - - MultitaskingPlugin @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Netwerk - - OnboardPlugin Onboard - - Settings - - PowerPlugin - - Power - Krag - - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +320,23 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -231,18 +353,10 @@ ShutdownPlugin - - Power - Krag - Shut down Skakel af - - Restart - Herlaai - Suspend Opskort @@ -267,6 +381,14 @@ Power settings + + Reboot + + + + Power + Krag + SoundApplet @@ -274,8 +396,15 @@ Device Toestel + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +419,11 @@ Demp - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +448,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +465,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown - Onbekend - - - Wired connection: %1 - - - - - WirelessItem - - No Network + Exit Safe Mode - Wireless Connection: %1 + Dock - Safe Mode - Connected but no Internet access - - - - - WirelessList - - Wireless Network - Draadlose Netwerk - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_ak.ts b/translations/dde-dock_ak.ts index 9b1c569c6..ebd7aa1fc 100644 --- a/translations/dde-dock_ak.ts +++ b/translations/dde-dock_ak.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,10 +6,148 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Open + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors Add keyboard layout + Add keyboard layout + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - - - - Open - Open - - - Unmount all + The plugin %1 is not compatible with the system. - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker Fashion Mode @@ -143,14 +279,7 @@ - Plugins - - - - - LauncherItem - - Launcher + Dock settings @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - Settings - PowerPlugin - - Power - Power - - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +320,23 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -231,17 +353,9 @@ ShutdownPlugin - - Power - Power - Shut down - - - - Restart - + Shut down Suspend @@ -249,7 +363,7 @@ Hibernate - + Hibernate Lock @@ -257,7 +371,7 @@ Log out - + Log out Switch account @@ -267,6 +381,14 @@ Power settings + + Reboot + Reboot + + + Power + Power + SoundApplet @@ -274,8 +396,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +419,11 @@ - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +448,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +465,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_am_ET.ts b/translations/dde-dock_am_ET.ts index 5f835ba63..b14dee71b 100644 --- a/translations/dde-dock_am_ET.ts +++ b/translations/dde-dock_am_ET.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + መክፈቻ + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + ብሉቱዝ + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + ብሉቱዝ + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + ብሉቱዝ + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ የ ፊደል ገበታ እቅድ መጨመሪያ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ ቀን እና ሰአት - 12 Hour Time - 12 ሰአት ጊዜ + 12-hour time + - 24 Hour Time - 24 ሰአት ጊዜ + 24-hour time + - Time Settings - ሰአት ማሰናጃ + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - ኔትዎርክ ማስቻያ - - - Disable network - ኔትዎርክ ማሰናከያ - - - Network settings - ኔትዎርክ ማሰናጃ + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - ያልታወቀ አካል - - - Unknown volume - ያልታወቀ መጠን + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - ዲስክ - - - Open - መክፈቻ - - - Unmount all - ሁሉንም ማውረጃ + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + ተሰናክሏል + + + + LauncherItem + + Launcher + ማስጀመሪያ + + + + MenuWorker Fashion Mode በ ዘመናዊ ዘዴ @@ -143,15 +279,8 @@ ሁኔታው - Plugins - ተሰኪዎች - - - - LauncherItem - - Launcher - ማስጀመሪያ + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - ኔትዎርክ - - OnboardPlugin Onboard - - Settings - ማሰናጃዎች - PowerPlugin - - Power - ሐይል - - - Power settings - ሐይል ማሰናጃ - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - ሞልቷል %1 - Charging %1, %2 min until full @@ -214,11 +320,23 @@ - Charging %1 .... + Capacity %1 - Charged + Charging %1 + በ መሙላት ላይ %1 + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -235,18 +353,10 @@ ShutdownPlugin - - Power - ሐይል - Shut down ማጥፊያ - - Restart - እንደገና ማስጀመሪያ - Suspend ማገጃ @@ -271,6 +381,14 @@ Power settings ሐይል ማሰናጃ + + Reboot + እንደገና ማስነሻ + + + Power + ሐይል + SoundApplet @@ -278,9 +396,16 @@ Device አካል + + + SoundDevicesWidget - Application - መተግበሪያ + Output Device + + + + Sound settings + @@ -294,12 +419,12 @@ መቀነሻ - Audio Settings - ድምፅ ማሰናጃ + Sound settings + - Current Volume %1 - የ አሁኑ መጠን %1 + Volume %1 + @@ -323,6 +448,10 @@ Trash - %1 files ቆሻሻ - %1 ፋይሎች + + Move to Trash + ወደ ቆሻሻ ማንቀሳቀሻ + TrashWidget @@ -336,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - የ ስርአት ትሪ: - - - - WiredItem - - Unknown - ያልታወቀ + Exit Safe Mode + - Wired connection: %1 - በ ሽቦ ግንኙነት: %1 - - - - WirelessItem - - No Network - ኔትዎርክ የለም + Dock - Safe Mode + - Wireless Connection: %1 - ሽቦ አልባ ኔትዎርክ: %1 - - - Connected but no Internet access + The Dock is in safe mode, please exit to show it properly - - WirelessList - - Wireless Network - ሽቦ አልባ ኔትዎርክ - - - Wireless Network %1 - ሽቦ አልባ ኔትዎርክ: %1 - - \ No newline at end of file diff --git a/translations/dde-dock_ar.ts b/translations/dde-dock_ar.ts index 131e5c46c..b715c7c12 100644 --- a/translations/dde-dock_ar.ts +++ b/translations/dde-dock_ar.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - إزالة + Open + فتح + + + + BloothAdapterWidget + + My Devices + أجهزتي + + + Other Devices + أجهزة أخرى @@ -88,12 +99,35 @@ + + BluetoothMainWidget + + Bluetooth + البلوتوث + + + Turn on + تشغيل + + + Turn off + ايقاف + + BluetoothPlugin Bluetooth البلوتوث + + Turn on + تشغيل + + + Turn off + ايقاف + DBusAdaptors @@ -102,6 +136,21 @@ إضافة تخطيط لوحة مفاتيح + + DateTimeDisplayer + + 12-hour time + توقيت 12-ساعة + + + 24-hour time + توقيت 24-ساعة + + + Time settings + إعدادات الوقت + + DatetimePlugin @@ -121,6 +170,13 @@ إعدادات الوقت + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -141,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - جهاز غير معروف - - - Unknown volume - مساحة غير معروفة + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - القرص + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - فتح - - - Unmount all - فصل الكل + Disabled + معطل @@ -173,21 +228,6 @@ المُطلق - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -243,93 +283,6 @@ - - ModuleWidget - - Size - الحجم - - - Multiple Displays - شاشات متعددة - - - Plugin Area - - - - Select which icons appear in the Dock - - - - Fashion mode - النمط الحداثي - - - Efficient mode - النمط الفعال - - - Mode - النمط - - - Top - أعلى - - - Bottom - أسفل - - - Left - يسار - - - Right - يمين - - - Location - الموقع - - - Keep shown - - - - Keep hidden - اﻹبقاء مخفياً - - - Smart hide - الاخفاء الذكي - - - Status - الحالة - - - Small - صغير - - - Large - كبير - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -347,21 +300,9 @@ Onboard لوحة المفاتيح الافتراضية - - Settings - الإعدادات - PowerPlugin - - Power - الطاقة - - - Power settings - إعدادت الطاقة - Capacity %1, %2 min remaining السعة 1%, 2% دقيقة متبقية @@ -394,13 +335,9 @@ Capacity %1, fully charged - - - SettingsModule - Dock - الرف - /personalization/Dock + Battery + @@ -416,10 +353,6 @@ ShutdownPlugin - - Power - الطاقة - Shut down إيقاف التشغيل @@ -452,6 +385,10 @@ Reboot إعادة التشغيل + + Power + الطاقة + SoundApplet @@ -460,6 +397,17 @@ الجهاز + + SoundDevicesWidget + + Output Device + + + + Sound settings + إعدادات الصوت + + SoundItem @@ -516,4 +464,19 @@ فارغ + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_ar_EG.ts b/translations/dde-dock_ar_EG.ts new file mode 100644 index 000000000..2366c6f3f --- /dev/null +++ b/translations/dde-dock_ar_EG.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + أغلق + + + Delete + إمسح + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_ast.ts b/translations/dde-dock_ast.ts index a1def8f13..064a8d068 100644 --- a/translations/dde-dock_ast.ts +++ b/translations/dde-dock_ast.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Abrir + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Amestar distribución de tecláu + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ Datetime - 12 Hour Time - 12h + 12-hour time + - 24 Hour Time - 24h + 24-hour time + - Time Settings - Axustes d'hora + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - Habilitar rede - - - Disable network - Deshabilitar rede - - - Network settings - Axustes de rede + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Preséu desconocíu - - - Unknown volume - Volume desconocíu + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Discu - - - Open - Abrir - - - Unmount all - Desmontar too + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Deshabilitau + + + + LauncherItem + + Launcher + Llanzador + + + + MenuWorker Fashion Mode Mou MacOS @@ -143,15 +279,8 @@ Estáu - Plugins - Complementos - - - - LauncherItem - - Launcher - Llanzador + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Rede - - OnboardPlugin Onboard - - Settings - Axustes - PowerPlugin - - Power - Enerxía - - - Power settings - Axustes d'enerxía - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - Cargóse %1 - Charging %1, %2 min until full @@ -214,11 +320,23 @@ - Charging %1 .... + Capacity %1 - Charged + Charging %1 + Cargando %1 + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -235,18 +353,10 @@ ShutdownPlugin - - Power - Enerxía - Shut down Apagar - - Restart - Reaniciar - Suspend Suspender @@ -271,6 +381,14 @@ Power settings Axustes d'enerxía + + Reboot + Reaniciar + + + Power + Enerxía + SoundApplet @@ -278,9 +396,16 @@ Device Preséu + + + SoundDevicesWidget - Application - Aplicación + Output Device + + + + Sound settings + @@ -294,12 +419,12 @@ Silenciar - Audio Settings - Axustes d'audiu + Sound settings + - Current Volume %1 - Volume actual %1 + Volume %1 + @@ -323,6 +448,10 @@ Trash - %1 files Papelera - %1 ficheros + + Move to Trash + Mover a la papelera + TrashWidget @@ -332,51 +461,22 @@ Empty - Baleru + Balero - TrayPlugin + WindowManager - System Tray - Bandexa del sistema - - - - WiredItem - - Unknown - Desconozse + Exit Safe Mode + - Wired connection: %1 - Conexón cableada: %1 - - - - WirelessItem - - No Network - Ensin rede + Dock - Safe Mode + - Wireless Connection: %1 - Conexón inalámbrica: %1 - - - Connected but no Internet access + The Dock is in safe mode, please exit to show it properly - - WirelessList - - Wireless Network - Rede inalámbrica - - - Wireless Network %1 - Rede inalámbrica %1 - - \ No newline at end of file diff --git a/translations/dde-dock_az.ts b/translations/dde-dock_az.ts index d727968d8..17c6857e8 100644 --- a/translations/dde-dock_az.ts +++ b/translations/dde-dock_az.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Silmək + Open + + + + + BloothAdapterWidget + + My Devices + Mənim cihazlarım + + + Other Devices + Digər cihazlar @@ -88,12 +99,35 @@ Söndürüldü + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Açmaq + + + Turn off + Söndürmək + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Açmaq + + + Turn off + Söndürmək + DBusAdaptors @@ -102,6 +136,21 @@ Klaviatura qatı əlavə etmək + + DateTimeDisplayer + + 12-hour time + 12 saat vaxt formatı + + + 24-hour time + 24 saat vaxt formatı + + + Time settings + Vaxt ayarları + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Bazar ertəsi - - - Tuesday - Çərşənbə axşamı - - - Wednesday - Çərşənbə - - - Thursday - Cümə axşamı - - - Friday - Cümə - - - Saturday - Şənbə - - - Sunday - Bazar - - - monday - bazar ertəsi - - - tuesday - çərşənbə axşamı - - - wednesday - çərşənbə - - - thursday - cümə axşamı - - - friday - cümə - - - saturday - şənbə - - - sunday - bazar - - - %1year%2month%3day - %1il%2ay%3gün + PC collaboration + PC ilə əməkdaşlıq @@ -196,7 +189,7 @@ Delete - Silmək + Sil This action cannot be restored @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Naməlum cihaz - - - Unknown volume - Naməlum həcm + Multi-Screen Collaboration + Çoxekranlı mübadilə - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Aktivdir - Open - - - - Unmount all - Hamısını çıxartmaq + Disabled + Aktiv deyil @@ -236,21 +228,6 @@ Başladıcı - - MainWindow - - Exit Safe Mode - Təhlükəsiz rejimdən çıxın - - - Dock - Safe Mode - Dok - Təhlükəsiz rejim - - - The Dock is in safe mode, please exit to show it properly - Dok təhlükəsiz rejimdədir, onun düzgün göstərilməsi üçün çıxın - - MenuWorker @@ -306,105 +283,6 @@ Dok panel ayarları - - ModuleWidget - - Size - Ölçü - Dock - /personalization/Dock - - - Multiple Displays - Çoxsaylı ekran - Dock - /personalization/Dock - - - Plugin Area - Plaqin sahəsi - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Dok paneldə görünəcək nişanları seçin - - - Fashion mode - Müasir rejim - - - Efficient mode - Səmərəli rejim - - - Mode - Rejim - Dock - /personalization/Dock - - - Top - Yuxarıda - - - Bottom - Aşağıda - - - Left - Sol - - - Right - Sağ - - - Location - Yerləşmə - Dock - /personalization/Dock - - - Keep shown - Görünsün - - - Keep hidden - Gizli qalsın - - - Smart hide - Ağıllı gizlənmə - - - Status - Vəziyyəti - Dock - /personalization/Dock - - - Small - Kiçik - - - Large - Geniş - - - Show Dock - Dok paneli göstərmək - - - On screen where the cursor is - Kursorun olduğu ekranda - - - Only on main screen - Yalnız əsas ekranda - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Ekran Klaviaturası - - Settings - Tənzimləmələr - PowerPlugin - - Power - Elektrik qidalanması - - - Power settings - Elektrik enerjisi ayarları - Capacity %1, %2 min remaining Tutum %1, %2 dəq qalır @@ -469,36 +335,9 @@ Capacity %1, fully charged Tutum %1, tam yükləndi - - - SettingsModule - Dock - Dok panel - - - Mode - Rejim - - - Location - Yerləşmə - - - Status - Vəziyyəti - - - Size - Ölçü - - - Show Dock - Dok paneli göstərmək - - - Plugin Area - Plaqin sahəsi + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Elektrik qidalanması - Shut down Sistemi söndür @@ -550,12 +385,27 @@ Reboot Yenidən başlatmaq + + Power + Elektrik qidalanması + SoundApplet - Volume - Səs səviyyəsi + Device + Avadanlıq + + + + SoundDevicesWidget + + Output Device + Çıxış cihazı + + + Sound settings + Səs ayarları @@ -576,10 +426,6 @@ Volume %1 Səs %1 - - No output devices - Çıxış cihazı tapılmadı - SoundPlugin @@ -618,4 +464,19 @@ Boş + + WindowManager + + Exit Safe Mode + Təhlükəsiz rejimdən çıxın + + + Dock - Safe Mode + Dok - Təhlükəsiz rejim + + + The Dock is in safe mode, please exit to show it properly + Dok təhlükəsiz rejimdədir, onun düzgün göstərilməsi üçün çıxın + + \ No newline at end of file diff --git a/translations/dde-dock_bg.ts b/translations/dde-dock_bg.ts index 7e85117a1..563732906 100644 --- a/translations/dde-dock_bg.ts +++ b/translations/dde-dock_bg.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ Приставката %1 не е съвместима със системата. + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Отваряне + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Добавяне на клавиатурна подредба + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -33,18 +171,10 @@ - DeviceItem + DevCollaborationWidget - Enable network - Включи мрежата - - - Disable network - Изключи мрежата - - - Network settings - Настройки на мрежата + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Непознато устройство - - - Unknown volume - Непознат носител + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Диск - - - Open - Отваряне - - - Unmount all - Демонтирай всички + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Изключен + + + + LauncherItem + + Launcher + Стартер + + + + MenuWorker Fashion Mode Модерен режим @@ -143,15 +279,8 @@ Статус - Plugins - Добавки - - - - LauncherItem - - Launcher - Стартер + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Мрежа - - OnboardPlugin Onboard На борда - - Settings - Настройки - PowerPlugin - - Power - Захранване - - - Power settings - Настройки на захранването - Capacity %1, %2 min remaining Капацитет %1, остават %2 минути @@ -209,10 +319,6 @@ Charging %1, %2 hr %3 min until full Зареждане на %1, %2 ч. %3 мин. до пълно зареждане - - Charged - Зареден - Capacity %1 @@ -229,6 +335,10 @@ Capacity %1, fully charged + + Battery + + ShowDesktopPlugin @@ -243,10 +353,6 @@ ShutdownPlugin - - Power - Захранване - Shut down Изключване @@ -279,6 +385,10 @@ Reboot Рестартиране + + Power + Захранване + SoundApplet @@ -286,9 +396,16 @@ Device Устройство + + + SoundDevicesWidget - Application - Приложение + Output Device + + + + Sound settings + @@ -331,6 +448,10 @@ Trash - %1 files Кошче - %1 файла + + Move to Trash + Премести в Кошчето + TrashWidget @@ -344,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - Зона за уведомяване - - - - WiredItem - - Unknown - Неизвестно + Exit Safe Mode + - Wired connection: %1 - Кабелна връзка: %1 - - - - WirelessItem - - No Network - Няма мрежа + Dock - Safe Mode + - Connected but no Internet access - Свързан но няма Интернет връзка - - - Wireless connection: %1 + The Dock is in safe mode, please exit to show it properly - - WirelessList - - Wireless Network - Безжична мрежа - - - Wireless Network %1 - Безжична връзка %1 - - \ No newline at end of file diff --git a/translations/dde-dock_bn.ts b/translations/dde-dock_bn.ts index 7797b0968..9b04079e5 100644 --- a/translations/dde-dock_bn.ts +++ b/translations/dde-dock_bn.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ %1 প্লাগিনটি সিস্টেমের জন্যে উপযুক্ত নয় + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + খুলুন + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + ব্লুটুথ + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + ব্লুটুথ + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + ব্লুটুথ + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ কীবোর্ড লেআউট যোগ করুন + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -33,18 +171,10 @@ - DeviceItem + DevCollaborationWidget - Enable network - নেটওয়ার্ক চালু করুন - - - Disable network - নেটওয়ার্ক বন্ধ করুন - - - Network settings - নেটওয়ার্কের সেটিংস + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - অপরিচিত ডিভাইস - - - Unknown volume - অজানা ভলিউম + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - ডিস্ক - - - Open - খুলুন - - - Unmount all - সবকিছু আনমাউন্ট করুন + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + অক্ষম + + + + LauncherItem + + Launcher + লঞ্চার + + + + MenuWorker Fashion Mode ফ্যাশন মোড @@ -143,15 +279,8 @@ অবস্থা - Plugins - প্লাগইন সমূহ - - - - LauncherItem - - Launcher - লঞ্চার + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - নেটওয়ার্ক - - OnboardPlugin Onboard ওনবোর্ড - - Settings - সেটিংস - PowerPlugin - - Power - পাওয়ার - - - Power settings - পাওয়ার সেটিংস - Capacity %1, %2 min remaining ধারণ ক্ষমতা %1, %2 min বাকি আছে @@ -209,10 +319,6 @@ Charging %1, %2 hr %3 min until full %1 চার্জ হচ্ছে, সম্পূর্ণ হতে %2 hr %3 min বাকি আছে - - Charged - - Capacity %1 @@ -229,6 +335,10 @@ Capacity %1, fully charged + + Battery + + ShowDesktopPlugin @@ -243,10 +353,6 @@ ShutdownPlugin - - Power - পাওয়ার - Shut down বন্ধ করুন @@ -279,6 +385,10 @@ Reboot পুনঃরায় চালু করুন + + Power + পাওয়ার + SoundApplet @@ -286,9 +396,16 @@ Device ডিভাইস + + + SoundDevicesWidget - Application - অ্যাপ্লিকেশন + Output Device + + + + Sound settings + @@ -331,6 +448,10 @@ Trash - %1 files %1 ফাইল ট্র্যাশ করুন + + Move to Trash + + TrashWidget @@ -344,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - সিস্টেম ট্রে - - - - WiredItem - - Unknown - অজানা + Exit Safe Mode + - Wired connection: %1 - তারের সংযোগঃ %1 - - - - WirelessItem - - No Network - নেটওয়ার্ক নেই + Dock - Safe Mode + - Connected but no Internet access - সংযুক্ত কিন্তু কোনো ইন্টারনেট এক্সেস নেই - - - Wireless connection: %1 + The Dock is in safe mode, please exit to show it properly - - WirelessList - - Wireless Network - ওয়্যারলেস নেটওয়ার্ক - - - Wireless Network %1 - ওয়্যারলেস নেটওয়ার্ক %1 - - \ No newline at end of file diff --git a/translations/dde-dock_bo.ts b/translations/dde-dock_bo.ts index a9c354ce5..8a1b1d497 100644 --- a/translations/dde-dock_bo.ts +++ b/translations/dde-dock_bo.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - སྤོ་འབུད། + Open + ཁ་ཕྱེ་བ། + + + + BloothAdapterWidget + + My Devices + ངའི་སྒྲིག་ཆས། + + + Other Devices + སྒྲིག་ཆས་གཞན། @@ -88,12 +99,35 @@ སོ་སྔོན་ཁ་རྒྱོབ། + + BluetoothMainWidget + + Bluetooth + སོ་སྔོན། + + + Turn on + སོ་སྔོན་ཁ་ཕྱེ། + + + Turn off + སོ་སྔོན་ཁ་རྒྱོབ། + + BluetoothPlugin Bluetooth སོ་སྔོན། + + Turn on + སོ་སྔོན་ཁ་ཕྱེ། + + + Turn off + སོ་སྔོན་ཁ་རྒྱོབ། + DBusAdaptors @@ -102,6 +136,21 @@ མཐེབ་གཞོང་བཀོད་པ་སྣོན་པ། + + DateTimeDisplayer + + 12-hour time + ཆུ་ཚོད་12ཀྱི་ལུགས། + + + 24-hour time + ཆུ་ཚོད་24ཡི་ལུགས། + + + Time settings + དུས་ཚོད་སྒྲིག་འགོད། + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - གཟའ་ཟླ་བ། - - - Tuesday - གཟའ་མིག་དམར། - - - Wednesday - གཟའ་ལྷག་པ། - - - Thursday - གཟའ་ཕུར་བུ། - - - Friday - གཟའ་པ་སངས། - - - Saturday - གཟའ་སྤེན་པ། - - - Sunday - གཟའ་ཉི་མ། - - - monday - གཟའ་ཟླ་བ། - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - གཟའ་ཉི་མ། - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - མ་ཤེས་པའི་སྒྲིག་ཆས། - - - Unknown volume - ཤོང་ཚད་མ་ཤེས་པ། + Multi-Screen Collaboration + གློག་ཀླད་མཐུན་སྦྱོར་སྒྲིག་འགོད། - DiskMountPlugin + DockPluginController - Disk - སྡུད་སྡེར། + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + འགོ་སློང་། - Open - ཁ་ཕྱེ་བ། - - - Unmount all - ཚང་མ་བཤིག་འདོན་བྱེད། + Disabled + སྤྱོད་མི་ཆོག @@ -236,21 +228,6 @@ འགོ་སློང་ཆས། - - MainWindow - - Exit Safe Mode - བདེ་འཇགས་དཔེ་རྣམ་ལས་ཕྱིར་དོན་པ། - - - Dock - Safe Mode - ལས་འགན་ཚན་བྱང་གི་བདེ་འཇགས་དཔེ་རྣམ། - - - The Dock is in safe mode, please exit to show it properly - ལས་འགན་ཚན་བྱང་བདེ་འཇགས་དཔེ་རྣམ་ནང་མཛུལ་ཟིན་པས། བདེ་འཇགས་དཔེ་རྣམ་ལས་ཕྱིར་དོན་རྗེས་རྒྱུན་ལྡན་ལྟར་ཤར་ཐུབ། - - MenuWorker @@ -306,105 +283,6 @@ ལས་འགན་ཚན་བྱང་སྒྲིག་འགོད། - - ModuleWidget - - Size - ཆེ་ཆུང་། - Dock - /personalization/Dock - - - Multiple Displays - བརྙན་མང་མངོན་སྟོན་སྒྲིག་འགོད། - Dock - /personalization/Dock - - - Plugin Area - ལྷུ་ལག་ཁུལ་ཁོངས། - Dock - /personalization/Dock - - - Select which icons appear in the Dock - ལས་འགན་ཚན་བྱང་གི་ལྷུ་ལག་ཁུལ་དུ་མངོན་པའི་པར་རིས་འདེམས་པ། - - - Fashion mode - དར་སྲོལ་དཔེ་རྣམ། - - - Efficient mode - ལས་ཆོད་ཆེ་བའི་དཔེ་རྣམ། - - - Mode - དཔེ་རྣམ། - Dock - /personalization/Dock - - - Top - གོང་། - - - Bottom - འོག - - - Left - གཡོན། - - - Right - གཡས། - - - Location - གནས་ས། - Dock - /personalization/Dock - - - Keep shown - རྟག་ཏུ་མངོན་པ། - - - Keep hidden - རྟག་ཏུ་ཡིབ་པ། - - - Smart hide - རིག་ནུས་གབ་ཡིབ། - - - Status - རྣམ་པ། - Dock - /personalization/Dock - - - Small - ཆུང་ངུ། - - - Large - ཆེ་བ། - - - Show Dock - ལས་འགན་ཚན་བྱང་གི་གནས་ས། - - - On screen where the cursor is - ཙི་གུའི་གནས་ཡུལ་ལྟར་མངོན་པ། - - - Only on main screen - བརྙན་ཡོལ་ཨ་མ་ཁོ་ན་མངོན་པ། - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard བརྙན་ཡོལ་མཐེབ་གཞོང་། - - Settings - སྒྲིག་འགོད། - PowerPlugin - - Power - གློག་ཁུངས་དོ་དམ། - - - Power settings - གློག་ཁུངས་སྒིག་འགོད། - Capacity %1, %2 min remaining གློག་ཚད་%1 སྐར་མ་%2ལྷག་འདུག @@ -469,36 +335,9 @@ Capacity %1, fully charged གློག་ཚད་%1 ཁེངས་ཟིན། - - - SettingsModule - Dock - ལས་འགན་ཚན་བྱང་། - - - Mode - དཔེ་རྣམ། - - - Location - གནས་ས། - - - Status - རྣམ་པ། - - - Size - ཆེ་ཆུང་། - - - Show Dock - ལས་འགན་ཚན་བྱང་གི་གནས་ས། - - - Plugin Area - ལྷུ་ལག་ཁུལ་ཁོངས། + Battery + @@ -514,13 +353,9 @@ ShutdownPlugin - - Power - གློག་ཁུངས་དོ་དམ། - Shut down - ཁ་བརྒྱབ། + རྩིས་འཁོར་གློག་གསོད། Suspend @@ -550,12 +385,27 @@ Reboot བསྐྱར་སློང་། + + Power + གློག་ཁུངས་དོ་དམ། + SoundApplet - Volume - + Device + སྒྲིག་ཆས། + + + + SoundDevicesWidget + + Output Device + ཕྱིར་འདྲེན་སྒྲིག་ཆས། + + + Sound settings + སྐད་གདངས་སྒྲིག་འགོད། @@ -576,10 +426,6 @@ Volume %1 མིག་སྔའི་སྐད་གདངས་%1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ གསལ་ཐོ་གཙང་སེལ། + + WindowManager + + Exit Safe Mode + བདེ་འཇགས་དཔེ་རྣམ་ལས་ཕྱིར་དོན་པ། + + + Dock - Safe Mode + ལས་འགན་ཚན་བྱང་གི་བདེ་འཇགས་དཔེ་རྣམ། + + + The Dock is in safe mode, please exit to show it properly + ལས་འགན་ཚན་བྱང་བདེ་འཇགས་དཔེ་རྣམ་ནང་མཛུལ་ཟིན་པས། བདེ་འཇགས་དཔེ་རྣམ་ལས་ཕྱིར་དོན་རྗེས་རྒྱུན་ལྡན་ལྟར་ཤར་ཐུབ། + + \ No newline at end of file diff --git a/translations/dde-dock_br.ts b/translations/dde-dock_br.ts new file mode 100644 index 000000000..9456acb59 --- /dev/null +++ b/translations/dde-dock_br.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Digeriñ + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + Nullañ + + + Delete + Dilemel + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + Mut + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + Son + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + Digeriñ + + + Empty + Goullo + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_ca.ts b/translations/dde-dock_ca.ts index d04e07c4a..234a922eb 100644 --- a/translations/dde-dock_ca.ts +++ b/translations/dde-dock_ca.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Elimina + Open + Obre + + + + BloothAdapterWidget + + My Devices + Els meus dispositius + + + Other Devices + Altres dispositius @@ -88,12 +99,35 @@ Apagat + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Activa + + + Turn off + Atura + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Activa + + + Turn off + Atura + DBusAdaptors @@ -102,6 +136,21 @@ Afegeix una disposició de teclat + + DateTimeDisplayer + + 12-hour time + 12 hores + + + 24-hour time + 24 hores + + + Time settings + Configuració de l'hora + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Dilluns - - - Tuesday - Dimarts - - - Wednesday - Dimecres - - - Thursday - Dijous - - - Friday - Divendres - - - Saturday - Dissabte - - - Sunday - Diumenge - - - monday - dilluns - - - tuesday - dimarts - - - wednesday - dimecres - - - thursday - dijous - - - friday - divendres - - - saturday - dissabte - - - sunday - diumenge - - - %1year%2month%3day - %3day%2month%1year + PC collaboration + Col·laboració de PC @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Dispositiu desconegut - - - Unknown volume - Volum desconegut + Multi-Screen Collaboration + Col·laboració multipantalla - DiskMountPlugin + DockPluginController - Disk - Disc + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Habilitat - Open - Obre - - - Unmount all - Desmunta-ho tot + Disabled + Inhabilitat @@ -236,21 +228,6 @@ Llançador - - MainWindow - - Exit Safe Mode - Surt del mode segur - - - Dock - Safe Mode - Acoblador - Mode segur - - - The Dock is in safe mode, please exit to show it properly - L'acoblador és en mode segur. Si us plau, sortiu-ne perquè es mostri adequadament. - - MenuWorker @@ -306,105 +283,6 @@ Paràmetres de l'acoblador - - ModuleWidget - - Size - Mida - Dock - /personalization/Dock - - - Multiple Displays - Pantalles múltiples - Dock - /personalization/Dock - - - Plugin Area - Àrea de connectors - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Seleccioneu quines icones apareixen a l'acoblador. - - - Fashion mode - Mode de moda - - - Efficient mode - Mode eficient - - - Mode - Mode - Dock - /personalization/Dock - - - Top - Dalt - - - Bottom - A baix - - - Left - A l'esquerra - - - Right - A la dreta - - - Location - Ubicació - Dock - /personalization/Dock - - - Keep shown - Mantén-lo visible - - - Keep hidden - Mantén-lo amagat - - - Smart hide - Ocultació intel·ligent - - - Status - Estat - Dock - /personalization/Dock - - - Small - petit - - - Large - gros - - - Show Dock - Mostra l'acoblador - - - On screen where the cursor is - A la pantalla el cursor és - - - Only on main screen - Només a la pantalla principal - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Abord - - Settings - Configuració - PowerPlugin - - Power - Energia - - - Power settings - Configuració de l'energia - Capacity %1, %2 min remaining Capacitat: %1, %2 min restants @@ -469,36 +335,9 @@ Capacity %1, fully charged Capacitat: 1%, completament carregada - - - SettingsModule - Dock - Acoblador - - - Mode - Mode - - - Location - Ubicació - - - Status - Estat - - - Size - Mida - - - Show Dock - Mostra l'acoblador - - - Plugin Area - Àrea de connectors + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Energia - Shut down Atura't @@ -536,7 +371,7 @@ Log out - Tanca la sessió + Surt de la sessió Switch account @@ -550,12 +385,27 @@ Reboot Reinicia + + Power + Energia + SoundApplet - Volume - Volum + Device + Dispositiu + + + + SoundDevicesWidget + + Output Device + Dispositiu de sortida + + + Sound settings + Configuració del so @@ -576,10 +426,6 @@ Volume %1 Volum: %1 - - No output devices - Sense dispositius de sortida - SoundPlugin @@ -618,4 +464,19 @@ Buit + + WindowManager + + Exit Safe Mode + Surt del mode segur + + + Dock - Safe Mode + Acoblador - Mode segur + + + The Dock is in safe mode, please exit to show it properly + L'acoblador està en mode segur. Si us plau, sortiu-ne perquè es mostri adequadament. + + \ No newline at end of file diff --git a/translations/dde-dock_cgg.ts b/translations/dde-dock_cgg.ts new file mode 100644 index 000000000..916e9d9d9 --- /dev/null +++ b/translations/dde-dock_cgg.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_cs.ts b/translations/dde-dock_cs.ts index a4b443e90..2e6cae348 100644 --- a/translations/dde-dock_cs.ts +++ b/translations/dde-dock_cs.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Odstranit + Open + Otevřít + + + + BloothAdapterWidget + + My Devices + Má zařízení + + + Other Devices + Ostatní zařízení @@ -88,12 +99,35 @@ Vypnuto + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Zapnout + + + Turn off + Vypnout + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Zapnout + + + Turn off + Vypnout + DBusAdaptors @@ -102,6 +136,21 @@ Přidat rozvržení klávesnice + + DateTimeDisplayer + + 12-hour time + 12 hodinový čas + + + 24-hour time + 24 hodinový čas + + + Time settings + Nastavení času + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - pondělí - - - Tuesday - úterý - - - Wednesday - středa - - - Thursday - čtvrtek - - - Friday - pátek - - - Saturday - sobota - - - Sunday - neděle - - - monday - pondělí - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - neděle - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Neznámé zařízení - - - Unknown volume - Neznámý svazek + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Zapnuto - Open - Otevřít - - - Unmount all - Odpojit vše + Disabled + Zakázáno @@ -236,21 +228,6 @@ Spouštěč - - MainWindow - - Exit Safe Mode - Ukončit náhradní režim - - - Dock - Safe Mode - Panel – náhradní režim - - - The Dock is in safe mode, please exit to show it properly - Dok je v náhradním režimu – ukončete, aby se zobrazil správně - - MenuWorker @@ -306,105 +283,6 @@ Nastavení panelu - - ModuleWidget - - Size - Velikost - Dock - /personalization/Dock - - - Multiple Displays - Více displejů - Dock - /personalization/Dock - - - Plugin Area - Oblast pluginu - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Vyberte, které ikony se zobrazí v Docku - - - Fashion mode - Módní režim - - - Efficient mode - Efektivní režim - - - Mode - Režim - Dock - /personalization/Dock - - - Top - Nahoře - - - Bottom - Dole - - - Left - Vlevo - - - Right - Vpravo - - - Location - Umístění - Dock - /personalization/Dock - - - Keep shown - Ponechat zobrazený - - - Keep hidden - Ponechat skrytý - - - Smart hide - Chytré skrývání - - - Status - Stav - Dock - /personalization/Dock - - - Small - Malý - - - Large - Velký - - - Show Dock - Zobrazit panel - - - On screen where the cursor is - Na obrazovce, kde je ukazovátko - - - Only on main screen - Pouze na hlavní obrazovce - - MultitaskingPlugin @@ -422,24 +300,12 @@ Onboard Na základní desce - - Settings - Nastavení - PowerPlugin - - Power - Napájení - - - Power settings - Nastavení správy napájení - Capacity %1, %2 min remaining - Stav %1, %2 min zbývá + Energie %1, %2 min zbývá Capacity %1, %2 hr %3 min remaining @@ -469,36 +335,9 @@ Capacity %1, fully charged Kapacita %1, plně nabito - - - SettingsModule - Dock - Panel - - - Mode - Režim - - - Location - Umístění - - - Status - Stav - - - Size - Velikost - - - Show Dock - Zobrazit panel - - - Plugin Area - Oblast zásuvného modulu + Battery + @@ -514,13 +353,9 @@ ShutdownPlugin - - Power - Napájení - Shut down - Vypínání + Vypnout Suspend @@ -550,12 +385,27 @@ Reboot Restartovat + + Power + Napájení + SoundApplet - Volume - Hlasitost + Device + Zařízení + + + + SoundDevicesWidget + + Output Device + Výstupní zařízení + + + Sound settings + Nastavení zvuku @@ -576,10 +426,6 @@ Volume %1 Hlasitost %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Prázdný + + WindowManager + + Exit Safe Mode + Ukončit náhradní režim + + + Dock - Safe Mode + Panel – náhradní režim + + + The Dock is in safe mode, please exit to show it properly + Dok je v náhradním režimu – ukončete, aby se zobrazil správně + + \ No newline at end of file diff --git a/translations/dde-dock_da.ts b/translations/dde-dock_da.ts index b0bf967e1..bd85285ae 100644 --- a/translations/dde-dock_da.ts +++ b/translations/dde-dock_da.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Fjern + Open + Åbn + + + + BloothAdapterWidget + + My Devices + Mine Enheder + + + Other Devices + Andre Enheder @@ -88,12 +99,35 @@ + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Tænd + + + Turn off + Sluk + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Tænd + + + Turn off + Sluk + DBusAdaptors @@ -102,6 +136,21 @@ Tilføj tastaturlayout + + DateTimeDisplayer + + 12-hour time + 12-timers klokkeslæt + + + 24-hour time + 24-timers klokkeslæt + + + Time settings + Tidsindstillinger + + DatetimePlugin @@ -121,6 +170,13 @@ Tidsindstillinger + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -141,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Ukendt enhed - - - Unknown volume - Ukendt volumen + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Aktiveret - Open - Åbn - - - Unmount all - Afmonter alle + Disabled + Deaktiveret @@ -173,21 +228,6 @@ Programstarter - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -243,93 +283,6 @@ - - ModuleWidget - - Size - Størrelse - - - Multiple Displays - Flere skærme - - - Plugin Area - - - - Select which icons appear in the Dock - - - - Fashion mode - Moderne tilstand - - - Efficient mode - Effektiv visning - - - Mode - Tilstand - - - Top - Øverst - - - Bottom - Nederst - - - Left - Venstre - - - Right - Højre - - - Location - Placering - - - Keep shown - - - - Keep hidden - Hold skjult - - - Smart hide - Smart skjuling - - - Status - Status - - - Small - Lille - - - Large - Stor - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -347,21 +300,9 @@ Onboard Onboard - - Settings - Indstillinger - PowerPlugin - - Power - Strøm - - - Power settings - Strømindstillinger - Capacity %1, %2 min remaining Kapacitet %1, %2 minutter tilbage @@ -394,13 +335,9 @@ Capacity %1, fully charged - - - SettingsModule - Dock - Dok - /personalization/Dock + Battery + @@ -416,10 +353,6 @@ ShutdownPlugin - - Power - Strøm - Shut down Luk ned @@ -452,6 +385,10 @@ Reboot Genstart + + Power + Strøm + SoundApplet @@ -460,6 +397,17 @@ Enhed + + SoundDevicesWidget + + Output Device + Udgående Enhed + + + Sound settings + Lydindstillinger + + SoundItem @@ -516,4 +464,19 @@ Tomt + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_de.ts b/translations/dde-dock_de.ts index 4e867a148..eb5758893 100644 --- a/translations/dde-dock_de.ts +++ b/translations/dde-dock_de.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Entfernen + Open + Öffnen + + + + BloothAdapterWidget + + My Devices + Meine Geräte + + + Other Devices + Andere Geräte @@ -88,12 +99,35 @@ Ausgeschaltet + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Einschalten + + + Turn off + Ausschalten + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Einschalten + + + Turn off + Ausschalten + DBusAdaptors @@ -102,6 +136,21 @@ Tastaturbelegung hinzufügen + + DateTimeDisplayer + + 12-hour time + 12-Stunden-Zeit + + + 24-hour time + 24-Stunden-Zeit + + + Time settings + Zeiteinstellungen + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Montag - - - Tuesday - Dienstag - - - Wednesday - Mittwoch - - - Thursday - Donnerstag - - - Friday - Freitag - - - Saturday - Samstag - - - Sunday - Sonntag - - - monday - Montag - - - tuesday - Dienstag - - - wednesday - Mittwoch - - - thursday - Donnerstag - - - friday - Freitag - - - saturday - Samstag - - - sunday - Sonntag - - - %1year%2month%3day - + PC collaboration + PC-Zusammenarbeit @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Unbekanntes Gerät - - - Unknown volume - Unbekannter Datenträger + Multi-Screen Collaboration + Bildschirmübergreifende Zusammenarbeit - DiskMountPlugin + DockPluginController - Disk - Festplatte + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Aktiviert - Open - Öffnen - - - Unmount all - Alle aushängen + Disabled + Deaktiviert @@ -236,21 +228,6 @@ Starter - - MainWindow - - Exit Safe Mode - Abgesicherten Modus beenden - - - Dock - Safe Mode - Dock - Abgesicherter Modus - - - The Dock is in safe mode, please exit to show it properly - Das Dock befindet sich im abgesicherten Modus, bitte beenden, um es richtig anzuzeigen - - MenuWorker @@ -306,105 +283,6 @@ Dock-Einstellungen - - ModuleWidget - - Size - Größe - Dock - /personalization/Dock - - - Multiple Displays - Mehrfachbildschirm - Dock - /personalization/Dock - - - Plugin Area - Pluginbereich - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Wählen Sie aus, welche Symbole im Dock erscheinen sollen - - - Fashion mode - Design-Modus - - - Efficient mode - Effizienzmodus - - - Mode - Modus - Dock - /personalization/Dock - - - Top - Oben - - - Bottom - Unten - - - Left - Links - - - Right - Rechts - - - Location - Standort - Dock - /personalization/Dock - - - Keep shown - Angezeigt lassen - - - Keep hidden - Ausgeblendet lassen - - - Smart hide - Intelligentes Ausblenden - - - Status - Status - Dock - /personalization/Dock - - - Small - Klein - - - Large - Groß - - - Show Dock - Dock anzeigen - - - On screen where the cursor is - Auf dem Bildschirm, wo sich der Zeiger befindet - - - Only on main screen - Nur auf dem Hauptbildschirm - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Touch-Tastatur - - Settings - Einstellungen - PowerPlugin - - Power - Ausschalten / Abmelden - - - Power settings - Energieeinstellungen - Capacity %1, %2 min remaining Kapazität %1, %2 Min. verbleibend @@ -469,36 +335,9 @@ Capacity %1, fully charged Kapazität %1, vollständig geladen - - - SettingsModule - Dock - Dock - - - Mode - Modus - - - Location - Standort - - - Status - Status - - - Size - Größe - - - Show Dock - Dock anzeigen - - - Plugin Area - Pluginbereich + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Energie - Shut down Herunterfahren @@ -550,12 +385,27 @@ Reboot Neu starten + + Power + Energie + SoundApplet - Volume - Lautstärke + Device + Gerät + + + + SoundDevicesWidget + + Output Device + Ausgabegerät + + + Sound settings + Toneinstellungen @@ -576,10 +426,6 @@ Volume %1 Lautstärke %1 - - No output devices - Keine Ausgabegeräte - SoundPlugin @@ -618,4 +464,19 @@ Leeren + + WindowManager + + Exit Safe Mode + Abgesicherten Modus beenden + + + Dock - Safe Mode + Dock - Abgesicherter Modus + + + The Dock is in safe mode, please exit to show it properly + Das Dock befindet sich im abgesicherten Modus, bitte beenden, um es richtig anzuzeigen + + \ No newline at end of file diff --git a/translations/dde-dock_de_CH.ts b/translations/dde-dock_de_CH.ts new file mode 100644 index 000000000..dc815b7bf --- /dev/null +++ b/translations/dde-dock_de_CH.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_el.ts b/translations/dde-dock_el.ts index 0edc08ce6..ad4f43f0e 100644 --- a/translations/dde-dock_el.ts +++ b/translations/dde-dock_el.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Αφαίρεση + Open + Άνοιγμα + + + + BloothAdapterWidget + + My Devices + Οι Συσκευές μου + + + Other Devices + Άλλες Συσκευές @@ -88,12 +99,35 @@ Απενεργοποιήθηκε + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Ενεργοποίηση + + + Turn off + Απενεργοποίηση + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Ενεργοποίηση + + + Turn off + Απενεργοποίηση + DBusAdaptors @@ -102,6 +136,21 @@ Προσθήκη διάταξης πληκτρολογίου + + DateTimeDisplayer + + 12-hour time + 12-ωρη ώρα + + + 24-hour time + 24-ωρη ώρα + + + Time settings + Ρυθμίσεις ώρας + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Δευτέρα - - - Tuesday - Τρίτη - - - Wednesday - Τετάρτη - - - Thursday - Πέμπτη - - - Friday - Παρασκευή - - - Saturday - Σάββατο - - - Sunday - Κυριακή - - - monday - Δευτέρα - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Άγνωστη συσκευή - - - Unknown volume - Άγνωστος τόμος + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Δίσκος + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Άνοιγμα - - - Unmount all - Αποπροσάρτηση όλων + Disabled + Απενεργοποιημένο @@ -236,21 +228,6 @@ Πρόγραμμα εκκίνησης - - MainWindow - - Exit Safe Mode - Έξοδος Ασφαλής Λειτουργίας - - - Dock - Safe Mode - Γραμμή Εργασιών - Ασφαλής Λειτουργία - - - The Dock is in safe mode, please exit to show it properly - Η Γραμμή Εργασιών είναι σε ασφαλή λειτουργία, παρακαλώ αποχωρήστε για να εμφανιστεί σωστά - - MenuWorker @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - Μέγεθος - Dock - /personalization/Dock - - - Multiple Displays - Πολλαπλές Οθόνες - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - Μοντέρνα λειτουργία - - - Efficient mode - Αποτελεσματική λειτουργία - - - Mode - Λειτουργία - Dock - /personalization/Dock - - - Top - Πάνω μέρος - - - Bottom - Κάτω μέρος - - - Left - Αριστερά - - - Right - Δεξιά - - - Location - Τοποθεσία - Dock - /personalization/Dock - - - Keep shown - - - - Keep hidden - Κρατήστε κρυφό - - - Smart hide - Έξυπνη απόκρυψη - - - Status - Κατάσταση - Dock - /personalization/Dock - - - Small - Μικρό - - - Large - Μεγάλο - - - Show Dock - - - - On screen where the cursor is - Στην οθόνη όπου βρίσκεται ο κέρσορας - - - Only on main screen - Μόνο στην κύρια οθόνη - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Onboard - - Settings - Ρυθμίσεις - PowerPlugin - - Power - Ενέργεια - - - Power settings - Ρυθμίσεις ενέργειας - Capacity %1, %2 min remaining Χωρητικότητα %1, απομένουν %2 λεπτά @@ -469,35 +335,8 @@ Capacity %1, fully charged Χωρητικότητα %1, πλήρης φόρτιση - - - SettingsModule - Dock - Προσθήκη στην γραμμή εργασιών - - - Mode - Λειτουργία - - - Location - Τοποθεσία - - - Status - Κατάσταση - - - Size - Μέγεθος - - - Show Dock - - - - Plugin Area + Battery @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Ενέργεια - Shut down Τερματισμός λειτουργίας @@ -550,12 +385,27 @@ Reboot Επανεκκίνηση + + Power + Ενέργεια + SoundApplet - Volume - Ένταση + Device + Συσκευή + + + + SoundDevicesWidget + + Output Device + Συσκευή Εξόδου + + + Sound settings + Ρυθμίσεις ήχου @@ -576,10 +426,6 @@ Volume %1 Ένταση %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Κενό + + WindowManager + + Exit Safe Mode + Έξοδος Ασφαλής Λειτουργίας + + + Dock - Safe Mode + Γραμμή Εργασιών - Ασφαλής Λειτουργία + + + The Dock is in safe mode, please exit to show it properly + Η Γραμμή Εργασιών είναι σε ασφαλή λειτουργία, παρακαλώ αποχωρήστε για να εμφανιστεί σωστά + + \ No newline at end of file diff --git a/translations/dde-dock_en_AU.ts b/translations/dde-dock_en_AU.ts index 592a41ee6..5cef8a0c0 100644 --- a/translations/dde-dock_en_AU.ts +++ b/translations/dde-dock_en_AU.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - + Open + Open + + + + BloothAdapterWidget + + My Devices + My Devices + + + Other Devices + Other Devices @@ -88,12 +99,35 @@ Turned off + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Turn on + + + Turn off + Turn off + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Turn on + + + Turn off + Turn off + DBusAdaptors @@ -102,6 +136,21 @@ Add keyboard layout + + DateTimeDisplayer + + 12-hour time + 12-hour time + + + 24-hour time + 24-hour time + + + Time settings + Time settings + + DatetimePlugin @@ -121,6 +170,13 @@ Time settings + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -141,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Unknown device - - - Unknown volume - Unknown volume + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Open - - - Unmount all - Unmount all + Disabled + Disabled @@ -173,21 +228,6 @@ Launcher - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -243,93 +283,6 @@ - - ModuleWidget - - Size - Size - - - Multiple Displays - Multiple Displays - - - Plugin Area - - - - Select which icons appear in the Dock - - - - Fashion mode - - - - Efficient mode - - - - Mode - Mode - - - Top - Top - - - Bottom - Bottom - - - Left - Left - - - Right - Right - - - Location - Location - - - Keep shown - - - - Keep hidden - - - - Smart hide - - - - Status - Status - - - Small - - - - Large - - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -347,21 +300,9 @@ Onboard Onboard - - Settings - Settings - PowerPlugin - - Power - Power - - - Power settings - Power settings - Capacity %1, %2 min remaining Capacity %1, %2 min remaining @@ -394,13 +335,9 @@ Capacity %1, fully charged Capacity %1, fully charged - - - SettingsModule - Dock - Dock - /personalization/Dock + Battery + @@ -416,10 +353,6 @@ ShutdownPlugin - - Power - Power - Shut down Shut down @@ -452,6 +385,10 @@ Reboot Reboot + + Power + Power + SoundApplet @@ -460,6 +397,17 @@ Device + + SoundDevicesWidget + + Output Device + + + + Sound settings + Sound settings + + SoundItem @@ -516,4 +464,19 @@ Empty + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_en_GB.ts b/translations/dde-dock_en_GB.ts index a3d61ad40..6ee01041e 100644 --- a/translations/dde-dock_en_GB.ts +++ b/translations/dde-dock_en_GB.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Open + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - - - - Open - - - - Unmount all + The plugin %1 is not compatible with the system. - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker Fashion Mode Beautiful mode @@ -132,7 +268,7 @@ Mode - + Mode Location @@ -143,14 +279,7 @@ - Plugins - - - - - LauncherItem - - Launcher + Dock settings @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - - PowerPlugin - - Power - - - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +320,23 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -231,18 +353,10 @@ ShutdownPlugin - - Power - - Shut down Shut down - - Restart - - Suspend @@ -267,6 +381,14 @@ Power settings + + Reboot + Reboot + + + Power + Power + SoundApplet @@ -274,8 +396,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +419,11 @@ - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -302,7 +431,7 @@ SoundPlugin Sound - + Sound @@ -319,12 +448,16 @@ Trash - %1 files + + Move to Trash + + TrashWidget Open - + Open Empty @@ -332,46 +465,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_en_US.ts b/translations/dde-dock_en_US.ts index 2e0a96881..2bde7e4f0 100644 --- a/translations/dde-dock_en_US.ts +++ b/translations/dde-dock_en_US.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Remove + Open + Open + + + + BloothAdapterWidget + + My Devices + My Devices + + + Other Devices + Other Devices @@ -88,12 +99,35 @@ Turned off + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Turn on + + + Turn off + Turn off + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Turn on + + + Turn off + Turn off + DBusAdaptors @@ -102,6 +136,21 @@ Add keyboard layout + + DateTimeDisplayer + + 12-hour time + 12-hour time + + + 24-hour time + 24-hour time + + + Time settings + Time settings + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Monday - - - Tuesday - Tuesday - - - Wednesday - Wednesday - - - Thursday - Thursday - - - Friday - Friday - - - Saturday - Saturday - - - Sunday - Sunday - - - monday - monday - - - tuesday - tuesday - - - wednesday - wednesday - - - thursday - thursday - - - friday - friday - - - saturday - saturday - - - sunday - sunday - - - %1year%2month%3day - %1year%2month%3day + PC collaboration + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Unknown device - - - Unknown volume - Unknown volume + Multi-Screen Collaboration + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Enabled - Open - Open - - - Unmount all - Unmount all + Disabled + Disabled @@ -236,21 +228,6 @@ Launcher - - MainWindow - - Exit Safe Mode - Exit Safe Mode - - - Dock - Safe Mode - Dock - Safe Mode - - - The Dock is in safe mode, please exit to show it properly - The Dock is in safe mode, please exit to show it properly - - MenuWorker @@ -306,105 +283,6 @@ Dock settings - - ModuleWidget - - Size - Size - Dock - /personalization/Dock - - - Multiple Displays - Multiple Displays - Dock - /personalization/Dock - - - Plugin Area - Plugin Area - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Select which icons appear in the Dock - - - Fashion mode - Fashion mode - - - Efficient mode - Efficient mode - - - Mode - Mode - Dock - /personalization/Dock - - - Top - Top - - - Bottom - Bottom - - - Left - Left - - - Right - Right - - - Location - Location - Dock - /personalization/Dock - - - Keep shown - Keep shown - - - Keep hidden - Keep hidden - - - Smart hide - Smart hide - - - Status - Status - Dock - /personalization/Dock - - - Small - Small - - - Large - Large - - - Show Dock - Show Dock - - - On screen where the cursor is - On screen where the cursor is - - - Only on main screen - Only on main screen - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Onboard - - Settings - Settings - PowerPlugin - - Power - Power - - - Power settings - Power settings - Capacity %1, %2 min remaining Capacity %1, %2 min remaining @@ -469,36 +335,9 @@ Capacity %1, fully charged Capacity %1, fully charged - - - SettingsModule - Dock - Dock - - - Mode - Mode - - - Location - Location - - - Status - Status - - - Size - Size - - - Show Dock - Show Dock - - - Plugin Area - Plugin Area + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Power - Shut down Shut down @@ -550,12 +385,27 @@ Reboot Reboot + + Power + Power + SoundApplet - Volume - Volume + Device + Device + + + + SoundDevicesWidget + + Output Device + Output Device + + + Sound settings + Sound settings @@ -576,10 +426,6 @@ Volume %1 Volume %1 - - No output devices - No output devices - SoundPlugin @@ -618,4 +464,19 @@ Empty + + WindowManager + + Exit Safe Mode + Exit Safe Mode + + + Dock - Safe Mode + Dock - Safe Mode + + + The Dock is in safe mode, please exit to show it properly + The Dock is in safe mode, please exit to show it properly + + \ No newline at end of file diff --git a/translations/dde-dock_eo.ts b/translations/dde-dock_eo.ts index 7a6a12a66..f4581db3f 100644 --- a/translations/dde-dock_eo.ts +++ b/translations/dde-dock_eo.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Aldoni klavararanĝon + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings - Hor-agordoj + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - Disko - - - Open - - - - Unmount all + The plugin %1 is not compatible with the system. - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Malŝaltita + + + + LauncherItem + + Launcher + Lanĉilo + + + + MenuWorker Fashion Mode @@ -143,17 +279,10 @@ - Plugins + Dock settings - - LauncherItem - - Launcher - Lanĉilo - - MultitaskingPlugin @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Reto - - OnboardPlugin Onboard - - Settings - Agordoj - PowerPlugin - - Power - Ŝalto - - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +320,23 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -231,18 +353,10 @@ ShutdownPlugin - - Power - Ŝalto - Shut down Elŝaltiti - - Restart - Rekomenci - Suspend Paŭzigi @@ -267,6 +381,14 @@ Power settings + + Reboot + Restartigi + + + Power + Ŝalto + SoundApplet @@ -274,8 +396,15 @@ Device Aparato + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +419,11 @@ Muta - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +448,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +465,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown - Nekonata - - - Wired connection: %1 - - - - - WirelessItem - - No Network + Exit Safe Mode - Wireless Connection: %1 + Dock - Safe Mode - Connected but no Internet access - - - - - WirelessList - - Wireless Network - Senkabla reto - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_es.ts b/translations/dde-dock_es.ts index 36d6e37b5..06948e82e 100644 --- a/translations/dde-dock_es.ts +++ b/translations/dde-dock_es.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Quitar + Open + Abrir + + + + BloothAdapterWidget + + My Devices + Mis dispositivos + + + Other Devices + Otros dispositivos @@ -85,7 +96,22 @@ Turned off - Apagado + Desactivado + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Activar + + + Turn off + Desactivar @@ -94,6 +120,14 @@ Bluetooth Bluetooth + + Turn on + Activar + + + Turn off + Desactivar + DBusAdaptors @@ -102,6 +136,21 @@ Añadir distribución de teclado + + DateTimeDisplayer + + 12-hour time + Formato de 12 horas + + + 24-hour time + Formato de 24 horas + + + Time settings + Ajustes de fecha y hora + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Lunes - - - Tuesday - Martes - - - Wednesday - Miércoles - - - Thursday - Jueves - - - Friday - Viernes - - - Saturday - Sábado - - - Sunday - Domingo - - - monday - Lunes - - - tuesday - martes - - - wednesday - miércoles - - - thursday - jueves - - - friday - viernes - - - saturday - sábado - - - sunday - domingo - - - %1year%2month%3day - %1año%2meses%3 día + PC collaboration + Colaboración de PC @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Dispositivo desconocido - - - Unknown volume - Volumen desconocido + Multi-Screen Collaboration + Colaboración multipantalla - DiskMountPlugin + DockPluginController - Disk - Disco + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Activado - Open - Abrir - - - Unmount all - Desmontar todo + Disabled + Desactivado @@ -236,21 +228,6 @@ Lanzador - - MainWindow - - Exit Safe Mode - Salir del modo seguro - - - Dock - Safe Mode - Muelle - Modo seguro - - - The Dock is in safe mode, please exit to show it properly - El muelle está en modo seguro, por favor salga para verlo correctamente - - MenuWorker @@ -303,106 +280,7 @@ Dock settings - Ajustes del dock - - - - ModuleWidget - - Size - Tamaño - Dock - /personalization/Dock - - - Multiple Displays - Múltiples pantallas - Dock - /personalization/Dock - - - Plugin Area - Área de complementos - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Seleccionar los iconos que aparecen en el Dock - - - Fashion mode - Modo elegante - - - Efficient mode - Modo eficiente - - - Mode - modo - Dock - /personalization/Dock - - - Top - Arriba - - - Bottom - Abajo - - - Left - Izquierda - - - Right - Derecha - - - Location - Ubicación - Dock - /personalization/Dock - - - Keep shown - Mantener visible - - - Keep hidden - Mantener oculto - - - Smart hide - Ocultar inteligentemente - - - Status - Estado - Dock - /personalization/Dock - - - Small - Pequeña - - - Large - Grandes - - - Show Dock - Mostrar el muelle - - - On screen where the cursor is - En la pantalla donde está el cursor - - - Only on main screen - Solo en la pantalla principal + Ajustes del muelle @@ -422,21 +300,9 @@ Onboard Teclado en pantalla - - Settings - Ajustes - PowerPlugin - - Power - Energía - - - Power settings - Ajustes de energía - Capacity %1, %2 min remaining Capacidad %1, %2 min restante @@ -469,36 +335,9 @@ Capacity %1, fully charged Capacidad %1, completamente cargada - - - SettingsModule - Dock - Dock - - - Mode - Modo - - - Location - Ubicación - - - Status - Estado - - - Size - Tamaño - - - Show Dock - Mostrar el dock - - - Plugin Area - Área de complementos + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Apagar - Shut down Apagar @@ -550,12 +385,27 @@ Reboot Reiniciar + + Power + Energía + SoundApplet - Volume - Volumen + Device + Dispositivo + + + + SoundDevicesWidget + + Output Device + Dispositivo de salida + + + Sound settings + Ajustes de sonido @@ -576,10 +426,6 @@ Volume %1 Volumen %1 - - No output devices - Sin dispositivos de salida - SoundPlugin @@ -618,4 +464,19 @@ Vaciar + + WindowManager + + Exit Safe Mode + Salir del modo seguro + + + Dock - Safe Mode + Muelle - Modo seguro + + + The Dock is in safe mode, please exit to show it properly + El muelle está en modo seguro, por favor salga para verlo correctamente + + \ No newline at end of file diff --git a/translations/dde-dock_es_MX.ts b/translations/dde-dock_es_MX.ts new file mode 100644 index 000000000..493a2dbc1 --- /dev/null +++ b/translations/dde-dock_es_MX.ts @@ -0,0 +1,482 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Abrir + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + Cancelar + + + Delete + Eliminar + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + DockPluginController + + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + Deshabilitado + + + + LauncherItem + + Launcher + Lanzador + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + Izquierda + + + Right + Derecha + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + Ubicación + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + Apagar + + + Suspend + Suspender + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Power + Energía + + + + SoundApplet + + Device + Dispositivo + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + Silencio + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + Sonido + + + + TrashPlugin + + Trash + Papelera + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + Mover a la papelera + + + + TrashWidget + + Open + Abrir + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_et.ts b/translations/dde-dock_et.ts index 54de0475a..5773ae29f 100644 --- a/translations/dde-dock_et.ts +++ b/translations/dde-dock_et.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Ava + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -14,36 +137,43 @@ - DatetimePlugin + DateTimeDisplayer - Datetime + 12-hour time - 12 Hour Time + 24-hour time - 24 Hour Time - - - - Time Settings - + Time settings + Kellaaja seaded - DeviceItem + DatetimePlugin - Enable network + Datetime + Kuupäev ja kellaaeg + + + 12-hour time - Disable network + 24-hour time - Network settings + Time settings + Kellaaja seaded + + + + DevCollaborationWidget + + PC collaboration @@ -55,11 +185,11 @@ Cancel - Tühista + Loobu Delete - + Kustuta This action cannot be restored @@ -67,83 +197,20 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + HomeMonitorPlugin - Disk + Enabled - Open - - - - Unmount all - - - - - DockSettings - - Fashion Mode - - - - Efficient Mode - - - - Top - - - - Bottom - - - - Left - - - - Right - - - - Keep Shown - - - - Keep Hidden - - - - Smart Hide - - - - Mode - - - - Location - - - - Status - - - - Plugins + Disabled @@ -151,6 +218,61 @@ LauncherItem Launcher + Käivitaja + + + + MenuWorker + + Fashion Mode + Moodne režiim + + + Efficient Mode + Efektiivne režiim + + + Top + Üleval + + + Bottom + All + + + Left + Vasakul + + + Right + Paremal + + + Keep Shown + Hoia nähtavana + + + Keep Hidden + Hoia peidetuna + + + Smart Hide + Nutikas peitmine + + + Mode + Režiim + + + Location + Aukoht + + + Status + Staatus + + + Dock settings @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -222,7 +337,7 @@ ShowDesktopPlugin Show Desktop - + Näita töölauda Undock @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down Sule arvuti - - Restart - - Suspend @@ -253,11 +360,11 @@ Lock - + Lukk Log out - + Logi välja Switch account @@ -267,34 +374,49 @@ Power settings + + Reboot + Taaskäivita + + + Plugged In + Võrgutoitel + SoundApplet Device + Seade + + + + SoundDevicesWidget + + Output Device - Application - + Sound settings + Heli seaded SoundItem Unmute - + Eemalda vaigistus Mute - + Vaigista - Audio Settings - + Sound settings + Heli seaded - Current Volume %1 + Volume %1 @@ -302,14 +424,14 @@ SoundPlugin Sound - + Heli TrashPlugin Trash - + Prügikast Trash - %1 file @@ -319,59 +441,34 @@ Trash - %1 files + + Move to Trash + + TrashWidget Open - + Ava Empty - + Tühi - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_eu.ts b/translations/dde-dock_eu.ts new file mode 100644 index 000000000..9b96058b4 --- /dev/null +++ b/translations/dde-dock_eu.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + Erakutsi mahaigaina + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_fa.ts b/translations/dde-dock_fa.ts index 70714a3aa..f461ed788 100644 --- a/translations/dde-dock_fa.ts +++ b/translations/dde-dock_fa.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -7,9 +7,57 @@ - AppDragWidget + AirplaneModeApplet - Remove + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + خاموش کردن + + + Turn on + روشن کردن + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + باز کردن + + + + BloothAdapterWidget + + My Devices + + + + Other Devices @@ -51,12 +99,35 @@ + + BluetoothMainWidget + + Bluetooth + بلوتوث + + + Turn on + روشن کردن + + + Turn off + خاموش کردن + + BluetoothPlugin Bluetooth بلوتوث + + Turn on + روشن کردن + + + Turn off + خاموش کردن + DBusAdaptors @@ -65,6 +136,21 @@ اضافه کردن طرح بندی صفحه کلید + + DateTimeDisplayer + + 12-hour time + زمان 12-ساعته + + + 24-hour time + زمان 24-ساعته + + + Time settings + تنظیمات زمان + + DatetimePlugin @@ -84,6 +170,13 @@ تنظیمات زمان + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -104,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - دستگاه ناشناخته - - - Unknown volume - حجم ناشناخته + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - دیسک + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - باز کردن - - - Unmount all - خارج کردن همه + Disabled + غیر فعال @@ -136,21 +228,6 @@ لانچر - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -202,19 +279,7 @@ وضعیت - Plugins - پلاگین ها - - - Only on main screen - - - - On screen where the cursor is - - - - Show the Dock + Dock settings @@ -235,21 +300,9 @@ Onboard روی صفحه - - Settings - تنظیمات - PowerPlugin - - Power - منبع قدرت - - - Power settings - تنظیمات برق - Capacity %1, %2 min remaining ظرفیت %1, %2 دقیقه باقی مانده است @@ -282,6 +335,10 @@ Capacity %1, fully charged + + Battery + + ShowDesktopPlugin @@ -296,10 +353,6 @@ ShutdownPlugin - - Power - منبع قدرت - Shut down خاموش شدن @@ -332,6 +385,10 @@ Reboot راه اندازی مجدد + + Power + منبع قدرت + SoundApplet @@ -340,6 +397,17 @@ دستگاه + + SoundDevicesWidget + + Output Device + + + + Sound settings + تنظیمات صدا + + SoundItem @@ -396,4 +464,19 @@ خالی + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_fi.ts b/translations/dde-dock_fi.ts index 75518791f..c4b1931ba 100644 --- a/translations/dde-dock_fi.ts +++ b/translations/dde-dock_fi.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Poista + Open + Avaa + + + + BloothAdapterWidget + + My Devices + Omat laitteet + + + Other Devices + Muut laitteet @@ -88,12 +99,35 @@ Pois päältä + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Kytke käyttöön + + + Turn off + Poista käytöstä + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Kytke käyttöön + + + Turn off + Poista käytöstä + DBusAdaptors @@ -102,6 +136,21 @@ Lisää näppäimistön asettelu + + DateTimeDisplayer + + 12-hour time + 12h aika + + + 24-hour time + 24h aika + + + Time settings + Aika-asetukset + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Maanantai - - - Tuesday - Tiistai - - - Wednesday - Keskiviikko - - - Thursday - Torstai - - - Friday - Perjantai - - - Saturday - Lauantai - - - Sunday - Sunnuntai - - - monday - maanantai - - - tuesday - tiistai - - - wednesday - keskiviikko - - - thursday - torstai - - - friday - perjantai - - - saturday - lauantai - - - sunday - sunnuntai - - - %1year%2month%3day - %3day%2month%1year + PC collaboration + @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Tuntematon laite - - - Unknown volume - Tuntematon asema + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Levy + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Avaa - - - Unmount all - Irroita kaikki + Disabled + Suljettu @@ -236,21 +228,6 @@ Käynnistin - - MainWindow - - Exit Safe Mode - Poistu vikasietotilasta - - - Dock - Safe Mode - Paneeli - vikasietotila - - - The Dock is in safe mode, please exit to show it properly - Paneeli on vikasietotilassa. Poistu nähtyäsi sen toimivan oikein - - MenuWorker @@ -306,105 +283,6 @@ Telakan asetukset - - ModuleWidget - - Size - Koko - Dock - /personalization/Dock - - - Multiple Displays - Useita näyttöjä - Dock - /personalization/Dock - - - Plugin Area - Laajennusalue - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Valitse mitkä kuvakkeet näkyvät telakassa - - - Fashion mode - Muodikas - - - Efficient mode - Tehokas - - - Mode - Tila - Dock - /personalization/Dock - - - Top - Ylhäällä - - - Bottom - Alhaalla - - - Left - Vasen - - - Right - Oikea - - - Location - Sijainti - Dock - /personalization/Dock - - - Keep shown - Näytä aina - - - Keep hidden - Pidä piilossa - - - Smart hide - Älykäs piilotus - - - Status - Tila - Dock - /personalization/Dock - - - Small - Pieni - - - Large - Suuri - - - Show Dock - Näytä telakka - - - On screen where the cursor is - Näytöllä, jossa kohdistin on - - - Only on main screen - Vain päänäytöllä - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Näppäimistö - - Settings - Asetukset - PowerPlugin - - Power - Virta - - - Power settings - Asetukset virta - Capacity %1, %2 min remaining Akku %1, %2 min jäljellä @@ -469,36 +335,9 @@ Capacity %1, fully charged Varaus %1, täyteen ladattu - - - SettingsModule - Dock - Telakka - - - Mode - Tila - - - Location - Sijainti - - - Status - Tila - - - Size - Koko - - - Show Dock - Näytä telakka - - - Plugin Area - Laajennusalue + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Virta - Shut down Sammuta @@ -550,12 +385,27 @@ Reboot Käynnistä + + Power + Virta + SoundApplet - Volume - Voimakkuus + Device + Laite + + + + SoundDevicesWidget + + Output Device + Ulostulon laite + + + Sound settings + Ääniasetukset @@ -576,10 +426,6 @@ Volume %1 Voimakkuus: %1 - - No output devices - Ei ulostulon laitteita - SoundPlugin @@ -618,4 +464,19 @@ Tyhjennä + + WindowManager + + Exit Safe Mode + Poistu vikasietotilasta + + + Dock - Safe Mode + Paneeli - vikasietotila + + + The Dock is in safe mode, please exit to show it properly + Paneeli on vikasietotilassa. Poistu nähtyäsi sen toimivan oikein + + \ No newline at end of file diff --git a/translations/dde-dock_fil.ts b/translations/dde-dock_fil.ts new file mode 100644 index 000000000..53d492483 --- /dev/null +++ b/translations/dde-dock_fil.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_fr.ts b/translations/dde-dock_fr.ts index 66faa32c8..6161e669b 100644 --- a/translations/dde-dock_fr.ts +++ b/translations/dde-dock_fr.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Retirer + Open + Ouvrir + + + + BloothAdapterWidget + + My Devices + Mes appareils + + + Other Devices + Autres appareils @@ -88,12 +99,35 @@ Eteint + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Allumer + + + Turn off + Éteindre + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Allumer + + + Turn off + Éteindre + DBusAdaptors @@ -102,6 +136,21 @@ Ajouter une disposition de clavier + + DateTimeDisplayer + + 12-hour time + Affichage 12 heures + + + 24-hour time + Affichage 24 heures + + + Time settings + Réglages de l'heure + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Lundi - - - Tuesday - Mardi - - - Wednesday - Mercredi - - - Thursday - Jeudi - - - Friday - Vendredi - - - Saturday - Samedi - - - Sunday - Dimanche - - - monday - lundi - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Périphérique inconnu - - - Unknown volume - Partition inconnue + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disque + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Activé - Open - Ouvrir - - - Unmount all - Tout démonter + Disabled + Désactivé @@ -236,21 +228,6 @@ Lanceur - - MainWindow - - Exit Safe Mode - Mode sans échec de sortie - - - Dock - Safe Mode - Dock - Mode sans échec - - - The Dock is in safe mode, please exit to show it properly - Le Dock est en mode sans échec, veuillez quitter pour l'afficher correctement - - MenuWorker @@ -306,105 +283,6 @@ Paramètres du dock - - ModuleWidget - - Size - Taille - Dock - /personalization/Dock - - - Multiple Displays - Affichages multiples - Dock - /personalization/Dock - - - Plugin Area - Zone de plugins - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Sélectionner les icônes qui apparaissent dans le dock - - - Fashion mode - Mode dock - - - Efficient mode - Mode étendu - - - Mode - Mode - Dock - /personalization/Dock - - - Top - Haut - - - Bottom - Bas - - - Left - Gauche - - - Right - Droite - - - Location - Emplacement - Dock - /personalization/Dock - - - Keep shown - Garder affiché - - - Keep hidden - Maintenir caché - - - Smart hide - Masquer intelligemment - - - Status - Statut - Dock - /personalization/Dock - - - Small - Petit - - - Large - Grand - - - Show Dock - Afficher le dock - - - On screen where the cursor is - Sur l'écran où se trouve le curseur - - - Only on main screen - Uniquement sur l'écran principal - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Clavier virtuel - - Settings - Paramètres - PowerPlugin - - Power - Alimentation - - - Power settings - Options d'alimentation - Capacity %1, %2 min remaining Capacité %1, %2 minutes restantes @@ -469,36 +335,9 @@ Capacity %1, fully charged Capacité %1, complètement chargé - - - SettingsModule - Dock - Dock - - - Mode - Mode - - - Location - Emplacement - - - Status - Statut - - - Size - Taille - - - Show Dock - Afficher le dock - - - Plugin Area - Zone de plugins + Battery + @@ -514,21 +353,17 @@ ShutdownPlugin - - Power - Alimentation - Shut down - Arrêter + Eteindre Suspend - Mise en veille + Mettre en veille Hibernate - Mise en veille prolongée + Mettre en veille prolongée Lock @@ -550,12 +385,27 @@ Reboot Redémarrer + + Power + Alimentation + SoundApplet - Volume - Volume + Device + Périphérique + + + + SoundDevicesWidget + + Output Device + Périphérique de sortie + + + Sound settings + Paramètres sonores @@ -576,10 +426,6 @@ Volume %1 Volume %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Vide + + WindowManager + + Exit Safe Mode + Mode sans échec de sortie + + + Dock - Safe Mode + Dock - Mode sans échec + + + The Dock is in safe mode, please exit to show it properly + Le Dock est en mode sans échec, veuillez quitter pour l'afficher correctement + + \ No newline at end of file diff --git a/translations/dde-dock_gl_ES.ts b/translations/dde-dock_gl_ES.ts index 6c25eaa44..9ea6e11f1 100644 --- a/translations/dde-dock_gl_ES.ts +++ b/translations/dde-dock_gl_ES.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Eliminar + Open + Abrir + + + + BloothAdapterWidget + + My Devices + Os meus dispositivos + + + Other Devices + Outros dispositivos @@ -88,12 +99,35 @@ Desactivado + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Acender + + + Turn off + Apagar + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Acender + + + Turn off + Apagar + DBusAdaptors @@ -102,6 +136,21 @@ Engadir disposición do teclado + + DateTimeDisplayer + + 12-hour time + formato 12 horas + + + 24-hour time + formato 24 horas + + + Time settings + Axustes da hora + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Luns - - - Tuesday - Martes - - - Wednesday - Mércores - - - Thursday - Xoves - - - Friday - Venres - - - Saturday - Sábado - - - Sunday - Domingo - - - monday - luns - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Dispositivo descoñecido - - - Unknown volume - Volume descoñecido + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disco + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Abrir - - - Unmount all - Desmontar todo + Disabled + Desactivado @@ -236,21 +228,6 @@ Lanzador - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - Tamaño - Dock - /personalization/Dock - - - Multiple Displays - Pantallas múltiple - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - Modo moderno - - - Efficient mode - Modo eficiente - - - Mode - Modo - Dock - /personalization/Dock - - - Top - Arriba - - - Bottom - Abaixo - - - Left - Esquerda - - - Right - Dereita - - - Location - Localización - Dock - /personalization/Dock - - - Keep shown - - - - Keep hidden - Manter oculto - - - Smart hide - Ocultar automaticamente - - - Status - Estado - Dock - /personalization/Dock - - - Small - Pequeno - - - Large - Grande - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard A bordo - - Settings - Axustes - PowerPlugin - - Power - Enerxía - - - Power settings - Axustes de enerxía - Capacity %1, %2 min remaining Capacidade %1, %2 minutos restantes @@ -469,35 +335,8 @@ Capacity %1, fully charged Capacidade %1, totalmente cargada - - - SettingsModule - Dock - Doca - - - Mode - Modo - - - Location - Localización - - - Status - Estado - - - Size - Tamaño - - - Show Dock - - - - Plugin Area + Battery @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Enerxía - Shut down Apagar @@ -550,12 +385,27 @@ Reboot Reiniciar + + Power + Enerxía + SoundApplet - Volume - Volume + Device + Dispositivo + + + + SoundDevicesWidget + + Output Device + Dispositivo de saída + + + Sound settings + Configuración do son @@ -576,10 +426,6 @@ Volume %1 Volume %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Baleirar + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_he.ts b/translations/dde-dock_he.ts index a36e6b7dd..8a227ba09 100644 --- a/translations/dde-dock_he.ts +++ b/translations/dde-dock_he.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + פתיחה + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - כונן - - - Open - פתיחה - - - Unmount all + The plugin %1 is not compatible with the system. - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + מושבת + + + + LauncherItem + + Launcher + משגר + + + + MenuWorker Fashion Mode @@ -143,15 +279,8 @@ - Plugins - פלאגינים - - - - LauncherItem - - Launcher - משגר + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - רשת - - OnboardPlugin Onboard - - Settings - הגדרות - PowerPlugin - - Power - צריכת חשמל - - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +320,23 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -231,25 +353,17 @@ ShutdownPlugin - - Power - צריכת חשמל - Shut down כיבוי - - Restart - אתחול - Suspend השהיה Hibernate - + תרדמת Lock @@ -267,6 +381,14 @@ Power settings + + Reboot + + + + Power + צריכת חשמל + SoundApplet @@ -274,8 +396,15 @@ Device התקן + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +419,11 @@ השתקה - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +448,10 @@ Trash - %1 files + + Move to Trash + העבר לאשפה + TrashWidget @@ -332,46 +465,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown - לא ידוע - - - Wired connection: %1 - - - - - WirelessItem - - No Network + Exit Safe Mode - Wireless Connection: %1 + Dock - Safe Mode - Connected but no Internet access - - - - - WirelessList - - Wireless Network - רשת אלחוטית - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_hi_IN.ts b/translations/dde-dock_hi_IN.ts index ebfe8c4fc..9e4e92197 100644 --- a/translations/dde-dock_hi_IN.ts +++ b/translations/dde-dock_hi_IN.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -7,9 +7,57 @@ - AppDragWidget + AirplaneModeApplet - Remove + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + ऑफ करें + + + Turn on + ऑन करें + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + खोलें + + + + BloothAdapterWidget + + My Devices + + + + Other Devices @@ -51,12 +99,35 @@ + + BluetoothMainWidget + + Bluetooth + ब्लूटुथ + + + Turn on + ऑन करें + + + Turn off + ऑफ करें + + BluetoothPlugin Bluetooth ब्लूटूथ + + Turn on + ऑन करें + + + Turn off + ऑफ करें + DBusAdaptors @@ -65,6 +136,21 @@ कुंजीपटल अभिन्यास जोड़ें + + DateTimeDisplayer + + 12-hour time + 12 घंटे का समय + + + 24-hour time + 24 घंटे का समय + + + Time settings + समय सेवाएं + + DatetimePlugin @@ -84,6 +170,13 @@ समय सेवाएं + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -100,33 +193,32 @@ This action cannot be restored - इस कार्रवाई को पुनः स्थापित नहीं किया जा सकता है + यह कार्य पूर्ववत नहीं हो सकता है - DiskControlItem + DisplaySettingWidget - Unknown device - अज्ञात डिवाइस - - - Unknown volume - अज्ञात वॉल्यूम + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - डिस्क + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - खोलें - - - Unmount all - सभी को माउंट से हटाएँ + Disabled + बंद किया हुआ है @@ -136,21 +228,6 @@ लॉन्चर - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -202,19 +279,7 @@ स्थिति - Plugins - प्लगिन - - - Only on main screen - - - - On screen where the cursor is - - - - Show the Dock + Dock settings @@ -235,21 +300,9 @@ Onboard ऑनबोर्ड - - Settings - सेटिंग्स - PowerPlugin - - Power - पॉवर - - - Power settings - पॉवर सेटिंग्स - Capacity %1, %2 min remaining क्षमता %1, %2 मिनट शेष @@ -282,6 +335,10 @@ Capacity %1, fully charged + + Battery + + ShowDesktopPlugin @@ -296,10 +353,6 @@ ShutdownPlugin - - Power - पॉवर - Shut down बंद करें @@ -310,7 +363,7 @@ Hibernate - हाइबरनेट + सुप्त करें Lock @@ -322,7 +375,7 @@ Switch account - खाता बदलें + अकाउंट बदलें Power settings @@ -332,12 +385,27 @@ Reboot पुनः आरंभ करें + + Power + पॉवर + SoundApplet Device - डिवाइस + उपकरण + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + ध्वनि सेटिंग्स @@ -370,15 +438,15 @@ TrashPlugin Trash - रद्दी + ट्रैश Trash - %1 file - कचरा - %1 फ़ाइल + ट्रैश - %1 फाइल Trash - %1 files - कचरा - %1 फ़ाइलें + ट्रैश - %1 फाइलें Move to Trash @@ -393,7 +461,22 @@ Empty - खाली + खाली करें + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + \ No newline at end of file diff --git a/translations/dde-dock_hr.ts b/translations/dde-dock_hr.ts index d73f401b6..8e8fb7e4d 100644 --- a/translations/dde-dock_hr.ts +++ b/translations/dde-dock_hr.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Ukloni + Open + Otvori + + + + BloothAdapterWidget + + My Devices + Moji uređaji + + + Other Devices + Ostali uređaji @@ -88,12 +99,35 @@ Isključeno + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Uključi + + + Turn off + Isključi + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Uključi + + + Turn off + Isključi + DBusAdaptors @@ -102,6 +136,21 @@ Dodaj raspored tipkovnice + + DateTimeDisplayer + + 12-hour time + 12-satno vrijeme + + + 24-hour time + 24-satno vrijeme + + + Time settings + Postavke vremena + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Ponedjeljak - - - Tuesday - Utorak - - - Wednesday - Srijeda - - - Thursday - Četvrtak - - - Friday - Petak - - - Saturday - Subota - - - Sunday - Nedjelja - - - monday - ponedjeljak - - - tuesday - utorak - - - wednesday - srijeda - - - thursday - četvrtak - - - friday - petak - - - saturday - subota - - - sunday - nedjelja - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Nepoznati uređaj - - - Unknown volume - Nepoznata količina + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Omogućeno - Open - Otvori - - - Unmount all - Sve odspoji + Disabled + Onemogućeno @@ -236,21 +228,6 @@ Pokretač - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - Veličina - Dock - /personalization/Dock - - - Multiple Displays - Višestruki zasloni - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - Moderan način - - - Efficient mode - Učinkoviti način - - - Mode - Način - Dock - /personalization/Dock - - - Top - Gore - - - Bottom - Dolje - - - Left - Lijevo - - - Right - Desno - - - Location - Lokacija - Dock - /personalization/Dock - - - Keep shown - Drži prikazano - - - Keep hidden - Drži skriveno - - - Smart hide - Pametno skrivanje - - - Status - Status - Dock - /personalization/Dock - - - Small - Maleno - - - Large - Veliko - - - Show Dock - - - - On screen where the cursor is - Na zaslon gdje je pokazivač - - - Only on main screen - Samo na glavni zaslon - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard - - Settings - Postavke - PowerPlugin - - Power - Energija - - - Power settings - Energetske postavke - Capacity %1, %2 min remaining Kapacitet %1, %2 min preostalo @@ -469,35 +335,8 @@ Capacity %1, fully charged Kapacitet %1, potpuno napunjen - - - SettingsModule - Dock - - - - Mode - Način - - - Location - Lokacija - - - Status - Status - - - Size - Veličina - - - Show Dock - - - - Plugin Area + Battery @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Energija - Shut down Isključi @@ -550,12 +385,27 @@ Reboot Ponovno podigni sustav + + Power + Energija + SoundApplet - Volume - Glasnoća + Device + Uređaj + + + + SoundDevicesWidget + + Output Device + Izlazni uređaj + + + Sound settings + Postavke zvuka @@ -576,10 +426,6 @@ Volume %1 Glasnoća %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Prazno + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_hu.ts b/translations/dde-dock_hu.ts index 09a3a8056..d4605f0df 100644 --- a/translations/dde-dock_hu.ts +++ b/translations/dde-dock_hu.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Eltávolítás + Open + Megnyitás + + + + BloothAdapterWidget + + My Devices + Eszközeim + + + Other Devices + Egyéb eszközök @@ -88,12 +99,35 @@ Kikapcsolva + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Bekapcsolás + + + Turn off + Kikapcsolás + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Bekapcsolás + + + Turn off + Kikapcsolás + DBusAdaptors @@ -102,11 +136,26 @@ Billentyűzetkiosztás megadása + + DateTimeDisplayer + + 12-hour time + 12 órás időformátum + + + 24-hour time + 24 órás időformátum + + + Time settings + Idő beállításai + + DatetimePlugin Datetime - Dátum és idő + Dátum és Idő 12-hour time @@ -122,73 +171,17 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Hétfő - - - Tuesday - Kedd - - - Wednesday - Szerda - - - Thursday - Csütörtök - - - Friday - Péntek - - - Saturday - Szombat - - - Sunday - Vasárnap - - - monday - Hétfő - - - tuesday - Kedd - - - wednesday - Szerda - - - thursday - Csütörtök - - - friday - Péntek - - - saturday - Szombat - - - sunday - Vasárnap - - - %1year%2month%3day - % 1év %2 hónap %3 nap + PC collaboration + PC együttműködés DialogManager Are you sure you want to empty %1 items? - Biztosan törölni akarja a %1 elemet? + Biztosan ki akarja üríteni a %1 elemet? Cancel @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Ismeretlen eszköz - - - Unknown volume - Ismeretlen kötet + Multi-Screen Collaboration + Többképernyős együttműködés - DiskMountPlugin + DockPluginController - Disk - Lemez + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Engedélyezve - Open - Megnyitás - - - Unmount all - Összes lecsatolása + Disabled + Letiltva @@ -236,21 +228,6 @@ Indító - - MainWindow - - Exit Safe Mode - Kilépés a biztonságos módból - - - Dock - Safe Mode - Dokkoló - Biztonságos mód - - - The Dock is in safe mode, please exit to show it properly - A Dokkoló biztonságos módban van. Kérjük lépjen ki a megfelelő megjelenítéshez - - MenuWorker @@ -306,105 +283,6 @@ Dokkoló beállításai - - ModuleWidget - - Size - Méret - Dock - /personalization/Dock - - - Multiple Displays - Többképernyős mód - Dock - /personalization/Dock - - - Plugin Area - Bővítmény terület - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Válassza ki, hogy mely ikonok jelenjenek meg a dokkolóban - - - Fashion mode - Stílusos mód - - - Efficient mode - Hatékony mód - - - Mode - Mód - Dock - /personalization/Dock - - - Top - Fent - - - Bottom - Lent - - - Left - Bal - - - Right - Jobb - - - Location - Hely - Dock - /personalization/Dock - - - Keep shown - Megjelenítve tartás - - - Keep hidden - Maradjon rejtett - - - Smart hide - Intelligens elrejtés - - - Status - Állapot - Dock - /personalization/Dock - - - Small - Kicsi - - - Large - Nagy - - - Show Dock - Dokkoló mutatása - - - On screen where the cursor is - A képernyőn, ahol a kurzor található - - - Only on main screen - Csak a főképernyőn - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Képernyő billentyűzet - - Settings - Beállítások - PowerPlugin - - Power - Kikapcsolás - - - Power settings - Energiagazdálkodási beállítások - Capacity %1, %2 min remaining Akkumulátor töltöttsége %1, %2 perc van még hátra a feltöltésig @@ -469,36 +335,9 @@ Capacity %1, fully charged Akkumulátor töltöttsége %1, teljesen feltöltve - - - SettingsModule - Dock - Dokkoló - - - Mode - Mód - - - Location - Hely - - - Status - Állapot - - - Size - Méret - - - Show Dock - Dokkoló mutatása - - - Plugin Area - Bővítmény terület + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Kikapcsolás - Shut down Leállítás @@ -550,12 +385,27 @@ Reboot Újraindítás + + Power + Energiaellátás + SoundApplet - Volume - Hangerő + Device + Eszköz + + + + SoundDevicesWidget + + Output Device + Kimeneti eszköz + + + Sound settings + Hang beállítások @@ -576,16 +426,12 @@ Volume %1 Hangerő: %1 - - No output devices - Nincsenek kimeneti eszközök - SoundPlugin Sound - Hang + Hangok @@ -596,11 +442,11 @@ Trash - %1 file - Kukában: %1 fájl + Kukában - %1 fájl Trash - %1 files - Kukában: %1 fájl + Kukában - %1 fájlok Move to Trash @@ -618,4 +464,19 @@ Ürítés + + WindowManager + + Exit Safe Mode + Kilépés a biztonságos módból + + + Dock - Safe Mode + Dokkoló - Biztonságos mód + + + The Dock is in safe mode, please exit to show it properly + A Dokkoló biztonságos módban van. Kérjük lépjen ki a megfelelő megjelenítéshez + + \ No newline at end of file diff --git a/translations/dde-dock_hy.ts b/translations/dde-dock_hy.ts index 215dc0165..b4d8ae30e 100644 --- a/translations/dde-dock_hy.ts +++ b/translations/dde-dock_hy.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,32 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + HomeMonitorPlugin - Disk + Enabled - Open - - - - Unmount all - + Disabled + Անջատված է - DockSettings + LauncherItem + + Launcher + Պիտակ + + + + MenuWorker Fashion Mode @@ -143,17 +272,10 @@ - Plugins + Dock settings - - LauncherItem - - Launcher - Պիտակ - - MultitaskingPlugin @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - Կարգավորումներ - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down Անջատել - - Restart - Վերսկսել - Suspend Ընդհատել @@ -267,6 +374,14 @@ Power settings + + Reboot + + + + Plugged In + + SoundApplet @@ -274,8 +389,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +412,11 @@ Անջատել ձայնը - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +441,10 @@ Trash - %1 files + + Move to Trash + Տեղափոխել աղբաման + TrashWidget @@ -332,46 +458,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown - Անհայտ - - - Wired connection: %1 - - - - - WirelessItem - - No Network + Exit Safe Mode - Wireless Connection: %1 + Dock - Safe Mode - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_id.ts b/translations/dde-dock_id.ts index 64f469a23..2f36e2d21 100644 --- a/translations/dde-dock_id.ts +++ b/translations/dde-dock_id.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Buka + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Tambah tata letak papan ketik + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ Tanggalwaktu - 12 Hour Time - Waktu 12 Jam + 12-hour time + - 24 Hour Time - Waktu 24 Jam + 24-hour time + - Time Settings - Pengaturan Waktu + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - Aktifkan jaringan - - - Disable network - Matikan jaringan - - - Network settings - Pengaturan jaringan + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Perangkat tidak diketahui - - - Unknown volume - Volume tidak diketahui + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Diska - - - Open - Terbuka - - - Unmount all - Lepaskan semua + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Nonaktifkan + + + + LauncherItem + + Launcher + Peluncur + + + + MenuWorker Fashion Mode Mode fasion @@ -143,15 +279,8 @@ Status - Plugins - Plugin - - - - LauncherItem - - Launcher - Peluncur + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Jaringan - - OnboardPlugin Onboard Pada papan - - Settings - Pengaturan - PowerPlugin - - Power - Daya - - - Power settings - Pengaturan daya - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - Terisi %1 - Charging %1, %2 min until full @@ -214,11 +320,23 @@ - Charging %1 .... + Capacity %1 - Charged + Charging %1 + Mengisi %1 + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -235,18 +353,10 @@ ShutdownPlugin - - Power - Daya - Shut down Matikan - - Restart - Nyalakan ulang - Suspend Tangguhkan @@ -271,6 +381,14 @@ Power settings Pengaturan daya + + Reboot + Boot ulang + + + Power + Daya + SoundApplet @@ -278,9 +396,16 @@ Device Perangkat + + + SoundDevicesWidget - Application - Aplikasi + Output Device + + + + Sound settings + @@ -294,12 +419,12 @@ Senyap - Audio Settings - Pengaturan Audio + Sound settings + - Current Volume %1 - Volume Saat ini %1 + Volume %1 + @@ -323,6 +448,10 @@ Trash - %1 files Tong sampah - %1 berkas + + Move to Trash + Pindah ke tempat sampah + TrashWidget @@ -336,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - Baki sistem - - - - WiredItem - - Unknown - Tidak diketahui + Exit Safe Mode + - Wired connection: %1 - Koneksi kabel: %1 - - - - WirelessItem - - No Network - Tidak ada jaringan + Dock - Safe Mode + - Wireless Connection: %1 - Koneksi nirkabel: %1 - - - Connected but no Internet access - Terhubung tetapi tidak ada akses Internet - - - - WirelessList - - Wireless Network - Jaringan Nirkabel - - - Wireless Network %1 - Jaringan Nirkabel %1 + The Dock is in safe mode, please exit to show it properly + \ No newline at end of file diff --git a/translations/dde-dock_it.ts b/translations/dde-dock_it.ts index c2de9a542..929606c44 100644 --- a/translations/dde-dock_it.ts +++ b/translations/dde-dock_it.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Rimuovi + Open + Apri + + + + BloothAdapterWidget + + My Devices + I miei dispositivi + + + Other Devices + Altri dispositivi @@ -88,12 +99,35 @@ Disattivato + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Attiva + + + Turn off + Disattiva + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Attiva + + + Turn off + Disattiva + DBusAdaptors @@ -102,6 +136,21 @@ Aggiungi un layout della Tastiera + + DateTimeDisplayer + + 12-hour time + Formato 12 ore + + + 24-hour time + Formato 24 ore + + + Time settings + Impostazioni orarie + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Lunedì - - - Tuesday - Martedì - - - Wednesday - Mercoledì - - - Thursday - Giovedì - - - Friday - Venerdì - - - Saturday - Sabato - - - Sunday - Domenica - - - monday - lunedì - - - tuesday - martedì - - - wednesday - mercoledì - - - thursday - giovedì - - - friday - venerdì - - - saturday - sabato - - - sunday - domenica - - - %1year%2month%3day - %1year%2month%3day + PC collaboration + @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Dispositivo sconosciuto - - - Unknown volume - Volume sconosciuto + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disco + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Attivo - Open - Apri - - - Unmount all - Smonta tutto + Disabled + Disabilitato @@ -236,21 +228,6 @@ Launcher - - MainWindow - - Exit Safe Mode - Esci dalla modalità provvisoria - - - Dock - Safe Mode - Dock - Modalità provvisoria - - - The Dock is in safe mode, please exit to show it properly - La Dock è in modalità provvisoria, esci per mostrarla in modo tradizionale - - MenuWorker @@ -306,105 +283,6 @@ Impostazioni Dock - - ModuleWidget - - Size - Dimensioni - Dock - /personalization/Dock - - - Multiple Displays - Display multipli - Dock - /personalization/Dock - - - Plugin Area - Area plugin - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Seleziona quali icone appaiono nel Dock - - - Fashion mode - Modalità Fashion - - - Efficient mode - Modalità Efficient - - - Mode - Modalità - Dock - /personalization/Dock - - - Top - Top - - - Bottom - Sotto - - - Left - Sinistra - - - Right - Destra - - - Location - Posizione - Dock - /personalization/Dock - - - Keep shown - Mostra sempre - - - Keep hidden - Nascondi sempre - - - Smart hide - Nascondi automaticamente - - - Status - Comportamento - Dock - /personalization/Dock - - - Small - Piccolo - - - Large - Grande - - - Show Dock - Mostra la Dock - - - On screen where the cursor is - Sullo schermo dove è presente il cursore - - - Only on main screen - Solo sullo schermo principale - - MultitaskingPlugin @@ -422,28 +300,16 @@ Onboard Tastiera - - Settings - Impostazioni - PowerPlugin - - Power - Alimentazione - - - Power settings - Impostazioni Alimentazione - Capacity %1, %2 min remaining - Carica %1, %2 min. rimanenti + Autonomia %1, %2 min. rimanenti Capacity %1, %2 hr %3 min remaining - Carica %1, %2 ore e %3 min. rimanenti + Autonomia %1, %2 ore e %3 min. rimanenti Charging %1, %2 min until full @@ -467,38 +333,11 @@ Capacity %1, fully charged - Carica completa %1 - - - - SettingsModule - - Dock - Dock + Carica completa, capacità %1 - Mode - Modalità - - - Location - Posizione - - - Status - Comportamento - - - Size - Dimensioni - - - Show Dock - Mostra la Dock - - - Plugin Area - Area plugin + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Alimentazione - Shut down Spegni @@ -550,12 +385,27 @@ Reboot Riavvia + + Power + Alimentazione + SoundApplet - Volume - Volume + Device + Dispositivo + + + + SoundDevicesWidget + + Output Device + Dispositivo output + + + Sound settings + Impostazioni audio @@ -576,10 +426,6 @@ Volume %1 Volume %1 - - No output devices - Nessun dispositivo di output - SoundPlugin @@ -618,4 +464,19 @@ Svuota + + WindowManager + + Exit Safe Mode + Esci dalla modalità provvisoria + + + Dock - Safe Mode + Dock - Modalità provvisoria + + + The Dock is in safe mode, please exit to show it properly + La Dock è in modalità provvisoria, esci per mostrarla in modo tradizionale + + \ No newline at end of file diff --git a/translations/dde-dock_ja.ts b/translations/dde-dock_ja.ts index a320212d2..1aedb7661 100644 --- a/translations/dde-dock_ja.ts +++ b/translations/dde-dock_ja.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - + Open + 開く + + + + BloothAdapterWidget + + My Devices + お使いのデバイス + + + Other Devices + 他のデバイス @@ -88,12 +99,35 @@ オフにしました + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + オンにする + + + Turn off + オフにする + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + オンにする + + + Turn off + オフにする + DBusAdaptors @@ -102,6 +136,21 @@ キーボードレイアウトを追加 + + DateTimeDisplayer + + 12-hour time + 12時間表示 + + + 24-hour time + 24時間表示 + + + Time settings + 時間設定 + + DatetimePlugin @@ -121,6 +170,13 @@ 時間設定 + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -141,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - 不明なデバイス - - - Unknown volume - 不明なボリューム + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - ディスク + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + 有効 - Open - 開く - - - Unmount all - すべてマウント解除 + Disabled + 無効 @@ -173,21 +228,6 @@ ランチャー - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -243,93 +283,6 @@ - - ModuleWidget - - Size - サイズ - - - Multiple Displays - マルチディスプレイ - - - Plugin Area - - - - Select which icons appear in the Dock - - - - Fashion mode - ファッションモード - - - Efficient mode - 効率モード - - - Mode - モード - - - Top - - - - Bottom - - - - Left - - - - Right - - - - Location - 位置 - - - Keep shown - - - - Keep hidden - 隠したままにする - - - Smart hide - スマートハイド - - - Status - 状態 - - - Small - - - - Large - - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -347,21 +300,9 @@ Onboard Onboard - - Settings - 設定 - PowerPlugin - - Power - 電源 - - - Power settings - 電源の設定 - Capacity %1, %2 min remaining バッテリー残量 %1、残り %2 分 @@ -394,13 +335,9 @@ Capacity %1, fully charged バッテリー残量 %1、フル充電済み - - - SettingsModule - Dock - ドック - /personalization/Dock + Battery + @@ -416,10 +353,6 @@ ShutdownPlugin - - Power - 電源 - Shut down シャットダウン @@ -452,6 +385,10 @@ Reboot 再起動 + + Power + 電源 + SoundApplet @@ -460,6 +397,17 @@ デバイス + + SoundDevicesWidget + + Output Device + 出力デバイス + + + Sound settings + サウンドの設定 + + SoundItem @@ -468,7 +416,7 @@ Mute - 消音 + ミュート Sound settings @@ -516,4 +464,19 @@ + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_ka.ts b/translations/dde-dock_ka.ts new file mode 100644 index 000000000..c356a1b9e --- /dev/null +++ b/translations/dde-dock_ka.ts @@ -0,0 +1,482 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + ჩემი მოწყობილობები + + + Other Devices + სხვა მოწყობილობები + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + გაუქმება + + + Delete + წაშლა + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + DockPluginController + + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + გაუქმებულია + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + მიმზიდველი რეჟიმი + + + Efficient Mode + ეფექტური რეჟიმი + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery + + + + + ShowDesktopPlugin + + Show Desktop + ეკრანის ჩვენება + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + გადატვირთვა + + + Power + კვება + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + ხმა + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_kab.ts b/translations/dde-dock_kab.ts new file mode 100644 index 000000000..480ef61ed --- /dev/null +++ b/translations/dde-dock_kab.ts @@ -0,0 +1,482 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + Sens + + + Turn on + Sermed + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Ldi + + + + BloothAdapterWidget + + My Devices + Ibenkan-inu + + + Other Devices + Ibenkan-nniḍen + + + + BluetoothApplet + + Bluetooth settings + Iɣewwaren n Bluetooth + + + + BluetoothItem + + Turn off + Sens + + + Turn on + Sermed + + + Bluetooth settings + Iɣewwaren n Bluetooth + + + %1 connected + %1 yettwaqqen + + + Connecting... + Ala yetteqqen... + + + Bluetooth + Bluetooth + + + Turned off + Yensa + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Sermed + + + Turn off + Sens + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + Sermed + + + Turn off + Sens + + + + DBusAdaptors + + Add keyboard layout + Rnu taneɣruft n unasiw + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + Iɣewwaren n wakud + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + Iɣewwaren n wakud + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + Sefsex + + + Delete + Kkes + + + This action cannot be restored + Tigawt-agi ulamek ara d-ttwarr + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + DockPluginController + + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + Yensa + + + + LauncherItem + + Launcher + Amsekker + + + + MenuWorker + + Fashion Mode + Askar atrar + + + Efficient Mode + Askar amellil + + + Top + Afella + + + Bottom + Adda + + + Left + Azelmaḍ + + + Right + Ayeffus + + + Keep Shown + Eǧǧ-it yettban + + + Keep Hidden + Eǧǧ-it yeffer + + + Smart Hide + + + + Mode + Askar + + + Location + Adig + + + Status + Addad + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + Kkes asekkeṛ + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery + + + + + ShowDesktopPlugin + + Show Desktop + Sken tanarit + + + Undock + Kkes asekkeṛ + + + + ShutdownPlugin + + Shut down + Sens + + + Suspend + Seḥbes + + + Hibernate + + + + Lock + Sekkeṛ + + + Log out + Ffeɣ + + + Switch account + Snifel amiḍan + + + Power settings + + + + Reboot + Ales asker + + + Power + Tazmert + + + + SoundApplet + + Device + Ibenk + + + + SoundDevicesWidget + + Output Device + Ibenk n tuffɣa + + + Sound settings + Iɣewwaren n yimesli + + + + SoundItem + + Unmute + Serreḥ i yimesli + + + Mute + Gzem imesli + + + Sound settings + Iɣewwaren n yimesli + + + Volume %1 + Ableɣ %1 + + + + SoundPlugin + + Sound + Imesli + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + Ldi + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_kk.ts b/translations/dde-dock_kk.ts new file mode 100644 index 000000000..896ae951a --- /dev/null +++ b/translations/dde-dock_kk.ts @@ -0,0 +1,482 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + Бас тарту + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + DockPluginController + + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Power + Қорек + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + Дыбыс + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_km_KH.ts b/translations/dde-dock_km_KH.ts new file mode 100644 index 000000000..aad7a5cc0 --- /dev/null +++ b/translations/dde-dock_km_KH.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + បោះបង់ + + + Delete + លុប + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + Fashion Mode + + + Efficient Mode + ម៉ូដប្រសិទ្ធភាព + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + បង្ហាញផ្ទៃតុ + + + Undock + + + + + ShutdownPlugin + + Shut down + បិទ + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + ចាប់ផ្តើមឡើងវិញ + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_kn_IN.ts b/translations/dde-dock_kn_IN.ts index d590664a0..eb9292b32 100644 --- a/translations/dde-dock_kn_IN.ts +++ b/translations/dde-dock_kn_IN.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + ತೆರೆಯಿರಿ + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ ದಿನ-ಸಮಯ - 12 Hour Time - 12 ಘಂಟೆ ಸಮಯ + 12-hour time + - 24 Hour Time - 24 ಘಂಟೆ ಸಮಯ + 24-hour time + - Time Settings - ಸಮಯದ ಸೆಟ್ಟಿಂಗ್ ಗಳು + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - ಜಾಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ - - - Disable network - ಜಾಲವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ - - - Network settings - ಜಾಲ ಸೆಟ್ಟಿಂಗ್ಗಳು + PC collaboration + @@ -67,33 +197,32 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - ಅಪರಿಚಿತ ಸಾಧನ - - - Unknown volume - ಅಪರಿಚಿತ ಸಂಪುಟ - - - - DiskMountPlugin - - Disk - ಡಿಸ್ಕ್ - - - Open - ತೆರೆಯಿರಿ - - - Unmount all + Multi-Screen Collaboration - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker Fashion Mode ಅಲಂಕೃತ ರೂಪ @@ -143,14 +272,7 @@ - Plugins - - - - - LauncherItem - - Launcher + Dock settings @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down - - Restart - - Suspend @@ -267,6 +374,14 @@ Power settings + + Reboot + + + + Plugged In + + SoundApplet @@ -274,8 +389,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +412,11 @@ - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +441,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +458,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_ko.ts b/translations/dde-dock_ko.ts index a430b1f07..40dcaf0fa 100644 --- a/translations/dde-dock_ko.ts +++ b/translations/dde-dock_ko.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - 제거 + Open + 열기 + + + + BloothAdapterWidget + + My Devices + 내 장치 + + + Other Devices + 기타 장치 @@ -88,12 +99,35 @@ 꺼짐 + + BluetoothMainWidget + + Bluetooth + 블루투스 + + + Turn on + 켜기 + + + Turn off + 끄기 + + BluetoothPlugin Bluetooth 블루투스 + + Turn on + 켜기 + + + Turn off + 끄기 + DBusAdaptors @@ -102,6 +136,21 @@ 키보드 레이아웃 추가 + + DateTimeDisplayer + + 12-hour time + 12 시간 + + + 24-hour time + 24시간 + + + Time settings + 시간 설정 + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - 월요일 - - - Tuesday - 화요일 - - - Wednesday - 수요일 - - - Thursday - 목요일 - - - Friday - 금요일 - - - Saturday - 토요일 - - - Sunday - 일요일 - - - monday - - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - 알 수 없는 장치 - - - Unknown volume - 알 수 없는 볼륨 + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - 디스크 + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + 활성상태 - Open - 열기 - - - Unmount all - 모두 마운트 해제 + Disabled + 사용안함 @@ -236,21 +228,6 @@ 실행도구 - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - 크기 - Dock - /personalization/Dock - - - Multiple Displays - 다중 디스플레이 - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - 패션(Fashion) 모드 - - - Efficient mode - 효율 모드 - - - Mode - 모드 - Dock - /personalization/Dock - - - Top - 상단 - - - Bottom - 하단 - - - Left - 왼쪽 - - - Right - 오른쪽 - - - Location - 위치 - Dock - /personalization/Dock - - - Keep shown - - - - Keep hidden - 숨겨두기 - - - Smart hide - 스마트하이드 - - - Status - 상태 - Dock - /personalization/Dock - - - Small - 소형 - - - Large - 대형 - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard 온보드 - - Settings - 설정 - PowerPlugin - - Power - 전원 - - - Power settings - 전원 설정 - Capacity %1, %2 min remaining 용량 %1, %2분 남음 @@ -469,35 +335,8 @@ Capacity %1, fully charged 용량 %1, 완전히 충전됨 - - - SettingsModule - Dock - 도구집 - - - Mode - 모드 - - - Location - 위치 - - - Status - 상태 - - - Size - 크기 - - - Show Dock - - - - Plugin Area + Battery @@ -514,13 +353,9 @@ ShutdownPlugin - - Power - 전원 - Shut down - 종료 + 컴퓨터 끄기 Suspend @@ -550,12 +385,27 @@ Reboot 재부팅 + + Power + 전원 + SoundApplet - Volume - 음량 + Device + 장치 + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + 사운드 설정 @@ -576,10 +426,6 @@ Volume %1 음량 %1% - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ 비우기 + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_ku.ts b/translations/dde-dock_ku.ts new file mode 100644 index 000000000..8fec1e232 --- /dev/null +++ b/translations/dde-dock_ku.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + Betal Bike + + + Delete + Jê Bibe + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + Hilpekîner + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + Bigire + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + Derkeve + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_ku_IQ.ts b/translations/dde-dock_ku_IQ.ts index 1ae1ae1ca..bd66c8756 100644 --- a/translations/dde-dock_ku_IQ.ts +++ b/translations/dde-dock_ku_IQ.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,32 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + HomeMonitorPlugin - Disk + Enabled - Open - + Disabled + ناچالاککراو + + + LauncherItem - Unmount all + Launcher - DockSettings + MenuWorker Fashion Mode @@ -143,14 +272,7 @@ - Plugins - - - - - LauncherItem - - Launcher + Dock settings @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - Mîheng - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down - - Restart - - Suspend @@ -267,6 +374,14 @@ Power settings + + Reboot + + + + Plugged In + + SoundApplet @@ -274,8 +389,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +412,11 @@ Bêdeng - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +441,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +458,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_ky.ts b/translations/dde-dock_ky.ts new file mode 100644 index 000000000..848ef5722 --- /dev/null +++ b/translations/dde-dock_ky.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + жокко чыгаруу + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_ky@Arab.ts b/translations/dde-dock_ky@Arab.ts new file mode 100644 index 000000000..ca66b2058 --- /dev/null +++ b/translations/dde-dock_ky@Arab.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + جوققو چىعارۇۇ + + + Delete + ۅچۉرۉۉ + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_la.ts b/translations/dde-dock_la.ts new file mode 100644 index 000000000..30076bc06 --- /dev/null +++ b/translations/dde-dock_la.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_lo.ts b/translations/dde-dock_lo.ts index 5b1a524b7..2d692bc80 100644 --- a/translations/dde-dock_lo.ts +++ b/translations/dde-dock_lo.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + ເປີດ + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ ເພີ່ມຮູບແບບແປ້ນພິມ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,32 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + HomeMonitorPlugin - Disk + Enabled - Open - ເປີດ - - - Unmount all + Disabled - DockSettings + LauncherItem + + Launcher + + + + + MenuWorker Fashion Mode @@ -143,14 +272,7 @@ - Plugins - - - - - LauncherItem - - Launcher + Dock settings @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down ປິດ​ເຄື່ອງ - - Restart - - Suspend ຢຸດໄວ້ @@ -267,6 +374,14 @@ Power settings + + Reboot + ເປີດຄືນ + + + Plugged In + + SoundApplet @@ -274,8 +389,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +412,11 @@ - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +441,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +458,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_lt.ts b/translations/dde-dock_lt.ts index c481c596f..435131299 100644 --- a/translations/dde-dock_lt.ts +++ b/translations/dde-dock_lt.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Šalinti + Open + Atverti + + + + BloothAdapterWidget + + My Devices + Mano įrenginiai + + + Other Devices + Kiti įrenginiai @@ -88,12 +99,35 @@ + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Įjungti + + + Turn off + Išjungti + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Įjungti + + + Turn off + Išjungti + DBusAdaptors @@ -102,6 +136,21 @@ Pridėti klaviatūros išdėstymą + + DateTimeDisplayer + + 12-hour time + 12 valandų laikas + + + 24-hour time + 24 valandų laikas + + + Time settings + Laiko nustatymai + + DatetimePlugin @@ -121,6 +170,13 @@ Laiko nustatymai + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -141,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Nežinomas įrenginys - - - Unknown volume - Nežinomas tomas + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Diskas + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Atverti - - - Unmount all - Atjungti visus + Disabled + Išjungta @@ -173,21 +228,6 @@ Leistukas - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -243,93 +283,6 @@ - - ModuleWidget - - Size - Dydis - - - Multiple Displays - Keli ekranai - - - Plugin Area - - - - Select which icons appear in the Dock - - - - Fashion mode - Madinga veiksena - - - Efficient mode - Efektyvi veiksena - - - Mode - Veiksena - - - Top - Viršus - - - Bottom - Apačia - - - Left - Kairė - - - Right - Dešinė - - - Location - Vieta - - - Keep shown - - - - Keep hidden - Laikyti paslėptą - - - Smart hide - Išmaniai slėpti - - - Status - Būsena - - - Small - Mažas - - - Large - Didelis - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -347,21 +300,9 @@ Onboard Onboard - - Settings - Nustatymai - PowerPlugin - - Power - Energija - - - Power settings - Energijos nustatymai - Capacity %1, %2 min remaining Talpa %1, liko %2 min. @@ -394,13 +335,9 @@ Capacity %1, fully charged - - - SettingsModule - Dock - Dokas - /personalization/Dock + Battery + @@ -416,10 +353,6 @@ ShutdownPlugin - - Power - Energija - Shut down Išjungti @@ -452,6 +385,10 @@ Reboot Paleisti iš naujo + + Power + Energija + SoundApplet @@ -460,6 +397,17 @@ Įrenginys + + SoundDevicesWidget + + Output Device + + + + Sound settings + Garso nustatymai + + SoundItem @@ -516,4 +464,19 @@ Išvalyti + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_lv.ts b/translations/dde-dock_lv.ts new file mode 100644 index 000000000..2f5b44f79 --- /dev/null +++ b/translations/dde-dock_lv.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + Atcelt + + + Delete + Dzēst + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + Izslēgt + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + Izrakstīties + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + Miskaste + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_ml.ts b/translations/dde-dock_ml.ts index fca0deca7..3a56d3104 100644 --- a/translations/dde-dock_ml.ts +++ b/translations/dde-dock_ml.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + ബ്ലൂടൂത്ത് + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + ബ്ലൂടൂത്ത് + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + ബ്ലൂടൂത്ത് + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,32 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - അറിയാത്ത ഉപകരണം - - - Unknown volume - അറിയാത്ത വോള്യം - - - - DiskMountPlugin - - Disk - ഡിസ്ക് - - - Open - - - - Unmount all + Multi-Screen Collaboration - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + ലോഞ്ചർ + + + + MenuWorker Fashion Mode ഫാഷൻ രീതി @@ -143,17 +272,10 @@ അവസ്ഥ - Plugins + Dock settings - - LauncherItem - - Launcher - ലോഞ്ചർ - - MultitaskingPlugin @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down നിർത്തുക - - Restart - - Suspend @@ -267,6 +374,14 @@ Power settings + + Reboot + + + + Plugged In + + SoundApplet @@ -274,9 +389,16 @@ Device ഉപകരണം + + + SoundDevicesWidget - Application - പ്രയോഗം + Output Device + + + + Sound settings + @@ -290,11 +412,11 @@ - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +441,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +458,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_mn.ts b/translations/dde-dock_mn.ts index 20866d697..b99f12c43 100644 --- a/translations/dde-dock_mn.ts +++ b/translations/dde-dock_mn.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ %1 нэмэлт нь үйлдэлийн үйлдэлийн системтэй нийцэхгүй байна. + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Нээх + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Блютүүт + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Блютүүт + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Блютүүт + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Гарын байрлал нэмэх + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ Огноо - 12 Hour Time - 12 цагаар + 12-hour time + - 24 Hour Time - 24 цагаар + 24-hour time + - Time Settings - Цагны тохиргоо + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - Сүлжээг идэвхижүүлэх - - - Disable network - Сүлжээг идэвхгүй болгох - - - Network settings - Сүлээний тохиргоо + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Тодорхойгүй төхөөрөмж - - - Unknown volume - Тодорхойгүй дууны хэм + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Диск - - - Open - Нээх - - - Unmount all - Бүгдийг салгах + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Идэвхигүй болсон + + + + LauncherItem + + Launcher + Эхлүүлэгч + + + + MenuWorker Fashion Mode Загварлаг горим @@ -143,15 +279,8 @@ Төлөв - Plugins - Нэмэлтүүд - - - - LauncherItem - - Launcher - Эхлүүлэгч + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Сүлжээ - - OnboardPlugin Onboard Дэлгэцийн гар - - Settings - Тохиргоо - PowerPlugin - - Power - Цэнэг - - - Power settings - Цэнэгийн тохиргоо - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - %1 цэнэглэсэн - Charging %1, %2 min until full @@ -214,11 +320,23 @@ - Charging %1 .... + Capacity %1 - Charged + Charging %1 + %1 цэнэглэж байна + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -235,18 +353,10 @@ ShutdownPlugin - - Power - Цэнэг - Shut down Унтраах - - Restart - Дахин эхлүүлэх - Suspend Түр зогсоох @@ -271,6 +381,14 @@ Power settings Цэнэгийн тохиргоо + + Reboot + Дахин ачааллах + + + Power + Цэнэг + SoundApplet @@ -278,9 +396,16 @@ Device Төхөөрөмж + + + SoundDevicesWidget - Application - Програм + Output Device + + + + Sound settings + @@ -294,12 +419,12 @@ Дуу хаах - Audio Settings - Дууны тохиргоо + Sound settings + - Current Volume %1 - Одоогийн дууны хэм %1 + Volume %1 + @@ -323,6 +448,10 @@ Trash - %1 files Хогийн сав - %1 файлтай + + Move to Trash + + TrashWidget @@ -336,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - Системийн тавиур - - - - WiredItem - - Unknown - Тодорхойгүй + Exit Safe Mode + - Wired connection: %1 - Утастай холболт: %1 - - - - WirelessItem - - No Network - Сүлжээ байхгүй + Dock - Safe Mode + - Wireless Connection: %1 - Утасгүй холболт: %1 - - - Connected but no Internet access - Холбогдсон боловч интернетэд холбогдоогүй байна - - - - WirelessList - - Wireless Network - Утасгүй сүлжээ - - - Wireless Network %1 - Утасгүй сүлжээ %1 + The Dock is in safe mode, please exit to show it properly + \ No newline at end of file diff --git a/translations/dde-dock_mr.ts b/translations/dde-dock_mr.ts new file mode 100644 index 000000000..a63512a74 --- /dev/null +++ b/translations/dde-dock_mr.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_ms.ts b/translations/dde-dock_ms.ts index 865844aed..b79ee6495 100644 --- a/translations/dde-dock_ms.ts +++ b/translations/dde-dock_ms.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Buang + Open + Buka + + + + BloothAdapterWidget + + My Devices + Peranti Saya + + + Other Devices + Peranti Lain @@ -88,12 +99,35 @@ Dimatikan + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Hidupkan + + + Turn off + Matikan + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Hidupkan + + + Turn off + Matikan + DBusAdaptors @@ -102,6 +136,21 @@ Tambah bentangan papan kekunci + + DateTimeDisplayer + + 12-hour time + Waktu 12-jam + + + 24-hour time + Waktu 24-jam + + + Time settings + Tetapan waktu + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Isnin - - - Tuesday - Selasa - - - Wednesday - Rabu - - - Thursday - Khamis - - - Friday - Jumaat - - - Saturday - Sabtu - - - Sunday - Ahad - - - monday - isnin - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Peranti tidak diketahui - - - Unknown volume - Volum tidak diketahui + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Cakera + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Buka - - - Unmount all - Tanggalkan semua + Disabled + Dilumpuhkan @@ -236,21 +228,6 @@ Pelancar - - MainWindow - - Exit Safe Mode - Keluar dari Mod Selamat - - - Dock - Safe Mode - Labuh - Mod Selamat - - - The Dock is in safe mode, please exit to show it properly - Labuh dalam mod selamat, sila keluar dahulu supaya dapat dipaparkan dengan baik - - MenuWorker @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - Saiz - Dock - /personalization/Dock - - - Multiple Displays - Paparan Berbilang - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - Mod fesyen - - - Efficient mode - Mod efisyen - - - Mode - Mod - Dock - /personalization/Dock - - - Top - Teratas - - - Bottom - Bawah - - - Left - Kiri - - - Right - Kanan - - - Location - Lokasi - Dock - /personalization/Dock - - - Keep shown - - - - Keep hidden - Kekal tersembunyi - - - Smart hide - Sembunyi pintar - - - Status - Status - Dock - /personalization/Dock - - - Small - Kecil - - - Large - Besar - - - Show Dock - - - - On screen where the cursor is - Atas skrin yang mana kursor berada - - - Only on main screen - Hanya dalam skrin utama - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Atas Papan - - Settings - Tetapan - PowerPlugin - - Power - Kuasa - - - Power settings - Tetapan kuasa - Capacity %1, %2 min remaining Kapasiti %1, %2 min berbaki @@ -469,35 +335,8 @@ Capacity %1, fully charged Kapasiti %1, sepenuhnya dicas - - - SettingsModule - Dock - Labuh - - - Mode - Mod - - - Location - Lokasi - - - Status - Status - - - Size - Saiz - - - Show Dock - - - - Plugin Area + Battery @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Kuasa - Shut down Matikan @@ -536,7 +371,7 @@ Log out - Daftar keluar + Daftar keluar Switch account @@ -550,12 +385,27 @@ Reboot But semula + + Power + Kuasa + SoundApplet - Volume - Volum + Device + Peranti + + + + SoundDevicesWidget + + Output Device + Peranti output + + + Sound settings + Tetapan bunyi @@ -576,10 +426,6 @@ Volume %1 Volum %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Kosong + + WindowManager + + Exit Safe Mode + Keluar dari Mod Selamat + + + Dock - Safe Mode + Labuh - Mod Selamat + + + The Dock is in safe mode, please exit to show it properly + Labuh dalam mod selamat, sila keluar dahulu supaya dapat dipaparkan dengan baik + + \ No newline at end of file diff --git a/translations/dde-dock_nb.ts b/translations/dde-dock_nb.ts index 7861d9231..d5fbbc8d7 100644 --- a/translations/dde-dock_nb.ts +++ b/translations/dde-dock_nb.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ Plugin %1 er ikke kompatibel med systemet + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Åpne + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Legg til tastaturlayout + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ Dato og tid - 12 Hour Time - 12 timers klokke + 12-hour time + - 24 Hour Time - 24 timers klokke + 24-hour time + - Time Settings - Tidsinnstillinger + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - Skru på nettverk - - - Disable network - Skru av nettverk - - - Network settings - Nettverksinnstillinger + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Ukjent enhet - - - Unknown volume - Ukjent volum + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk - - - Open - Åpne - - - Unmount all - Avmonter alle + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Deaktiver + + + + LauncherItem + + Launcher + Starteren + + + + MenuWorker Fashion Mode Fashion Mode @@ -143,15 +279,8 @@ Status - Plugins - Utvidelser - - - - LauncherItem - - Launcher - Starteren + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Nettverk - - OnboardPlugin Onboard Ombord - - Settings - Instillinger - PowerPlugin - - Power - Strøm - - - Power settings - Strøminnstillinger - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - Ladet opp %1 - Charging %1, %2 min until full @@ -214,12 +320,24 @@ - Charging %1 .... + Capacity %1 - Charged - Endret + Charging %1 + Lader %1 + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery + @@ -235,25 +353,17 @@ ShutdownPlugin - - Power - Strøm - Shut down Slå av - - Restart - Restart - Suspend Suspendere Hibernate - Dvalemodus + Dvale Lock @@ -271,6 +381,14 @@ Power settings Strøminnstillinger + + Reboot + Omstart + + + Power + Strøm + SoundApplet @@ -278,9 +396,16 @@ Device Enhet + + + SoundDevicesWidget - Application - Applikasjon + Output Device + + + + Sound settings + @@ -294,12 +419,12 @@ Demp - Audio Settings - Lydinnstillinger + Sound settings + - Current Volume %1 - Nåværende Volum %1 + Volume %1 + @@ -323,6 +448,10 @@ Trash - %1 files Søppel - %1 filer + + Move to Trash + Flytt til søpla + TrashWidget @@ -336,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - Oppgavelinje - - - - WiredItem - - Unknown - Ukjent + Exit Safe Mode + - Wired connection: %1 - Kablet tilkobling: %1 - - - - WirelessItem - - No Network - Ingen Nettverk + Dock - Safe Mode + - Wireless Connection: %1 - Trådløs Tilkobling: %1 - - - Connected but no Internet access - Tilkoblet men ingen tilgang til internett - - - - WirelessList - - Wireless Network - Trådløs Nettverk - - - Wireless Network %1 - Trådløst Nettverk: %1 + The Dock is in safe mode, please exit to show it properly + \ No newline at end of file diff --git a/translations/dde-dock_ne.ts b/translations/dde-dock_ne.ts index 179878caa..2c4ed511d 100644 --- a/translations/dde-dock_ne.ts +++ b/translations/dde-dock_ne.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ प्लगिन %1 प्रणाली मा समर्थित छैन + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + खोल्नुहोस् + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + ब्लुटूथ + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + ब्लुटूथ + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + ब्लुटूथ + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ कीबोर्ड थप्नुहोस् + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -33,18 +171,10 @@ - DeviceItem + DevCollaborationWidget - Enable network - नेटवर्क सुचारु गर्नुहोस - - - Disable network - नेटवर्क निस्क्रिय - - - Network settings - नेटवर्क सेटिंग्स + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - अज्ञात उपकरण - - - Unknown volume - अज्ञात भण्डारण आयतन + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - भण्डारण - - - Open - खोल्नुहोस् - - - Unmount all - सबै निष्कासित गर्नुहोस् + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + अक्षम + + + + LauncherItem + + Launcher + लन्चर + + + + MenuWorker Fashion Mode आधुनिक शैली @@ -143,15 +279,8 @@ स्थिती - Plugins - प्लगइनहरू - - - - LauncherItem - - Launcher - लन्चर + Dock settings + @@ -165,34 +294,15 @@ हटाउने - - NetworkPlugin - - Network - नेटवर्क - - OnboardPlugin Onboard अन-बोर्ड - - Settings - सेटिंग्स - PowerPlugin - - Power - पावर - - - Power settings - पावर सेटिङहरू - Capacity %1, %2 min remaining क्षमता %1, %2मिनट बाँकी @@ -209,10 +319,6 @@ Charging %1, %2 hr %3 min until full %1 मा चार्ज हुंदै, पुर्ण हुन %2 घण्टा %3 मिनट लाग्छ - - Charged - - Capacity %1 @@ -229,6 +335,10 @@ Capacity %1, fully charged + + Battery + + ShowDesktopPlugin @@ -243,10 +353,6 @@ ShutdownPlugin - - Power - पावर - Shut down बन्द गर्नुहोस् @@ -279,6 +385,10 @@ Reboot रिबुट गर्नुहोस् + + Power + पावर + SoundApplet @@ -286,9 +396,16 @@ Device उपकरण + + + SoundDevicesWidget - Application - Application + Output Device + + + + Sound settings + @@ -331,6 +448,10 @@ Trash - %1 files रद्दीटोकरी -% 1 फाइलहरू + + Move to Trash + + TrashWidget @@ -344,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - प्रणाली ट्रे - - - - WiredItem - - Unknown - अज्ञात - - - Wired connection: %1 - तारको जडान:% 1 - - - - WirelessItem - - No Network - नेटवर्क छैन - - - Connected but no Internet access + Exit Safe Mode - Wireless connection: %1 + Dock - Safe Mode - - - WirelessList - Wireless Network - वायरलेस नेटवर्क - - - Wireless Network %1 - वायरलेस नेटवर्क% 1 + The Dock is in safe mode, please exit to show it properly + \ No newline at end of file diff --git a/translations/dde-dock_nl.ts b/translations/dde-dock_nl.ts index 0f6606d8e..d1eacebde 100644 --- a/translations/dde-dock_nl.ts +++ b/translations/dde-dock_nl.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Verwijderen + Open + Openen + + + + BloothAdapterWidget + + My Devices + Mijn apparaten + + + Other Devices + Andere apparaten @@ -88,12 +99,35 @@ Uitgeschakeld + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Inschakelen + + + Turn off + Uitschakelen + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Inschakelen + + + Turn off + Uitschakelen + DBusAdaptors @@ -102,6 +136,21 @@ Toetsenbordindeling toevoegen + + DateTimeDisplayer + + 12-hour time + 12-uursklok + + + 24-hour time + 24-uursklok + + + Time settings + Tijdinstellingen + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Maandag - - - Tuesday - Dinsdag - - - Wednesday - Woensdag - - - Thursday - Donderdag - - - Friday - Vrijdag - - - Saturday - Zaterdag - - - Sunday - Zondag - - - monday - maandag - - - tuesday - dinsdag - - - wednesday - woensdag - - - thursday - donderdag - - - friday - vrijdag - - - saturday - zaterdag - - - sunday - zondag - - - %1year%2month%3day - %1jaar%2maand%3dag + PC collaboration + Computersamenwerking @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Onbekend apparaat - - - Unknown volume - Onbekende schijf + Multi-Screen Collaboration + Samenwerken op meerdere schermen - DiskMountPlugin + DockPluginController - Disk - Schijf + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Ingeschakeld - Open - Openen - - - Unmount all - Alles ontkoppelen + Disabled + Uitgeschakeld @@ -236,21 +228,6 @@ Programmastarter - - MainWindow - - Exit Safe Mode - Veilige modus afsluiten - - - Dock - Safe Mode - Dock - Veilige modus - - - The Dock is in safe mode, please exit to show it properly - Het dock draait in de veilige modus. Sluit af om het dock correct te tonen. - - MenuWorker @@ -306,105 +283,6 @@ Dockinstellingen - - ModuleWidget - - Size - Grootte - Dock - /personalization/Dock - - - Multiple Displays - Meerdere beeldschermen - Dock - /personalization/Dock - - - Plugin Area - Invoegtoepassingsgebied - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Geef aan welke pictogrammen moeten worden getoond op het dock - - - Fashion mode - Moderne modus - - - Efficient mode - Efficiënte modus - - - Mode - Modus - Dock - /personalization/Dock - - - Top - Bovenaan - - - Bottom - Onderaan - - - Left - Links - - - Right - Rechts - - - Location - Locatie - Dock - /personalization/Dock - - - Keep shown - Altijd tonen - - - Keep hidden - Altijd verbergen - - - Smart hide - Slim verbergen - - - Status - Status - Dock - /personalization/Dock - - - Small - Klein - - - Large - Groot - - - Show Dock - Dock tonen - - - On screen where the cursor is - Op het scherm waar de cursor is - - - Only on main screen - Alleen op hoofdscherm - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Onboard - - Settings - Instellingen - PowerPlugin - - Power - Energie - - - Power settings - Energie-instellingen - Capacity %1, %2 min remaining Capaciteit: %1 - %2 min resterend @@ -469,36 +335,9 @@ Capacity %1, fully charged Capaciteit: %1 - volledig opgeladen - - - SettingsModule - Dock - Vastmaken - - - Mode - Modus - - - Location - Locatie - - - Status - Status - - - Size - Grootte - - - Show Dock - Dock tonen - - - Plugin Area - Invoegtoepassingsgebied + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Energie - Shut down Afsluiten @@ -550,12 +385,27 @@ Reboot Herstarten + + Power + Energie + SoundApplet - Volume - Volume + Device + Apparaat + + + + SoundDevicesWidget + + Output Device + Uitvoerapparaat + + + Sound settings + Geluidsinstellingen @@ -576,10 +426,6 @@ Volume %1 %1 volume - - No output devices - Geen uitvoerapparaten - SoundPlugin @@ -615,7 +461,22 @@ Empty - Leeg + Legen + + + + WindowManager + + Exit Safe Mode + Veilige modus afsluiten + + + Dock - Safe Mode + Dock - Veilige modus + + + The Dock is in safe mode, please exit to show it properly + Het dock draait in de veilige modus. Sluit af om het dock correct te tonen. \ No newline at end of file diff --git a/translations/dde-dock_pa.ts b/translations/dde-dock_pa.ts index b0db1435b..18d3fac14 100644 --- a/translations/dde-dock_pa.ts +++ b/translations/dde-dock_pa.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + ਖੋਲ੍ਹੋ + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + ਬਲੂਟੁੱਥ + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + ਬਲੂਟੁੱਥ + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + ਬਲੂਟੁੱਥ + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ ਤਾਰੀਖ ਸਮਾਂ - 12 Hour Time - 12 ਘੰਟਿਆਂ ਵਾਲਾ ਵੇਲਾ + 12-hour time + - 24 Hour Time - 24 ਘੰਟਿਆਂ ਵਾਲਾ ਵੇਲਾ + 24-hour time + - Time Settings - ਸਮਾਂ ਸੈਟਿੰਗਾਂ + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - ਨੈੱਟਵਰਕ ਸਮਰੱਥ ਕਰੋ - - - Disable network - ਨੈੱਟਵਰਕ ਅਸਮਰੱਥ ਕਰੋ - - - Network settings - ਨੈੱਟਵਰਕ ਸੈਟਿੰਗਾਂ + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - ਡਿਸਕ - - - Open - ਖੋਲ੍ਹੋ - - - Unmount all + The plugin %1 is not compatible with the system. - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + ਲਾਂਚਰ + + + + MenuWorker Fashion Mode @@ -143,17 +279,10 @@ - Plugins + Dock settings - - LauncherItem - - Launcher - ਲਾਂਚਰ - - MultitaskingPlugin @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - ਨੈੱਟਵਰਕ - - OnboardPlugin Onboard ਆਨ-ਬੋਰਡ - - Settings - ਸੈਟਿੰਗਾਂ - PowerPlugin - - Power - ਪਾਵਰ - - - Power settings - ਪਾਵਰ ਸੈਟਿੰਗਾਂ - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +320,23 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -231,18 +353,10 @@ ShutdownPlugin - - Power - ਪਾਵਰ - Shut down ਬੰਦ ਕਰੋ - - Restart - ਮੁੜ-ਚਾਲੂ ਕਰੋ - Suspend ਸਸਪੈਂਡ ਕਰੋ @@ -253,11 +367,11 @@ Lock - ਤਾਲਾਬੰਦ + ਲਾਕ ਕਰੋ Log out - ਲਾਗ ਆਉਟ + ਲਾਗ ਆਉਟ ਕਰੋ Switch account @@ -267,6 +381,14 @@ Power settings ਪਾਵਰ ਸੈਟਿੰਗਾਂ + + Reboot + ਮੁੜ-ਚਾਲੂ ਕਰੋ + + + Power + ਊਰਜਾ + SoundApplet @@ -274,9 +396,16 @@ Device ਡਿਵਾਈਸ + + + SoundDevicesWidget - Application - ਐਪਲੀਕੇਸ਼ਨ + Output Device + + + + Sound settings + @@ -290,11 +419,11 @@ - Audio Settings - ਆਡੀਓ ਸੈਟਿੰਗਾਂ + Sound settings + - Current Volume %1 + Volume %1 @@ -302,7 +431,7 @@ SoundPlugin Sound - + ਆਵਾਜ਼ @@ -319,12 +448,16 @@ Trash - %1 files + + Move to Trash + + TrashWidget Open - + ਖੋਲ੍ਹੋ Empty @@ -332,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - ਸਿਸਟਮ ਟਰੇ - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - ਤਾਰਾ ਵਾਲਾ ਕਨੈਕਸ਼ਨ: %1 - - - - WirelessItem - - No Network - ਕੋਈ ਨੈੱਟਵਰਕ ਨਹੀਂ ਹੈ - - - Wireless Connection: %1 - ਬੇਤਾਰ ਕਨੈਕਸ਼ਨ: %1 - - - Connected but no Internet access + Dock - Safe Mode - - - WirelessList - Wireless Network - ਬੇਤਾਰ ਨੈੱਟਵਰਕ - - - Wireless Network %1 - ਬੇਤਾਰ ਨੈੱਟਵਰਕ: %1 + The Dock is in safe mode, please exit to show it properly + \ No newline at end of file diff --git a/translations/dde-dock_pam.ts b/translations/dde-dock_pam.ts index 258667c99..c98053988 100644 --- a/translations/dde-dock_pam.ts +++ b/translations/dde-dock_pam.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Ibuklat + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,32 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + HomeMonitorPlugin - Disk + Enabled - Open - Ibuklat + Disabled + Eya magsilbi + + + LauncherItem - Unmount all + Launcher - DockSettings + MenuWorker Fashion Mode @@ -143,14 +272,7 @@ - Plugins - - - - - LauncherItem - - Launcher + Dock settings @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down - - Restart - - Suspend @@ -267,6 +374,14 @@ Power settings + + Reboot + + + + Plugged In + + SoundApplet @@ -274,8 +389,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +412,11 @@ I-mute - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +441,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +458,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_pl.ts b/translations/dde-dock_pl.ts index 4839a9f7f..9493d482a 100644 --- a/translations/dde-dock_pl.ts +++ b/translations/dde-dock_pl.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Usuń + Open + Otwórz + + + + BloothAdapterWidget + + My Devices + Moje urządzenia + + + Other Devices + Inne urządzenia @@ -73,7 +84,7 @@ %1 connected - Podłączono %1 + %1 połączono Connecting... @@ -88,12 +99,35 @@ Wyłączony + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Włącz + + + Turn off + Wyłącz + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Włącz + + + Turn off + Wyłącz + DBusAdaptors @@ -102,6 +136,21 @@ Dodaj układ klawiatury + + DateTimeDisplayer + + 12-hour time + Format 12-godzinny + + + 24-hour time + Format 24-godzinny + + + Time settings + Ustawienia czasu + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Poniedziałek - - - Tuesday - Wtorek - - - Wednesday - Środa - - - Thursday - Czwartek - - - Friday - Piątek - - - Saturday - Sobota - - - Sunday - Niedziela - - - monday - poniedziałek - - - tuesday - wtorek - - - wednesday - środa - - - thursday - czwartek - - - friday - piątek - - - saturday - sobota - - - sunday - niedziela - - - %1year%2month%3day - %1rok%2miesiąc%3dzień + PC collaboration + Kolaboracja PC @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Nieznane urządzenie - - - Unknown volume - Nieznana głośność + Multi-Screen Collaboration + Kolaboracja wieloekranowa - DiskMountPlugin + DockPluginController - Disk - Dysk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Włączone - Open - Otwórz - - - Unmount all - Odmontuj wszystkie + Disabled + Wyłączone @@ -236,21 +228,6 @@ Program wywołujący - - MainWindow - - Exit Safe Mode - Wyjdź z trybu bezpiecznego - - - Dock - Safe Mode - Dok - Tryb bezpieczny - - - The Dock is in safe mode, please exit to show it properly - Dok jest w trybie bezpiecznym, wyjdź z niego, aby wyświetlić go poprawnie - - MenuWorker @@ -306,105 +283,6 @@ Ustawienia doku - - ModuleWidget - - Size - Rozmiar - Dock - /personalization/Dock - - - Multiple Displays - Wiele ekranów - Dock - /personalization/Dock - - - Plugin Area - Strefa wtyczek - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Wybierz, które wtyczki pojawią się w doku - - - Fashion mode - Tryb modny - - - Efficient mode - Tryb wydajny - - - Mode - Tryb - Dock - /personalization/Dock - - - Top - Góra - - - Bottom - Dół - - - Left - Lewo - - - Right - Prawo - - - Location - Położenie - Dock - /personalization/Dock - - - Keep shown - Zawsze wyświetlaj - - - Keep hidden - Zawsze ukrywaj - - - Smart hide - Inteligentne ukrywanie - - - Status - Status - Dock - /personalization/Dock - - - Small - Mały - - - Large - Ogromny - - - Show Dock - Pokaż dok - - - On screen where the cursor is - Na ekranie, tam gdzie jest kursor - - - Only on main screen - Tylko na ekranie głównym - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Klawiatura ekranowa - - Settings - Ustawienia - PowerPlugin - - Power - Zasilanie - - - Power settings - Ustawienia zasilania - Capacity %1, %2 min remaining Poziom: %1, pozostało: %2min @@ -469,36 +335,9 @@ Capacity %1, fully charged Pojemność %1, w pełni naładowana - - - SettingsModule - Dock - Dok - - - Mode - Tryb - - - Location - Położenie - - - Status - Status - - - Size - Rozmiar - - - Show Dock - Pokaż dok - - - Plugin Area - Strefa wtyczek + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Zasilanie - Shut down Wyłącz @@ -548,14 +383,29 @@ Reboot - Uruchom ponownie + Uruchomienie ponowne + + + Power + Zasilanie SoundApplet - Volume - Głośność + Device + Urządzenie + + + + SoundDevicesWidget + + Output Device + Urządzenie wyjściowe + + + Sound settings + Ustawienia dźwięku @@ -576,10 +426,6 @@ Volume %1 Głośność %1 - - No output devices - Brak urządzeń wyjściowych - SoundPlugin @@ -618,4 +464,19 @@ Opróżnij + + WindowManager + + Exit Safe Mode + Wyjdź z trybu bezpiecznego + + + Dock - Safe Mode + Dok - Tryb bezpieczny + + + The Dock is in safe mode, please exit to show it properly + Dok jest w trybie bezpiecznym, wyjdź z niego, aby wyświetlić go poprawnie + + \ No newline at end of file diff --git a/translations/dde-dock_ps.ts b/translations/dde-dock_ps.ts new file mode 100644 index 000000000..4d1a72a12 --- /dev/null +++ b/translations/dde-dock_ps.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_pt.ts b/translations/dde-dock_pt.ts index cff4fd447..9e36c8bde 100644 --- a/translations/dde-dock_pt.ts +++ b/translations/dde-dock_pt.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Remover + Open + Abrir + + + + BloothAdapterWidget + + My Devices + Os meus dispositivos + + + Other Devices + Outros Dispositivos @@ -88,12 +99,35 @@ Desligado + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Ligar + + + Turn off + Desligar + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Ligar + + + Turn off + Desligar + DBusAdaptors @@ -102,6 +136,21 @@ Adicionar esquema de teclado + + DateTimeDisplayer + + 12-hour time + 12 horas + + + 24-hour time + 24 horas + + + Time settings + Definições horárias + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Segunda - - - Tuesday - Terça - - - Wednesday - Quarta - - - Thursday - Quinta - - - Friday - Sexta - - - Saturday - Sábado - - - Sunday - Domingo - - - monday - segunda - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - domingo - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Dispositivo desconhecido - - - Unknown volume - Volume desconhecido + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disco + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Abrir - - - Unmount all - Desmontar tudo + Disabled + Desativado @@ -236,21 +228,6 @@ Lançador - - MainWindow - - Exit Safe Mode - Sair do Modo Seguro - - - Dock - Safe Mode - Doca - Modo Seguro - - - The Dock is in safe mode, please exit to show it properly - A Doca está em modo seguro, saia para a mostrar corretamente - - MenuWorker @@ -306,105 +283,6 @@ Definições da doca - - ModuleWidget - - Size - Tamanho - Dock - /personalization/Dock - - - Multiple Displays - Vários ecrãs - Dock - /personalization/Dock - - - Plugin Area - Área de plugins - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Selecione quais os ícones que aparecem na Doca - - - Fashion mode - Modo Elegante - - - Efficient mode - Modo eficiente - - - Mode - Modo - Dock - /personalization/Dock - - - Top - Superior - - - Bottom - Inferior - - - Left - Esquerda - - - Right - Direita - - - Location - Localização - Dock - /personalization/Dock - - - Keep shown - Manter visível - - - Keep hidden - Manter ocultada - - - Smart hide - Ocultação inteligente - - - Status - Estado - Dock - /personalization/Dock - - - Small - Pequeno - - - Large - Grande - - - Show Dock - Mostrar Doca - - - On screen where the cursor is - No ecrã onde está o cursor - - - Only on main screen - Apenas no ecrã principal - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Onboard - - Settings - Definições - PowerPlugin - - Power - Energia - - - Power settings - Definições de energia - Capacity %1, %2 min remaining Capacidade %1, %2 min restantes @@ -469,36 +335,9 @@ Capacity %1, fully charged Capacidade 1%, totalmente carregada - - - SettingsModule - Dock - Doca - - - Mode - Modo - - - Location - Localização - - - Status - Estado - - - Size - Tamanho - - - Show Dock - Mostrar Doca - - - Plugin Area - Área de plugins + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Energia - Shut down Encerrar @@ -550,12 +385,27 @@ Reboot Reiniciar + + Power + Energia + SoundApplet - Volume - Volume + Device + Dispositivo + + + + SoundDevicesWidget + + Output Device + Dispositivo de saída + + + Sound settings + Definições de som @@ -576,10 +426,6 @@ Volume %1 Volume %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Esvaziar + + WindowManager + + Exit Safe Mode + Sair do Modo Seguro + + + Dock - Safe Mode + Doca - Modo Seguro + + + The Dock is in safe mode, please exit to show it properly + A Doca está em modo seguro, saia para a mostrar corretamente + + \ No newline at end of file diff --git a/translations/dde-dock_pt_BR.ts b/translations/dde-dock_pt_BR.ts index d7c15e78d..eacca2cb8 100644 --- a/translations/dde-dock_pt_BR.ts +++ b/translations/dde-dock_pt_BR.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Remover + Open + Abrir + + + + BloothAdapterWidget + + My Devices + Meus dispositivos + + + Other Devices + Outros dispositivos @@ -69,7 +80,7 @@ Bluetooth settings - Configurações de Bluetooth + Configurações do Bluetooth %1 connected @@ -88,18 +99,56 @@ Desativado + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Ativar + + + Turn off + Desativar + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Ativar + + + Turn off + Desativar + DBusAdaptors Add keyboard layout - Adicionar o layout de teclado + Adicionar layout de teclado + + + + DateTimeDisplayer + + 12-hour time + Formato de 12 horas + + + 24-hour time + Formato de 24 horas + + + Time settings + Configurações de data e hora @@ -118,69 +167,13 @@ Time settings - Configurações de Data e Hora + Configurações de data e hora - DatetimeWidget + DevCollaborationWidget - Monday - Segunda-feira - - - Tuesday - Terça-feira - - - Wednesday - Quarta-feira - - - Thursday - Quinta-feira - - - Friday - Sexta-feira - - - Saturday - Sábado - - - Sunday - Domingo - - - monday - segunda-feira - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - domingo - - - %1year%2month%3day + PC collaboration @@ -200,33 +193,32 @@ This action cannot be restored - Esta ação não pode ser desfeita + Esta ação não pode ser revertida - DiskControlItem + DisplaySettingWidget - Unknown device - Dispositivo desconhecido - - - Unknown volume - Volume desconhecido + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Dispositivos + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Abrir - - - Unmount all - Desmontar todos + Disabled + Desativado @@ -236,21 +228,6 @@ Lançador - - MainWindow - - Exit Safe Mode - Sair do Modo de Segurança - - - Dock - Safe Mode - Dock - Modo de Segurança - - - The Dock is in safe mode, please exit to show it properly - A Dock está em modo de segurança; saia para exibi-lo corretamente - - MenuWorker @@ -306,105 +283,6 @@ Configurações da Dock - - ModuleWidget - - Size - Tamanho - Dock - /personalization/Dock - - - Multiple Displays - Múltiplas telas - Dock - /personalization/Dock - - - Plugin Area - Área de plugins - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Selecione quais ícones aparecem na Dock - - - Fashion mode - Modo Fashion - - - Efficient mode - Modo Eficiente - - - Mode - Modo - Dock - /personalization/Dock - - - Top - Superior - - - Bottom - Inferior - - - Left - Esquerda - - - Right - Direita - - - Location - Local - Dock - /personalization/Dock - - - Keep shown - Manter exibindo - - - Keep hidden - Manter oculta - - - Smart hide - Ocultar inteligente - - - Status - Estado - Dock - /personalization/Dock - - - Small - Pequeno - - - Large - Grande - - - Show Dock - Exibir Dock - - - On screen where the cursor is - Na tela onde está o cursor - - - Only on main screen - Apenas na tela principal - - MultitaskingPlugin @@ -413,30 +291,18 @@ Undock - Remover da Dock + Remover da dock OnboardPlugin Onboard - Teclado Virtual - - - Settings - Configurações + Teclado virtual PowerPlugin - - Power - Energia - - - Power settings - Configurações de energia - Capacity %1, %2 min remaining %1 Carregado - %2m restantes @@ -469,36 +335,9 @@ Capacity %1, fully charged %1 Carregado - Bateria Cheia - - - SettingsModule - Dock - Dock - - - Mode - Mode - - - Location - Location - - - Status - Status - - - Size - Tamanho - - - Show Dock - Show Dock - - - Plugin Area - Plugin Area + Battery + @@ -509,15 +348,11 @@ Undock - Remover da Dock + Remover da dock ShutdownPlugin - - Power - Energia - Shut down Desligar @@ -536,7 +371,7 @@ Log out - Encerrar sessão + Sair Switch account @@ -550,19 +385,34 @@ Reboot Reiniciar + + Power + Energia + SoundApplet - Volume - Volume + Device + Dispositivo + + + + SoundDevicesWidget + + Output Device + Dispositivo de Saída + + + Sound settings + Configurações de som SoundItem Unmute - Com Áudio + Com áudio Mute @@ -570,16 +420,12 @@ Sound settings - Configurações de Som + Configurações de som Volume %1 Volume %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Esvaziar + + WindowManager + + Exit Safe Mode + Sair do Modo de Segurança + + + Dock - Safe Mode + Dock - Modo de Segurança + + + The Dock is in safe mode, please exit to show it properly + A Dock está em modo de segurança; saia para exibi-lo corretamente + + \ No newline at end of file diff --git a/translations/dde-dock_ro.ts b/translations/dde-dock_ro.ts index c88a3c2b9..787c4e0b7 100644 --- a/translations/dde-dock_ro.ts +++ b/translations/dde-dock_ro.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Elimină + Open + Deschide + + + + BloothAdapterWidget + + My Devices + Dispozitivele mele + + + Other Devices + Alte dispozitive @@ -88,12 +99,35 @@ Oprit + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Pornește + + + Turn off + Oprește + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Pornește + + + Turn off + Oprește + DBusAdaptors @@ -102,6 +136,21 @@ Adăugare aspect tastatură + + DateTimeDisplayer + + 12-hour time + Format 12-ore + + + 24-hour time + Format 24-ore + + + Time settings + Configurări pentru timp + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Luni - - - Tuesday - Marţi - - - Wednesday - Miercuri - - - Thursday - Joi - - - Friday - Vineri - - - Saturday - Sâmbătă - - - Sunday - Duminică - - - monday - luni - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Dispozitiv necunoscut - - - Unknown volume - Volum necunoscut + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disc + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Deschide - - - Unmount all - Demontați-le pe toate + Disabled + Dezactivat @@ -236,21 +228,6 @@ Lansator - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - Dimensiune - Dock - /personalization/Dock - - - Multiple Displays - Afișaje multiple - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - Mod fashion - - - Efficient mode - Mod eficient - - - Mode - Mod - Dock - /personalization/Dock - - - Top - Sus - - - Bottom - Jos - - - Left - Stânga - - - Right - Dreapta - - - Location - Locație - Dock - /personalization/Dock - - - Keep shown - - - - Keep hidden - Păstraţi ascuns - - - Smart hide - Ascundere inteligentă - - - Status - Stare - Dock - /personalization/Dock - - - Small - Mic - - - Large - Mare - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard La bord - - Settings - Setări - PowerPlugin - - Power - Energie - - - Power settings - Setări pentru administrare de energie - Capacity %1, %2 min remaining Capacitate %1, %2 Min rămase @@ -469,35 +335,8 @@ Capacity %1, fully charged Capacitate %1, complet încărcat - - - SettingsModule - Dock - Dock - - - Mode - Mod - - - Location - Locație - - - Status - Stare - - - Size - Dimensiune - - - Show Dock - - - - Plugin Area + Battery @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Energie - Shut down Închidere @@ -550,12 +385,27 @@ Reboot Repornire + + Power + Energie + SoundApplet - Volume - Volum + Device + Dispozitiv + + + + SoundDevicesWidget + + Output Device + Dispozitiv de ieșire + + + Sound settings + Setări Sunet @@ -576,10 +426,6 @@ Volume %1 Volum %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Gol + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_ru.ts b/translations/dde-dock_ru.ts index 4083dacf0..04f1bed9f 100644 --- a/translations/dde-dock_ru.ts +++ b/translations/dde-dock_ru.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Удалить + Open + Открыть + + + + BloothAdapterWidget + + My Devices + Мои устройства + + + Other Devices + Другие устройства @@ -88,12 +99,35 @@ Выключен + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Включить + + + Turn off + Выключить + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Включить + + + Turn off + Выключить + DBusAdaptors @@ -102,6 +136,21 @@ Добавить раскладку клавиатуры + + DateTimeDisplayer + + 12-hour time + 12-часовой формат времени + + + 24-hour time + 24-часовой формат времени + + + Time settings + Настройки времени + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Понедельник - - - Tuesday - Вторник - - - Wednesday - Среда - - - Thursday - Четверг - - - Friday - Пятница - - - Saturday - Суббота - - - Sunday - Воскресенье - - - monday - понедельник - - - tuesday - Вторник - - - wednesday - Среда - - - thursday - Четверг - - - friday - Пятница - - - saturday - Суббота - - - sunday - воскресенье - - - %1year%2month%3day + PC collaboration @@ -204,51 +197,35 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Неизвестное устройство - - - Unknown volume - Неизвестный объем + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Диск + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Включено - Open - Открыть - - - Unmount all - Отмонтировать все + Disabled + Отключено LauncherItem Launcher - Выбор Программ - - - - MainWindow - - Exit Safe Mode - Выйти из Безопасного Режима - - - Dock - Safe Mode - Dock - Безопасный Режим - - - The Dock is in safe mode, please exit to show it properly - Dock находится в безопасном режиме, пожалуйста, выйдите, чтобы показать ее нормально + Запуск программ @@ -306,106 +283,6 @@ Настройки Dock - - ModuleWidget - - Size - Размер - Dock - /personalization/Dock - - - Multiple Displays - Несколько Дисплеев - Dock - /personalization/Dock - - - Plugin Area - Область Плагина - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Выбрать значки появляющиеся в Dock - - - Fashion mode - Стильный режим - - - Efficient mode - Эффективный режим - - - Mode - Режим - Dock - /personalization/Dock - - - Top - На верху - - - Bottom - Внизу - - - Left - Слева - - - - Right - Справа - - - Location - Расположение - Dock - /personalization/Dock - - - Keep shown - Отображать - - - Keep hidden - Скрывать - - - Smart hide - Умное скрытие - - - Status - Статус - Dock - /personalization/Dock - - - Small - Маленький - - - Large - Большой - - - Show Dock - Показывать Dock - - - On screen where the cursor is - На экране, где располагается курсор - - - Only on main screen - Только на главном экране - - MultitaskingPlugin @@ -423,21 +300,9 @@ Onboard Экранная Клавиатура - - Settings - Настройки - PowerPlugin - - Power - Питание - - - Power settings - Параметры питания - Capacity %1, %2 min remaining Емкость %1, %2 мин. осталось @@ -470,36 +335,9 @@ Capacity %1, fully charged Заряд %1, полностью заряжен - - - SettingsModule - Dock - Dock - - - Mode - Режим - - - Location - Расположение - - - Status - Статус - - - Size - Размер - - - Show Dock - Показывать Dock - - - Plugin Area - Область Плагина + Battery + @@ -515,10 +353,6 @@ ShutdownPlugin - - Power - Питание - Shut down Выключить @@ -529,7 +363,7 @@ Hibernate - Спящий Режим + Спящий режим Lock @@ -551,12 +385,27 @@ Reboot Перезагрузить + + Power + Питание + SoundApplet - Volume - Громкость + Device + Устройство + + + + SoundDevicesWidget + + Output Device + Выходное устройство + + + Sound settings + Настройки звука @@ -577,10 +426,6 @@ Volume %1 Громкость %1 - - No output devices - - SoundPlugin @@ -619,4 +464,19 @@ Очистить + + WindowManager + + Exit Safe Mode + Выйти из Безопасного Режима + + + Dock - Safe Mode + Dock - Безопасный Режим + + + The Dock is in safe mode, please exit to show it properly + Dock находится в безопасном режиме, пожалуйста, выйдите, чтобы показать ее нормально + + \ No newline at end of file diff --git a/translations/dde-dock_sc.ts b/translations/dde-dock_sc.ts new file mode 100644 index 000000000..067498af7 --- /dev/null +++ b/translations/dde-dock_sc.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_si.ts b/translations/dde-dock_si.ts index 8c37a61bf..168b64960 100644 --- a/translations/dde-dock_si.ts +++ b/translations/dde-dock_si.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -7,12 +7,60 @@ - AppDragWidget + AirplaneModeApplet - Remove + Airplane Mode + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + වසා දමන්න + + + Turn on + ක්‍රියාත්මක කරන්න + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + විවෘත කරන්න + + + + BloothAdapterWidget + + My Devices + මගේ උපාංග + + + Other Devices + වෙනත් උපාංග + + BluetoothApplet @@ -51,12 +99,35 @@ වසා දමා ඇත + + BluetoothMainWidget + + Bluetooth + බ්ලූටූත් + + + Turn on + ක්‍රියාත්මක කරන්න + + + Turn off + වසා දමන්න + + BluetoothPlugin Bluetooth බ්ලූටූත් + + Turn on + ක්‍රියාත්මක කරන්න + + + Turn off + වසා දමන්න + DBusAdaptors @@ -65,6 +136,21 @@ යතුරුපුවරු පිරිසැලසුම එක් කරන්න + + DateTimeDisplayer + + 12-hour time + පැය-12 වේලාව + + + 24-hour time + පැය-24 වේලාව + + + Time settings + වේලා සැකසුම් + + DatetimePlugin @@ -84,6 +170,13 @@ වේලා සැකසුම් + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -104,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - හඳුනානොගත් උපකරණය - - - Unknown volume - හදුනානොගත් කාණ්ඩයකි + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - ඩිස්කය + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - විවෘත කරන්න - - - Unmount all - සියල්ල ගලවන්න + Disabled + අක්‍රීයයි @@ -136,21 +228,6 @@ රදවනය - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -202,19 +279,7 @@ තත්ත්වය - Plugins - ආධාරක යෙදවුම් - - - Only on main screen - - - - On screen where the cursor is - - - - Show the Dock + Dock settings @@ -235,21 +300,9 @@ Onboard පවතින - - Settings - සැකසුම් - PowerPlugin - - Power - බලය - - - Power settings - බල සැකසුම් - Capacity %1, %2 min remaining ධාරිතාව %1, මිනිත්තු %2 ක් ඉතිරි වී ඇත @@ -282,6 +335,10 @@ Capacity %1, fully charged ධාරිතාවය %1, සම්පූර්ණයෙන්ම ආරෝපිතයි + + Battery + + ShowDesktopPlugin @@ -296,10 +353,6 @@ ShutdownPlugin - - Power - බලය - Shut down වසා දමන්න @@ -332,6 +385,10 @@ Reboot පද්ධතිය නැවත අරඹන්න + + Power + බලය + SoundApplet @@ -340,6 +397,17 @@ උපාංගය + + SoundDevicesWidget + + Output Device + + + + Sound settings + ශබ්ද සැකසුම් + + SoundItem @@ -396,4 +464,19 @@ හිස් + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_sk.ts b/translations/dde-dock_sk.ts index 1725e084a..229bb3d3f 100644 --- a/translations/dde-dock_sk.ts +++ b/translations/dde-dock_sk.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -7,9 +7,57 @@ - AppDragWidget + AirplaneModeApplet - Remove + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Otvoriť + + + + BloothAdapterWidget + + My Devices + + + + Other Devices @@ -51,12 +99,35 @@ + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + + + + Turn off + + DBusAdaptors @@ -65,6 +136,21 @@ Pridať rozloženie klávesnice + + DateTimeDisplayer + + 12-hour time + 12-hodinový čas + + + 24-hour time + 24-hodinový čas + + + Time settings + Nastavenia času + + DatetimePlugin @@ -84,6 +170,13 @@ Nastavenia času + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -104,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Neznáme zariadenie - - - Unknown volume - Neznámy zväzok + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Otvoriť - - - Unmount all - Odpojiť všetko + Disabled + Zakázané @@ -136,21 +228,6 @@ Spúšťač - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -202,19 +279,7 @@ Stav - Plugins - Pluginy - - - Only on main screen - - - - On screen where the cursor is - - - - Show the Dock + Dock settings @@ -235,21 +300,9 @@ Onboard Onboard - - Settings - Nastavenia - PowerPlugin - - Power - Napájanie - - - Power settings - Nastavenia napájania - Capacity %1, %2 min remaining Nabíjanie %1, zostávajú %2 min @@ -282,6 +335,10 @@ Capacity %1, fully charged Kapacita %1, plne nabité + + Battery + + ShowDesktopPlugin @@ -296,10 +353,6 @@ ShutdownPlugin - - Power - Napájanie - Shut down Vypnúť @@ -332,6 +385,10 @@ Reboot Reštart + + Power + Napájanie + SoundApplet @@ -340,6 +397,17 @@ Zariadenie + + SoundDevicesWidget + + Output Device + + + + Sound settings + Nastavenia zvuku + + SoundItem @@ -396,4 +464,19 @@ Vysypať + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_sl.ts b/translations/dde-dock_sl.ts index 26aabe788..113dfcf28 100644 --- a/translations/dde-dock_sl.ts +++ b/translations/dde-dock_sl.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Odstrani + Open + Odpri + + + + BloothAdapterWidget + + My Devices + Moje naprave + + + Other Devices + Druge naprave @@ -88,12 +99,35 @@ Izklopljen + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Vklopi + + + Turn off + Izklopi + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Vklopi + + + Turn off + Izklopi + DBusAdaptors @@ -102,6 +136,21 @@ Dodaj razpored tipk + + DateTimeDisplayer + + 12-hour time + 12 urni čas + + + 24-hour time + 24 urni čas + + + Time settings + Nastavitve časa + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Ponedeljek - - - Tuesday - Torek - - - Wednesday - Sreda - - - Thursday - Četrtek - - - Friday - Petek - - - Saturday - Sobota - - - Sunday - Nedelja - - - monday - ponedeljek - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -192,7 +185,7 @@ Cancel - Prekliči + Prekini Delete @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Neznana naprava - - - Unknown volume - Neznan prostor + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Odpri - - - Unmount all - Odklopi vse + Disabled + Onemogočeno @@ -236,21 +228,6 @@ Zaganjalnik - - MainWindow - - Exit Safe Mode - Zapri varni način - - - Dock - Safe Mode - Varni način sidrišča - - - The Dock is in safe mode, please exit to show it properly - Sidrišče deluje v varnem načinu. Izhod za pravilen prikaz - - MenuWorker @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - Velikost - Dock - /personalization/Dock - - - Multiple Displays - Več zaslonov - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - - - - Efficient mode - - - - Mode - Način - Dock - /personalization/Dock - - - Top - Vrh - - - Bottom - Dno - - - Left - Levo - - - Right - Desno - - - Location - Položaj - Dock - /personalization/Dock - - - Keep shown - - - - Keep hidden - - - - Smart hide - - - - Status - Status - Dock - /personalization/Dock - - - Small - Majhno - - - Large - Veliko - - - Show Dock - - - - On screen where the cursor is - Na zaslonu s kurzorjem - - - Only on main screen - Zgolj na glavnem zaslonu - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Na plošči - - Settings - Nastavitve - PowerPlugin - - Power - Napajanje - - - Power settings - Nastavitve energijske porabe - Capacity %1, %2 min remaining Zmogljivost %1 za %2 min @@ -469,35 +335,8 @@ Capacity %1, fully charged Zmogljivost %1 - polno - - - SettingsModule - Dock - Zasidraj - - - Mode - Način - - - Location - Položaj - - - Status - Status - - - Size - Velikost - - - Show Dock - - - - Plugin Area + Battery @@ -514,13 +353,9 @@ ShutdownPlugin - - Power - Napajanje - Shut down - Zaustavitev sistema + zaustavitev sistema Suspend @@ -528,7 +363,7 @@ Hibernate - Spanje + spanje Lock @@ -536,7 +371,7 @@ Log out - Izpis + Odjava Switch account @@ -550,12 +385,27 @@ Reboot Ponovni zagon + + Power + Napajanje + SoundApplet - Volume - Glasnost + Device + Naprava + + + + SoundDevicesWidget + + Output Device + Izhodna naprava + + + Sound settings + Nastavitve zvoka @@ -576,10 +426,6 @@ Volume %1 Glasnost %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Prazno + + WindowManager + + Exit Safe Mode + Zapri varni način + + + Dock - Safe Mode + Varni način sidrišča + + + The Dock is in safe mode, please exit to show it properly + Sidrišče deluje v varnem načinu. Izhod za pravilen prikaz + + \ No newline at end of file diff --git a/translations/dde-dock_sq.ts b/translations/dde-dock_sq.ts index 70fa8a650..cc9742143 100644 --- a/translations/dde-dock_sq.ts +++ b/translations/dde-dock_sq.ts @@ -17,7 +17,7 @@ AirplaneModeItem Airplane mode enabled - Mënyra aeroplan është e aktivizuar + Mënyra aeroplan e aktivizuar Turn off @@ -33,7 +33,7 @@ Airplane mode disabled - Mënyra aeroplan është e çaktivizuar + Mënyra aeroplan e çaktivizuar @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Hiqe + Open + Hape + + + + BloothAdapterWidget + + My Devices + Pajisjet e Mia + + + Other Devices + Pajisje të Tjera @@ -73,7 +84,7 @@ %1 connected - %1 u lidh + %1 e lidhur Connecting... @@ -85,7 +96,22 @@ Turned off - I çaktivizuar + Çaktivizuar + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Aktivizoje + + + Turn off + Çaktivizoje @@ -94,6 +120,14 @@ Bluetooth Bluetooth + + Turn on + Aktivizoje + + + Turn off + Çaktivizoje + DBusAdaptors @@ -103,18 +137,14 @@ - DatetimePlugin - - Datetime - Datë dhe kohë - + DateTimeDisplayer 12-hour time - Orë 12-orëshe + Kohë 12-orëshe 24-hour time - Orë 24-orëshe + Kohë 24-orëshe Time settings @@ -122,73 +152,36 @@ - DatetimeWidget + DatetimePlugin - Monday - E hënë + Datetime + Datë dhe kohë - Tuesday - E martë + 12-hour time + orë 12-orëshe - Wednesday - E mërkurë + 24-hour time + orë 24-orëshe - Thursday - E enjte + Time settings + Rregullime kohe + + + DevCollaborationWidget - Friday - E premte - - - Saturday - E shtunë - - - Sunday - E diel - - - monday - e hënë - - - tuesday - e martë - - - wednesday - e mërkurë - - - thursday - e enjte - - - friday - e premte - - - saturday - e shtunë - - - sunday - e diel - - - %1year%2month%3day - + PC collaboration + Bashkëpunim me PC DialogManager Are you sure you want to empty %1 items? - Jeni i sigurt se doni të zbrazen $1 objekte? + Jeni i sigurt se doni të zbrazen %1 objekte? Cancel @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Pajisje e panjohur - - - Unknown volume - Vëllim i panjohur + Multi-Screen Collaboration + Bashkëpunim me Shumë Ekrane - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Aktivizuar - Open - Hap - - - Unmount all - Çmontoji krejt + Disabled + Çaktivizuar @@ -236,21 +228,6 @@ Nisës - - MainWindow - - Exit Safe Mode - Dil nga Mënyra e Parrezik - - - Dock - Safe Mode - Panel - Mënyra e Parrezik - - - The Dock is in safe mode, please exit to show it properly - Paneli gjendet nën Mënyrën e Parrezik, ju lutemi, dilni prej saj, që të shfaqet si duhet - - MenuWorker @@ -259,15 +236,15 @@ Efficient Mode - Mënyra Efikase + Mënyra Efikasitet Top - Në Krye + Në krye Bottom - Në Fund + Në fund Left @@ -306,105 +283,6 @@ Rregullime paneli - - ModuleWidget - - Size - Madhësi - Dock - /personalization/Dock - - - Multiple Displays - Shumë Ekrane - Dock - /personalization/Dock - - - Plugin Area - Zonë Shtojcash - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Përzgjidhni cilat ikona shfaqen te Paneli - - - Fashion mode - Mënyra modë - - - Efficient mode - Mënyra efikasitet - - - Mode - Mënyrë - Dock - /personalization/Dock - - - Top - Në Krye - - - Bottom - Në Fund - - - Left - Majtas - - - Right - Djathtas - - - Location - Vendndodhje - Dock - /personalization/Dock - - - Keep shown - Mbaje të shfaqur - - - Keep hidden - Mbaje të fshehur - - - Smart hide - Fshehje e mençur - - - Status - Gjendje - Dock - /personalization/Dock - - - Small - I vogël - - - Large - I madh - - - Show Dock - Shfaqe Panelin - - - On screen where the cursor is - Në ekranin ku është kursori - - - Only on main screen - Vetëm në ekranin kryesor - - MultitaskingPlugin @@ -420,23 +298,11 @@ OnboardPlugin Onboard - Onboard - - - Settings - Rregullime + PowerPlugin - - Power - Energji - - - Power settings - Rregullime energjie - Capacity %1, %2 min remaining Kapacitet %1, edhe %2 min @@ -451,7 +317,7 @@ Charging %1, %2 hr %3 min until full - Po ngarkohet %1, edhe %2 hr e %3 min deri sa të jetë plot + Po ngarkohet %1, edhe %2 hr e %3 minuta deri sa të jetë plot Capacity %1 @@ -463,42 +329,15 @@ Capacity %1 ... - Kapacitet %1 … + Kapacitet %1… Capacity %1, fully charged - Kapacitet 1%, plotësisht e ngarkuar - - - - SettingsModule - - Dock - Panel + Kapacitet %1, plotësisht e ngarkuar - Mode - Mënyrë - - - Location - Vendndodhje - - - Status - Gjendje - - - Size - Madhësi - - - Show Dock - Shfaqe Panelin - - - Plugin Area - Zonë Shtojcash + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Energji - Shut down Fike @@ -550,12 +385,27 @@ Reboot Rinisu + + Power + Energji + SoundApplet - Volume - Volum + Device + Pajisje + + + + SoundDevicesWidget + + Output Device + Pajisje Në Dalje + + + Sound settings + Rregullime zëri @@ -566,7 +416,7 @@ Mute - Pa zë + Hiqi zërin Sound settings @@ -576,10 +426,6 @@ Volume %1 Volumi %1 - - No output devices - S’ka pajisje output-i - SoundPlugin @@ -604,7 +450,7 @@ Move to Trash - Shpjere te Hedhurinat + Shpjere te Hedhurina @@ -615,7 +461,22 @@ Empty - E zbrazët + Zbraze + + + + WindowManager + + Exit Safe Mode + Dil nga Mënyra e Parrezik + + + Dock - Safe Mode + Panel - Mënyra e Parrezik + + + The Dock is in safe mode, please exit to show it properly + Paneli gjendet nën mënyrën e parrezik, ju lutemi, dilni prej saj, që të shfaqet si duhet \ No newline at end of file diff --git a/translations/dde-dock_sr.ts b/translations/dde-dock_sr.ts index a655a7220..36e515ab6 100644 --- a/translations/dde-dock_sr.ts +++ b/translations/dde-dock_sr.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Уклони + Open + Покрени + + + + BloothAdapterWidget + + My Devices + Моји уређаји + + + Other Devices + Остали уређаји @@ -88,12 +99,35 @@ Искључен + + BluetoothMainWidget + + Bluetooth + Блутут + + + Turn on + Укључи + + + Turn off + Искључи + + BluetoothPlugin Bluetooth Блутут + + Turn on + Укључи + + + Turn off + Искључи + DBusAdaptors @@ -102,6 +136,21 @@ Додај распоред тастатуре + + DateTimeDisplayer + + 12-hour time + 12-часовно време + + + 24-hour time + 24-часовно време + + + Time settings + Подешавање времена + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Понедељак - - - Tuesday - Уторак - - - Wednesday - Среда - - - Thursday - Четвртак - - - Friday - Петак - - - Saturday - Субота - - - Sunday - Недеља - - - monday - понедељак - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,51 +197,35 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Непознат уређај - - - Unknown volume - Непознат систем + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Диск + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Покрени - - - Unmount all - Демонтирај све + Disabled + Онемогућенo LauncherItem Launcher - Покретач Програма - - - - MainWindow - - Exit Safe Mode - Изађи из безбедног режима - - - Dock - Safe Mode - Док - Безбедни режим - - - The Dock is in safe mode, please exit to show it properly - Док је у безбедном режиму, изађите за нормалан приказ + Покретач програма @@ -306,105 +283,6 @@ - - ModuleWidget - - Size - Величина - Dock - /personalization/Dock - - - Multiple Displays - Вишеструки прикази - Dock - /personalization/Dock - - - Plugin Area - - Dock - /personalization/Dock - - - Select which icons appear in the Dock - - - - Fashion mode - - - - Efficient mode - - - - Mode - Режим - Dock - /personalization/Dock - - - Top - Врх - - - Bottom - Дно - - - Left - Лево - - - Right - Десно - - - Location - Позиција - Dock - /personalization/Dock - - - Keep shown - - - - Keep hidden - - - - Smart hide - - - - Status - Стање - Dock - /personalization/Dock - - - Small - Мала - - - Large - Велика - - - Show Dock - - - - On screen where the cursor is - На екрану где је показивач - - - Only on main screen - Само на главном екрану - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Онборд - - Settings - Подeшавања - PowerPlugin - - Power - Напајање - - - Power settings - Управљање напајањем - Capacity %1, %2 min remaining Ниво %1, %2 мин преостало @@ -469,35 +335,8 @@ Capacity %1, fully charged Ниво %1, напуњено - - - SettingsModule - Dock - Закачи - - - Mode - Режим - - - Location - Позиција - - - Status - Стање - - - Size - Величина - - - Show Dock - - - - Plugin Area + Battery @@ -514,13 +353,9 @@ ShutdownPlugin - - Power - Напајање - Shut down - Искључи + Искључивање Suspend @@ -550,12 +385,27 @@ Reboot Поново покрени + + Power + Напајање + SoundApplet - Volume - + Device + Уређај + + + + SoundDevicesWidget + + Output Device + Излазни уређај + + + Sound settings + Подешавање звука @@ -576,10 +426,6 @@ Volume %1 Јачина %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Испразни + + WindowManager + + Exit Safe Mode + Изађи из безбедног режима + + + Dock - Safe Mode + Док - Безбедни режим + + + The Dock is in safe mode, please exit to show it properly + Док је у безбедном режиму, изађите за нормалан приказ + + \ No newline at end of file diff --git a/translations/dde-dock_sv.ts b/translations/dde-dock_sv.ts index 768a1288b..d575b864e 100644 --- a/translations/dde-dock_sv.ts +++ b/translations/dde-dock_sv.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ Plugin %1 är ej kompatibelt med systemet + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Öppna + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + Bluetooth + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Lägg till tangentbordslayout + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -33,18 +171,10 @@ - DeviceItem + DevCollaborationWidget - Enable network - Aktivera nätverk - - - Disable network - Inaktivera nätverk - - - Network settings - Nätverks inställingar + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Okänd enhet - - - Unknown volume - Okänd volym + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Hårddisk - - - Open - Öppna - - - Unmount all - Avmontera alla + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + Inaktiverad + + + + LauncherItem + + Launcher + Launcher + + + + MenuWorker Fashion Mode Mode läge @@ -143,15 +279,8 @@ Status - Plugins - Plugin - - - - LauncherItem - - Launcher - Launcher + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Nätverk - - OnboardPlugin Onboard Virtuellt - - Settings - Inställningar - PowerPlugin - - Power - Stäng av - - - Power settings - Ströminställningar - Capacity %1, %2 min remaining Kapacitet %1, %2 min kvarstår @@ -209,10 +319,6 @@ Charging %1, %2 hr %3 min until full Laddar %1, %2 hr %3 min tills fulladdad - - Charged - - Capacity %1 @@ -229,6 +335,10 @@ Capacity %1, fully charged + + Battery + + ShowDesktopPlugin @@ -243,10 +353,6 @@ ShutdownPlugin - - Power - Stäng av - Shut down Stäng av @@ -279,6 +385,10 @@ Reboot Starta om + + Power + Stäng av + SoundApplet @@ -286,9 +396,16 @@ Device Enhet + + + SoundDevicesWidget - Application - Applikation + Output Device + + + + Sound settings + @@ -331,6 +448,10 @@ Trash - %1 files Skräp %1 filer + + Move to Trash + Flytta till Papperskorg + TrashWidget @@ -344,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - Systemfält - - - - WiredItem - - Unknown - Okänd + Exit Safe Mode + - Wired connection: %1 - Trådanslutning: %1 - - - - WirelessItem - - No Network - Inga nätverk + Dock - Safe Mode + - Connected but no Internet access - Uppkopplad men ingen internet åtkomst - - - Wireless connection: %1 + The Dock is in safe mode, please exit to show it properly - - WirelessList - - Wireless Network - Trådlöst nätverk - - - Wireless Network %1 - Trådlöst nätverk %1 - - \ No newline at end of file diff --git a/translations/dde-dock_sw.ts b/translations/dde-dock_sw.ts index cbb80ed82..584e7a361 100644 --- a/translations/dde-dock_sw.ts +++ b/translations/dde-dock_sw.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Fungua + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ Ongeza mpangilio ya kibodi + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,31 +158,23 @@ Tarehe na saa - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings - Sifa za saa + Time settings + - DeviceItem + DevCollaborationWidget - Enable network - Wezesha mtandao - - - Disable network - Lemaza mtandao - - - Network settings - Sifa ya mtandao + PC collaboration + @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Kifaa haijulikana - - - Unknown volume - Sauti haijulikana + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Diski - - - Open - Fungua - - - Unmount all - Pungua yote + The plugin %1 is not compatible with the system. + - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + Kizinduzi + + + + MenuWorker Fashion Mode Hali urembo @@ -143,15 +279,8 @@ Hadhi - Plugins - Kijenzi ya maziada - - - - LauncherItem - - Launcher - Kizindua + Dock settings + @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - Mtandao - - OnboardPlugin Onboard Ndani ya - - Settings - Sifa - PowerPlugin - - Power - Kiwashio - - - Power settings - Sifa za kiwashio - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,11 +320,23 @@ - Charging %1 .... + Capacity %1 - Charged + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -235,18 +353,10 @@ ShutdownPlugin - - Power - Kiwashio - Shut down Zima - - Restart - Washa upya - Suspend Ahirisha @@ -271,6 +381,14 @@ Power settings Sifa za kiwashio + + Reboot + Washa upya + + + Power + Kiwashio + SoundApplet @@ -278,9 +396,16 @@ Device Kifaa + + + SoundDevicesWidget - Application - Programu + Output Device + + + + Sound settings + @@ -294,12 +419,12 @@ Zima sauti - Audio Settings - Sifa za sauti + Sound settings + - Current Volume %1 - Sasa, sauti ni %1 + Volume %1 + @@ -323,6 +448,10 @@ Trash - %1 files Taka - 1% faili + + Move to Trash + + TrashWidget @@ -336,47 +465,18 @@ - TrayPlugin + WindowManager - System Tray - Debe ya mfumo - - - - WiredItem - - Unknown - Haijulikana + Exit Safe Mode + - Wired connection: %1 - Muunganisho wa kebo: 1% - - - - WirelessItem - - No Network - Hakuna mtandao + Dock - Safe Mode + - Wireless Connection: %1 - Muunganisho bila kabo: %1 - - - Connected but no Internet access - Imebandikiwa, lakini haiko muunganisho wa wavuti - - - - WirelessList - - Wireless Network - Mtandao wa muunganisho bila kabo - - - Wireless Network %1 - Mtandao wa muunganisho bila kabo %1 + The Dock is in safe mode, please exit to show it properly + \ No newline at end of file diff --git a/translations/dde-dock_ta.ts b/translations/dde-dock_ta.ts index ff3b84961..4489294df 100644 --- a/translations/dde-dock_ta.ts +++ b/translations/dde-dock_ta.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + திற + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + புளூடூத் + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + புளூடூத் + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + புளூடூத் + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ விசைப்பலகை அமைப்பைச் சேர்க்கவும் + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,39 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + DockPluginController - Disk - வட்டு - - - Open - திற - - - Unmount all + The plugin %1 is not compatible with the system. - DockSettings + HomeMonitorPlugin + + Enabled + + + + Disabled + முடக்கப்பட்டது + + + + LauncherItem + + Launcher + துவக்கி + + + + MenuWorker Fashion Mode @@ -143,17 +279,10 @@ - Plugins + Dock settings - - LauncherItem - - Launcher - துவக்கி - - MultitaskingPlugin @@ -165,34 +294,15 @@ - - NetworkPlugin - - Network - பிணையம் - - OnboardPlugin Onboard - - Settings - அமைவுகள் - PowerPlugin - - Power - மின்திறன் - - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +311,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +320,23 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery @@ -231,18 +353,10 @@ ShutdownPlugin - - Power - மின்திறன் - Shut down நிறுத்து - - Restart - மறுதொடக்கம் - Suspend தற்காலிகமாக நிறுத்தம் செய்தல் @@ -267,6 +381,14 @@ Power settings + + Reboot + மறுதொடக்கம் + + + Power + மின்திறன் + SoundApplet @@ -274,8 +396,15 @@ Device கருவி + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +419,11 @@ ஒலியடக்கு - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +448,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +465,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown - தெரியாத - - - Wired connection: %1 - - - - - WirelessItem - - No Network + Exit Safe Mode - Wireless Connection: %1 + Dock - Safe Mode - Connected but no Internet access - - - - - WirelessList - - Wireless Network - கம்பியில்லா இணையம் - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_te.ts b/translations/dde-dock_te.ts new file mode 100644 index 000000000..8361bfc74 --- /dev/null +++ b/translations/dde-dock_te.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_th.ts b/translations/dde-dock_th.ts new file mode 100644 index 000000000..d2c37899c --- /dev/null +++ b/translations/dde-dock_th.ts @@ -0,0 +1,482 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + บลูทูธ + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + บลูทูธ + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + บลูทูธ + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + ยกเลิก + + + Delete + ลบ + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + DockPluginController + + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + Battery + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + ปิดเครื่อง + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + รีบูต + + + Power + พลังงาน + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + เสียง + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_tr.ts b/translations/dde-dock_tr.ts index 7f60a51af..9fd25730c 100644 --- a/translations/dde-dock_tr.ts +++ b/translations/dde-dock_tr.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Kaldır + Open + + + + + BloothAdapterWidget + + My Devices + Aygıtlarım + + + Other Devices + Diğer Aygıtlar @@ -88,12 +99,35 @@ Kapat + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + + + + Turn off + Kapat + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + + + + Turn off + Kapat + DBusAdaptors @@ -102,6 +136,21 @@ Klavye düzeni ekle + + DateTimeDisplayer + + 12-hour time + 12-saatlik zaman + + + 24-hour time + 24-saatlik zaman + + + Time settings + Zaman ayarları + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Pazartesi - - - Tuesday - Salı - - - Wednesday - Çarşamba - - - Thursday - Perşembe - - - Friday - Cuma - - - Saturday - Cumartesi - - - Sunday - Pazar - - - monday - pazartesi - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - pazar - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Bilinmeyen aygıt - - - Unknown volume - Bilinmeyen birim + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Disk + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Etkin - Open - - - - Unmount all - Tüm bağı kaldır + Disabled + Devre Dışı @@ -236,21 +228,6 @@ Başlatıcı - - MainWindow - - Exit Safe Mode - Güvenli Kipten Çık - - - Dock - Safe Mode - Rıhtım - Güvenli Kip - - - The Dock is in safe mode, please exit to show it properly - Rıhtım güvenli kipte, düzgün şekilde göstermek için lütfen çıkın - - MenuWorker @@ -306,105 +283,6 @@ Rıhtım ayarları - - ModuleWidget - - Size - Boyut - Dock - /personalization/Dock - - - Multiple Displays - Çoklu Ekran - Dock - /personalization/Dock - - - Plugin Area - Eklenti Alanı - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Rıhtım'da hangi simgelerin görüneceğini seçin - - - Fashion mode - Moda Kip - - - Efficient mode - Verimli Kip - - - Mode - Kip - Dock - /personalization/Dock - - - Top - Üst - - - Bottom - Alt - - - Left - Sol - - - Right - Sağ - - - Location - Konum - Dock - /personalization/Dock - - - Keep shown - Gösterilmeyi sürdür - - - Keep hidden - Gizli tut - - - Smart hide - Akıll gizle - - - Status - Durum - Dock - /personalization/Dock - - - Small - Küçük - - - Large - Büyük - - - Show Dock - Rıhtımı Göster - - - On screen where the cursor is - İmlecin bulunduğu ekranda - - - Only on main screen - Sadece ana ekranda - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Ekran Klavyesi - - Settings - Ayarlar - PowerPlugin - - Power - Güç - - - Power settings - Güç ayarları - Capacity %1, %2 min remaining %1 ve azalıyor, %2 dakika kaldı @@ -451,7 +317,7 @@ Charging %1, %2 hr %3 min until full - %1 ve doluyor, tam dolmaya %2 saat %3 dakika kaldı + %1 doluyor, doluma %2 saat %3 dakika var Capacity %1 @@ -469,36 +335,9 @@ Capacity %1, fully charged Kapasite %1, tam şarjlı - - - SettingsModule - Dock - Rıhtım - - - Mode - Kip - - - Location - Konum - - - Status - Durum - - - Size - Boyut - - - Show Dock - Rıhtımı Göster - - - Plugin Area - Eklenti Alanı + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Güç - Shut down Kapat @@ -550,12 +385,27 @@ Reboot Yeniden başlat + + Power + Güç + SoundApplet - Volume - Ses + Device + Aygıt + + + + SoundDevicesWidget + + Output Device + Çıkış Cihazı + + + Sound settings + Ses ayarları @@ -576,10 +426,6 @@ Volume %1 Ses %1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ Boşalt + + WindowManager + + Exit Safe Mode + Güvenli Kipten Çık + + + Dock - Safe Mode + Rıhtım - Güvenli Kip + + + The Dock is in safe mode, please exit to show it properly + Rıhtım güvenli kipte, düzgün şekilde göstermek için lütfen çıkın + + \ No newline at end of file diff --git a/translations/dde-dock_tzm.ts b/translations/dde-dock_tzm.ts new file mode 100644 index 000000000..b27c73eac --- /dev/null +++ b/translations/dde-dock_tzm.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + Ṛẓem + + + + BloothAdapterWidget + + My Devices + Allalen inu + + + Other Devices + Allalen yaḍnin + + + + BluetoothApplet + + Bluetooth settings + Tisɣal n ublutut + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + Tisɣal n ublutut + + + %1 connected + + + + Connecting... + Azday... + + + Bluetooth + Ablutut + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + Ablutut + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + Ablutut + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + Tisɣal n wakud + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + Tisɣal n wakud + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + Sser + + + Delete + Kkes + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + Ssexsi + + + Suspend + + + + Hibernate + + + + Lock + Rgel + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + Imesli + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + Ṛẓem + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_ug.ts b/translations/dde-dock_ug.ts index 3260f692d..51778244f 100644 --- a/translations/dde-dock_ug.ts +++ b/translations/dde-dock_ug.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - چىقىرىۋېتىش + Open + ئوچۇق + + + + BloothAdapterWidget + + My Devices + ئۈسكۈنەم + + + Other Devices + باشقا ئۈسكۈنە @@ -88,12 +99,35 @@ كۆكچىشنى تاقاش + + BluetoothMainWidget + + Bluetooth + كۆكچىش + + + Turn on + كۆكچىشنى ئېچىش + + + Turn off + كۆكچىشنى تاقاش + + BluetoothPlugin Bluetooth كۆكچىش + + Turn on + كۆكچىشنى ئېچىش + + + Turn off + كۆكچىشنى تاقاش + DBusAdaptors @@ -102,6 +136,21 @@ كۇنۇپكا تاختىسى ئورۇنلاشتۇرۇلۇشى قوشۇش + + DateTimeDisplayer + + 12-hour time + 12 سائەتلىك + + + 24-hour time + 24 سائەتلىك + + + Time settings + ۋاقىت تەڭشىكى + + DatetimePlugin @@ -122,65 +171,9 @@ - DatetimeWidget + DevCollaborationWidget - Monday - دۈشەنبە - - - Tuesday - سەيشەنبە - - - Wednesday - چارشەنبە - - - Thursday - پەيشەنبە - - - Friday - جۈمە - - - Saturday - شەنبە - - - Sunday - يەكشەنبە - - - monday - دۈشەنبە - - - tuesday - - - - wednesday - - - - thursday - - - - friday - - - - saturday - - - - sunday - - - - %1year%2month%3day + PC collaboration @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - نامەلۇم ئۈسكۈنە - - - Unknown volume - سىغىمى نامەلۇم + Multi-Screen Collaboration + كومپيۇتېرلار ئارا ھەمكارلىشىش - DiskMountPlugin + DockPluginController - Disk - دېسكا + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + قوزغىتىش - Open - ئوچۇق - - - Unmount all - ھەممىنى ئۆچۈرۈش + Disabled + تاقاق @@ -236,21 +228,6 @@ ئۈستەليۈزى قوزغاتقۇچ - - MainWindow - - Exit Safe Mode - بىخەتەر ھالەتتىن چېكىنىش - - - Dock - Safe Mode - ۋەزىپە ئىستونى بىخەتەرلىك ھالىتى - - - The Dock is in safe mode, please exit to show it properly - ۋەزىپە ئىستونى بىخەتەر ھالەتكە كىردى، چېكىنگەندىن كېيىن نورمال كۆرۈنىدۇ - - MenuWorker @@ -306,105 +283,6 @@ ۋەزىپە ئىستونى تەڭشىكى - - ModuleWidget - - Size - چوڭلۇقى - Dock - /personalization/Dock - - - Multiple Displays - كۆپ ئېكرانلىق كۆرسىتىش تەڭشىكى - Dock - /personalization/Dock - - - Plugin Area - قىستۇرما رايونى - Dock - /personalization/Dock - - - Select which icons appear in the Dock - ۋەزىپە ئىستونى قىستۇرما رايونىدا كۆرسىتىلىدىغان سىنبەلگىنى تاللاڭ - - - Fashion mode - مودا ھالەت - - - Efficient mode - يۇقىرى ئۈنۈملۈك ھالەت - - - Mode - ھالىتى - Dock - /personalization/Dock - - - Top - ئۈستى - - - Bottom - ئاستى - - - Left - سول - - - Right - ئوڭ - - - Location - ئورنى - Dock - /personalization/Dock - - - Keep shown - داۋاملىق كۆرسىتىش - - - Keep hidden - داۋاملىق يوشۇرۇش - - - Smart hide - ئەقلىي يوشۇرۇش - - - Status - ھالىتى - Dock - /personalization/Dock - - - Small - كىچىك - - - Large - چوڭ - - - Show Dock - ۋەزىپە ئىستونىنىڭ ئورنى - - - On screen where the cursor is - مائۇسنىڭ ئورنىغا ئەگىشىپ كۆرۈنسۇن - - - Only on main screen - ئاساسىي ئېكراندىلا كۆرۈنسۇن - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard ئېكران كۇنۇپكىسى - - Settings - تەڭشەك - PowerPlugin - - Power - توك مەنبە - - - Power settings - باتارىيە تەڭشىكى - Capacity %1, %2 min remaining توك %1 قالدى، %2 مىنۇت يېتىدۇ @@ -469,36 +335,9 @@ Capacity %1, fully charged توك%1، توشتى - - - SettingsModule - Dock - ۋەزىپە ئىستونى - - - Mode - ھالىتى - - - Location - ئورنى - - - Status - ھالىتى - - - Size - چوڭلۇقى - - - Show Dock - ۋەزىپە ئىستونىنىڭ ئورنى - - - Plugin Area - قىستۇرما رايونى + Battery + @@ -509,15 +348,11 @@ Undock - تۇرغۇنلارنى چىقىرىۋېتىش + چىقىرىۋېتىش ShutdownPlugin - - Power - توك مەنبە - Shut down تاقاش @@ -550,12 +385,27 @@ Reboot قايتا قوزغىتىش + + Power + توك مەنبە + SoundApplet - Volume - + Device + ئۈسكۈنە + + + + SoundDevicesWidget + + Output Device + چىقىرىش ئۈسكۈنىلىرى + + + Sound settings + ئاۋاز تەڭشىكى @@ -576,10 +426,6 @@ Volume %1 ئاۋاز%1 - - No output devices - - SoundPlugin @@ -618,4 +464,19 @@ قۇرۇق + + WindowManager + + Exit Safe Mode + بىخەتەر ھالەتتىن چېكىنىش + + + Dock - Safe Mode + ۋەزىپە ئىستونى بىخەتەرلىك ھالىتى + + + The Dock is in safe mode, please exit to show it properly + ۋەزىپە ئىستونى بىخەتەر ھالەتكە كىردى، چېكىنگەندىن كېيىن نورمال كۆرۈنىدۇ + + \ No newline at end of file diff --git a/translations/dde-dock_uk.ts b/translations/dde-dock_uk.ts index 60ddf5638..1e1e4c7d5 100644 --- a/translations/dde-dock_uk.ts +++ b/translations/dde-dock_uk.ts @@ -3,7 +3,7 @@ AbstractPluginsController The plugin %1 is not compatible with the system. - Плагін %1 не сумісний із системою. + Додаток %1 не сумісний із системою. @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - Видалити + Open + Відкрити + + + + BloothAdapterWidget + + My Devices + Мої пристрої + + + Other Devices + Інші пристрої @@ -88,12 +99,35 @@ Вимкнено + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Увімкнути + + + Turn off + Вимкнути + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Увімкнути + + + Turn off + Вимкнути + DBusAdaptors @@ -102,6 +136,21 @@ Додати розкладку клавіатури + + DateTimeDisplayer + + 12-hour time + 12-годинний час + + + 24-hour time + 24-годинний час + + + Time settings + Параметри часу + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - Понеділок - - - Tuesday - Вівторок - - - Wednesday - Середа - - - Thursday - Четвер - - - Friday - П'ятниця - - - Saturday - Субота - - - Sunday - Неділя - - - monday - Понеділок - - - tuesday - вівторок - - - wednesday - середа - - - thursday - четвер - - - friday - п'ятниця - - - saturday - субота - - - sunday - неділя - - - %1year%2month%3day - %1рік%2місяць%3день + PC collaboration + Взаємодія ПК @@ -196,7 +189,7 @@ Delete - Видалити + Вилучити This action cannot be restored @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Невідомий пристрій - - - Unknown volume - Невідомий том + Multi-Screen Collaboration + Сумісне використання декількох екранів - DiskMountPlugin + DockPluginController - Disk - Диск + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + Увімкнено - Open - Відкрити - - - Unmount all - Відмонтувати все + Disabled + Вимкнено @@ -236,21 +228,6 @@ Запускач - - MainWindow - - Exit Safe Mode - Вийти з безпечного режиму - - - Dock - Safe Mode - Док-станція — безпечний режим - - - The Dock is in safe mode, please exit to show it properly - Док-станція перебуває у безпечному режимі — будь ласка, вийдіть з нього для належного показу - - MenuWorker @@ -306,105 +283,6 @@ Параметри бічної панелі - - ModuleWidget - - Size - Розмір - Dock - /personalization/Dock - - - Multiple Displays - Кілька дисплеїв - Dock - /personalization/Dock - - - Plugin Area - Область додатків - Dock - /personalization/Dock - - - Select which icons appear in the Dock - Виберіть, які піктограми буде показано на бічній панелі - - - Fashion mode - Модний режим - - - Efficient mode - Ефективний режим - - - Mode - Режим - Dock - /personalization/Dock - - - Top - Вгорі - - - Bottom - Внизу - - - Left - Ліворуч - - - Right - Праворуч - - - Location - Розташування - Dock - /personalization/Dock - - - Keep shown - Показувати постійно - - - Keep hidden - Залишати прихованим - - - Smart hide - Розумне приховування - - - Status - Стан - Dock - /personalization/Dock - - - Small - Малий - - - Large - Великий - - - Show Dock - Показувати панель - - - On screen where the cursor is - На екрані, де перебуває вказівник - - - Only on main screen - Лише на головному екрані - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard Клавіатура - - Settings - Налаштування - PowerPlugin - - Power - Живлення - - - Power settings - Параметри живлення - Capacity %1, %2 min remaining Батарея %1, %2 хв залишилося @@ -469,36 +335,9 @@ Capacity %1, fully charged Ємність %1, повністю заряджено - - - SettingsModule - Dock - Панель - - - Mode - Режим - - - Location - Розташування - - - Status - Стан - - - Size - Розмір - - - Show Dock - Показувати панель - - - Plugin Area - Область додатків + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - Живлення - Shut down Вимкнути @@ -550,12 +385,27 @@ Reboot Перезавантажити + + Power + Живлення + SoundApplet - Volume - Гучність + Device + Пристрій + + + + SoundDevicesWidget + + Output Device + Пристрій виведення + + + Sound settings + Параметри звуку @@ -576,10 +426,6 @@ Volume %1 Гучність %1 - - No output devices - Немає пристроїв виведення - SoundPlugin @@ -618,4 +464,19 @@ Пусто + + WindowManager + + Exit Safe Mode + Вийти з безпечного режиму + + + Dock - Safe Mode + Док-станція — безпечний режим + + + The Dock is in safe mode, please exit to show it properly + Док-станція перебуває у безпечному режимі — будь ласка, вийдіть з нього для належного показу + + \ No newline at end of file diff --git a/translations/dde-dock_ur.ts b/translations/dde-dock_ur.ts index c1e56552c..2eb27cc9e 100644 --- a/translations/dde-dock_ur.ts +++ b/translations/dde-dock_ur.ts @@ -1,4 +1,4 @@ - + AbstractPluginsController @@ -6,6 +6,129 @@ + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + DBusAdaptors @@ -13,6 +136,21 @@ + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + DatetimePlugin @@ -20,30 +158,22 @@ - 12 Hour Time + 12-hour time - 24 Hour Time + 24-hour time - Time Settings + Time settings - DeviceItem + DevCollaborationWidget - Enable network - - - - Disable network - - - - Network settings + PC collaboration @@ -67,33 +197,32 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - - - - Unknown volume + Multi-Screen Collaboration - DiskMountPlugin + HomeMonitorPlugin - Disk + Enabled - Open - - - - Unmount all + Disabled - DockSettings + LauncherItem + + Launcher + + + + + MenuWorker Fashion Mode @@ -143,14 +272,7 @@ - Plugins - - - - - LauncherItem - - Launcher + Dock settings @@ -165,23 +287,12 @@ - - NetworkPlugin - - Network - - - OnboardPlugin Onboard - - Settings - - PowerPlugin @@ -189,10 +300,6 @@ Power - - Power settings - - Capacity %1, %2 min remaining @@ -201,10 +308,6 @@ Capacity %1, %2 hr %3 min remaining - - Charged %1 - - Charging %1, %2 min until full @@ -214,7 +317,19 @@ - Charging %1 .... + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged @@ -231,18 +346,10 @@ ShutdownPlugin - - Power - - Shut down شٹڈاون - - Restart - ریسٹارٹ - Suspend @@ -267,6 +374,14 @@ Power settings + + Reboot + + + + Plugged In + + SoundApplet @@ -274,8 +389,15 @@ Device + + + SoundDevicesWidget - Application + Output Device + + + + Sound settings @@ -290,11 +412,11 @@ - Audio Settings + Sound settings - Current Volume %1 + Volume %1 @@ -319,6 +441,10 @@ Trash - %1 files + + Move to Trash + + TrashWidget @@ -332,46 +458,17 @@ - TrayPlugin + WindowManager - System Tray - - - - - WiredItem - - Unknown + Exit Safe Mode - Wired connection: %1 - - - - - WirelessItem - - No Network + Dock - Safe Mode - Wireless Connection: %1 - - - - Connected but no Internet access - - - - - WirelessList - - Wireless Network - - - - Wireless Network %1 + The Dock is in safe mode, please exit to show it properly diff --git a/translations/dde-dock_uz.ts b/translations/dde-dock_uz.ts new file mode 100644 index 000000000..44f82725d --- /dev/null +++ b/translations/dde-dock_uz.ts @@ -0,0 +1,475 @@ + + + AbstractPluginsController + + The plugin %1 is not compatible with the system. + + + + + AirplaneModeApplet + + Airplane Mode + + + + + AirplaneModeItem + + Airplane mode enabled + + + + Turn off + + + + Turn on + + + + Airplane Mode settings + + + + Airplane mode disabled + + + + + AirplaneModePlugin + + Airplane Mode + + + + + AppMultiItem + + Open + + + + + BloothAdapterWidget + + My Devices + + + + Other Devices + + + + + BluetoothApplet + + Bluetooth settings + + + + + BluetoothItem + + Turn off + + + + Turn on + + + + Bluetooth settings + + + + %1 connected + + + + Connecting... + + + + Bluetooth + + + + Turned off + + + + + BluetoothMainWidget + + Bluetooth + + + + Turn on + + + + Turn off + + + + + BluetoothPlugin + + Bluetooth + + + + Turn on + + + + Turn off + + + + + DBusAdaptors + + Add keyboard layout + + + + + DateTimeDisplayer + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DatetimePlugin + + Datetime + + + + 12-hour time + + + + 24-hour time + + + + Time settings + + + + + DevCollaborationWidget + + PC collaboration + + + + + DialogManager + + Are you sure you want to empty %1 items? + + + + Cancel + + + + Delete + + + + This action cannot be restored + + + + + DisplaySettingWidget + + Multi-Screen Collaboration + + + + + HomeMonitorPlugin + + Enabled + + + + Disabled + + + + + LauncherItem + + Launcher + + + + + MenuWorker + + Fashion Mode + + + + Efficient Mode + + + + Top + + + + Bottom + + + + Left + + + + Right + + + + Keep Shown + + + + Keep Hidden + + + + Smart Hide + + + + Mode + + + + Location + + + + Status + + + + Dock settings + + + + + MultitaskingPlugin + + Multitasking View + + + + Undock + + + + + OnboardPlugin + + Onboard + + + + + PowerPlugin + + Power + + + + Capacity %1, %2 min remaining + + + + Capacity %1, %2 hr %3 min remaining + + + + Charging %1, %2 min until full + + + + Charging %1, %2 hr %3 min until full + + + + Capacity %1 + + + + Charging %1 + + + + Capacity %1 ... + + + + Capacity %1, fully charged + + + + + ShowDesktopPlugin + + Show Desktop + + + + Undock + + + + + ShutdownPlugin + + Shut down + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch account + + + + Power settings + + + + Reboot + + + + Plugged In + + + + + SoundApplet + + Device + + + + + SoundDevicesWidget + + Output Device + + + + Sound settings + + + + + SoundItem + + Unmute + + + + Mute + + + + Sound settings + + + + Volume %1 + + + + + SoundPlugin + + Sound + + + + + TrashPlugin + + Trash + + + + Trash - %1 file + + + + Trash - %1 files + + + + Move to Trash + + + + + TrashWidget + + Open + + + + Empty + + + + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + + \ No newline at end of file diff --git a/translations/dde-dock_vi.ts b/translations/dde-dock_vi.ts index d90a79294..1701e7526 100644 --- a/translations/dde-dock_vi.ts +++ b/translations/dde-dock_vi.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - + Open + Mở + + + + BloothAdapterWidget + + My Devices + Thiết bị của tôi + + + Other Devices + Thiết bị khác @@ -88,12 +99,35 @@ Đã tắt + + BluetoothMainWidget + + Bluetooth + Bluetooth + + + Turn on + Mở + + + Turn off + Tắt + + BluetoothPlugin Bluetooth Bluetooth + + Turn on + Mở + + + Turn off + Tắt + DBusAdaptors @@ -102,6 +136,21 @@ Thêm bố cục bàn phím + + DateTimeDisplayer + + 12-hour time + Chế độ 12 giờ + + + 24-hour time + Chế độ 24 giờ + + + Time settings + Cài đặt thời gian + + DatetimePlugin @@ -121,6 +170,13 @@ Cài đặt thời gian + + DevCollaborationWidget + + PC collaboration + + + DialogManager @@ -141,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - Thiết bị không xác định - - - Unknown volume - Âm lượng không xác định + Multi-Screen Collaboration + - DiskMountPlugin + DockPluginController - Disk - Đĩa + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + - Open - Mở - - - Unmount all - Tháo tất cả + Disabled + Đã ngắt @@ -173,21 +228,6 @@ Khởi chạy - - MainWindow - - Exit Safe Mode - - - - Dock - Safe Mode - - - - The Dock is in safe mode, please exit to show it properly - - - MenuWorker @@ -243,93 +283,6 @@ - - ModuleWidget - - Size - Kích thước - - - Multiple Displays - Nhiều màn hình - - - Plugin Area - - - - Select which icons appear in the Dock - - - - Fashion mode - Dạng thời trang - - - Efficient mode - Dạng hiệu quả - - - Mode - Chế độ - - - Top - Trên đỉnh - - - Bottom - Dưới đáy - - - Left - Trái - - - Right - Phải - - - Location - Nơi chốn - - - Keep shown - - - - Keep hidden - Tiếp tục ẩn - - - Smart hide - Ẩn thông minh - - - Status - Tình trạng - - - Small - Nhỏ - - - Large - Lớn - - - Show Dock - - - - On screen where the cursor is - - - - Only on main screen - - - MultitaskingPlugin @@ -347,21 +300,9 @@ Onboard Onboard - - Settings - Cài đặt - PowerPlugin - - Power - Năng lượng - - - Power settings - Thiết lập năng lượng - Capacity %1, %2 min remaining Năng lượng %1, %2 còn lại @@ -394,13 +335,9 @@ Capacity %1, fully charged Công suất 1%, sạc đã đầy - - - SettingsModule - Dock - Dock - /personalization/Dock + Battery + @@ -416,10 +353,6 @@ ShutdownPlugin - - Power - Năng lượng - Shut down Tắt máy @@ -452,6 +385,10 @@ Reboot Khởi động lại + + Power + Năng lượng + SoundApplet @@ -460,6 +397,17 @@ Thiết bị + + SoundDevicesWidget + + Output Device + + + + Sound settings + Cài đặt âm thanh + + SoundItem @@ -516,4 +464,19 @@ Làm sạch + + WindowManager + + Exit Safe Mode + + + + Dock - Safe Mode + + + + The Dock is in safe mode, please exit to show it properly + + + \ No newline at end of file diff --git a/translations/dde-dock_zh_CN.ts b/translations/dde-dock_zh_CN.ts index f1f38b19c..ea7c9b043 100644 --- a/translations/dde-dock_zh_CN.ts +++ b/translations/dde-dock_zh_CN.ts @@ -44,10 +44,21 @@ - AppDragWidget + AppMultiItem - Remove - 移除 + Open + 打开 + + + + BloothAdapterWidget + + My Devices + 我的设备 + + + Other Devices + 其他设备 @@ -88,12 +99,35 @@ 蓝牙关闭 + + BluetoothMainWidget + + Bluetooth + 蓝牙 + + + Turn on + 开启 + + + Turn off + 关闭 + + BluetoothPlugin Bluetooth 蓝牙 + + Turn on + 开启 + + + Turn off + 关闭 + DBusAdaptors @@ -102,6 +136,21 @@ 添加键盘布局 + + DateTimeDisplayer + + 12-hour time + 12小时制 + + + 24-hour time + 24小时制 + + + Time settings + 时间设置 + + DatetimePlugin @@ -122,66 +171,10 @@ - DatetimeWidget + DevCollaborationWidget - Monday - 星期一 - - - Tuesday - 星期二 - - - Wednesday - 星期三 - - - Thursday - 星期四 - - - Friday - 星期五 - - - Saturday - 星期六 - - - Sunday - 星期日 - - - monday - 周一 - - - tuesday - 周二 - - - wednesday - 周三 - - - thursday - 周四 - - - friday - 周五 - - - saturday - 周六 - - - sunday - 周日 - - - %1year%2month%3day - %1年%2月%3日 + PC collaboration + 电脑协同 @@ -204,29 +197,28 @@ - DiskControlItem + DisplaySettingWidget - Unknown device - 未知的设备 - - - Unknown volume - 容量未知 + Multi-Screen Collaboration + 电脑协同设置 - DiskMountPlugin + DockPluginController - Disk - 磁盘 + The plugin %1 is not compatible with the system. + The plugin %1 is not compatible with the system. + + + + HomeMonitorPlugin + + Enabled + 启用 - Open - 打开 - - - Unmount all - 卸载全部 + Disabled + 已禁用 @@ -236,21 +228,6 @@ 启动器 - - MainWindow - - Exit Safe Mode - 退出安全模式 - - - Dock - Safe Mode - 任务栏安全模式 - - - The Dock is in safe mode, please exit to show it properly - 任务栏已进入安全模式,退出安全模式后即可正常显示 - - MenuWorker @@ -306,105 +283,6 @@ 任务栏设置 - - ModuleWidget - - Size - 大小 - Dock - /personalization/Dock - - - Multiple Displays - 多屏显示设置 - Dock - /personalization/Dock - - - Plugin Area - 插件区域 - Dock - /personalization/Dock - - - Select which icons appear in the Dock - 选择显示在任务栏插件区域的图标 - - - Fashion mode - 时尚模式 - - - Efficient mode - 高效模式 - - - Mode - 模式 - Dock - /personalization/Dock - - - Top - - - - Bottom - - - - Left - - - - Right - - - - Location - 位置 - Dock - /personalization/Dock - - - Keep shown - 一直显示 - - - Keep hidden - 一直隐藏 - - - Smart hide - 智能隐藏 - - - Status - 状态 - Dock - /personalization/Dock - - - Small - - - - Large - - - - Show Dock - 任务栏位置 - - - On screen where the cursor is - 跟随鼠标位置显示 - - - Only on main screen - 仅主屏显示 - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard 屏幕键盘 - - Settings - 设置 - PowerPlugin - - Power - 电源 - - - Power settings - 电源设置 - Capacity %1, %2 min remaining 电量%1,剩余%2分钟 @@ -469,36 +335,9 @@ Capacity %1, fully charged 电量%1,已充满 - - - SettingsModule - Dock - 任务栏 - - - Mode - 模式 - - - Location - 位置 - - - Status - 状态 - - - Size - 大小 - - - Show Dock - 任务栏位置 - - - Plugin Area - 插件区域 + Battery + 电池 @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - 电源 - Shut down 关机 @@ -550,12 +385,27 @@ Reboot 重启 + + Power + 电源 + SoundApplet - Volume - 音量 + Device + 设备 + + + + SoundDevicesWidget + + Output Device + 输出设备 + + + Sound settings + 音量设置 @@ -576,10 +426,6 @@ Volume %1 当前音量 %1 - - No output devices - 无声音输出设备 - SoundPlugin @@ -618,4 +464,19 @@ 清空 + + WindowManager + + Exit Safe Mode + 退出安全模式 + + + Dock - Safe Mode + 任务栏安全模式 + + + The Dock is in safe mode, please exit to show it properly + 任务栏已进入安全模式,退出安全模式后即可正常显示 + + \ No newline at end of file diff --git a/translations/dde-dock_zh_HK.ts b/translations/dde-dock_zh_HK.ts index 855366cc4..9cd1fdfde 100644 --- a/translations/dde-dock_zh_HK.ts +++ b/translations/dde-dock_zh_HK.ts @@ -44,17 +44,28 @@ - AppDragWidget + AppMultiItem - Remove - 移除 + Open + 打開 + + + + BloothAdapterWidget + + My Devices + 我的設備 + + + Other Devices + 其他設備 BluetoothApplet Bluetooth settings - 藍牙設置 + 藍牙設定 @@ -69,11 +80,11 @@ Bluetooth settings - 藍牙設置 + 藍牙設定 %1 connected - 已連接%1 + %1 已連接 Connecting... @@ -88,12 +99,35 @@ 藍牙關閉 + + BluetoothMainWidget + + Bluetooth + 藍牙 + + + Turn on + 開啟 + + + Turn off + 關閉 + + BluetoothPlugin Bluetooth 藍牙 + + Turn on + 開啟 + + + Turn off + 關閉 + DBusAdaptors @@ -102,6 +136,21 @@ 添加鍵盤佈局 + + DateTimeDisplayer + + 12-hour time + 12小時制 + + + 24-hour time + 24小時制 + + + Time settings + 時間設定 + + DatetimePlugin @@ -118,70 +167,14 @@ Time settings - 時間設置 + 時間設定 - DatetimeWidget + DevCollaborationWidget - Monday - 星期一 - - - Tuesday - 星期二 - - - Wednesday - 星期三 - - - Thursday - 星期四 - - - Friday - 星期五 - - - Saturday - 星期六 - - - Sunday - 星期日 - - - monday - 週一 - - - tuesday - 週二 - - - wednesday - 週三 - - - thursday - 週四 - - - friday - 週五 - - - saturday - 週六 - - - sunday - 週日 - - - %1year%2month%3day - %1年%2月%3日 + PC collaboration + 電腦協同 @@ -200,33 +193,32 @@ This action cannot be restored - 這個動作不可復原 + 此操作不可恢復 - DiskControlItem + DisplaySettingWidget - Unknown device - 未知的設備 - - - Unknown volume - 容量未知 + Multi-Screen Collaboration + 電腦協同設置 - DiskMountPlugin + DockPluginController - Disk - 磁碟 + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + 啟用 - Open - 打開 - - - Unmount all - 卸載全部 + Disabled + 已禁用 @@ -236,21 +228,6 @@ 啟動器 - - MainWindow - - Exit Safe Mode - 退出安全模式 - - - Dock - Safe Mode - 任務欄安全模式 - - - The Dock is in safe mode, please exit to show it properly - 任務欄已進入安全模式,退出安全模式後即可正常顯示 - - MenuWorker @@ -263,11 +240,11 @@ Top - + Bottom - + Left @@ -306,105 +283,6 @@ 任務欄設置 - - ModuleWidget - - Size - 大小 - Dock - /personalization/Dock - - - Multiple Displays - 多屏顯示設置 - Dock - /personalization/Dock - - - Plugin Area - 插件區域 - Dock - /personalization/Dock - - - Select which icons appear in the Dock - 選擇顯示在任務欄插件區域的圖標 - - - Fashion mode - 時尚模式 - - - Efficient mode - 高效模式 - - - Mode - 模式 - Dock - /personalization/Dock - - - Top - - - - Bottom - - - - Left - - - - Right - - - - Location - 位置 - Dock - /personalization/Dock - - - Keep shown - 一直顯示 - - - Keep hidden - 一直隱藏 - - - Smart hide - 智能隱藏 - - - Status - 狀態 - Dock - /personalization/Dock - - - Small - - - - Large - - - - Show Dock - 任務欄位置 - - - On screen where the cursor is - 跟隨鼠標位置顯示 - - - Only on main screen - 僅主屏顯示 - - MultitaskingPlugin @@ -422,21 +300,9 @@ Onboard 螢幕鍵盤 - - Settings - 設置 - PowerPlugin - - Power - 電源 - - - Power settings - 電源設置 - Capacity %1, %2 min remaining 電量%1,剩餘%2分鐘 @@ -455,7 +321,7 @@ Capacity %1 - 電量 %1 + 電量%1 Charging %1 @@ -469,36 +335,9 @@ Capacity %1, fully charged 電量%1,已充滿 - - - SettingsModule - Dock - 任務欄 - - - Mode - 模式 - - - Location - 位置 - - - Status - 狀態 - - - Size - 大小 - - - Show Dock - 任務欄位置 - - - Plugin Area - 插件區域 + Battery + @@ -514,10 +353,6 @@ ShutdownPlugin - - Power - 電源 - Shut down 關機 @@ -548,14 +383,29 @@ Reboot - 重新啟動 + 重啟 + + + Power + 電源 SoundApplet - Volume - 音量 + Device + 設備 + + + + SoundDevicesWidget + + Output Device + 輸出設備 + + + Sound settings + 音量設定 @@ -570,16 +420,12 @@ Sound settings - 音量設置 + 音量設定 Volume %1 當前音量 %1 - - No output devices - 無聲音輸出設備 - SoundPlugin @@ -604,7 +450,7 @@ Move to Trash - 移動到回收站 + 移至回收站 @@ -618,4 +464,19 @@ 清空 + + WindowManager + + Exit Safe Mode + 退出安全模式 + + + Dock - Safe Mode + 任務欄安全模式 + + + The Dock is in safe mode, please exit to show it properly + 任務欄已進入安全模式,退出安全模式後即可正常顯示 + + \ No newline at end of file diff --git a/translations/dde-dock_zh_TW.ts b/translations/dde-dock_zh_TW.ts index 6523edb77..7a8aafc31 100644 --- a/translations/dde-dock_zh_TW.ts +++ b/translations/dde-dock_zh_TW.ts @@ -3,21 +3,21 @@ AbstractPluginsController The plugin %1 is not compatible with the system. - %1 外掛程式不相容此系統。 + 外掛程式%1和系統版本不相容。 AirplaneModeApplet Airplane Mode - 飛航模式 + 飛行模式 AirplaneModeItem Airplane mode enabled - 飛航模式開啟 + 飛行模式開啟 Turn off @@ -29,25 +29,36 @@ Airplane Mode settings - 飛航模式設定 + 飛行模式設定 Airplane mode disabled - 飛航模式關閉 + 飛行模式關閉 AirplaneModePlugin Airplane Mode - 飛航模式 + 飛行模式 - AppDragWidget + AppMultiItem - Remove - 移除 + Open + 打開 + + + + BloothAdapterWidget + + My Devices + 我的裝置 + + + Other Devices + 其他裝置 @@ -73,7 +84,7 @@ %1 connected - 已連接%1 + %1 已連接 Connecting... @@ -88,33 +99,52 @@ 藍牙關閉 + + BluetoothMainWidget + + Bluetooth + 藍牙 + + + Turn on + 開啟 + + + Turn off + 關閉 + + BluetoothPlugin Bluetooth 藍牙 + + Turn on + 開啟 + + + Turn off + 關閉 + DBusAdaptors Add keyboard layout - 新增鍵盤配置 + 添加鍵盤布局 - DatetimePlugin - - Datetime - 日期時間 - + DateTimeDisplayer 12-hour time - 12 小時制 + 12小時制 24-hour time - 24 小時制 + 24小時制 Time settings @@ -122,73 +152,36 @@ - DatetimeWidget + DatetimePlugin - Monday - 星期一 + Datetime + 時間 - Tuesday - 星期二 + 12-hour time + 12小時制 - Wednesday - 星期三 + 24-hour time + 24小時制 - Thursday - 星期四 + Time settings + 時間設定 + + + DevCollaborationWidget - Friday - 星期五 - - - Saturday - 星期六 - - - Sunday - 星期日 - - - monday - 週一 - - - tuesday - 週二 - - - wednesday - 週三 - - - thursday - 週四 - - - friday - 週五 - - - saturday - 週六 - - - sunday - 週日 - - - %1year%2month%3day - %1年%2月%3日 + PC collaboration + 電腦協同 DialogManager Are you sure you want to empty %1 items? - 確定清空 %1 個項目? + 您確定要清空回收站裡的%1項內容嗎? Cancel @@ -200,33 +193,32 @@ This action cannot be restored - 此動作無法復原 + 此操作不可復原 - DiskControlItem + DisplaySettingWidget - Unknown device - 未知裝置 - - - Unknown volume - 未知磁碟區 + Multi-Screen Collaboration + 電腦協同設定 - DiskMountPlugin + DockPluginController - Disk - 磁碟 + The plugin %1 is not compatible with the system. + + + + + HomeMonitorPlugin + + Enabled + 啟用 - Open - 開啟 - - - Unmount all - 全部卸載 + Disabled + 已禁用 @@ -236,21 +228,6 @@ 啟動器 - - MainWindow - - Exit Safe Mode - 退出安全模式 - - - Dock - Safe Mode - 任務欄安全模式 - - - The Dock is in safe mode, please exit to show it properly - 任務欄已進入安全模式,退出安全模式後即可正常顯示 - - MenuWorker @@ -263,27 +240,27 @@ Top - 頂部 + Bottom - 底部 + Left - 左側 + Right - 右側 + Keep Shown - 永遠顯示 + 一直顯示 Keep Hidden - 永遠隱藏 + 一直隱藏 Smart Hide @@ -306,105 +283,6 @@ 任務欄設定 - - ModuleWidget - - Size - 大小 - Dock - /personalization/Dock - - - Multiple Displays - 多屏顯示設定 - Dock - /personalization/Dock - - - Plugin Area - 外掛程式區域 - Dock - /personalization/Dock - - - Select which icons appear in the Dock - 選擇顯示在任務欄外掛程式區域的圖示 - - - Fashion mode - 時尚模式 - - - Efficient mode - 高效模式 - - - Mode - 模式 - Dock - /personalization/Dock - - - Top - 頂部 - - - Bottom - 底部 - - - Left - 左側 - - - Right - 右側 - - - Location - 位置 - Dock - /personalization/Dock - - - Keep shown - 永遠顯示 - - - Keep hidden - 永遠隱藏 - - - Smart hide - 智慧隱藏 - - - Status - 狀態 - Dock - /personalization/Dock - - - Small - - - - Large - - - - Show Dock - 任務欄位置 - - - On screen where the cursor is - 跟隨滑鼠位置顯示 - - - Only on main screen - 僅主屏顯示 - - MultitaskingPlugin @@ -413,7 +291,7 @@ Undock - 解除駐停 + 移除駐留 @@ -422,44 +300,32 @@ Onboard 螢幕鍵盤 - - Settings - 設定 - PowerPlugin - - Power - 電源 - - - Power settings - 電源設定 - Capacity %1, %2 min remaining - 電量 %1,剩餘 %2 分鐘 + 電量%1,剩餘%2分鐘 Capacity %1, %2 hr %3 min remaining - 電量 %1,剩餘 %2 小時 %3 分鐘 + 電量%1,剩餘%2小時%3分鐘 Charging %1, %2 min until full - 正在充電 %1,距離完成尚餘 %2 分鐘 + 正在充電%1,還需%2分鐘 Charging %1, %2 hr %3 min until full - 正在充電 %1,距離完成尚餘 %2 小時 %3 分鐘 + 正在充電%1,還需%2小時%3分鐘 Capacity %1 - 電量 %1 + 電量%1 Charging %1 - %1 正在充電 + 正在充電%1 Capacity %1 ... @@ -469,36 +335,9 @@ Capacity %1, fully charged 電量%1,已充滿 - - - SettingsModule - Dock - 任務欄 - - - Mode - 模式 - - - Location - 位置 - - - Status - 狀態 - - - Size - 大小 - - - Show Dock - 任務欄位置 - - - Plugin Area - 外掛程式區域 + Battery + @@ -509,15 +348,11 @@ Undock - 解除駐停 + 移除駐留 ShutdownPlugin - - Power - 電源 - Shut down 關機 @@ -536,7 +371,7 @@ Log out - 登出 + 註銷 Switch account @@ -548,14 +383,29 @@ Reboot - 重新啟動 + 重啟 + + + Power + 電源 SoundApplet - Volume - 音量 + Device + 裝置 + + + + SoundDevicesWidget + + Output Device + 輸出裝置 + + + Sound settings + 音量設定 @@ -570,15 +420,11 @@ Sound settings - 音效設定 + 音量設定 Volume %1 - 音量 %1 - - - No output devices - 無聲音輸出裝置 + 目前音量 %1 @@ -592,30 +438,45 @@ TrashPlugin Trash - 回收桶 + 回收站 Trash - %1 file - 回收桶-%1 個檔案 + 回收站 - %1個文件 Trash - %1 files - 回收桶-%1 個檔案 + 回收站 - %1個文件 Move to Trash - 移動到回收站 + 移至回收站 TrashWidget Open - 開啟 + 打開 Empty 清空 + + WindowManager + + Exit Safe Mode + 退出安全模式 + + + Dock - Safe Mode + 任務欄安全模式 + + + The Dock is in safe mode, please exit to show it properly + 任務欄已進入安全模式,退出安全模式後即可正常顯示 + + \ No newline at end of file diff --git a/widgets/settingdelegate.cpp b/widgets/settingdelegate.cpp new file mode 100644 index 000000000..062265657 --- /dev/null +++ b/widgets/settingdelegate.cpp @@ -0,0 +1,95 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "settingdelegate.h" + +#include +#include +#include +#include +#include + +DWIDGET_USE_NAMESPACE + +SettingDelegate::SettingDelegate(QAbstractItemView *parent) + : DStyledItemDelegate(parent) +{ + parent->installEventFilter(this); +} + +SettingDelegate::~SettingDelegate() +{ +} + +void SettingDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + painter->save(); + + QRect indexRect = option.rect; + // 绘制背景色 + bool isOver = option.state & QStyle::State_MouseOver; + bool isDefault = index.data(itemCheckRole).toBool(); + if (isDefault) { + QPainterPath path, path1; + path.addRoundedRect(indexRect, 8, 8); + + DPalette palette = DGuiApplicationHelper::instance()->applicationPalette(); + painter->fillPath(path, palette.color(QPalette::ColorRole::Highlight)); + } else { + QPainterPath path; + path.addRoundedRect(indexRect, 8, 8); + painter->fillPath(path, isOver ? QColor(0, 0, 0, 100) : QColor(0, 0, 0, 64)); + } + // 绘制图标 + QRect rectIcon = indexRect; + rectIcon.setX(20); + QIcon icon = index.data(Qt::DecorationRole).value(); + QPixmap pixmap(icon.pixmap(16, 16)); + rectIcon.setY(indexRect.y() + (rectIcon.height() - pixmap.height()) / 2); + rectIcon.setWidth(pixmap.width()); + rectIcon.setHeight(pixmap.height()); + painter->drawPixmap(rectIcon, pixmap); +#define RIGHTSPACE 11 +#define SELECTICONSIZE 10 + // 绘制文本 + QRect rectText; + rectText.setX(rectIcon.left() + rectIcon.width() + 8); + rectText.setWidth(indexRect.width() - rectText.x() - RIGHTSPACE - SELECTICONSIZE - 5); + QPen pen(isDefault ? QColor(255, 255, 255) : QColor(0, 0, 0)); + pen.setWidth(2); + painter->setPen(pen); + QFont ft(DFontSizeManager::instance()->t6()); + QFontMetrics ftm(ft); + QString text = QFontMetrics(ft).elidedText(index.data(Qt::DisplayRole).toString(), Qt::TextElideMode::ElideRight, + rectText.width()); + painter->setFont(ft); + rectText.setY(indexRect.y() + (indexRect.height() - QFontMetrics(ft).height()) / 2); + rectText.setHeight(QFontMetrics(ft).height()); + painter->drawText(rectText, text); + // 如果当前是默认的输出设备,则绘制右侧的对钩 + if (isDefault) { + QPointF points[3] = { + QPointF(indexRect.width() - RIGHTSPACE - SELECTICONSIZE, indexRect.center().y()), + QPointF(indexRect.width() - RIGHTSPACE - SELECTICONSIZE / 2, rectIcon.bottom() + 2), + QPointF(indexRect.width() - RIGHTSPACE, rectIcon.top() - 2) + }; + painter->drawPolyline(points, 3); + } + + painter->restore(); +} + +bool SettingDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + if (event->type() == QEvent::MouseButtonRelease) { + QRect rctIndex = option.rect; + rctIndex.setHeight(rctIndex.height() - spacing()); + QMouseEvent *mouseEvent = static_cast(event); + if (rctIndex.contains(mouseEvent->pos())) + Q_EMIT selectIndexChanged(index); + } + + return DStyledItemDelegate::editorEvent(event, model, option, index); +} diff --git a/widgets/settingdelegate.h b/widgets/settingdelegate.h new file mode 100644 index 000000000..475de8c34 --- /dev/null +++ b/widgets/settingdelegate.h @@ -0,0 +1,33 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SETTINGDELEGATE_H +#define SETTINGDELEGATE_H + +#include + +DWIDGET_USE_NAMESPACE + +static const int itemCheckRole = Dtk::UserRole + 1; +static const int itemDataRole = Dtk::UserRole + 2; +static const int itemFlagRole = Dtk::UserRole + 3; + +class SettingDelegate : public DStyledItemDelegate +{ + Q_OBJECT + +public: + explicit SettingDelegate(QAbstractItemView *parent = nullptr); + ~SettingDelegate() override; + +Q_SIGNALS: + void selectIndexChanged(const QModelIndex &); + +protected: + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; +}; + +#endif // SETTINGDELEGATE_H diff --git a/widgets/slidercontainer.cpp b/widgets/slidercontainer.cpp new file mode 100644 index 000000000..2e32f8595 --- /dev/null +++ b/widgets/slidercontainer.cpp @@ -0,0 +1,287 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "slidercontainer.h" + +#include +#include +#include + +#include +#include +#include +#include + +DWIDGET_USE_NAMESPACE + +// 用于绘制图标的窗体,此窗体不想让其在外部调用,因此,将其作为一个私有类 +class SliderIconWidget : public QWidget +{ +public: + explicit SliderIconWidget(QWidget *parent) + : QWidget(parent) + , m_iconSize(QSize(24, 24)) + , m_shadowSize(QSize()) + {} + + void updateData(const QIcon &icon, const QSize &iconSize, const QSize &shadowSize) + { + m_icon = icon; + m_iconSize = iconSize; + m_shadowSize = shadowSize; + update(); + } + + void updateIcon(const QIcon &icon) + { + m_icon = icon; + update(); + } + +protected: + void paintEvent(QPaintEvent *e) override; + +private: + QIcon m_icon; + QSize m_iconSize; + QSize m_shadowSize; +}; + +void SliderIconWidget::paintEvent(QPaintEvent *e) +{ + if (m_iconSize.isNull() || m_icon.isNull()) + return QWidget::paintEvent(e); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + if (m_shadowSize.isValid() && !m_shadowSize.isNull() && !m_shadowSize.isEmpty()) { + // 绘制圆形背景 + painter.setPen(Qt::NoPen); + // 获取阴影部分背景颜色 + DPalette dpa = DPaletteHelper::instance()->palette(this); + painter.setBrush(dpa.brush(DPalette::ColorRole::Midlight)); + int x = (rect().width() - m_shadowSize.width() ) / 2; + int y = (rect().height() - m_shadowSize.height() ) / 2; + painter.drawEllipse(QRect(x, y, m_shadowSize.width(), m_shadowSize.height())); + } + // 绘制图标 + QPixmap pixmap = m_icon.pixmap(m_iconSize); + int iconWidth = static_cast(m_iconSize.width() / qApp->devicePixelRatio()); + int iconHeight = static_cast(m_iconSize.height() / qApp->devicePixelRatio()); + int x = (rect().width() - iconWidth) / 2; + int y = (rect().height() - iconHeight) / 2; + painter.drawPixmap(x, y, iconWidth, iconHeight, pixmap); +} + +SliderContainer::SliderContainer(QWidget *parent) + : QWidget(parent) + , m_leftIconWidget(new SliderIconWidget(this)) + , m_slider(new QSlider(Qt::Orientation::Horizontal, this)) + , m_titleLabel(new QLabel(this)) + , m_rightIconWidget(new SliderIconWidget(this)) + , m_spaceLeftWidget(new QWidget(this)) + , m_spaceRightWidget(new QWidget(this)) +{ + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + + QHBoxLayout *sliderLayout = new QHBoxLayout(this); + sliderLayout->setContentsMargins(0, 0, 0, 0); + sliderLayout->setSpacing(0); + sliderLayout->addWidget(m_leftIconWidget); + sliderLayout->addWidget(m_spaceLeftWidget); + sliderLayout->addWidget(m_slider); + sliderLayout->addWidget(m_spaceRightWidget); + sliderLayout->addWidget(m_rightIconWidget); + + mainLayout->addWidget(m_titleLabel); + mainLayout->addLayout(sliderLayout); + + m_titleLabel->setVisible(false); + + m_leftIconWidget->installEventFilter(this); + m_slider->installEventFilter(this); + m_rightIconWidget->installEventFilter(this); + + connect(m_slider, &QSlider::valueChanged, this, &SliderContainer::sliderValueChanged); +} + +SliderContainer::~SliderContainer() +{ +} + +void SliderContainer::setTitle(const QString &text) +{ + m_titleLabel->setText(text); + m_titleLabel->setVisible(!text.isEmpty()); +} + +QSize SliderContainer::getSuitableSize(const QSize &iconSize, const QSize &bgSize) +{ + if (bgSize.isValid() && !bgSize.isNull() && !bgSize.isEmpty()) + return bgSize; + + return iconSize; +} + +void SliderContainer::setIcon(const SliderContainer::IconPosition &iconPosition, const QPixmap &icon, + const QSize &shadowSize, int space) +{ + if (icon.isNull()) { + return; + } + + switch (iconPosition) { + case IconPosition::LeftIcon: { + m_leftIconWidget->setFixedSize(getSuitableSize(icon.size(), shadowSize)); + m_leftIconWidget->updateData(icon, icon.size(), shadowSize); + m_spaceLeftWidget->setFixedWidth(space); + break; + } + case IconPosition::RightIcon: { + m_rightIconWidget->setFixedSize(getSuitableSize(icon.size(), shadowSize)); + m_rightIconWidget->updateData(icon, icon.size(), shadowSize); + m_spaceRightWidget->setFixedWidth(space); + break; + } + } +} + +void SliderContainer::setIcon(const SliderContainer::IconPosition &iconPosition, const QIcon &icon) +{ + switch (iconPosition) { + case IconPosition::LeftIcon: { + m_leftIconWidget->updateIcon(icon); + break; + } + case IconPosition::RightIcon: { + m_rightIconWidget->updateIcon(icon); + break; + } + } +} + +void SliderContainer::setPageStep(int step) +{ + return m_slider->setPageStep(step); +} + +void SliderContainer::setRange(int min, int max) +{ + return m_slider->setRange(min, max); +} + +bool SliderContainer::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonRelease) { + if (watched == m_leftIconWidget) + Q_EMIT iconClicked(IconPosition::LeftIcon); + else if (watched == m_rightIconWidget) + Q_EMIT iconClicked(IconPosition::RightIcon); + } + + return QWidget::eventFilter(watched, event); +} + +void SliderContainer::updateSliderValue(int value) +{ + m_slider->blockSignals(true); + m_slider->setValue(value); + m_slider->blockSignals(false); +} + +void SliderContainer::setSliderProxyStyle(QProxyStyle *proxyStyle) +{ + proxyStyle->setParent(m_slider); + m_slider->setStyle(proxyStyle); +} + +SliderProxyStyle::SliderProxyStyle(StyleType drawSpecial, QStyle *style) + : QProxyStyle(style) + , m_drawSpecial(drawSpecial) +{ +} + +SliderProxyStyle::~SliderProxyStyle() +{ +} + +void SliderProxyStyle::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + if (control != ComplexControl::CC_Slider) + return; + + // 绘制之前先保存之前的画笔 + painter->save(); + painter->setRenderHint(QPainter::RenderHint::Antialiasing); + // 获取滑动条和滑块的区域 + const QStyleOptionSlider *sliderOption = static_cast(option); + QRect rectGroove = subControlRect(CC_Slider, sliderOption, SC_SliderGroove, widget); + QRect rectHandle = subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget); + if (m_drawSpecial == RoundHandler) + drawRoundSlider(painter, rectGroove, rectHandle, widget); + else + drawNormalSlider(painter, rectGroove, rectHandle, widget); + + painter->restore(); +} + +// 绘制通用的滑动条 +void SliderProxyStyle::drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const +{ + DPalette dpa = DPaletteHelper::instance()->palette(wigdet); + QColor color = dpa.color(DPalette::Highlight); + QColor rightColor(Qt::gray); + if (!wigdet->isEnabled()) { + color.setAlphaF(0.8); + rightColor.setAlphaF(0.8); + } + + QPen penLine = QPen(color, 2); + // 绘制上下的竖线,一根竖线的宽度是2,+4个像素刚好保证中间也是间隔2个像素 + for (int i = rectGroove.x(); i < rectGroove.x() + rectGroove.width(); i = i + 4) { + if (i < rectHandle.x()) + painter->setPen(penLine); + else + painter->setPen(QPen(rightColor, 2)); + + painter->drawLine(i, rectGroove.y() + 2, i, rectGroove.y() + rectGroove.height() - 2); + } + // 绘制滚动区域 + painter->setBrush(color); + painter->setPen(Qt::NoPen); + QPainterPath path; + path.addRoundedRect(rectHandle, 6, 6); + painter->drawPath(path); +} + +// 绘制设计师定义的那种圆形滑块,黑色的滑条 +void SliderProxyStyle::drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const +{ + // 深色背景下,滑块和滑动条白色,浅色背景下,滑块和滑动条黑色 + QColor color = wigdet->isEnabled() ? (DGuiApplicationHelper::DarkType == DGuiApplicationHelper::instance()->themeType() ? Qt::white : Qt::black) : Qt::gray; + + QBrush brush(color); + // 此处中绘制圆形滑动条,需要绘制圆角,圆角大小为其高度的一半 + QPainterPath pathGroove; + int radius = rectGroove.height() / 2; + pathGroove.addRoundedRect(rectGroove, radius, radius); + painter->fillPath(pathGroove, brush); + + // 绘制滑块,因为滑块是正圆形,而它本来的区域是一个长方形区域,因此,需要计算当前 + // 区域的正中心区域,将其作为一个正方形区域来绘制圆形滑块 + int handleSize = qMin(rectHandle.width(), rectHandle.height()); + int x = rectHandle.x() + (rectHandle.width() - handleSize) / 2; + int y = rectHandle.y() + (rectHandle.height() - handleSize) / 2; + rectHandle.setX(x); + rectHandle.setY(y); + rectHandle.setWidth(handleSize); + rectHandle.setHeight(handleSize); + + QPainterPath pathHandle; + pathHandle.addEllipse(rectHandle); + painter->fillPath(pathHandle, brush); +} diff --git a/widgets/slidercontainer.h b/widgets/slidercontainer.h new file mode 100644 index 000000000..dd85c7bc5 --- /dev/null +++ b/widgets/slidercontainer.h @@ -0,0 +1,94 @@ +// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef SLIDERCONTAINER_H +#define SLIDERCONTAINER_H + +#include + +#include +#include + +class QLabel; +class SliderProxyStyle; +class SliderIconWidget; + +/** + * @brief 滚动条的类的封装,封装这个类的原因,是为了方便设置左右图标,dtk中的对应的DSlider类也有这个功能, + * 但是只能简单的设置左右图标,对于右边图标有阴影的,需要外部提供一个带阴影图标,但是如果由外部来提供, + * 通过QPixmap绘制的带阴影的图标无法消除锯齿(即使通过反走样也不行),因此在此处封装这个类 + */ +class SliderContainer : public QWidget +{ + Q_OBJECT + +public: + enum IconPosition { + LeftIcon = 0, + RightIcon + }; + +public: + explicit SliderContainer(QWidget *parent); + ~SliderContainer() override; + + void setTitle(const QString &text); + void setSliderProxyStyle(QProxyStyle *proxyStyle); + void setIcon(const IconPosition &iconPosition, const QIcon &icon); + void setIcon(const IconPosition &iconPosition, const QPixmap &icon, const QSize &shadowSize, int space); + + void setPageStep(int step); + void setRange(int min, int max); + +Q_SIGNALS: + void iconClicked(const IconPosition &); + void sliderValueChanged(int value); + +public slots: + void updateSliderValue(int value); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + QSize getSuitableSize(const QSize &iconSize, const QSize &bgSize); + +private: + SliderIconWidget *m_leftIconWidget; + QSlider *m_slider; + QLabel *m_titleLabel; + SliderIconWidget *m_rightIconWidget; + QWidget *m_spaceLeftWidget; + QWidget *m_spaceRightWidget; +}; + +/** + * @brief 用来设置滚动条的样式 + * @param drawSpecial: true + */ +class SliderProxyStyle : public QProxyStyle +{ + Q_OBJECT + +public: + enum StyleType { + RoundHandler = 0, // 绘制那种黑色圆底滑动条 + Normal // 绘制那种通用的滑动条 + }; + +public: + explicit SliderProxyStyle(StyleType drawSpecial = RoundHandler, QStyle *style = nullptr); + ~SliderProxyStyle() override; + +protected: + void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const override; + +private: + void drawNormalSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const; + void drawRoundSlider(QPainter *painter, QRect rectGroove, QRect rectHandle, const QWidget *wigdet) const; + +private: + StyleType m_drawSpecial; +}; + +#endif // VOLUMESLIDER_H diff --git a/widgets/tipswidget.cpp b/widgets/tipswidget.cpp index 5be5ddcbb..899655de5 100644 --- a/widgets/tipswidget.cpp +++ b/widgets/tipswidget.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,8 +8,6 @@ #include #include -#define PADDING 4 - namespace Dock{ TipsWidget::TipsWidget(QWidget *parent) : QFrame(parent) @@ -32,7 +30,7 @@ void TipsWidget::setText(const QString &text) m_text = "བོད་སྐད་ཡིག་གཟུགས་ཚད་ལེན་ཚོད་ལྟའི་སྐོར་གྱི་རྗོད་ཚིག"; #endif - setFixedSize(fontMetrics().width(m_text) + 20, fontMetrics().boundingRect(m_text).height() + PADDING); + setFixedSize(fontMetrics().horizontalAdvance(m_text) + 20, fontMetrics().boundingRect(m_text).height()); update(); @@ -52,11 +50,11 @@ void TipsWidget::setTextList(const QStringList &textList) int width = 0; int height = 0; for (QString text : m_textList) { - width = qMax(width, fontMetrics().width(text)); + width = qMax(width, fontMetrics().horizontalAdvance(text) + 20); height += fontMetrics().boundingRect(text).height(); } - setFixedSize(width + 20, height + PADDING); + setFixedSize(width, height); update(); } @@ -81,18 +79,16 @@ void TipsWidget::paintEvent(QPaintEvent *event) } break; case MultiLine: { - int x = rect().x(); - int y = rect().y(); - if (m_textList.size() != 1) { - x += 10; + int y = 0; + if (m_textList.size() != 1) option.setAlignment(Qt::AlignLeft | Qt::AlignVCenter); - } for (QString text : m_textList) { int lineHeight = fontMetrics().boundingRect(text).height(); - painter.drawText(QRect(x, y, rect().width(), lineHeight), text, option); + painter.drawText(QRect(0, y, rect().width(), lineHeight), text, option); y += lineHeight; } - } break; + } + break; } } diff --git a/widgets/tipswidget.h b/widgets/tipswidget.h index f3bfc1d35..8fef3edb9 100644 --- a/widgets/tipswidget.h +++ b/widgets/tipswidget.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later