mirror of
https://github.com/KDE/latte-dock.git
synced 2025-03-29 10:50:33 +03:00
Compare commits
492 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6aa19750e5 | ||
|
e8e8229465 | ||
|
db20896762 | ||
|
3eb57736fb | ||
|
7de7ed150c | ||
|
60bc8ee65b | ||
|
6acb37bc5a | ||
|
a53f381352 | ||
|
67bc5c9801 | ||
|
824feedbe2 | ||
|
1ac1a76b53 | ||
|
f79594dd01 | ||
|
6e21efcd2b | ||
|
56a0b8d34f | ||
|
fecbc680a6 | ||
|
86731f1566 | ||
|
5c241eed78 | ||
|
9b6f42d888 | ||
|
62febcef54 | ||
|
3f43a2ec5e | ||
|
9e3f53321c | ||
|
e1bd2c02ec | ||
|
a46fe062cf | ||
|
31a6135fd9 | ||
|
4f1c08054b | ||
|
6858dcdeb8 | ||
|
30b3d4c761 | ||
|
fd459df480 | ||
|
6d286ea440 | ||
|
f6ff829371 | ||
|
a9ce43f133 | ||
|
d1d57b7d01 | ||
|
10be08a794 | ||
|
78d0bc8a0f | ||
|
ae7854c16a | ||
|
23b9e9ea36 | ||
|
a815969fa4 | ||
|
4c504a318a | ||
|
b784da8d1c | ||
|
1398747bb8 | ||
|
3365b2c400 | ||
|
f5df4ae3d1 | ||
|
5c48f63afb | ||
|
6f1834d6da | ||
|
1a2a1dcbe6 | ||
|
fccdb88630 | ||
|
a2860999eb | ||
|
c7bd1bfdff | ||
|
1fc935038a | ||
|
9c09448ddd | ||
|
6160c679c6 | ||
|
b4b16f61f1 | ||
|
cc737af39f | ||
|
4d7595469d | ||
|
71f3112a08 | ||
|
7184d79c95 | ||
|
93b55677ef | ||
|
eeab393c55 | ||
|
4c7fbeb1e0 | ||
|
6d9f516581 | ||
|
d185475c3e | ||
|
fe12d95454 | ||
|
d3cc4aad00 | ||
|
8328f9a686 | ||
|
0c95dd84aa | ||
|
5e0872c396 | ||
|
131ee4d39c | ||
|
6356c472fe | ||
|
b1ea81662c | ||
|
358acbf1f6 | ||
|
ca6af59420 | ||
|
110adba6c2 | ||
|
df36844edd | ||
|
8d64858029 | ||
|
7c9c8f1f01 | ||
|
8ae05c72df | ||
|
afab5529df | ||
|
6ef3ebf245 | ||
|
3d26e09efd | ||
|
c250bd7413 | ||
|
99b6b9475a | ||
|
6b2741d1f4 | ||
|
5fef17739b | ||
|
6fcf67aa73 | ||
|
c6882e79c4 | ||
|
4a6be0a96b | ||
|
755676d752 | ||
|
de6c48cdbc | ||
|
0a960689e4 | ||
|
6c29aaabeb | ||
|
ea822c7c01 | ||
|
304f8c2aea | ||
|
fd67338d16 | ||
|
a9880aa8d7 | ||
|
06b3c89a01 | ||
|
d3d043d2e1 | ||
|
1d7b8519d9 | ||
|
237ec8c4bf | ||
|
05e4885ef3 | ||
|
6aae3646e8 | ||
|
32ce630b51 | ||
|
b6884636b1 | ||
|
054c9e5c94 | ||
|
f9727cdac5 | ||
|
66e52716b4 | ||
|
7b210a9970 | ||
|
8ea7f3e066 | ||
|
620c7fa986 | ||
|
bf320e2d15 | ||
|
98d25c1427 | ||
|
7524c210b9 | ||
|
cb44b6f84d | ||
|
71e0243709 | ||
|
65b6761237 | ||
|
902092f2a8 | ||
|
5dc506b49f | ||
|
0423fd4259 | ||
|
427b6ba690 | ||
|
853a7735a4 | ||
|
4f7f4c2395 | ||
|
3b67d2112d | ||
|
1aa9d9f825 | ||
|
81ea60df72 | ||
|
61fa1b0e23 | ||
|
720fc92d14 | ||
|
2d7c1642fc | ||
|
5956db83ec | ||
|
a0ff6e7817 | ||
|
edb8a258a2 | ||
|
ea8c4b9714 | ||
|
459f0d54ff | ||
|
a0e6eae9c8 | ||
|
892ac7868b | ||
|
67591cf616 | ||
|
a91a1ef227 | ||
|
6532af166f | ||
|
5c2158b969 | ||
|
b58cdd7882 | ||
|
4cc612284d | ||
|
1193856d40 | ||
|
5e5c352421 | ||
|
515238b4b9 | ||
|
6263a65606 | ||
|
e295e8a782 | ||
|
819720a9e6 | ||
|
93fcab6217 | ||
|
657e243951 | ||
|
70eef99173 | ||
|
a2339ed3e3 | ||
|
de353395dc | ||
|
e1e8c47aec | ||
|
79033efbcc | ||
|
6a78c351d9 | ||
|
4f93251d8c | ||
|
06fbe1fd4d | ||
|
0db62d6bdc | ||
|
a0a4911a69 | ||
|
98ac3dc225 | ||
|
491a5b0f49 | ||
|
f37c8531a8 | ||
|
a7e875e567 | ||
|
a111d8153a | ||
|
7564e0ee52 | ||
|
c73d03b2b3 | ||
|
76302ee78a | ||
|
906fdf796a | ||
|
63043c0b34 | ||
|
911bc0bd7e | ||
|
9fbafbfbb4 | ||
|
159496edc0 | ||
|
aa04303c63 | ||
|
30def9c505 | ||
|
6c2b5f4971 | ||
|
f7088bf0ba | ||
|
e9269e5151 | ||
|
218ff83986 | ||
|
57c6148dc4 | ||
|
daa1e6b066 | ||
|
957fece0ca | ||
|
6a677d7b95 | ||
|
c04bda6d92 | ||
|
29ae2aa698 | ||
|
af28885b81 | ||
|
531d2bce80 | ||
|
d882578f6f | ||
|
a3467a975d | ||
|
93c50a7e8f | ||
|
7d8a939f81 | ||
|
f8afad52fb | ||
|
60826a13c9 | ||
|
8783d07542 | ||
|
4ec72572f2 | ||
|
42fedafc02 | ||
|
45d4ccc6d3 | ||
|
61b1441f5b | ||
|
1d468a94e9 | ||
|
8588614fbf | ||
|
8b60c00cf1 | ||
|
bf7bee9b20 | ||
|
051aad2661 | ||
|
f9c1854438 | ||
|
d170d540b4 | ||
|
e433d1c7f0 | ||
|
c755c7f534 | ||
|
27fbdff59d | ||
|
b55a7b24fa | ||
|
e6e50d712f | ||
|
b7797307e7 | ||
|
db47394e33 | ||
|
d7e9fbe772 | ||
|
0acb003769 | ||
|
24776aa572 | ||
|
53fce38f9e | ||
|
1b01e945b9 | ||
|
cff02dcc30 | ||
|
5f0a553ec3 | ||
|
6d74ebb2d9 | ||
|
cd36798a61 | ||
|
5971fca696 | ||
|
a9d8687073 | ||
|
c459397db7 | ||
|
55caf75ab4 | ||
|
bbb155c6bb | ||
|
ff511ccc1d | ||
|
7c4ab40769 | ||
|
d404ca5219 | ||
|
b0885a1711 | ||
|
960186b147 | ||
|
a3bdc89a0f | ||
|
2e252b5420 | ||
|
777d16b3d3 | ||
|
24b1e8faae | ||
|
0cc73324c3 | ||
|
899c0155c7 | ||
|
54ccf51cda | ||
|
c758a694e0 | ||
|
46f343aa5c | ||
|
bdf92099bb | ||
|
cbf9088f60 | ||
|
d5bbdf57dc | ||
|
80931bd3d5 | ||
|
4ae96e718c | ||
|
ec51d21eae | ||
|
81e0f90f43 | ||
|
3c155198a1 | ||
|
48a60c6268 | ||
|
bef155238a | ||
|
6009db6163 | ||
|
73abdf7a13 | ||
|
2157c0d455 | ||
|
a014f386fb | ||
|
5a691197e8 | ||
|
3c3b5c6d11 | ||
|
771f059e63 | ||
|
220b8b98da | ||
|
ac3505b076 | ||
|
917e928dbd | ||
|
420cb4198a | ||
|
0a0110f534 | ||
|
c4abc2eaf5 | ||
|
66a1713b40 | ||
|
4e1fdc4466 | ||
|
8c26f50fa4 | ||
|
abe7c19547 | ||
|
9c1728cd25 | ||
|
d3538eeec3 | ||
|
cbd30a8c22 | ||
|
b7c7e9ebd4 | ||
|
625b852ba7 | ||
|
d208698143 | ||
|
18b47b607f | ||
|
02d3c37f93 | ||
|
90e4ea28c4 | ||
|
dd8756ad79 | ||
|
b4b6979ea7 | ||
|
4f7812338e | ||
|
f9b264e053 | ||
|
f94e5bc843 | ||
|
163720adef | ||
|
1c9ec6ef73 | ||
|
866fc3eb16 | ||
|
e1ad706481 | ||
|
a2fb837ea1 | ||
|
cb32286a8f | ||
|
3f9fdf996b | ||
|
44287ff696 | ||
|
4e6dca0879 | ||
|
8c21550f18 | ||
|
f1f1668394 | ||
|
1cb7e1c8b0 | ||
|
0d461b1cad | ||
|
7cda1c66e1 | ||
|
a11b9a8d62 | ||
|
4374dace17 | ||
|
3ea1e904a2 | ||
|
8f48f4ea9b | ||
|
83d4da52e6 | ||
|
3b480d42d9 | ||
|
e49404db7c | ||
|
be9799b342 | ||
|
b1d57051c2 | ||
|
4401fdbb0f | ||
|
5100deee38 | ||
|
6750f02d6f | ||
|
6bce84c68b | ||
|
bd6ae904b9 | ||
|
ec5b56031a | ||
|
538dba0a02 | ||
|
d43f3d5ac4 | ||
|
45619c7248 | ||
|
a42bc6788c | ||
|
3f90a49b55 | ||
|
21d8728498 | ||
|
ac021a38b7 | ||
|
bf7a87a81b | ||
|
8476a796d2 | ||
|
fe63a63efc | ||
|
0f3c2b8468 | ||
|
dea478f16e | ||
|
59b422448b | ||
|
d841e1e443 | ||
|
f1472db653 | ||
|
48ecda9723 | ||
|
6e1c45d087 | ||
|
40b4851dac | ||
|
b6a38e3830 | ||
|
4d1fbfd584 | ||
|
11f42978fa | ||
|
8a2e2581ef | ||
|
097ceed7d2 | ||
|
f0ad7b23c7 | ||
|
c7bb46b217 | ||
|
219e901e87 | ||
|
e326dddbd6 | ||
|
2b039e1275 | ||
|
ee307a0759 | ||
|
84fe31c318 | ||
|
60095bba3b | ||
|
8a0f18326e | ||
|
fa4db13e81 | ||
|
6fa1d1cc87 | ||
|
ec62b36018 | ||
|
0657ca1e4e | ||
|
6187f4d997 | ||
|
c4afa37465 | ||
|
837f0a81e7 | ||
|
3c5b474a97 | ||
|
aa57d21515 | ||
|
20e3f3cbb3 | ||
|
a12565ab1f | ||
|
d0f4bcfa33 | ||
|
98f39e17e3 | ||
|
b1c3594367 | ||
|
78b124e8f4 | ||
|
7d180f8dd6 | ||
|
4de51de221 | ||
|
c9aa147b7b | ||
|
c6ea796f00 | ||
|
02d7e2a7d8 | ||
|
850937ca22 | ||
|
4c1c65e353 | ||
|
765aa45c72 | ||
|
1e841db497 | ||
|
1a12bce8af | ||
|
fc8c439787 | ||
|
ce15e4e511 | ||
|
9351277cd7 | ||
|
8bd168a5a5 | ||
|
5ecb8ab767 | ||
|
cd2ec88274 | ||
|
c98f6679b8 | ||
|
7304025bc3 | ||
|
3b8c4392c1 | ||
|
362b21ee08 | ||
|
346381370b | ||
|
74626f7bdf | ||
|
4e28392c3e | ||
|
51f166bf51 | ||
|
74d5b567ed | ||
|
055e92b0d6 | ||
|
a033a20062 | ||
|
7a7af88e99 | ||
|
c317d3257a | ||
|
c15a97bacf | ||
|
45db72b5db | ||
|
720a9ca5b0 | ||
|
ccbf079113 | ||
|
de61ff48ad | ||
|
fb4cfaa399 | ||
|
24fc1e8709 | ||
|
5e0feef0f6 | ||
|
62ed63daf1 | ||
|
ca83433ce0 | ||
|
bce0d74e5f | ||
|
c2b20852ea | ||
|
aeb934d0fb | ||
|
6a66dd0000 | ||
|
3287a293b9 | ||
|
a553f7403f | ||
|
7258920d70 | ||
|
ea19ff18ad | ||
|
11a8c3fee7 | ||
|
321a50627d | ||
|
434f3b16e6 | ||
|
229f92b2c8 | ||
|
1365b9f24f | ||
|
e88aaf27a9 | ||
|
b4da839df4 | ||
|
3067b6d51c | ||
|
05e588c333 | ||
|
e0bfff4c48 | ||
|
127f24bb24 | ||
|
fae5fcffb7 | ||
|
eb6ae017fe | ||
|
518563a8c1 | ||
|
5dc6cea1f8 | ||
|
0c1e29bf4e | ||
|
b3efb73aef | ||
|
23ec03a9fd | ||
|
27062087ea | ||
|
c4964d0b1f | ||
|
199effaf2b | ||
|
55e893b43b | ||
|
90405fef8a | ||
|
e642087e31 | ||
|
956b589764 | ||
|
eda019016d | ||
|
6f30380802 | ||
|
7e1b0bc2ee | ||
|
9ce7c5b72d | ||
|
81c298114b | ||
|
61d4ff64d8 | ||
|
36af1f27e8 | ||
|
e2b98892e5 | ||
|
ea500a8ec0 | ||
|
04929b0138 | ||
|
33428af95b | ||
|
1aeae6d256 | ||
|
e822062668 | ||
|
cbbfc55861 | ||
|
63a54b40db | ||
|
3769cef501 | ||
|
dacf4d71a8 | ||
|
c9515a0353 | ||
|
59360176ee | ||
|
d354cc4513 | ||
|
4ca17600c6 | ||
|
c24cd92c98 | ||
|
c86878f6c7 | ||
|
fc4dc6dacc | ||
|
58c7093be9 | ||
|
53674a65e1 | ||
|
ad3f97d6df | ||
|
a2813a1c43 | ||
|
a80c71981a | ||
|
d47f01a499 | ||
|
596a184fa1 | ||
|
5e55abbff5 | ||
|
5c9dc950d7 | ||
|
bcae47a3f9 | ||
|
463437d8d0 | ||
|
a192b66a16 | ||
|
eb95f2ef13 | ||
|
25e05070bb | ||
|
27b90bb89c | ||
|
9f89d13c7b | ||
|
66ddda956b | ||
|
38455ea76a | ||
|
df9117d010 | ||
|
949e9c5c5e | ||
|
f7032f7f19 | ||
|
2f6808b626 | ||
|
c02e4b6a7e | ||
|
71f9e89157 | ||
|
47702a59be | ||
|
f2c401b02f | ||
|
d84e50a594 | ||
|
27c6225b1a | ||
|
d600bbeb63 | ||
|
834f71d266 | ||
|
72ff76033b | ||
|
e0e3f19f7a | ||
|
19defa08cd | ||
|
bb713e1092 | ||
|
750785b5e5 | ||
|
92aec503f5 | ||
|
fd5b4e53ec | ||
|
30de674870 | ||
|
8ec97ed6c4 | ||
|
469a5e48cc | ||
|
ce9fd0132d | ||
|
d699e144ce |
@ -1,3 +0,0 @@
|
||||
{
|
||||
"phabricator.uri" : "https://phabricator.kde.org/"
|
||||
}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
*~
|
||||
.*
|
||||
!.arcconfig
|
||||
!.gitignore
|
||||
|
||||
|
6
.gitlab-ci.yml
Normal file
6
.gitlab-ci.yml
Normal file
@ -0,0 +1,6 @@
|
||||
# SPDX-FileCopyrightText: None
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
include:
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
|
29
.kde-ci.yml
Normal file
29
.kde-ci.yml
Normal file
@ -0,0 +1,29 @@
|
||||
# SPDX-FileCopyrightText: None
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
Dependencies:
|
||||
- 'on': ['@all']
|
||||
'require':
|
||||
'frameworks/extra-cmake-modules': '@latest'
|
||||
'frameworks/kdoctools': '@latest'
|
||||
'frameworks/kio': '@latest'
|
||||
'frameworks/ki18n': '@latest'
|
||||
'frameworks/kwidgetsaddons': '@latest'
|
||||
'frameworks/karchive': '@latest'
|
||||
'frameworks/kcoreaddons': '@latest'
|
||||
'frameworks/kguiaddons': '@latest'
|
||||
'frameworks/kdbusaddons': '@latest'
|
||||
'frameworks/kcrash': '@latest'
|
||||
'frameworks/kdeclarative': '@latest'
|
||||
'frameworks/kglobalaccel': '@latest'
|
||||
'frameworks/kirigami': '@latest'
|
||||
'frameworks/ki18n': '@latest'
|
||||
'frameworks/kiconthemes': '@latest'
|
||||
'frameworks/knewstuff': '@latest'
|
||||
'frameworks/knotifications': '@latest'
|
||||
'frameworks/kwindowsystem': '@latest'
|
||||
'frameworks/kxmlgui': '@latest'
|
||||
'plasma/kwayland': '@latest'
|
||||
'plasma/libplasma': '@latest'
|
||||
'plasma/plasma-workspace': '@stable'
|
||||
'plasma/plasma-activities': '@latest'
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -1,5 +1,31 @@
|
||||
#**CHANGELOG**#
|
||||
|
||||
#### Version 0.10.X (current development build)
|
||||
* optionally maximise panel size in presence of maximised windows (https://invent.kde.org/plasma/latte-dock/-/merge_requests/46)
|
||||
|
||||
#### Version 0.10.8
|
||||
* multi-screen: fix docks/panels screen repositioning when the user specifies different screen for dock or panel
|
||||
* fix borders identification for autopositioning vertical docks/panels
|
||||
* fix vertical docks/panels autopositioning which is relevant to top and bottom panels
|
||||
* position kwin edges helper window properly on startup after offscreen positioning
|
||||
* x11: center applets config window on screen
|
||||
* do not shrink vertical docks/panels on startup after switching from offscreen to onscreen
|
||||
* make dock and panel work properly when they undo their removal
|
||||
|
||||
#### Version 0.10.7
|
||||
* multi-screen: always trust KWin under X11 in order to set correct struts for panels and docks
|
||||
* automatically offset centered applets when the left or right widgets overlap the centered one
|
||||
* windowsgobelow: show properly during startup
|
||||
* kwinedges: calculate accurately their size and position
|
||||
* improve applets dragging during rearrange and configure widgets mode
|
||||
* hide thin tooltips properly at some cases that were stack
|
||||
* fill one pixel gap of justify splitters during rearrange and configure widgets mode
|
||||
* fix, windows belong to screen whenever they are touching it. This way a window could belong in more than one screens and be taken into account for visibility modes and active window tracking
|
||||
* remove file extensions for layouts and templates properly in order to identify the layout or template name
|
||||
* fix build for Freebsd
|
||||
* x11: force OnAllDesktops for all docks and panels during creation
|
||||
* fix empty availableScreenRegion broadcast to Plasma
|
||||
|
||||
#### Version 0.10.6
|
||||
* fix build with Qt 5.12
|
||||
* initialize windows tracking properly
|
||||
|
@ -1,27 +1,43 @@
|
||||
project(lattedock)
|
||||
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(VERSION 0.10.6)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(VERSION 0.10.77)
|
||||
set(AUTHOR "Michail Vourlakos, Smith Ar")
|
||||
set(EMAIL "mvourlakos@gmail.com, audoban@openmailbox.org")
|
||||
set(WEBSITE "https://userbase.kde.org/LatteDock")
|
||||
set(BUG_ADDRESS "https://bugs.kde.org/enter_bug.cgi?product=lattedock")
|
||||
set(FAQS "https://userbase.kde.org/LatteDock/FAQ")
|
||||
|
||||
set(QT_MIN_VERSION "5.9.0")
|
||||
set(KF5_MIN_VERSION "5.48.0")
|
||||
set(QT_MIN_VERSION "5.15.0")
|
||||
set(KF5_MIN_VERSION "5.88.0")
|
||||
set(KDE_COMPILERSETTINGS_LEVEL "5.84.0")
|
||||
|
||||
set(KF5_LOCALE_PREFIX "")
|
||||
|
||||
find_package(ECM ${KF5_MIN_VER} REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
|
||||
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(CheckIncludeFiles)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(ECMOptionalAddSubdirectory)
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
include(KDECMakeSettings)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(KDEPackageAppTemplates)
|
||||
include(WriteBasicConfigVersionFile)
|
||||
|
||||
|
||||
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED NO_MODULE COMPONENTS DBus Gui Qml Quick)
|
||||
|
||||
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
|
||||
Activities Archive CoreAddons GuiAddons Crash DBusAddons Declarative GlobalAccel Kirigami2
|
||||
I18n IconThemes KIO NewStuff Notifications Plasma PlasmaQuick Wayland WindowSystem XmlGui)
|
||||
|
||||
find_package(LibTaskManager REQUIRED)
|
||||
add_definitions(-DPLASMA_WORKSPACE_VERSION="${LibTaskManager_VERSION}")
|
||||
|
||||
find_package(X11 REQUIRED)
|
||||
set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries"
|
||||
@ -45,17 +61,20 @@ if(X11_FOUND AND XCB_XCB_FOUND)
|
||||
set(HAVE_X11 ON)
|
||||
endif()
|
||||
|
||||
|
||||
find_package(QtWaylandScanner REQUIRED)
|
||||
find_package(Qt${QT_MAJOR_VERSION}WaylandClient)
|
||||
find_package(PlasmaWaylandProtocols 1.6 REQUIRED)
|
||||
find_package(Wayland REQUIRED COMPONENTS Client)
|
||||
|
||||
string(REGEX MATCH "\\.([^]]+)\\." KF5_VERSION_MINOR ${KF5_VERSION})
|
||||
string(REGEX REPLACE "\\." "" KF5_VERSION_MINOR ${KF5_VERSION_MINOR})
|
||||
|
||||
message(STATUS "KF5 VERSION : ${KF5_VERSION}")
|
||||
message(STATUS "KF5 VERSION MINOR : ${KF5_VERSION_MINOR}")
|
||||
|
||||
if(${KF5_VERSION_MINOR} LESS "62")
|
||||
find_package(KF5 REQUIRED COMPONENTS SysGuard)
|
||||
endif()
|
||||
|
||||
include(ECMQMLModules)
|
||||
include(ECMFindQmlModule)
|
||||
ecm_find_qmlmodule(QtQuick 2.7)
|
||||
ecm_find_qmlmodule(QtQuick.Layouts 1.3)
|
||||
ecm_find_qmlmodule(QtQuick.Controls 1.4)
|
||||
@ -65,17 +84,8 @@ ecm_find_qmlmodule(org.kde.kquickcontrolsaddons 2.0)
|
||||
ecm_find_qmlmodule(org.kde.plasma.core 2.0)
|
||||
ecm_find_qmlmodule(org.kde.plasma.components 2.0)
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(ECMOptionalAddSubdirectory)
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
include(KDECMakeSettings)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(KDEInstallDirs)
|
||||
include(KDEPackageAppTemplates)
|
||||
include(WriteBasicConfigVersionFile)
|
||||
|
||||
include(Definitions.cmake)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app/config-latte.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/app/config-latte.h)
|
||||
|
||||
#hide warnings
|
||||
string(REPLACE "-Wall" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
|
@ -1,2 +0,0 @@
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app/config-latte.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/app/config-latte.h)
|
@ -17,22 +17,26 @@ sudo apt dist-upgrade
|
||||
### Kubuntu and KDE Neon
|
||||
|
||||
```
|
||||
sudo apt install cmake extra-cmake-modules qtdeclarative5-dev libqt5x11extras5-dev libkf5iconthemes-dev libkf5plasma-dev libkf5windowsystem-dev libkf5declarative-dev libkf5xmlgui-dev libkf5activities-dev build-essential libxcb-util-dev libkf5wayland-dev git gettext libkf5archive-dev libkf5notifications-dev libxcb-util0-dev libsm-dev libkf5crash-dev libkf5newstuff-dev libxcb-shape0-dev libxcb-randr0-dev libx11-dev libx11-xcb-dev kirigami2-dev
|
||||
|
||||
sudo apt install cmake extra-cmake-modules qtdeclarative5-dev libqt5x11extras5-dev libkf5iconthemes-dev libkf5plasma-dev libkf5windowsystem-dev libkf5declarative-dev libkf5xmlgui-dev libkf5activities-dev build-essential libxcb-util-dev libkf5wayland-dev git gettext libkf5archive-dev libkf5notifications-dev libxcb-util0-dev libsm-dev libkf5crash-dev libkf5newstuff-dev libxcb-shape0-dev libxcb-randr0-dev libx11-dev libx11-xcb-dev kirigami2-dev libwayland-dev libwayland-client0 plasma-wayland-protocols libqt5waylandclient5-dev qtwayland5-dev-tools
|
||||
```
|
||||
|
||||
### Arch Linux
|
||||
|
||||
```
|
||||
sudo pacman -Syu
|
||||
sudo pacman -S cmake extra-cmake-modules python plasma-framework plasma-desktop
|
||||
sudo pacman -S cmake extra-cmake-modules python plasma-framework plasma-desktop plasma-wayland-protocols
|
||||
```
|
||||
|
||||
### Fedora/RHEL
|
||||
```
|
||||
sudo dnf install cmake extra-cmake-modules qt5-qtdeclarative-devel qt5-qtx11extras-devel kf5-kiconthemes-devel kf5-plasma-devel kf5-kwindowsystem-devel kf5-kdeclarative-devel kf5-kxmlgui-devel kf5-kactivities-devel gcc-c++ gcc xcb-util-devel kf5-kwayland-devel git gettext kf5-karchive-devel kf5-knotifications-devel libSM-devel kf5-kcrash-devel kf5-knewstuff-devel kf5-kdbusaddons-devel kf5-kxmlgui-devel kf5-kglobalaccel-devel kf5-kio-devel kf5-kguiaddons-devel kf5-kirigami2-devel kf5-kirigami-devel
|
||||
sudo dnf install cmake extra-cmake-modules qt5-qtdeclarative-devel qt5-qtx11extras-devel kf5-kiconthemes-devel kf5-plasma-devel kf5-kwindowsystem-devel kf5-kdeclarative-devel kf5-kxmlgui-devel kf5-kactivities-devel gcc-c++ gcc xcb-util-devel kf5-kwayland-devel git gettext kf5-karchive-devel kf5-knotifications-devel libSM-devel kf5-kcrash-devel kf5-knewstuff-devel kf5-kdbusaddons-devel kf5-kxmlgui-devel kf5-kglobalaccel-devel kf5-kio-devel kf5-kguiaddons-devel kf5-kirigami2-devel kf5-kirigami-devel kf5-ki18n-devel qt5-qtwayland-devel plasma-wayland-protocols-devel wayland-devel
|
||||
```
|
||||
|
||||
### openSUSE
|
||||
```
|
||||
sudo zypper install cmake extra-cmake-modules gcc-c++ gcc xcb-util-devel git gettext libSM-devel wayland-devel libQt5DBus-devel libQt5Gui-devel qtdeclarative-imports-provides-qt5 libqt5-qtdeclarative-devel knotifications-devel kactivities5-devel karchive-devel kcoreaddons-devel kcoreaddons-devel kguiaddons-devel kcrash-devel kdbusaddons-devel kdeclarative-devel kglobalaccel-devel kirigami2-devel ki18n-devel kiconthemes-devel kio-devel knewstuff-devel plasma-framework-devel kwayland-devel plasma5-workspace-devel kitemmodels-devel libqt5-qtx11extras-devel plasma-wayland-protocols libqt5-qtwayland
|
||||
```
|
||||
|
||||
### Building and Installing
|
||||
|
||||
**Now you can run the installation script.**
|
||||
|
121
LICENSES/CC0-1.0.txt
Normal file
121
LICENSES/CC0-1.0.txt
Normal file
@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
67
README.md
67
README.md
@ -1,6 +1,6 @@
|
||||
About
|
||||
=====
|
||||
Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and trys to be there only when it is needed.
|
||||
Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.
|
||||
|
||||
**"Art in Coffee"**
|
||||
|
||||
@ -15,7 +15,7 @@ Development
|
||||
============
|
||||
|
||||
- Official KDE repo in which you can also send your MRs is located at: https://invent.kde.org/plasma/latte-dock
|
||||
- Bug reports can be send at: https://bugs.kde.org/enter_bug.cgi?product=lattedock
|
||||
- Bug reports can be sent at: https://bugs.kde.org/enter_bug.cgi?product=lattedock
|
||||
|
||||
|
||||
Installation
|
||||
@ -23,10 +23,11 @@ Installation
|
||||
|
||||
## Requirements
|
||||
|
||||
We recommend to use at least:
|
||||
**Plasma >= 5.15.0**
|
||||
**Qt >= 5.12**
|
||||
We need to use at least:
|
||||
|
||||
- **Plasma >= 5.24.0**
|
||||
- **PlasmaWaylandProtocols >= 1.6.0**
|
||||
- **Qt >= 5.15**
|
||||
|
||||
Minimum requirements:
|
||||
|
||||
@ -37,34 +38,32 @@ Minimum requirements:
|
||||
|
||||
**development packages for:**
|
||||
```
|
||||
Qt5Core >= 5.12.0
|
||||
Qt5Gui >= 5.12.0
|
||||
Qt5Dbus >= 5.12.0
|
||||
Qt5Core >= 5.15.0
|
||||
Qt5Gui >= 5.15.0
|
||||
Qt5Dbus >= 5.15.0
|
||||
|
||||
KF5Plasma >= 5.48.0
|
||||
KF5PlasmaQuick >= 5.48.0
|
||||
KF5Activities >= 5.48.0
|
||||
KF5CoreAddons >= 5.48.0
|
||||
KF5GuiAddons >= 5.48.0
|
||||
KF5DBusAddons >= 5.48.0
|
||||
KF5Declarative >= 5.48.0
|
||||
KF5Kirigami2 >= 5.48.0
|
||||
KF5Wayland >= 5.48.0
|
||||
KF5Package >= 5.48.0
|
||||
KF5XmlGui >= 5.48.0
|
||||
KF5IconThemes >= 5.48.0
|
||||
KF5KIO >= 5.48.0
|
||||
KF5I18n >= 5.48.0
|
||||
KF5Notifications >= 5.48.0
|
||||
KF5NewStuff >= 5.48.0
|
||||
KF5Archive >= 5.48.0
|
||||
KF5GlobalAccel >= 5.48.0
|
||||
KF5Crash >= 5.48.0
|
||||
KF5Plasma >= 5.82.0
|
||||
KF5PlasmaQuick >= 5.82.0
|
||||
KF5Activities >= 5.82.0
|
||||
KF5CoreAddons >= 5.82.0
|
||||
KF5GuiAddons >= 5.82.0
|
||||
KF5DBusAddons >= 5.82.0
|
||||
KF5Declarative >= 5.82.0
|
||||
KF5Kirigami2 >= 5.82.0
|
||||
KF5Wayland >= 5.82.0
|
||||
KF5Package >= 5.82.0
|
||||
KF5XmlGui >= 5.82.0
|
||||
KF5IconThemes >= 5.82.0
|
||||
KF5KIO >= 5.82.0
|
||||
KF5I18n >= 5.82.0
|
||||
KF5Notifications >= 5.82.0
|
||||
KF5NewStuff >= 5.82.0
|
||||
KF5Archive >= 5.82.0
|
||||
KF5GlobalAccel >= 5.82.0
|
||||
KF5Crash >= 5.82.0
|
||||
|
||||
KSysGuard [reguired only for kf5<=5.61]
|
||||
|
||||
For X11 support:
|
||||
KF5WindowSystem >= 5.48.0
|
||||
For X11 support:
|
||||
KF5WindowSystem >= 5.82.0
|
||||
Qt5X11Extras >= 5.7.0
|
||||
libxcb
|
||||
libxcb-randr
|
||||
@ -89,7 +88,7 @@ Minimum requirements:
|
||||
|
||||
### Arch Linux
|
||||
|
||||
- [Arch Linux](https://www.archlinux.org/packages/?sort=&q=latte-dock)
|
||||
- [Arch Linux](https://aur.archlinux.org/packages/latte-dock)
|
||||
|
||||
### Gentoo
|
||||
|
||||
@ -106,7 +105,7 @@ Minimum requirements:
|
||||
### FreeBSD
|
||||
- [FreeBSD Port](https://www.freshports.org/deskutils/latte-dock/)
|
||||
|
||||
See the [installation instruction](./INSTALLATION.md) for others Linux distribution or development build
|
||||
See the [installation instructions](./INSTALLATION.md) for other Linux distributions or development builds
|
||||
|
||||
## Run Latte-Dock
|
||||
|
||||
@ -115,7 +114,7 @@ Latte is now ready to be used by executing
|
||||
latte-dock
|
||||
```
|
||||
|
||||
or activating **Latte Dock** from applications menu.
|
||||
or activating **Latte Dock** from the applications menu.
|
||||
|
||||
|
||||
Contributors
|
||||
|
@ -4,7 +4,8 @@ set(lattedock-app_SRCS
|
||||
infoview.cpp
|
||||
lattecorona.cpp
|
||||
screenpool.cpp
|
||||
main.cpp
|
||||
primaryoutputwatcher.cpp
|
||||
main.cpp
|
||||
coretypes.h
|
||||
)
|
||||
|
||||
@ -49,61 +50,40 @@ ki18n_wrap_ui(lattedock-app_SRCS settings/screensdialog/screensdialog.ui)
|
||||
ki18n_wrap_ui(lattedock-app_SRCS settings/settingsdialog/settingsdialog.ui)
|
||||
ki18n_wrap_ui(lattedock-app_SRCS settings/viewsdialog/viewsdialog.ui)
|
||||
|
||||
ecm_add_qtwayland_client_protocol(lattedock-app_SRCS
|
||||
PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/kde-primary-output-v1.xml
|
||||
BASENAME kde-primary-output-v1
|
||||
)
|
||||
|
||||
add_executable(latte-dock ${lattedock-app_SRCS})
|
||||
|
||||
include(FakeTarget.cmake)
|
||||
|
||||
if(${KF5_VERSION_MINOR} LESS "62")
|
||||
target_link_libraries(latte-dock
|
||||
Qt5::DBus
|
||||
Qt5::Quick
|
||||
Qt5::Qml
|
||||
KF5::Activities
|
||||
KF5::Archive
|
||||
KF5::CoreAddons
|
||||
KF5::Crash
|
||||
KF5::DBusAddons
|
||||
KF5::Declarative
|
||||
KF5::GuiAddons
|
||||
KF5::GlobalAccel
|
||||
KF5::I18n
|
||||
KF5::IconThemes
|
||||
KF5::KIOWidgets
|
||||
KF5::Notifications
|
||||
KF5::NewStuff
|
||||
KF5::QuickAddons
|
||||
KF5::Plasma
|
||||
KF5::PlasmaQuick
|
||||
KF5::ProcessCore
|
||||
KF5::WaylandClient
|
||||
KF5::XmlGui
|
||||
)
|
||||
else()
|
||||
target_link_libraries(latte-dock
|
||||
Qt5::DBus
|
||||
Qt5::Quick
|
||||
Qt5::Qml
|
||||
KF5::Activities
|
||||
KF5::Archive
|
||||
KF5::CoreAddons
|
||||
KF5::Crash
|
||||
KF5::DBusAddons
|
||||
KF5::Declarative
|
||||
KF5::GuiAddons
|
||||
KF5::GlobalAccel
|
||||
KF5::I18n
|
||||
KF5::IconThemes
|
||||
KF5::KIOWidgets
|
||||
KF5::Notifications
|
||||
KF5::NewStuff
|
||||
KF5::QuickAddons
|
||||
KF5::Plasma
|
||||
KF5::PlasmaQuick
|
||||
KF5::WaylandClient
|
||||
KF5::XmlGui
|
||||
)
|
||||
target_link_libraries(latte-dock
|
||||
Qt5::DBus
|
||||
Qt5::Quick
|
||||
Qt5::Qml
|
||||
KF5::Activities
|
||||
KF5::Archive
|
||||
KF5::CoreAddons
|
||||
KF5::Crash
|
||||
KF5::DBusAddons
|
||||
KF5::Declarative
|
||||
KF5::GuiAddons
|
||||
KF5::GlobalAccel
|
||||
KF5::I18n
|
||||
KF5::IconThemes
|
||||
KF5::KIOWidgets
|
||||
KF5::Notifications
|
||||
KF5::NewStuff
|
||||
KF5::QuickAddons
|
||||
KF5::Plasma
|
||||
KF5::PlasmaQuick
|
||||
KF5::WaylandClient
|
||||
KF5::XmlGui
|
||||
Wayland::Client
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
if(HAVE_X11)
|
||||
target_link_libraries(latte-dock
|
||||
@ -122,13 +102,8 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.desktop DESTINATION
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
|
||||
install(FILES dbus/org.kde.LatteDock.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR})
|
||||
install(FILES lattedock.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR})
|
||||
install(FILES latte-layouts.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
|
||||
install(FILES latte-indicators.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
|
||||
|
||||
if(${KF5_VERSION_MINOR} LESS "57")
|
||||
install(FILES latte-layouts.knsrc DESTINATION ${CONFIG_INSTALL_DIR})
|
||||
install(FILES latte-indicators.knsrc DESTINATION ${CONFIG_INSTALL_DIR})
|
||||
else()
|
||||
install(FILES latte-layouts.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
|
||||
install(FILES latte-indicators.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
|
||||
endif()
|
||||
|
||||
add_subdirectory(packageplugins)
|
||||
|
@ -40,6 +40,19 @@ enum LayoutsMemory
|
||||
}
|
||||
}
|
||||
|
||||
namespace Latte {
|
||||
namespace MultipleLayouts {
|
||||
|
||||
enum Status
|
||||
{
|
||||
Uninitialized = -1,
|
||||
Paused,
|
||||
Running
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//! These are LatteApp::Types that will be used from Latte App c++ implementation AND
|
||||
//! Latte containment qml. Such types are irrelevant and not used from plasma applets.
|
||||
|
||||
|
@ -15,7 +15,9 @@ const bool Preferences::BORDERLESSMAXIMIZED;
|
||||
const bool Preferences::ISAVAILABLEGEOMETRYBROADCASTEDTOPLASMA;
|
||||
const bool Preferences::METAPRESSFORAPPLAUNCHER;
|
||||
const bool Preferences::METAHOLDFORBADGES;
|
||||
const int Preferences::PARABOLICSPREAD;
|
||||
const int Preferences::SCREENSDELAY;
|
||||
const float Preferences::THICKNESSMARGININFLUENCE = 1.0f;
|
||||
const Settings::MouseSensitivity Preferences::MOUSESENSITIVITY;
|
||||
|
||||
Preferences::Preferences()
|
||||
@ -32,6 +34,8 @@ Preferences::Preferences(Preferences &&o)
|
||||
metaPressForAppLauncher(o.metaPressForAppLauncher),
|
||||
metaHoldForBadges(o.metaHoldForBadges),
|
||||
mouseSensitivity(o.mouseSensitivity),
|
||||
parabolicSpread(o.parabolicSpread),
|
||||
thicknessMarginInfluence(o.thicknessMarginInfluence),
|
||||
screensDelay(o.screensDelay)
|
||||
{
|
||||
}
|
||||
@ -46,6 +50,8 @@ Preferences::Preferences(const Preferences &o)
|
||||
metaPressForAppLauncher(o.metaPressForAppLauncher),
|
||||
metaHoldForBadges(o.metaHoldForBadges),
|
||||
mouseSensitivity(o.mouseSensitivity),
|
||||
parabolicSpread(o.parabolicSpread),
|
||||
thicknessMarginInfluence(o.thicknessMarginInfluence),
|
||||
screensDelay(o.screensDelay)
|
||||
{
|
||||
}
|
||||
@ -61,6 +67,8 @@ Preferences &Preferences::operator=(const Preferences &rhs)
|
||||
metaPressForAppLauncher = rhs.metaPressForAppLauncher;
|
||||
metaHoldForBadges = rhs.metaHoldForBadges;
|
||||
mouseSensitivity = rhs.mouseSensitivity;
|
||||
parabolicSpread = rhs.parabolicSpread;
|
||||
thicknessMarginInfluence = rhs.thicknessMarginInfluence;
|
||||
screensDelay = rhs.screensDelay;
|
||||
|
||||
return (*this);
|
||||
@ -77,6 +85,8 @@ Preferences &Preferences::operator=(Preferences &&rhs)
|
||||
metaPressForAppLauncher = rhs.metaPressForAppLauncher;
|
||||
metaHoldForBadges = rhs.metaHoldForBadges;
|
||||
mouseSensitivity = rhs.mouseSensitivity;
|
||||
parabolicSpread = rhs.parabolicSpread;
|
||||
thicknessMarginInfluence = rhs.thicknessMarginInfluence;
|
||||
screensDelay = rhs.screensDelay;
|
||||
|
||||
return (*this);
|
||||
@ -93,6 +103,8 @@ bool Preferences::operator==(const Preferences &rhs) const
|
||||
&& (metaPressForAppLauncher == rhs.metaPressForAppLauncher)
|
||||
&& (metaHoldForBadges == rhs.metaHoldForBadges)
|
||||
&& (mouseSensitivity == rhs.mouseSensitivity)
|
||||
&& (parabolicSpread == rhs.parabolicSpread)
|
||||
&& (thicknessMarginInfluence == rhs.thicknessMarginInfluence)
|
||||
&& (screensDelay == rhs.screensDelay);
|
||||
}
|
||||
|
||||
@ -112,6 +124,8 @@ bool Preferences::inDefaultValues() const
|
||||
&& (metaPressForAppLauncher == METAPRESSFORAPPLAUNCHER)
|
||||
&& (metaHoldForBadges == METAHOLDFORBADGES)
|
||||
&& (mouseSensitivity == MOUSESENSITIVITY)
|
||||
&& (parabolicSpread == PARABOLICSPREAD)
|
||||
&& (thicknessMarginInfluence == THICKNESSMARGININFLUENCE)
|
||||
&& (screensDelay == SCREENSDELAY);
|
||||
}
|
||||
|
||||
@ -126,6 +140,8 @@ void Preferences::setToDefaults()
|
||||
metaPressForAppLauncher = METAPRESSFORAPPLAUNCHER;
|
||||
metaHoldForBadges = METAHOLDFORBADGES;
|
||||
mouseSensitivity = MOUSESENSITIVITY;
|
||||
parabolicSpread = PARABOLICSPREAD;
|
||||
thicknessMarginInfluence = THICKNESSMARGININFLUENCE;
|
||||
screensDelay = SCREENSDELAY;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,9 @@ public:
|
||||
static const bool ISAVAILABLEGEOMETRYBROADCASTEDTOPLASMA = true;
|
||||
static const bool METAPRESSFORAPPLAUNCHER = false;
|
||||
static const bool METAHOLDFORBADGES = true;
|
||||
static const int PARABOLICSPREAD = 3;
|
||||
static const int SCREENSDELAY = 2500;
|
||||
static const float THICKNESSMARGININFLUENCE;
|
||||
static const Settings::MouseSensitivity MOUSESENSITIVITY = Settings::HighMouseSensitivity;
|
||||
|
||||
Preferences();
|
||||
@ -41,7 +43,9 @@ public:
|
||||
bool isAvailableGeometryBroadcastedToPlasma{ISAVAILABLEGEOMETRYBROADCASTEDTOPLASMA};
|
||||
bool metaPressForAppLauncher{METAPRESSFORAPPLAUNCHER};
|
||||
bool metaHoldForBadges{METAHOLDFORBADGES};
|
||||
int parabolicSpread{PARABOLICSPREAD};
|
||||
int screensDelay{SCREENSDELAY};
|
||||
float thicknessMarginInfluence{THICKNESSMARGININFLUENCE};
|
||||
QStringList contextMenuAlwaysActions{Data::ContextMenu::ACTIONSALWAYSVISIBLE};
|
||||
Settings::MouseSensitivity mouseSensitivity{MOUSESENSITIVITY};
|
||||
|
||||
|
@ -103,6 +103,12 @@ void Screen::init(const QString &screenId, const QString &serialized)
|
||||
}
|
||||
}
|
||||
|
||||
bool Screen::isScreensGroup() const
|
||||
{
|
||||
int sid = id.toInt();
|
||||
return ((sid == ONALLSCREENSID) || (sid == ONALLSECONDARYSCREENSID));
|
||||
}
|
||||
|
||||
QString Screen::serialize() const
|
||||
{
|
||||
QStringList result;
|
||||
|
@ -23,7 +23,11 @@ class Screen : public Generic
|
||||
public:
|
||||
static constexpr const char* SERIALIZESPLITTER = ":::";
|
||||
static const int ONPRIMARYID = 0;
|
||||
static const int ONALLSCREENSID = -100;
|
||||
static const int ONALLSECONDARYSCREENSID = -101;
|
||||
static constexpr const char* ONPRIMARYNAME = "{primary-screen}";
|
||||
static constexpr const char* ONALLSCREENSNAME = "{all-screens}";
|
||||
static constexpr const char* ONALLSECONDARYSCREENSNAME = "{all-secondary-screens}";
|
||||
|
||||
Screen();
|
||||
Screen(Screen &&o);
|
||||
@ -43,6 +47,8 @@ public:
|
||||
bool operator==(const Screen &rhs) const;
|
||||
bool operator!=(const Screen &rhs) const;
|
||||
|
||||
bool isScreensGroup() const;
|
||||
|
||||
void init(const QString &screenId, const QString &serialized);
|
||||
QString serialize() const;
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
namespace Latte {
|
||||
namespace Data {
|
||||
|
||||
const int View::ISCLONEDNULL = -1;
|
||||
|
||||
View::View()
|
||||
: Generic()
|
||||
{
|
||||
@ -19,8 +21,10 @@ View::View(View &&o)
|
||||
isMoveOrigin(o.isMoveOrigin),
|
||||
isMoveDestination(o.isMoveDestination),
|
||||
onPrimary(o.onPrimary),
|
||||
isClonedFrom(o.isClonedFrom),
|
||||
screen(o.screen),
|
||||
screenEdgeMargin(o.screenEdgeMargin),
|
||||
screensGroup(o.screensGroup),
|
||||
maxLength(o.maxLength),
|
||||
edge(o.edge),
|
||||
alignment(o.alignment),
|
||||
@ -40,8 +44,10 @@ View::View(const View &o)
|
||||
isMoveOrigin(o.isMoveOrigin),
|
||||
isMoveDestination(o.isMoveDestination),
|
||||
onPrimary(o.onPrimary),
|
||||
isClonedFrom(o.isClonedFrom),
|
||||
screen(o.screen),
|
||||
screenEdgeMargin(o.screenEdgeMargin),
|
||||
screensGroup(o.screensGroup),
|
||||
maxLength(o.maxLength),
|
||||
edge(o.edge),
|
||||
alignment(o.alignment),
|
||||
@ -68,8 +74,10 @@ View &View::operator=(const View &rhs)
|
||||
isMoveOrigin = rhs.isMoveOrigin;
|
||||
isMoveDestination = rhs.isMoveDestination;
|
||||
onPrimary = rhs.onPrimary;
|
||||
isClonedFrom = rhs.isClonedFrom;
|
||||
screen = rhs.screen;
|
||||
screenEdgeMargin = rhs.screenEdgeMargin,
|
||||
screenEdgeMargin = rhs.screenEdgeMargin;
|
||||
screensGroup = rhs.screensGroup;
|
||||
maxLength = rhs.maxLength;
|
||||
edge = rhs.edge;
|
||||
alignment = rhs.alignment;
|
||||
@ -93,8 +101,10 @@ View &View::operator=(View &&rhs)
|
||||
isMoveOrigin = rhs.isMoveOrigin;
|
||||
isMoveDestination = rhs.isMoveDestination;
|
||||
onPrimary = rhs.onPrimary;
|
||||
isClonedFrom = rhs.isClonedFrom;
|
||||
screen = rhs.screen;
|
||||
screenEdgeMargin = rhs.screenEdgeMargin,
|
||||
screenEdgeMargin = rhs.screenEdgeMargin;
|
||||
screensGroup = rhs.screensGroup;
|
||||
maxLength = rhs.maxLength;
|
||||
edge = rhs.edge;
|
||||
alignment = rhs.alignment;
|
||||
@ -118,8 +128,10 @@ bool View::operator==(const View &rhs) const
|
||||
//&& (isMoveOrigin == rhs.isMoveOrigin) /*Disabled because this is not needed in order to track view changes for saving*/
|
||||
//&& (isMoveDestination == rhs.isMoveDestination) /*Disabled because this is not needed in order to track view changes for saving*/
|
||||
&& (onPrimary == rhs.onPrimary)
|
||||
&& (isClonedFrom == rhs.isClonedFrom)
|
||||
&& (screen == rhs.screen)
|
||||
&& (screenEdgeMargin == rhs.screenEdgeMargin)
|
||||
&& (screensGroup == rhs.screensGroup)
|
||||
&& (maxLength == rhs.maxLength)
|
||||
&& (edge == rhs.edge)
|
||||
&& (alignment == rhs.alignment)
|
||||
@ -168,6 +180,21 @@ View::operator QString() const
|
||||
}
|
||||
|
||||
result += " : ";
|
||||
if (isCloned()) {
|
||||
result += ("Cloned from:"+ isClonedFrom);
|
||||
} else {
|
||||
result += "Original";
|
||||
}
|
||||
|
||||
result += " : ";
|
||||
if (screensGroup == Latte::Types::SingleScreenGroup) {
|
||||
result += onPrimary ? "Primary" : "Explicit";
|
||||
} else if (screensGroup == Latte::Types::AllScreensGroup) {
|
||||
result += "All Screens";
|
||||
} else if (screensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
result += "All Secondary Screens";
|
||||
}
|
||||
|
||||
result += onPrimary ? "Primary" : "Explicit";
|
||||
result += " : ";
|
||||
result += QString::number(screen);
|
||||
@ -212,6 +239,16 @@ bool View::isCreated() const
|
||||
return m_state == IsCreated;
|
||||
}
|
||||
|
||||
bool View::isOriginal() const
|
||||
{
|
||||
return !isCloned();
|
||||
}
|
||||
|
||||
bool View::isCloned() const
|
||||
{
|
||||
return isClonedFrom != ISCLONEDNULL;
|
||||
}
|
||||
|
||||
bool View::isValid() const
|
||||
{
|
||||
return m_state != IsInvalid;
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
OriginFromLayout /*used from duplicate, copy, move view functions*/
|
||||
};
|
||||
|
||||
static const int ISCLONEDNULL;
|
||||
|
||||
View();
|
||||
View(View &&o);
|
||||
View(const View &o);
|
||||
@ -40,11 +42,13 @@ public:
|
||||
//! View data
|
||||
bool isActive{false};
|
||||
bool onPrimary{true};
|
||||
int isClonedFrom{ISCLONEDNULL};
|
||||
int screen{Latte::ScreenPool::FIRSTSCREENID};
|
||||
int screenEdgeMargin{0};
|
||||
float maxLength{1.0};
|
||||
Plasma::Types::Location edge{Plasma::Types::BottomEdge};
|
||||
Latte::Types::Alignment alignment{Latte::Types::Center};
|
||||
Latte::Types::ScreensGroup screensGroup{Latte::Types::SingleScreenGroup};
|
||||
GenericTable<Data::Generic> subcontainments;
|
||||
|
||||
int errors{0};
|
||||
@ -56,6 +60,8 @@ public:
|
||||
|
||||
bool isValid() const;
|
||||
bool isCreated() const;
|
||||
bool isOriginal() const;
|
||||
bool isCloned() const;
|
||||
bool hasViewTemplateOrigin() const;
|
||||
bool hasLayoutOrigin() const;
|
||||
bool hasSubContainment(const QString &subId) const;
|
||||
|
@ -90,6 +90,19 @@ ViewsTable ViewsTable::subtracted(const ViewsTable &rhs) const
|
||||
return subtract;
|
||||
}
|
||||
|
||||
ViewsTable ViewsTable::onlyOriginals() const
|
||||
{
|
||||
ViewsTable originals;
|
||||
|
||||
for(int i=0; i<m_list.count(); ++i) {
|
||||
if (m_list[i].isOriginal()) {
|
||||
originals << m_list[i];
|
||||
}
|
||||
}
|
||||
|
||||
return originals;
|
||||
}
|
||||
|
||||
void ViewsTable::appendTemporaryView(const Data::View &view)
|
||||
{
|
||||
int maxTempId = 0;
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
bool operator==(const ViewsTable &rhs) const;
|
||||
bool operator!=(const ViewsTable &rhs) const;
|
||||
ViewsTable subtracted(const ViewsTable &rhs) const;
|
||||
ViewsTable onlyOriginals() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
set(lattedock-app_SRCS
|
||||
${lattedock-app_SRCS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contextmenulayerquickitem.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/interfaces.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
515
app/declarativeimports/contextmenulayerquickitem.cpp
Normal file
515
app/declarativeimports/contextmenulayerquickitem.cpp
Normal file
@ -0,0 +1,515 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2022 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "contextmenulayerquickitem.h"
|
||||
|
||||
// local
|
||||
#include "../lattecorona.h"
|
||||
#include "../layouts/storage.h"
|
||||
#include "../view/view.h"
|
||||
|
||||
// Qt
|
||||
#include <QMouseEvent>
|
||||
#include <QVersionNumber>
|
||||
#include <QLatin1String>
|
||||
|
||||
// KDE
|
||||
#include <KAcceleratorManager>
|
||||
#include <KActionCollection>
|
||||
#include <KAuthorized>
|
||||
#include <KLocalizedString>
|
||||
|
||||
// Plasma
|
||||
#include <Plasma/Applet>
|
||||
#include <Plasma/Containment>
|
||||
#include <Plasma/ContainmentActions>
|
||||
#include <Plasma/Corona>
|
||||
#include <PlasmaQuick/AppletQuickItem>
|
||||
|
||||
namespace Latte {
|
||||
|
||||
ContextMenuLayerQuickItem::ContextMenuLayerQuickItem(QQuickItem *parent) :
|
||||
QQuickItem(parent)
|
||||
{
|
||||
setAcceptedMouseButtons(Qt::AllButtons);
|
||||
}
|
||||
|
||||
ContextMenuLayerQuickItem::~ContextMenuLayerQuickItem()
|
||||
{
|
||||
}
|
||||
|
||||
bool ContextMenuLayerQuickItem::menuIsShown() const
|
||||
{
|
||||
return m_contextMenu != nullptr;
|
||||
}
|
||||
|
||||
QObject *ContextMenuLayerQuickItem::view() const
|
||||
{
|
||||
return m_latteView;
|
||||
}
|
||||
|
||||
void ContextMenuLayerQuickItem::setView(QObject *view)
|
||||
{
|
||||
if (m_latteView == view) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_latteView = qobject_cast<Latte::View *>(view);
|
||||
emit viewChanged();
|
||||
}
|
||||
|
||||
void ContextMenuLayerQuickItem::onMenuAboutToHide()
|
||||
{
|
||||
if (!m_latteView) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_latteView->containment()->setStatus(m_lastContainmentStatus);
|
||||
m_contextMenu = nullptr;
|
||||
emit menuChanged();
|
||||
}
|
||||
|
||||
QPoint ContextMenuLayerQuickItem::popUpRelevantToParent(const QRect &parentItem, const QRect popUpRect)
|
||||
{
|
||||
QPoint resultPoint;
|
||||
|
||||
if (!m_latteView) {
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
resultPoint.setX(parentItem.left());
|
||||
resultPoint.setY(parentItem.bottom());
|
||||
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
resultPoint.setX(parentItem.left());
|
||||
resultPoint.setY(parentItem.top() - popUpRect.height() - 1);
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
resultPoint.setX(parentItem.right());
|
||||
resultPoint.setY(parentItem.top());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
resultPoint.setX(parentItem.left() - popUpRect.width());
|
||||
resultPoint.setY(parentItem.top());
|
||||
}
|
||||
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
QPoint ContextMenuLayerQuickItem::popUpRelevantToGlobalPoint(const QRect &parentItem, const QRect popUpRect)
|
||||
{
|
||||
QPoint resultPoint;
|
||||
|
||||
if (!m_latteView) {
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
resultPoint.setX(popUpRect.x());
|
||||
resultPoint.setY(popUpRect.y() + 1);
|
||||
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
resultPoint.setX(popUpRect.x());
|
||||
resultPoint.setY(popUpRect.y() - popUpRect.height() - 1);
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
resultPoint.setX(popUpRect.x() + 1);
|
||||
resultPoint.setY(popUpRect.y());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
resultPoint.setX(popUpRect.x() - popUpRect.width() - 1);
|
||||
resultPoint.setY(popUpRect.y());
|
||||
}
|
||||
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
QPoint ContextMenuLayerQuickItem::popUpTopLeft(Plasma::Applet *applet, const QRect popUpRect)
|
||||
{
|
||||
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
QRect globalItemRect = m_latteView->absoluteGeometry();
|
||||
|
||||
if (ai && applet != m_latteView->containment()) {
|
||||
QPointF appletGlobalTopLeft = ai->mapToGlobal(QPointF(ai->x(), ai->y()));
|
||||
globalItemRect = QRect(appletGlobalTopLeft.x(), appletGlobalTopLeft.y(), ai->width(), ai->height());
|
||||
}
|
||||
|
||||
int itemLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? globalItemRect.width() : globalItemRect.height());
|
||||
int menuLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? popUpRect.width() : popUpRect.height());
|
||||
|
||||
if ((itemLength > menuLength)
|
||||
|| (applet == m_latteView->containment())
|
||||
|| (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->corona(), applet)) ) {
|
||||
return popUpRelevantToGlobalPoint(globalItemRect, popUpRect);
|
||||
} else {
|
||||
return popUpRelevantToParent(globalItemRect, popUpRect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ContextMenuLayerQuickItem::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (!event || !m_latteView) {
|
||||
return;
|
||||
}
|
||||
|
||||
event->setAccepted(m_latteView->containment()->containmentActions().contains(Plasma::ContainmentActions::eventToString(event)));
|
||||
emit menuChanged();
|
||||
}
|
||||
|
||||
void ContextMenuLayerQuickItem::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
//qDebug() << "Step -1 ...";
|
||||
|
||||
if (!event || !m_latteView || !m_latteView->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//qDebug() << "Step 0...";
|
||||
|
||||
//even if the menu is executed synchronously, other events may be processed
|
||||
//by the qml incubator when plasma is loading, so we need to guard there
|
||||
if (m_contextMenu) {
|
||||
//qDebug() << "Step 0.5 ...";
|
||||
m_contextMenu->close();
|
||||
m_contextMenu = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
//qDebug() << "1 ...";
|
||||
const QString trigger = Plasma::ContainmentActions::eventToString(event);
|
||||
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
|
||||
|
||||
if (!plugin || plugin->contextualActions().isEmpty()) {
|
||||
event->setAccepted(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// the plugin can be a single action or a context menu
|
||||
// Don't have an action list? execute as single action
|
||||
// and set the event position as action data
|
||||
if (plugin->contextualActions().length() == 1) {
|
||||
QAction *action = plugin->contextualActions().at(0);
|
||||
action->setData(event->pos());
|
||||
action->trigger();
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
//qDebug() << "2 ...";
|
||||
//the plugin can be a single action or a context menu
|
||||
//Don't have an action list? execute as single action
|
||||
//and set the event position as action data
|
||||
/*if (plugin->contextualActions().length() == 1) {
|
||||
QAction *action = plugin->contextualActions().at(0);
|
||||
action->setData(event->pos());
|
||||
action->trigger();
|
||||
event->accept();
|
||||
return;
|
||||
}*/
|
||||
//FIXME: very inefficient appletAt() implementation
|
||||
Plasma::Applet *applet = 0;
|
||||
|
||||
//! initialize the appletContainsMethod on the first right click
|
||||
if (!m_appletContainsMethod.isValid()) {
|
||||
updateAppletContainsMethod();
|
||||
}
|
||||
|
||||
for (const Plasma::Applet *appletTemp : m_latteView->containment()->applets()) {
|
||||
PlasmaQuick::AppletQuickItem *ai = appletTemp->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
bool appletContainsMouse = false;
|
||||
|
||||
if (m_appletContainsMethod.isValid()) {
|
||||
QVariant retVal;
|
||||
m_appletContainsMethod.invoke(m_appletContainsMethodItem, Qt::DirectConnection, Q_RETURN_ARG(QVariant, retVal)
|
||||
, Q_ARG(QVariant, appletTemp->id()), Q_ARG(QVariant, event->pos()));
|
||||
appletContainsMouse = retVal.toBool();
|
||||
} else {
|
||||
appletContainsMouse = ai->contains(ai->mapFromItem(this, event->pos()));
|
||||
}
|
||||
|
||||
if (ai && ai->isVisible() && appletContainsMouse) {
|
||||
applet = ai->applet();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!applet) {
|
||||
applet = m_latteView->containment();
|
||||
}
|
||||
|
||||
//qDebug() << "3 ...";
|
||||
|
||||
QMenu *desktopMenu = new QMenu;
|
||||
|
||||
//this is a workaround where Qt now creates the menu widget
|
||||
//in .exec before oxygen can polish it and set the following attribute
|
||||
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
|
||||
//end workaround
|
||||
|
||||
if (desktopMenu->winId()) {
|
||||
desktopMenu->windowHandle()->setTransientParent(window());
|
||||
}
|
||||
|
||||
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_contextMenu = desktopMenu;
|
||||
emit menuChanged();
|
||||
|
||||
//end workaround
|
||||
//!end of plasma official code(workaround)
|
||||
|
||||
//qDebug() << "5 ...";
|
||||
|
||||
emit m_latteView->containment()->contextualActionsAboutToShow();
|
||||
|
||||
if (applet && applet != m_latteView->containment()) {
|
||||
//qDebug() << "5.3 ...";
|
||||
emit applet->contextualActionsAboutToShow();
|
||||
addAppletActions(desktopMenu, applet, event);
|
||||
} else {
|
||||
//qDebug() << "5.6 ...";
|
||||
addContainmentActions(desktopMenu, event);
|
||||
}
|
||||
|
||||
//!plasma official code
|
||||
//this is a workaround where Qt will fail to realize a mouse has been released
|
||||
|
||||
// this happens if a window which does not accept focus spawns a new window that takes focus and X grab
|
||||
// whilst the mouse is depressed
|
||||
// https://bugreports.qt.io/browse/QTBUG-59044
|
||||
// this causes the next click to go missing
|
||||
|
||||
//by releasing manually we avoid that situation
|
||||
auto ungrabMouseHack = [this]() {
|
||||
if (window() && window()->mouseGrabberItem()) {
|
||||
window()->mouseGrabberItem()->ungrabMouse();
|
||||
}
|
||||
};
|
||||
|
||||
//post 5.8.0 QQuickWindow code is sendEvent(item, mouseEvent); item->grabMouse()
|
||||
QTimer::singleShot(0, this, ungrabMouseHack);
|
||||
|
||||
//this is a workaround where Qt now creates the menu widget
|
||||
//in .exec before oxygen can polish it and set the following attribute
|
||||
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
|
||||
//end workaround
|
||||
QPoint globalPos = event->globalPos();
|
||||
desktopMenu->adjustSize();
|
||||
|
||||
QRect popUpRect(globalPos.x(), globalPos.y(), desktopMenu->width(), desktopMenu->height());
|
||||
|
||||
if (applet) {
|
||||
globalPos = popUpTopLeft(applet, popUpRect);
|
||||
} else {
|
||||
globalPos = popUpRelevantToGlobalPoint(QRect(0,0,0,0), popUpRect);
|
||||
}
|
||||
|
||||
//qDebug() << "7...";
|
||||
|
||||
if (desktopMenu->isEmpty()) {
|
||||
//qDebug() << "7.5 ...";
|
||||
delete desktopMenu;
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
// Bug 344205 keep panel visible while menu is open
|
||||
m_lastContainmentStatus = m_latteView->containment()->status();
|
||||
m_latteView->containment()->setStatus(Plasma::Types::RequiresAttentionStatus);
|
||||
|
||||
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(onMenuAboutToHide()));
|
||||
|
||||
KAcceleratorManager::manage(desktopMenu);
|
||||
|
||||
for (auto action : desktopMenu->actions()) {
|
||||
if (action->menu()) {
|
||||
connect(action->menu(), &QMenu::aboutToShow, desktopMenu, [action, desktopMenu] {
|
||||
if (action->menu()->windowHandle()) {
|
||||
// Need to add the transient parent otherwise Qt will create a new toplevel
|
||||
action->menu()->windowHandle()->setTransientParent(desktopMenu->windowHandle());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//qDebug() << "8 ...";
|
||||
desktopMenu->popup(globalPos);
|
||||
event->setAccepted(true);
|
||||
}
|
||||
|
||||
//! update the appletContainsPos method from Panel view
|
||||
void ContextMenuLayerQuickItem::updateAppletContainsMethod()
|
||||
{
|
||||
if (!m_latteView) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (QQuickItem *item : m_latteView->contentItem()->childItems()) {
|
||||
if (auto *metaObject = item->metaObject()) {
|
||||
// not using QMetaObject::invokeMethod to avoid warnings when calling
|
||||
// this on applets that don't have it or other child items since this
|
||||
// is pretty much trial and error.
|
||||
// Also, "var" arguments are treated as QVariant in QMetaObject
|
||||
|
||||
int methodIndex = metaObject->indexOfMethod("appletContainsPos(QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_appletContainsMethod = metaObject->method(methodIndex);
|
||||
m_appletContainsMethodItem = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContextMenuLayerQuickItem::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event)
|
||||
{
|
||||
if (!m_latteView || !m_latteView->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
desktopMenu->addSection(applet->pluginMetaData().name());
|
||||
|
||||
for (QAction *action : applet->contextualActions()) {
|
||||
if (action) {
|
||||
desktopMenu->addAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
if (!applet->failedToLaunch()) {
|
||||
QAction *runAssociatedApplication = applet->actions()->action(QStringLiteral("run associated application"));
|
||||
|
||||
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
|
||||
desktopMenu->addAction(runAssociatedApplication);
|
||||
}
|
||||
|
||||
QAction *configureApplet = applet->actions()->action(QStringLiteral("configure"));
|
||||
|
||||
if (configureApplet && configureApplet->isEnabled()) {
|
||||
desktopMenu->addAction(configureApplet);
|
||||
}
|
||||
|
||||
QAction *appletAlternatives = applet->actions()->action(QStringLiteral("alternatives"));
|
||||
|
||||
if (appletAlternatives && appletAlternatives->isEnabled() && m_latteView->containment()->isUserConfiguring()) {
|
||||
desktopMenu->addAction(appletAlternatives);
|
||||
}
|
||||
}
|
||||
|
||||
QAction *containmentAction = desktopMenu->menuAction();
|
||||
containmentAction->setText(i18nc("%1 is the name of the containment", "%1 Options", m_latteView->containment()->title()));
|
||||
|
||||
if (desktopMenu->actions().count()>1) { /*take into account the Applet Name Section*/
|
||||
addContainmentActions(containmentAction->menu(), event);
|
||||
}
|
||||
|
||||
if (!containmentAction->menu()->isEmpty()) {
|
||||
int enabled = 0;
|
||||
//count number of real actions
|
||||
QListIterator<QAction *> actionsIt(containmentAction->menu()->actions());
|
||||
|
||||
while (enabled < 3 && actionsIt.hasNext()) {
|
||||
QAction *action = actionsIt.next();
|
||||
|
||||
if (action->isVisible() && !action->isSeparator()) {
|
||||
++enabled;
|
||||
}
|
||||
}
|
||||
|
||||
desktopMenu->addSeparator();
|
||||
|
||||
if (enabled) {
|
||||
//if there is only one, don't create a submenu
|
||||
// if (enabled < 2) {
|
||||
for (QAction *action : containmentAction->menu()->actions()) {
|
||||
if (action && action->isVisible()) {
|
||||
desktopMenu->addAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
// } else {
|
||||
// desktopMenu->addMenu(containmentMenu);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
if (m_latteView->containment()->immutability() == Plasma::Types::Mutable &&
|
||||
(m_latteView->containment()->containmentType() != Plasma::Types::PanelContainment || m_latteView->containment()->isUserConfiguring())) {
|
||||
QAction *closeApplet = applet->actions()->action(QStringLiteral("remove"));
|
||||
|
||||
//qDebug() << "checking for removal" << closeApplet;
|
||||
if (closeApplet) {
|
||||
if (!desktopMenu->isEmpty()) {
|
||||
desktopMenu->addSeparator();
|
||||
}
|
||||
|
||||
//qDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
|
||||
desktopMenu->addAction(closeApplet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContextMenuLayerQuickItem::addContainmentActions(QMenu *desktopMenu, QEvent *event)
|
||||
{
|
||||
if (!m_latteView || !m_latteView->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_latteView->containment()->corona()->immutability() != Plasma::Types::Mutable &&
|
||||
!KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) {
|
||||
//qDebug() << "immutability";
|
||||
return;
|
||||
}
|
||||
|
||||
//this is what ContainmentPrivate::prepareContainmentActions was
|
||||
const QString trigger = Plasma::ContainmentActions::eventToString(event);
|
||||
//"RightButton;NoModifier"
|
||||
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
|
||||
|
||||
if (!plugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin->containment() != m_latteView->containment()) {
|
||||
plugin->setContainment(m_latteView->containment());
|
||||
// now configure it
|
||||
KConfigGroup cfg(m_latteView->containment()->corona()->config(), "ActionPlugins");
|
||||
cfg = KConfigGroup(&cfg, QString::number(m_latteView->containment()->containmentType()));
|
||||
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
|
||||
plugin->restore(pluginConfig);
|
||||
}
|
||||
|
||||
QList<QAction *> actions = plugin->contextualActions();
|
||||
|
||||
/* for (const QAction *act : actions) {
|
||||
if (act->menu()) {
|
||||
//this is a workaround where Qt now creates the menu widget
|
||||
//in .exec before oxygen can polish it and set the following attribute
|
||||
act->menu()->setAttribute(Qt::WA_TranslucentBackground);
|
||||
//end workaround
|
||||
|
||||
if (act->menu()->winId()) {
|
||||
act->menu()->windowHandle()->setTransientParent(m_latteView);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
desktopMenu->addActions(actions);
|
||||
}
|
||||
|
||||
Plasma::Containment *ContextMenuLayerQuickItem::containmentById(uint id)
|
||||
{
|
||||
if (!m_latteView) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const auto containment : m_latteView->corona()->containments()) {
|
||||
if (id == containment->id()) {
|
||||
return containment;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2018 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-FileCopyrightText: 2022 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef CONTEXTMENU_H
|
||||
#define CONTEXTMENU_H
|
||||
#ifndef CONTEXTMENULAYERQUICKITEM_H
|
||||
#define CONTEXTMENULAYERQUICKITEM_H
|
||||
|
||||
// Qt
|
||||
#include <QEvent>
|
||||
@ -16,9 +16,13 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QObject>
|
||||
|
||||
// Plasma
|
||||
#include <Plasma>
|
||||
|
||||
namespace Plasma {
|
||||
class Applet;
|
||||
class Containment;
|
||||
class Types;
|
||||
}
|
||||
|
||||
namespace Latte {
|
||||
@ -26,26 +30,32 @@ class View;
|
||||
}
|
||||
|
||||
namespace Latte {
|
||||
namespace ViewPart {
|
||||
|
||||
class ContextMenu : public QObject
|
||||
class ContextMenuLayerQuickItem : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool menuIsShown READ menuIsShown NOTIFY menuChanged)
|
||||
Q_PROPERTY(QObject *view READ view WRITE setView NOTIFY viewChanged)
|
||||
|
||||
public:
|
||||
ContextMenu(Latte::View *view);
|
||||
~ContextMenu() override;
|
||||
ContextMenuLayerQuickItem(QQuickItem *parent = nullptr);
|
||||
~ContextMenuLayerQuickItem() override;
|
||||
|
||||
QMenu *menu();
|
||||
QObject *view() const;
|
||||
void setView(QObject *view);
|
||||
|
||||
bool mousePressEvent(QMouseEvent *event);
|
||||
bool mousePressEventForContainmentMenu(QQuickView *view, QMouseEvent *event);
|
||||
bool menuIsShown() const;
|
||||
|
||||
signals:
|
||||
void menuChanged();
|
||||
void viewChanged();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void menuAboutToHide();
|
||||
void onMenuAboutToHide();
|
||||
|
||||
private:
|
||||
void addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event);
|
||||
@ -61,16 +71,17 @@ private:
|
||||
|
||||
|
||||
private:
|
||||
Plasma::Types::ItemStatus m_lastContainmentStatus;
|
||||
|
||||
QPointer<QMenu> m_contextMenu;
|
||||
QMetaMethod m_appletContainsMethod;
|
||||
QQuickItem *m_appletContainsMethodItem{nullptr};
|
||||
|
||||
Latte::View *m_latteView;
|
||||
Latte::View *m_latteView{nullptr};
|
||||
|
||||
friend class Latte::View;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DOCKMENUMANAGER_H
|
@ -29,7 +29,7 @@
|
||||
#include <KArchive/KZip>
|
||||
#include <KArchive/KArchiveEntry>
|
||||
#include <KArchive/KArchiveDirectory>
|
||||
#include <KNewStuff3/KNS3/DownloadDialog>
|
||||
#include <KNewStuff3/KNS3/QtQuickDialogWrapper>
|
||||
|
||||
namespace Latte {
|
||||
namespace Indicator {
|
||||
@ -115,10 +115,10 @@ void Factory::reload(const QString &indicatorPath)
|
||||
QString pluginChangedId;
|
||||
|
||||
if (!indicatorPath.isEmpty() && indicatorPath != "." && indicatorPath != "..") {
|
||||
QString metadataFile = indicatorPath + "/metadata.desktop";
|
||||
QString metadataFile = metadataFileAbsolutePath(indicatorPath);
|
||||
|
||||
if(QFileInfo(metadataFile).exists()) {
|
||||
KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(metadataFile);
|
||||
KPluginMetaData metadata = KPluginMetaData(metadataFile);
|
||||
|
||||
if (metadataAreValid(metadata)) {
|
||||
pluginChangedId = metadata.pluginId();
|
||||
@ -244,7 +244,7 @@ bool Factory::metadataAreValid(KPluginMetaData &metadata)
|
||||
bool Factory::metadataAreValid(QString &file)
|
||||
{
|
||||
if (QFileInfo(file).exists()) {
|
||||
KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(file);
|
||||
KPluginMetaData metadata(file);
|
||||
return metadata.isValid();
|
||||
}
|
||||
|
||||
@ -260,6 +260,23 @@ QString Factory::uiPath(QString pluginName) const
|
||||
return m_pluginUiPaths[pluginName];
|
||||
}
|
||||
|
||||
QString Factory::metadataFileAbsolutePath(const QString &directoryPath)
|
||||
{
|
||||
QString metadataFile = directoryPath + "/metadata.json";
|
||||
|
||||
if(QFileInfo(metadataFile).exists()) {
|
||||
return metadataFile;
|
||||
}
|
||||
|
||||
metadataFile = directoryPath + "/metadata.desktop";
|
||||
|
||||
if(QFileInfo(metadataFile).exists()) {
|
||||
return metadataFile;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
|
||||
{
|
||||
auto showNotificationError = []() {
|
||||
@ -303,7 +320,7 @@ Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
|
||||
|
||||
//metadata file
|
||||
QString packagePath = archiveTempDir.path();
|
||||
QString metadataFile = archiveTempDir.path() + "/metadata.desktop";
|
||||
QString metadataFile = metadataFileAbsolutePath(archiveTempDir.path());
|
||||
|
||||
if (!QFileInfo(metadataFile).exists()){
|
||||
QDirIterator iter(archiveTempDir.path(), QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@ -311,7 +328,7 @@ Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
|
||||
while(iter.hasNext() ) {
|
||||
QString currentPath = iter.next();
|
||||
|
||||
QString tempMetadata = currentPath + "/metadata.desktop";
|
||||
QString tempMetadata = metadataFileAbsolutePath(currentPath);
|
||||
|
||||
if (QFileInfo(tempMetadata).exists()) {
|
||||
metadataFile = tempMetadata;
|
||||
@ -320,7 +337,7 @@ Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
|
||||
}
|
||||
}
|
||||
|
||||
KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(metadataFile);
|
||||
KPluginMetaData metadata = KPluginMetaData(metadataFile);
|
||||
|
||||
if (metadataAreValid(metadata)) {
|
||||
QStringList standardPaths = Latte::Layouts::Importer::standardPaths();
|
||||
@ -387,8 +404,7 @@ void Factory::removeIndicator(QString id)
|
||||
|
||||
void Factory::downloadIndicator()
|
||||
{
|
||||
KNS3::DownloadDialog dialog(QStringLiteral("latte-indicators.knsrc"), m_parentWidget);
|
||||
|
||||
KNS3::QtQuickDialogWrapper dialog(QStringLiteral("latte-indicators.knsrc"), m_parentWidget);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
|
||||
QString uiPath(QString pluginName) const;
|
||||
|
||||
static QString metadataFileAbsolutePath(const QString &directoryPath);
|
||||
|
||||
//! metadata record
|
||||
static bool metadataAreValid(KPluginMetaData &metadata);
|
||||
//! metadata file
|
||||
|
@ -80,12 +80,8 @@ void InfoView::init()
|
||||
KDeclarative::KDeclarative kdeclarative;
|
||||
kdeclarative.setDeclarativeEngine(engine());
|
||||
kdeclarative.setTranslationDomain(QStringLiteral("latte-dock"));
|
||||
#if KF5_VERSION_MINOR >= 45
|
||||
kdeclarative.setupContext();
|
||||
kdeclarative.setupEngine(engine());
|
||||
#else
|
||||
kdeclarative.setupBindings();
|
||||
#endif
|
||||
|
||||
auto source = QUrl::fromLocalFile(m_corona->kPackage().filePath("infoviewui"));
|
||||
setSource(source);
|
||||
|
@ -32,7 +32,7 @@ class InfoView : public QQuickView
|
||||
Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged)
|
||||
|
||||
public:
|
||||
InfoView(Latte::Corona *corona, QString message, QScreen *screen = qGuiApp->primaryScreen(), QWindow *parent = nullptr);
|
||||
InfoView(Latte::Corona *corona, QString message, QScreen *screen, QWindow *parent = nullptr);
|
||||
~InfoView() override;
|
||||
|
||||
QString validTitle() const;
|
||||
|
@ -1,11 +1,13 @@
|
||||
[KNewStuff3]
|
||||
Name=Latte Indicators
|
||||
Name[ar]=مؤشرات لاتيه
|
||||
Name[az]=Latte İndikatorları
|
||||
Name[ca]=Indicadors del Latte
|
||||
Name[ca@valencia]=Indicadors del Latte
|
||||
Name[ca@valencia]=Indicadors de Latte
|
||||
Name[cs]=Ukazatele Latte
|
||||
Name[el]=Δείκτες Latte
|
||||
Name[en_GB]=Latte Indicators
|
||||
Name[eo]=Latte Indikiloj
|
||||
Name[es]=Indicadores de Latte
|
||||
Name[et]=Latte indikaatorid
|
||||
Name[eu]=Latte adierazleak
|
||||
@ -15,6 +17,8 @@ Name[gl]=Indicadores de Latte
|
||||
Name[hsb]=Latte pokazowaki
|
||||
Name[id]=Indikator Latte
|
||||
Name[it]=Indicatori Latte
|
||||
Name[ja]=Latte インジケータ
|
||||
Name[ka]=Latte -ის ინდიკატორები
|
||||
Name[ko]=Latte 표시기
|
||||
Name[lt]=Latte indikatoriai
|
||||
Name[nl]=Indicatoren van Latte
|
||||
@ -26,6 +30,7 @@ Name[ru]=Индикаторы Latte
|
||||
Name[sk]=Indikátory Latte
|
||||
Name[sl]=Kazalniki Latte
|
||||
Name[sv]=Latte indikatorer
|
||||
Name[tr]=Latte Göstergeleri
|
||||
Name[uk]=Індикатори Латте
|
||||
Name[x-test]=xxLatte Indicatorsxx
|
||||
Name[zh_CN]=Latte 指示器
|
||||
@ -34,5 +39,5 @@ Name[zh_TW]=Latte 指示器
|
||||
ProvidersUrl=https://autoconfig.kde.org/ocs/providers.xml
|
||||
Categories=Latte Indicators
|
||||
StandardResource=tmp
|
||||
InstallationCommand=kpackagetool5 --install %f --type Latte/Indicator
|
||||
UninstallCommand=kpackagetool5 --remove %f --type Latte/Indicator
|
||||
Uncompress=kpackage
|
||||
KPackageType=Latte/Indicator
|
||||
|
@ -3,11 +3,12 @@ Name=Latte Layouts
|
||||
Name[ar]=مخطّطات لاتيه
|
||||
Name[az]=Latte Maketləri
|
||||
Name[ca]=Disposicions del Latte
|
||||
Name[ca@valencia]=Disposicions del Latte
|
||||
Name[cs]=Rozložení Latte
|
||||
Name[ca@valencia]=Disposicions de Latte
|
||||
Name[cs]=Rozvržení Latte
|
||||
Name[de]=Latte-Profile
|
||||
Name[el]=Προφίλ Latte
|
||||
Name[en_GB]=Latte Layouts
|
||||
Name[eo]=Latteaj Aranĝoj
|
||||
Name[es]=Distribuciones de Latte
|
||||
Name[et]=Latte paigutused
|
||||
Name[eu]=Latte antolamenduak
|
||||
@ -17,6 +18,8 @@ Name[gl]=Disposicións de Latte
|
||||
Name[hsb]=Latte layouty
|
||||
Name[id]=Tataletak Latte
|
||||
Name[it]=Disposizioni di Latte
|
||||
Name[ja]=Latte レイアウト
|
||||
Name[ka]=Latte -ის განლაგებები
|
||||
Name[ko]=Latte 레이아웃
|
||||
Name[lt]=Latte išdėstymai
|
||||
Name[nl]=Latte-indelingen
|
||||
@ -28,10 +31,11 @@ Name[ru]=Макеты Latte
|
||||
Name[sk]=Rozloženia Latte
|
||||
Name[sl]=Postavitve Latte
|
||||
Name[sv]=Latte layouter
|
||||
Name[tr]=Latte Yerleşimleri
|
||||
Name[uk]=Компонування Латте
|
||||
Name[x-test]=xxLatte Layoutsxx
|
||||
Name[zh_CN]=Latte 布局
|
||||
Name[zh_TW]=Latte 版面
|
||||
Name[zh_TW]=Latte 佈局
|
||||
|
||||
ProvidersUrl=https://autoconfig.kde.org/ocs/providers.xml
|
||||
Categories=Latte Layouts
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "data/generictable.h"
|
||||
#include "data/layouticondata.h"
|
||||
#include "declarativeimports/interfaces.h"
|
||||
#include "declarativeimports/contextmenulayerquickitem.h"
|
||||
#include "indicator/factory.h"
|
||||
#include "layout/abstractlayout.h"
|
||||
#include "layout/centrallayout.h"
|
||||
@ -32,6 +33,7 @@
|
||||
#include "plasma/extended/theme.h"
|
||||
#include "settings/universalsettings.h"
|
||||
#include "templates/templatesmanager.h"
|
||||
#include "view/originalview.h"
|
||||
#include "view/view.h"
|
||||
#include "view/settings/viewsettingsfactory.h"
|
||||
#include "view/windowstracker/windowstracker.h"
|
||||
@ -206,6 +208,10 @@ void Corona::onAboutToQuit()
|
||||
cleanConfig();
|
||||
}
|
||||
|
||||
if (m_layoutsManager->memoryUsage() == Latte::MemoryUsage::MultipleLayouts) {
|
||||
m_layoutsManager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Paused);
|
||||
}
|
||||
|
||||
qDebug() << "Latte Corona - unload: containments ...";
|
||||
m_layoutsManager->unload();
|
||||
}
|
||||
@ -220,10 +226,9 @@ void Corona::load()
|
||||
m_templatesManager->init();
|
||||
m_layoutsManager->init();
|
||||
|
||||
connect(this, &Corona::availableScreenRectChangedFrom, this, &Plasma::Corona::availableScreenRectChanged);
|
||||
connect(this, &Corona::availableScreenRegionChangedFrom, this, &Plasma::Corona::availableScreenRegionChanged);
|
||||
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &Corona::primaryOutputChanged, Qt::UniqueConnection);
|
||||
connect(m_screenPool, &ScreenPool::primaryPoolChanged, this, &Corona::screenCountChanged);
|
||||
connect(this, &Corona::availableScreenRectChangedFrom, this, &Plasma::Corona::availableScreenRectChanged, Qt::UniqueConnection);
|
||||
connect(this, &Corona::availableScreenRegionChangedFrom, this, &Plasma::Corona::availableScreenRegionChanged, Qt::UniqueConnection);
|
||||
connect(m_screenPool, &ScreenPool::primaryScreenChanged, this, &Corona::onScreenCountChanged, Qt::UniqueConnection);
|
||||
|
||||
QString loadLayoutName = "";
|
||||
|
||||
@ -265,7 +270,7 @@ void Corona::load()
|
||||
//! load screens signals such screenGeometryChanged in order to support
|
||||
//! plasmoid.screenGeometry properly
|
||||
for (QScreen *screen : qGuiApp->screens()) {
|
||||
addOutput(screen);
|
||||
onScreenAdded(screen);
|
||||
}
|
||||
|
||||
connect(m_layoutsManager->synchronizer(), &Layouts::Synchronizer::initializationFinished, [this]() {
|
||||
@ -279,8 +284,8 @@ void Corona::load()
|
||||
|
||||
m_inStartup = false;
|
||||
|
||||
connect(qGuiApp, &QGuiApplication::screenAdded, this, &Corona::addOutput, Qt::UniqueConnection);
|
||||
connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Corona::screenRemoved, Qt::UniqueConnection);
|
||||
connect(qGuiApp, &QGuiApplication::screenAdded, this, &Corona::onScreenAdded, Qt::UniqueConnection);
|
||||
connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Corona::onScreenRemoved, Qt::UniqueConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,7 +333,7 @@ void Corona::setupWaylandIntegration()
|
||||
}
|
||||
});
|
||||
|
||||
#if KF5_VERSION_MINOR >= 52
|
||||
|
||||
QObject::connect(registry, &KWayland::Client::Registry::plasmaVirtualDesktopManagementAnnounced,
|
||||
[this, registry] (quint32 name, quint32 version) {
|
||||
KWayland::Client::PlasmaVirtualDesktopManagement *vdm = registry->createPlasmaVirtualDesktopManagement(name, version, this);
|
||||
@ -339,7 +344,7 @@ void Corona::setupWaylandIntegration()
|
||||
wI->initVirtualDesktopManagement(vdm);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
|
||||
registry->setup();
|
||||
connection->roundtrip();
|
||||
@ -489,7 +494,7 @@ int Corona::numScreens() const
|
||||
QRect Corona::screenGeometry(int id) const
|
||||
{
|
||||
const auto screens = qGuiApp->screens();
|
||||
const QScreen *screen{qGuiApp->primaryScreen()};
|
||||
const QScreen *screen{m_screenPool->primaryScreen()};
|
||||
|
||||
QString screenName;
|
||||
|
||||
@ -583,7 +588,9 @@ QRegion Corona::availableScreenRegionWithCriteria(int id,
|
||||
bool allEdges = ignoreEdges.isEmpty();
|
||||
|
||||
for (const auto *view : views) {
|
||||
if (view && view->containment() && view->screen() == screen
|
||||
bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen();
|
||||
|
||||
if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup
|
||||
&& ((allEdges || !ignoreEdges.contains(view->location()))
|
||||
&& (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) {
|
||||
int realThickness = view->normalThickness();
|
||||
@ -606,11 +613,11 @@ QRegion Corona::availableScreenRegionWithCriteria(int id,
|
||||
|
||||
case Latte::Types::Center:
|
||||
case Latte::Types::Justify:
|
||||
x = (view->geometry().center().x() - w/2) + offsetW;
|
||||
x = (view->geometry().center().x() - w/2) + 1 + offsetW;
|
||||
break;
|
||||
|
||||
case Latte::Types::Right:
|
||||
x = view->geometry().right() - w - offsetW;
|
||||
x = view->geometry().right() + 1 - w - offsetW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -630,7 +637,7 @@ QRegion Corona::availableScreenRegionWithCriteria(int id,
|
||||
|
||||
case Latte::Types::Center:
|
||||
case Latte::Types::Justify:
|
||||
y = (view->geometry().center().y() - h/2) + offsetH;
|
||||
y = (view->geometry().center().y() - h/2) + 1 + offsetH;
|
||||
break;
|
||||
|
||||
case Latte::Types::Bottom:
|
||||
@ -785,7 +792,9 @@ QRect Corona::availableScreenRectWithCriteria(int id,
|
||||
bool allEdges = ignoreEdges.isEmpty();
|
||||
|
||||
for (const auto *view : views) {
|
||||
if (view && view->containment() && view->screen() == screen
|
||||
bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen();
|
||||
|
||||
if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup
|
||||
&& ((allEdges || !ignoreEdges.contains(view->location()))
|
||||
&& (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) {
|
||||
|
||||
@ -842,7 +851,7 @@ QRect Corona::availableScreenRectWithCriteria(int id,
|
||||
return available;
|
||||
}
|
||||
|
||||
void Corona::addOutput(QScreen *screen)
|
||||
void Corona::onScreenAdded(QScreen *screen)
|
||||
{
|
||||
Q_ASSERT(screen);
|
||||
|
||||
@ -852,35 +861,42 @@ void Corona::addOutput(QScreen *screen)
|
||||
m_screenPool->insertScreenMapping(screen->name());
|
||||
}
|
||||
|
||||
connect(screen, &QScreen::geometryChanged, this, [ = ]() {
|
||||
const int id = m_screenPool->id(screen->name());
|
||||
|
||||
if (id >= 0) {
|
||||
emit screenGeometryChanged(id);
|
||||
emit availableScreenRegionChanged();
|
||||
emit availableScreenRectChanged();
|
||||
}
|
||||
});
|
||||
connect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged);
|
||||
|
||||
emit availableScreenRectChanged();
|
||||
emit screenAdded(m_screenPool->id(screen->name()));
|
||||
|
||||
screenCountChanged();
|
||||
onScreenCountChanged();
|
||||
}
|
||||
|
||||
void Corona::primaryOutputChanged()
|
||||
void Corona::onScreenRemoved(QScreen *screen)
|
||||
{
|
||||
disconnect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged);
|
||||
onScreenCountChanged();
|
||||
}
|
||||
|
||||
void Corona::onScreenCountChanged()
|
||||
{
|
||||
m_viewsScreenSyncTimer.start();
|
||||
}
|
||||
|
||||
void Corona::screenRemoved(QScreen *screen)
|
||||
void Corona::onScreenGeometryChanged(const QRect &geometry)
|
||||
{
|
||||
screenCountChanged();
|
||||
}
|
||||
Q_UNUSED(geometry);
|
||||
|
||||
void Corona::screenCountChanged()
|
||||
{
|
||||
m_viewsScreenSyncTimer.start();
|
||||
QScreen *screen = qobject_cast<QScreen *>(sender());
|
||||
|
||||
if (!screen) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int id = m_screenPool->id(screen->name());
|
||||
|
||||
if (id >= 0) {
|
||||
emit screenGeometryChanged(id);
|
||||
emit availableScreenRegionChanged();
|
||||
emit availableScreenRectChanged();
|
||||
}
|
||||
}
|
||||
|
||||
//! the central functions that updates loading/unloading latteviews
|
||||
@ -892,7 +908,7 @@ void Corona::syncLatteViewsToScreens()
|
||||
|
||||
int Corona::primaryScreenId() const
|
||||
{
|
||||
return m_screenPool->id(qGuiApp->primaryScreen()->name());
|
||||
return m_screenPool->primaryScreenId();
|
||||
}
|
||||
|
||||
void Corona::quitApplication()
|
||||
@ -1188,9 +1204,25 @@ QStringList Corona::contextMenuData(const uint &containmentId)
|
||||
}
|
||||
|
||||
data << layoutsmenu.join(";;");
|
||||
data << QString::number((int)viewType); //Selected View type
|
||||
data << (view ? view->layout()->name() : QString()); //Selected View layout*/
|
||||
|
||||
QStringList viewtype;
|
||||
viewtype << QString::number((int)viewType); //Selected View type
|
||||
|
||||
if (view && view->isOriginal()) { /*View*/
|
||||
auto originalview = qobject_cast<Latte::OriginalView *>(view);
|
||||
viewtype << "0"; //original view
|
||||
viewtype << QString::number(originalview->clonesCount());
|
||||
} else if (view && view->isCloned()) {
|
||||
viewtype << "1"; //cloned view
|
||||
viewtype << "0"; //has no clones
|
||||
} else {
|
||||
viewtype << "0"; //original view
|
||||
viewtype << "0"; //has no clones
|
||||
}
|
||||
|
||||
data << viewtype.join(";;");
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1243,7 +1275,14 @@ void Corona::moveViewToLayout(const uint &containmentId, const QString &layoutNa
|
||||
{
|
||||
auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
|
||||
if (view && !layoutName.isEmpty() && view->layout()->name() != layoutName) {
|
||||
view->positioner()->setNextLocation(layoutName, "", Plasma::Types::Floating, Latte::Types::NoneAlignment);
|
||||
Latte::Types::ScreensGroup screensgroup{Latte::Types::SingleScreenGroup};
|
||||
|
||||
if (view->isOriginal()) {
|
||||
auto originalview = qobject_cast<Latte::OriginalView *>(view);
|
||||
screensgroup = originalview->screensGroup();
|
||||
}
|
||||
|
||||
view->positioner()->setNextLocation(layoutName, screensgroup, "", Plasma::Types::Floating, Latte::Types::NoneAlignment);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1300,18 +1339,7 @@ inline void Corona::qmlRegisterTypes() const
|
||||
|
||||
qmlRegisterType<Latte::BackgroundTracker>("org.kde.latte.private.app", 0, 1, "BackgroundTracker");
|
||||
qmlRegisterType<Latte::Interfaces>("org.kde.latte.private.app", 0, 1, "Interfaces");
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
qmlRegisterType<QScreen>();
|
||||
qmlRegisterType<Latte::View>();
|
||||
qmlRegisterType<Latte::ViewPart::WindowsTracker>();
|
||||
qmlRegisterType<Latte::ViewPart::TrackerPart::CurrentScreenTracker>();
|
||||
qmlRegisterType<Latte::ViewPart::TrackerPart::AllScreensTracker>();
|
||||
qmlRegisterType<Latte::WindowSystem::SchemeColors>();
|
||||
qmlRegisterType<Latte::WindowSystem::Tracker::LastActiveWindow>();
|
||||
qmlRegisterType<Latte::Types>();
|
||||
#else
|
||||
qmlRegisterType<Latte::ContextMenuLayerQuickItem>("org.kde.latte.private.app", 0, 1, "ContextMenuLayer");
|
||||
qmlRegisterAnonymousType<QScreen>("latte-dock", 1);
|
||||
qmlRegisterAnonymousType<Latte::View>("latte-dock", 1);
|
||||
qmlRegisterAnonymousType<Latte::ViewPart::WindowsTracker>("latte-dock", 1);
|
||||
@ -1320,7 +1348,7 @@ inline void Corona::qmlRegisterTypes() const
|
||||
qmlRegisterAnonymousType<Latte::WindowSystem::SchemeColors>("latte-dock", 1);
|
||||
qmlRegisterAnonymousType<Latte::WindowSystem::Tracker::LastActiveWindow>("latte-dock", 1);
|
||||
qmlRegisterAnonymousType<Latte::Types>("latte-dock", 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -189,10 +189,10 @@ private slots:
|
||||
|
||||
void onAboutToQuit();
|
||||
|
||||
void addOutput(QScreen *screen);
|
||||
void primaryOutputChanged();
|
||||
void screenRemoved(QScreen *screen);
|
||||
void screenCountChanged();
|
||||
void onScreenAdded(QScreen *screen);
|
||||
void onScreenRemoved(QScreen *screen);
|
||||
void onScreenCountChanged();
|
||||
void onScreenGeometryChanged(const QRect &geometry);
|
||||
void syncLatteViewsToScreens();
|
||||
|
||||
private:
|
||||
|
@ -9,6 +9,7 @@ Name[da]=Latte-dok
|
||||
Name[de]=Latte-Dock
|
||||
Name[el]=Latte Dock
|
||||
Name[en_GB]=Latte Dock
|
||||
Name[eo]=Latte Doko
|
||||
Name[es]=Latte Dock
|
||||
Name[et]=Latte dokk
|
||||
Name[eu]=Latte Dock
|
||||
@ -29,6 +30,7 @@ Name[ru]=Latte Dock
|
||||
Name[sk]=Dok Latte
|
||||
Name[sl]=Latte Dock
|
||||
Name[sv]=Latte dockningsfönster
|
||||
Name[tr]=Latte Rıhtım
|
||||
Name[uk]=Панель Латте
|
||||
Name[x-test]=xxLatte Dockxx
|
||||
Name[zh_CN]=Latte 停靠栏
|
||||
@ -43,6 +45,7 @@ Comment[da]=Latte-dok
|
||||
Comment[de]=Latte-Dock
|
||||
Comment[el]=Διαχειριστής εργασιών Latte
|
||||
Comment[en_GB]=Latte Dock
|
||||
Comment[eo]=Latte Doko
|
||||
Comment[es]=Latte Dock
|
||||
Comment[et]=Latte dokk
|
||||
Comment[eu]=Latte Dock
|
||||
@ -63,6 +66,7 @@ Comment[ru]=Latte Dock
|
||||
Comment[sk]=Dok Latte
|
||||
Comment[sl]=Latte Dock
|
||||
Comment[sv]=Latte dockningsfönster
|
||||
Comment[tr]=Latte Rıhtım
|
||||
Comment[uk]=Панель Латте
|
||||
Comment[x-test]=xxLatte Dockxx
|
||||
Comment[zh_CN]=Latte 停靠栏
|
||||
@ -71,6 +75,7 @@ IconName=latte-dock
|
||||
|
||||
[Event/import-done]
|
||||
Name=Imported successfully
|
||||
Name[ar]=استوردتُ بنجاح
|
||||
Name[az]=Müvəffəqiyyətlə İdxal Olundu
|
||||
Name[ca]=S'ha importat amb èxit
|
||||
Name[ca@valencia]=S'ha importat amb èxit
|
||||
@ -78,6 +83,7 @@ Name[cs]=Importováno úspěšně
|
||||
Name[de]=Erfolgreich importiert
|
||||
Name[el]=Επιτυχής εισαγωγή
|
||||
Name[en_GB]=Imported successfully
|
||||
Name[eo]=Importita sukcese
|
||||
Name[es]=Importada exitosamente
|
||||
Name[et]=Imporditi edukalt
|
||||
Name[eu]=Inportatze arrakastatsua
|
||||
@ -87,6 +93,8 @@ Name[gl]=Importouse correctamente
|
||||
Name[hsb]=Wuspěšnje importował
|
||||
Name[id]=Berhasil diimpor
|
||||
Name[it]=Importata con successo
|
||||
Name[ja]=インポートに成功しました
|
||||
Name[ka]=შემოტანა წარმატებულია
|
||||
Name[ko]=성공적으로 가져왔습니다
|
||||
Name[lt]=Sėkmingai importuota
|
||||
Name[nl]=Met succes geïmporteerd
|
||||
@ -107,22 +115,26 @@ Action=Popup
|
||||
|
||||
[Event/import-fail]
|
||||
Name=Failed to import
|
||||
Name[ar]=فشل استيراد
|
||||
Name[az]=İdxal baş tutmadı
|
||||
Name[ca]=Ha fallat en importar
|
||||
Name[ca@valencia]=Ha fallat en importar
|
||||
Name[ca@valencia]=No s'ha pogut importar
|
||||
Name[cs]=Nepodařilo se importovat
|
||||
Name[de]=Importieren fehlgeschlagen
|
||||
Name[el]=Αποτυχία εισαγωγής
|
||||
Name[en_GB]=Failed to import
|
||||
Name[eo]=Malsukcesis importi
|
||||
Name[es]=Error al importar
|
||||
Name[et]=Importimine nurjus
|
||||
Name[eu]=Huts egin du inportatzea
|
||||
Name[fi]=Tuonti epäonnistui
|
||||
Name[fr]=Échec de l'importation
|
||||
Name[gl]=Non se puido importar
|
||||
Name[gl]=Non foi posíbel importar
|
||||
Name[hsb]=Njemóžach importować
|
||||
Name[id]=Gagal mengimpor
|
||||
Name[it]=Impossibile importare
|
||||
Name[ja]=インポートに失敗しました
|
||||
Name[ka]=შემოტანის შეცდომა
|
||||
Name[ko]=가져오지 못했습니다
|
||||
Name[lt]=Nepavyko importuoti
|
||||
Name[nl]=Importeren is mislukt
|
||||
@ -143,6 +155,7 @@ Action=Popup
|
||||
|
||||
[Event/export-done]
|
||||
Name=Exported successfully
|
||||
Name[ar]=صدّرتُ بنجاح
|
||||
Name[az]=Müvəffəqiyyətlə ixrac olundu
|
||||
Name[ca]=S'ha exportat amb èxit
|
||||
Name[ca@valencia]=S'ha exportat amb èxit
|
||||
@ -150,6 +163,7 @@ Name[cs]=Exportováno úspěšně
|
||||
Name[de]=Erfolgreich exportiert
|
||||
Name[el]=Επιτυχής εξαγωγή
|
||||
Name[en_GB]=Exported successfully
|
||||
Name[eo]=Sukcese eksportita
|
||||
Name[es]=Exportada exitosamente
|
||||
Name[et]=Eksporditi edukalt
|
||||
Name[eu]=Esportatze arrakastatsua
|
||||
@ -159,6 +173,8 @@ Name[gl]=Exportouse correctamente
|
||||
Name[hsb]=Wuspěšnje eksportował
|
||||
Name[id]=Berhasil diekspor
|
||||
Name[it]=Esportata correttamente
|
||||
Name[ja]=エクスポートに成功しました
|
||||
Name[ka]=გატანა წარმატებულია
|
||||
Name[ko]=성공적으로 내보냈습니다
|
||||
Name[lt]=Sėkmingai eksportuota
|
||||
Name[nl]=Met succes geëxporteerd
|
||||
@ -179,22 +195,27 @@ Action=Popup
|
||||
|
||||
[Event/export-fail]
|
||||
Name=Failed to export
|
||||
Name[ar]=فشل تصدير
|
||||
Name[az]=İxrac baş tutmadı
|
||||
Name[ca]=Ha fallat en exportar
|
||||
Name[ca@valencia]=Ha fallat en exportar
|
||||
Name[ca@valencia]=No s'ha pogut exportar
|
||||
Name[cs]=Export selhal
|
||||
Name[de]=Exportieren fehlgeschlagen
|
||||
Name[el]=Αποτυχία εξαγωγής
|
||||
Name[en_GB]=Failed to export
|
||||
Name[eo]=Malsukcesis eksporti
|
||||
Name[es]=Error al exportar
|
||||
Name[et]=Eksportimine nurjus
|
||||
Name[eu]=Huts egin du esportatzea
|
||||
Name[fi]=Vienti epäonnistui
|
||||
Name[fr]=Exportation impossible
|
||||
Name[gl]=Non se puido exportar
|
||||
Name[gl]=Non foi posíbel exportar
|
||||
Name[hsb]=Njemóžach eksportować
|
||||
Name[ia]=Falleva a exportar
|
||||
Name[id]=Gagal mengekspor
|
||||
Name[it]=Impossibile esportare
|
||||
Name[ja]=エクスポートに失敗しました
|
||||
Name[ka]=გატანის შეცდომა
|
||||
Name[ko]=내보내지 못했습니다
|
||||
Name[lt]=Nepavyko eksportuoti
|
||||
Name[nl]=Exporteren is mislukt
|
||||
@ -215,6 +236,7 @@ Action=Popup
|
||||
|
||||
[Event/remove-done]
|
||||
Name=Removed successfully
|
||||
Name[ar]=استوردتُ بنجاح
|
||||
Name[az]=Müvəffəqiyyətlə silindi
|
||||
Name[ca]=S'ha eliminat amb èxit
|
||||
Name[ca@valencia]=S'ha eliminat amb èxit
|
||||
@ -222,6 +244,7 @@ Name[cs]=Úspěšně odstraněno
|
||||
Name[de]=Erfolgreich entfernt
|
||||
Name[el]=Επιτυχής αφαίρεση
|
||||
Name[en_GB]=Removed successfully
|
||||
Name[eo]=Forigita sukcese
|
||||
Name[es]=Eliminada exitosamente
|
||||
Name[et]=Eemaldati edukalt
|
||||
Name[eu]=Ezabatze arrakastatsua
|
||||
@ -231,6 +254,8 @@ Name[gl]=Retirouse correctamente
|
||||
Name[hsb]=Wuspěšnje wumazał
|
||||
Name[id]=Berhasil dihapus
|
||||
Name[it]=Rimossa con successo
|
||||
Name[ja]=削除に成功しました
|
||||
Name[ka]=წაშლა წარმატებულია
|
||||
Name[ko]=성공적으로 삭제했습니다
|
||||
Name[lt]=Sėkmingai pašalinta
|
||||
Name[nl]=Met succes verwijderd
|
||||
@ -251,23 +276,27 @@ Action=Popup
|
||||
|
||||
[Event/remove-fail]
|
||||
Name=Failed to remove
|
||||
Name[ar]=فشلت إزالة
|
||||
Name[az]=Silinmə alınmadı
|
||||
Name[ca]=Ha fallat en eliminar
|
||||
Name[ca@valencia]=Ha fallat en eliminar
|
||||
Name[ca@valencia]=No s'ha pogut eliminar
|
||||
Name[cs]=Selhalo odstranění
|
||||
Name[de]=Entfernen fehlgeschlagen
|
||||
Name[el]=Αποτυχία αφαίρεσης
|
||||
Name[en_GB]=Failed to remove
|
||||
Name[eo]=Malsukcesis forigi
|
||||
Name[es]=Error al eliminar
|
||||
Name[et]=Eemaldamine nurjus
|
||||
Name[eu]=Huts egin du ezabatzea
|
||||
Name[fi]=Poistaminen epäonnistui
|
||||
Name[fr]=Échec de la suppression
|
||||
Name[gl]=Non se puido retirar
|
||||
Name[gl]=Non foi posíbel retirar
|
||||
Name[hsb]=Njemóžach wumazać
|
||||
Name[ia]=Il falleva a remover
|
||||
Name[id]=Gagal menghapus
|
||||
Name[it]=Impossibile rimuovere
|
||||
Name[ja]=削除に失敗しました
|
||||
Name[ka]=წაშლის შეცდომა
|
||||
Name[ko]=삭제하지 못했습니다
|
||||
Name[lt]=Nepavyko pašalinti
|
||||
Name[nl]=Verwijderen is mislukt
|
||||
@ -288,14 +317,16 @@ Action=Popup
|
||||
|
||||
[Event/switch-layout]
|
||||
Name=Switch to layout
|
||||
Name[ar]=بدل إلى تخطيط
|
||||
Name[az]=Maketi Keçmək
|
||||
Name[ca]=Commuta a la disposició
|
||||
Name[ca@valencia]=Commuta a la disposició
|
||||
Name[cs]=Přepnout na rozložení
|
||||
Name[ca@valencia]=Canvia a la disposició
|
||||
Name[cs]=Přepnout na rozvržení
|
||||
Name[da]=Skift til layout
|
||||
Name[de]=Wechsel zu Profil
|
||||
Name[el]=Εναλλαγή στο προφίλ
|
||||
Name[en_GB]=Switch to layout
|
||||
Name[eo]=Ŝaltu al aranĝo
|
||||
Name[es]=Cambiar a distribución
|
||||
Name[et]=Paigutusele lülitumine
|
||||
Name[eu]=Aldatu antolamendura
|
||||
@ -305,6 +336,8 @@ Name[gl]=Cambiar á disposición
|
||||
Name[hsb]=Layout přešaltować
|
||||
Name[id]=Beralih ke tataletak
|
||||
Name[it]=Passa alla disposizione
|
||||
Name[ja]=レイアウトの切り替え
|
||||
Name[ka]=განლაგებაზე გადართვა
|
||||
Name[ko]=레이아웃으로 전환
|
||||
Name[lt]=Perjungti į išdėstymą
|
||||
Name[nl]=Naar indeling omschakelen
|
||||
@ -316,6 +349,7 @@ Name[ru]=Использовать макет
|
||||
Name[sk]=Prepnúť na rozloženie
|
||||
Name[sl]=Preklop na postavitev
|
||||
Name[sv]=Byt till layout
|
||||
Name[tr]=Yerleşime geç
|
||||
Name[uk]=Перемкнутися на компонування
|
||||
Name[x-test]=xxSwitch to layoutxx
|
||||
Name[zh_CN]=切换布局
|
||||
|
@ -46,9 +46,9 @@ void CentralLayout::init()
|
||||
connect(this, &CentralLayout::showInMenuChanged, this, &CentralLayout::saveConfig);
|
||||
}
|
||||
|
||||
void CentralLayout::initToCorona(Latte::Corona *corona)
|
||||
bool CentralLayout::initCorona()
|
||||
{
|
||||
if (GenericLayout::initToCorona(corona)) {
|
||||
if (GenericLayout::initCorona()) {
|
||||
onSchemeFileChanged();
|
||||
|
||||
connect(this, &CentralLayout::disableBordersForMaximizedWindowsChanged,
|
||||
@ -56,7 +56,10 @@ void CentralLayout::initToCorona(Latte::Corona *corona)
|
||||
|
||||
connect(this, &Layout::AbstractLayout::schemeFileChanged, this, &CentralLayout::onSchemeFileChanged);
|
||||
connect(m_corona->wm()->schemesTracker(), &WindowSystem::Tracker::Schemes::defaultSchemeChanged, this, &CentralLayout::onSchemeFileChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CentralLayout::disableBordersForMaximizedWindows() const
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
CentralLayout(QObject *parent, QString layoutFile, QString layoutName = QString());
|
||||
~CentralLayout() override;
|
||||
|
||||
void initToCorona(Latte::Corona *corona);
|
||||
bool initCorona() override;
|
||||
|
||||
bool disableBordersForMaximizedWindows() const;
|
||||
void setDisableBordersForMaximizedWindows(bool disable);
|
||||
|
@ -17,8 +17,10 @@
|
||||
#include "../layouts/synchronizer.h"
|
||||
#include "../shortcuts/shortcutstracker.h"
|
||||
#include "../templates/templatesmanager.h"
|
||||
#include "../view/view.h"
|
||||
#include "../view/clonedview.h"
|
||||
#include "../view/originalview.h"
|
||||
#include "../view/positioner.h"
|
||||
#include "../view/view.h"
|
||||
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
@ -143,7 +145,7 @@ void GenericLayout::setBlockAutomaticLatteViewCreation(bool block)
|
||||
|
||||
bool GenericLayout::isActive() const
|
||||
{
|
||||
return m_corona && (m_corona->layoutsManager()->synchronizer()->layout(m_layoutName) != nullptr);
|
||||
return m_corona && m_hasInitializedContainments && (m_corona->layoutsManager()->synchronizer()->layout(m_layoutName) != nullptr);
|
||||
}
|
||||
|
||||
bool GenericLayout::isCurrent()
|
||||
@ -155,6 +157,16 @@ bool GenericLayout::isCurrent()
|
||||
return m_corona->layoutsManager()->currentLayoutsNames().contains(name());
|
||||
}
|
||||
|
||||
bool GenericLayout::hasCorona() const
|
||||
{
|
||||
return (m_corona!=nullptr);
|
||||
}
|
||||
|
||||
void GenericLayout::setCorona(Latte::Corona *corona)
|
||||
{
|
||||
m_corona = corona;
|
||||
}
|
||||
|
||||
QString GenericLayout::background() const
|
||||
{
|
||||
QString colorsPath = m_corona->kPackage().path() + "../../shells/org.kde.latte.shell/contents/images/canvas/";
|
||||
@ -368,6 +380,12 @@ Latte::View *GenericLayout::viewForContainment(uint id) const
|
||||
}
|
||||
}
|
||||
|
||||
for(auto view : m_waitingLatteViews) {
|
||||
if (view && view->containment()->id() == id) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -449,12 +467,26 @@ QList<Latte::View *> GenericLayout::latteViews()
|
||||
return m_latteViews.values();
|
||||
}
|
||||
|
||||
QList<Latte::View *> GenericLayout::sortedLatteViews()
|
||||
QList<Latte::View *> GenericLayout::onlyOriginalViews()
|
||||
{
|
||||
return sortedLatteViews(latteViews());
|
||||
QList<Latte::View *> viewslist;
|
||||
|
||||
for (const auto v : m_latteViews) {
|
||||
if (v->isOriginal()) {
|
||||
viewslist << v;
|
||||
}
|
||||
}
|
||||
|
||||
return viewslist;
|
||||
}
|
||||
|
||||
QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views)
|
||||
QList<Latte::View *> GenericLayout::sortedLatteViews()
|
||||
{
|
||||
QScreen *primaryScreen = (m_corona ? m_corona->screenPool()->primaryScreen() : nullptr);
|
||||
return sortedLatteViews(latteViews(), primaryScreen);
|
||||
}
|
||||
|
||||
QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views, QScreen *primaryScreen)
|
||||
{
|
||||
QList<Latte::View *> sortedViews = views;
|
||||
|
||||
@ -470,7 +502,7 @@ QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views)
|
||||
//! Bottom,Left,Top,Right
|
||||
for (int i = 0; i < sortedViews.size(); ++i) {
|
||||
for (int j = 0; j < sortedViews.size() - i - 1; ++j) {
|
||||
if (viewAtLowerScreenPriority(sortedViews[j], sortedViews[j + 1])
|
||||
if (viewAtLowerScreenPriority(sortedViews[j], sortedViews[j + 1], primaryScreen)
|
||||
|| (sortedViews[j]->screen() == sortedViews[j + 1]->screen()
|
||||
&& viewAtLowerEdgePriority(sortedViews[j], sortedViews[j + 1]))) {
|
||||
Latte::View *temp = sortedViews[j + 1];
|
||||
@ -503,7 +535,7 @@ QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views)
|
||||
return sortedViews;
|
||||
}
|
||||
|
||||
bool GenericLayout::viewAtLowerScreenPriority(Latte::View *test, Latte::View *base)
|
||||
bool GenericLayout::viewAtLowerScreenPriority(Latte::View *test, Latte::View *base, QScreen *primaryScreen)
|
||||
{
|
||||
if (!base || ! test) {
|
||||
return true;
|
||||
@ -511,9 +543,9 @@ bool GenericLayout::viewAtLowerScreenPriority(Latte::View *test, Latte::View *ba
|
||||
|
||||
if (base->screen() == test->screen()) {
|
||||
return false;
|
||||
} else if (base->screen() != qGuiApp->primaryScreen() && test->screen() == qGuiApp->primaryScreen()) {
|
||||
} else if (base->screen() != primaryScreen && test->screen() == primaryScreen) {
|
||||
return false;
|
||||
} else if (base->screen() == qGuiApp->primaryScreen() && test->screen() != qGuiApp->primaryScreen()) {
|
||||
} else if (base->screen() == primaryScreen && test->screen() != primaryScreen) {
|
||||
return true;
|
||||
} else {
|
||||
int basePriority = -1;
|
||||
@ -819,109 +851,55 @@ void GenericLayout::renameLayout(QString newName)
|
||||
}
|
||||
}
|
||||
|
||||
void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimary, int explicitScreen, Layout::ViewsMap *occupied)
|
||||
void GenericLayout::addView(Plasma::Containment *containment)
|
||||
{
|
||||
qDebug() << "Layout :::: " << m_layoutName << " ::: addView was called... m_containments :: " << m_containments.size();
|
||||
qDebug().noquote() << "Adding View: Called for layout:" << m_layoutName << "with m_containments.size() ::" << m_containments.size();
|
||||
|
||||
if (!containment || !m_corona || !containment->kPackage().isValid()) {
|
||||
qWarning() << "the requested containment plugin can not be located or loaded";
|
||||
qWarning() << "Adding View: The requested containment plugin can not be located or loaded";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "step 1...";
|
||||
qDebug() << "Adding View:" << containment->id() << "- Step 1...";
|
||||
|
||||
if (!Layouts::Storage::self()->isLatteContainment(containment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "step 2...";
|
||||
qDebug() << "Adding View:" << containment->id() << "- Step 2...";
|
||||
|
||||
for (auto *dock : m_latteViews) {
|
||||
if (dock->containment() == containment)
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "step 3...";
|
||||
|
||||
QScreen *nextScreen{qGuiApp->primaryScreen()};
|
||||
|
||||
bool onPrimary = containment->config().readEntry("onPrimary", true);
|
||||
int id = containment->screen();
|
||||
|
||||
if (!Layouts::Storage::isValid(id) && !Layouts::Storage::isValid(explicitScreen)) {
|
||||
id = containment->lastScreen();
|
||||
}
|
||||
|
||||
if (onPrimary) {
|
||||
id = m_corona->screenPool()->primaryScreenId();
|
||||
} else if (Layouts::Storage::isValid(explicitScreen)) {
|
||||
id = explicitScreen;
|
||||
}
|
||||
|
||||
Plasma::Types::Location edge = containment->location();
|
||||
|
||||
QString connector = m_corona->screenPool()->hasScreenId(id) ? m_corona->screenPool()->connector(id) : "";
|
||||
|
||||
qDebug() << "Adding view - containment id:" << containment->id() << " ,screen :" << id << " - " << connector
|
||||
<< " ,onprimary:" << onPrimary << " - " << " edge:" << edge << " ,screenName:" << qGuiApp->primaryScreen()->name() << " ,forceOnPrimary:" << forceOnPrimary;
|
||||
|
||||
if (occupied && m_corona->screenPool()->hasScreenId(id) && (*occupied).contains(connector) && (*occupied)[connector].contains(edge)) {
|
||||
qDebug() << "Rejected : adding view because the edge is already occupied by a higher priority view ! : " << (*occupied)[connector][edge];
|
||||
if (hasLatteView(containment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Layouts::Storage::isValid(id) && !onPrimary && !forceOnPrimary) {
|
||||
qDebug() << "Add view - connector : " << connector;
|
||||
bool found{false};
|
||||
qDebug() << "Adding View:" << containment->id() << "- Step 3...";
|
||||
|
||||
if (m_corona->screenPool()->hasScreenId(id)) {
|
||||
for (const auto scr : qGuiApp->screens()) {
|
||||
if (scr && scr->name() == connector) {
|
||||
found = true;
|
||||
nextScreen = scr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
QScreen *nextScreen{m_corona->screenPool()->primaryScreen()};
|
||||
Data::View viewdata = Layouts::Storage::self()->view(this, containment);
|
||||
viewdata.screen = Layouts::Storage::self()->expectedViewScreenId(m_corona, viewdata);
|
||||
|
||||
QString nextScreenName = m_corona->screenPool()->hasScreenId(viewdata.screen) ? m_corona->screenPool()->connector(viewdata.screen) : "";
|
||||
|
||||
qDebug().noquote() << "Adding View:" << viewdata.id << "-"
|
||||
<< "IsClonedFrom:" << viewdata.isClonedFrom
|
||||
<< ", NextScreen:" << viewdata.screen << "-" << nextScreenName
|
||||
<< ", OnPrimary:" << viewdata.onPrimary
|
||||
<< ", Edge:" << viewdata.edge;
|
||||
|
||||
if (!viewdata.onPrimary && Layouts::Storage::isValid(viewdata.screen)) {
|
||||
bool foundNextExplicitScreen{false};
|
||||
|
||||
if (m_corona->screenPool()->isScreenActive(viewdata.screen)) {
|
||||
foundNextExplicitScreen = true;
|
||||
nextScreen = m_corona->screenPool()->screenForId(viewdata.screen);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
qDebug() << "Rejected : adding explicit view, screen not available ! : " << connector;
|
||||
if (!foundNextExplicitScreen) {
|
||||
qDebug().noquote() << "Adding View:" << viewdata.id << "- Rejected because Screen is not available :: " << nextScreenName;
|
||||
return;
|
||||
}
|
||||
|
||||
//! explicit dock can not be added at explicit screen when that screen is the same with
|
||||
//! primary screen and that edge is already occupied by a primary dock
|
||||
//! CAN BE REMOVED because we now accept primary and explicit views on ACTIVE SCREENS at ALL CASES
|
||||
//if (nextScreen == qGuiApp->primaryScreen() && primaryDockOccupyEdge(containment->location())) {
|
||||
// qDebug() << "Rejected : adding explicit view, primary dock occupies edge at screen ! : " << connector;
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
if (Layouts::Storage::isValid(id) && onPrimary) {
|
||||
qDebug() << "add dock - connector : " << connector;
|
||||
|
||||
for (const Plasma::Containment *testContainment : m_latteViews.keys()) {
|
||||
int testScreenId = testContainment->screen();
|
||||
|
||||
if (!Layouts::Storage::isValid(testScreenId)) {
|
||||
testScreenId = testContainment->lastScreen();
|
||||
}
|
||||
|
||||
bool testOnPrimary = testContainment->config().readEntry("onPrimary", true);
|
||||
Plasma::Types::Location testLocation = static_cast<Plasma::Types::Location>((int)testContainment->config().readEntry("location", (int)Plasma::Types::BottomEdge));
|
||||
|
||||
if (!testOnPrimary && m_corona->screenPool()->primaryScreenId() == testScreenId && testLocation == containment->location()) {
|
||||
qDebug() << "Rejected explicit latteView and removing it in order add an onPrimary with higher priority at screen: " << connector;
|
||||
auto viewToDelete = m_latteViews.take(testContainment);
|
||||
viewToDelete->disconnectSensitiveSignals();
|
||||
viewToDelete->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Adding view passed ALL checks" << " ,onPrimary:" << onPrimary << " ,screen:" << nextScreen->name() << " !!!";
|
||||
|
||||
//! it is used to set the correct flag during the creation
|
||||
//! of the window... This of course is also used during
|
||||
//! recreations of the window between different visibility modes
|
||||
@ -937,21 +915,29 @@ void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimar
|
||||
byPassWM = containment->config().readEntry("byPassWM", false);
|
||||
}
|
||||
|
||||
auto latteView = new Latte::View(m_corona, nextScreen, byPassWM);
|
||||
Latte::View *latteView;
|
||||
|
||||
if (!viewdata.isCloned()) {
|
||||
latteView = new Latte::OriginalView(m_corona, nextScreen, byPassWM);
|
||||
} else {
|
||||
auto view = viewForContainment((uint)viewdata.isClonedFrom);
|
||||
|
||||
if (!containsView(viewdata.isClonedFrom) || !view) {
|
||||
qDebug().noquote() << "Adding View:" << viewdata.id << "- Clone did not find OriginalView and as such was stopped!!!";
|
||||
return;
|
||||
}
|
||||
|
||||
auto originalview = qobject_cast<Latte::OriginalView *>(view);
|
||||
latteView = new Latte::ClonedView(m_corona, originalview, nextScreen, byPassWM);
|
||||
}
|
||||
|
||||
qDebug().noquote() << "Adding View:" << viewdata.id << "- Passed ALL checks !!!";
|
||||
m_latteViews[containment] = latteView;
|
||||
|
||||
latteView->init(containment);
|
||||
latteView->setContainment(containment);
|
||||
|
||||
//! force this special dock case to become primary
|
||||
//! even though it isnt
|
||||
if (forceOnPrimary) {
|
||||
qDebug() << "Enforcing onPrimary:true as requested for LatteView...";
|
||||
latteView->setOnPrimary(true);
|
||||
}
|
||||
|
||||
latteView->setLayout(this);
|
||||
|
||||
|
||||
//! Qt 5.9 creates a crash for this in wayland, that is why the check is used
|
||||
//! but on the other hand we need this for copy to work correctly and show
|
||||
//! the copied dock under X11
|
||||
@ -959,8 +945,6 @@ void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimar
|
||||
latteView->show();
|
||||
//}
|
||||
|
||||
m_latteViews[containment] = latteView;
|
||||
|
||||
emit viewsCountChanged();
|
||||
}
|
||||
|
||||
@ -970,7 +954,7 @@ void GenericLayout::toggleHiddenState(QString viewName, QString screenName, Plas
|
||||
return;
|
||||
}
|
||||
|
||||
QString validScreenName = qGuiApp->primaryScreen()->name();
|
||||
QString validScreenName = m_corona->screenPool()->primaryScreen()->name();
|
||||
if (!screenName.isEmpty()) {
|
||||
validScreenName = screenName;
|
||||
}
|
||||
@ -996,27 +980,13 @@ void GenericLayout::toggleHiddenState(QString viewName, QString screenName, Plas
|
||||
}
|
||||
}
|
||||
|
||||
bool GenericLayout::initToCorona(Latte::Corona *corona)
|
||||
bool GenericLayout::initCorona()
|
||||
{
|
||||
if (m_corona) {
|
||||
if (!m_corona) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_corona = corona;
|
||||
|
||||
for (const auto containment : m_corona->containments()) {
|
||||
if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
|
||||
addContainment(containment);
|
||||
} else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
|
||||
QString layoutId = containment->config().readEntry("layoutId", QString());
|
||||
|
||||
if (!layoutId.isEmpty() && (layoutId == m_layoutName)) {
|
||||
addContainment(containment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Layout ::::: " << name() << " added containments ::: " << m_containments.size();
|
||||
connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
|
||||
|
||||
updateLastUsedActivity();
|
||||
|
||||
@ -1025,8 +995,6 @@ bool GenericLayout::initToCorona(Latte::Corona *corona)
|
||||
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, &GenericLayout::updateLastUsedActivity);
|
||||
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, &GenericLayout::updateLastUsedActivity);
|
||||
|
||||
connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
|
||||
|
||||
connect(this, &GenericLayout::lastConfigViewForChanged, m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom);
|
||||
connect(m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom, this, &GenericLayout::onLastConfigViewChangedFrom);
|
||||
|
||||
@ -1034,8 +1002,41 @@ bool GenericLayout::initToCorona(Latte::Corona *corona)
|
||||
connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRectChanged);
|
||||
connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRegionChanged);
|
||||
|
||||
emit viewsCountChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GenericLayout::initContainments()
|
||||
{
|
||||
if (!m_corona || m_hasInitializedContainments) {
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "Layout ::::: " << name() << " added containments ::: " << m_containments.size();
|
||||
|
||||
for(int pass=1; pass<=2; ++pass) {
|
||||
for (const auto containment : m_corona->containments()) {
|
||||
//! in first pass we load subcontainments
|
||||
//! in second pass we load main dock and panel containments
|
||||
//! this way subcontainments will be always available to find when the layout is activating
|
||||
//! for example during startup that clones must be created and subcontainments should be taken into account
|
||||
if ((pass==1 && Layouts::Storage::self()->isLatteContainment(containment)
|
||||
|| (pass==2 && !Layouts::Storage::self()->isLatteContainment(containment)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
|
||||
addContainment(containment);
|
||||
} else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
|
||||
QString layoutId = containment->config().readEntry("layoutId", QString());
|
||||
|
||||
if (!layoutId.isEmpty() && (layoutId == m_layoutName)) {
|
||||
addContainment(containment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_hasInitializedContainments = true;
|
||||
emit viewsCountChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1163,7 +1164,7 @@ void GenericLayout::recreateView(Plasma::Containment *containment, bool delayed)
|
||||
}
|
||||
|
||||
|
||||
bool GenericLayout::latteViewExists(Plasma::Containment *containment)
|
||||
bool GenericLayout::hasLatteView(Plasma::Containment *containment)
|
||||
{
|
||||
if (!m_corona) {
|
||||
return false;
|
||||
@ -1254,119 +1255,55 @@ bool GenericLayout::mapContainsId(const Layout::ViewsMap *map, uint viewId) cons
|
||||
return false;
|
||||
}
|
||||
|
||||
//! screen name, location, containmentId
|
||||
Layout::ViewsMap GenericLayout::validViewsMap(Layout::ViewsMap *occupiedMap)
|
||||
QString GenericLayout::mapScreenName(const ViewsMap *map, uint viewId) const
|
||||
{
|
||||
for(const auto &scr : map->keys()) {
|
||||
for(const auto &edge : (*map)[scr].keys()) {
|
||||
if ((*map)[scr][edge].contains(viewId)) {
|
||||
return scr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QString::number(Latte::ScreenPool::NOSCREENID);
|
||||
}
|
||||
|
||||
//! screen name, location, containmentId
|
||||
Layout::ViewsMap GenericLayout::validViewsMap()
|
||||
{
|
||||
//! Shared Views occupy the screen edge first
|
||||
//! Primary Views occupy the screen edge if Shared Views do not exist already on that screen edge
|
||||
//! Explicity Views occypy the screen edge if Shared Views and Primary Views do not exist already on that screen edge
|
||||
Layout::ViewsMap map;
|
||||
|
||||
if (!m_corona) {
|
||||
return map;
|
||||
}
|
||||
|
||||
if (occupiedMap != nullptr) {
|
||||
map = (*occupiedMap);
|
||||
}
|
||||
QString prmScreenName = m_corona->screenPool()->primaryScreen()->name();
|
||||
|
||||
QString prmScreenName = qGuiApp->primaryScreen()->name();
|
||||
|
||||
//! first step: primary docks must be placed in primary screen free edges
|
||||
for (const auto containment : m_containments) {
|
||||
if (Layouts::Storage::self()->isLatteContainment(containment)) {
|
||||
int screenId{Layouts::Storage::IDNULL};
|
||||
if (Layouts::Storage::self()->isLatteContainment(containment)
|
||||
&& !Layouts::Storage::self()->isClonedView(containment)) {
|
||||
Data::View view = hasLatteView(containment) ? m_latteViews[containment]->data() : Latte::Layouts::Storage::self()->view(this, containment);
|
||||
view.screen = Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
|
||||
|
||||
//! valid screen id
|
||||
if (latteViewExists(containment)) {
|
||||
screenId = m_latteViews[containment]->positioner()->currentScreenId();
|
||||
if (view.onPrimary) {
|
||||
map[prmScreenName][view.edge] << containment->id();
|
||||
} else {
|
||||
screenId = containment->screen();
|
||||
QString expScreenName = m_corona->screenPool()->connector(view.screen);
|
||||
|
||||
if (!Layouts::Storage::isValid(screenId)) {
|
||||
screenId = containment->lastScreen();
|
||||
}
|
||||
}
|
||||
|
||||
bool onPrimary{true};
|
||||
|
||||
//! valid onPrimary flag
|
||||
if (latteViewExists(containment)) {
|
||||
onPrimary = m_latteViews[containment]->onPrimary();
|
||||
} else {
|
||||
onPrimary = containment->config().readEntry("onPrimary", true);
|
||||
}
|
||||
|
||||
//! valid location
|
||||
Plasma::Types::Location location = containment->location();
|
||||
|
||||
if (onPrimary) {
|
||||
map[prmScreenName][location] << containment->id();
|
||||
} else {
|
||||
QString expScreenName = m_corona->screenPool()->connector(screenId);
|
||||
|
||||
if (m_corona->screenPool()->isScreenActive(screenId)) {
|
||||
map[expScreenName][location] << containment->id();
|
||||
if (m_corona->screenPool()->isScreenActive(view.screen)) {
|
||||
map[expScreenName][view.edge] << containment->id();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//! CAN BE REMOVED because we now accept primary and explicit views on ACTIVE SCREENS at ALL CASES
|
||||
Layout::ViewsMap explicitMap;
|
||||
|
||||
//! second step: explicit docks must be placed in their screens if the screen edge is free
|
||||
for (const auto containment : m_containments) {
|
||||
if (Layouts::Storage::self()->isLatteContainment(containment)) {
|
||||
int screenId{Layouts::Storage::IDNULL};
|
||||
|
||||
//! valid screen id
|
||||
if (latteViewExists(containment)) {
|
||||
screenId = m_latteViews[containment]->positioner()->currentScreenId();
|
||||
} else {
|
||||
screenId = containment->screen();
|
||||
|
||||
if (!Layouts::Storage::isValid(screenId)) {
|
||||
screenId = containment->lastScreen();
|
||||
}
|
||||
}
|
||||
|
||||
bool onPrimary{true};
|
||||
|
||||
//! valid onPrimary flag
|
||||
if (latteViewExists(containment)) {
|
||||
onPrimary = m_latteViews[containment]->onPrimary();
|
||||
} else {
|
||||
onPrimary = containment->config().readEntry("onPrimary", true);
|
||||
}
|
||||
|
||||
//! valid location
|
||||
Plasma::Types::Location location = containment->location();
|
||||
|
||||
if (!onPrimary) {
|
||||
QString expScreenName = m_corona->screenPool()->connector(screenId);
|
||||
|
||||
if (m_corona->screenPool()->isScreenActive(screenId) && !map[expScreenName].contains(location)) {
|
||||
explicitMap[expScreenName][location] << containment->id();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const QString &expScreenName : explicitMap.keys()) {
|
||||
for(const Plasma::Types::Location &expLocation : explicitMap[expScreenName].keys()) {
|
||||
map[expScreenName][expLocation] << explicitMap[expScreenName][expLocation];
|
||||
}
|
||||
}*/
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
//! the central functions that updates loading/unloading latteviews
|
||||
//! concerning screen changed (for multi-screen setups mainly)
|
||||
void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
|
||||
void GenericLayout::syncLatteViewsToScreens()
|
||||
{
|
||||
if (!m_corona) {
|
||||
return;
|
||||
@ -1400,27 +1337,17 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
|
||||
}
|
||||
|
||||
//! use valid views map based on active screens
|
||||
Layout::ViewsMap viewsMap = validViewsMap(occupiedMap);
|
||||
Layout::ViewsMap viewsMap = validViewsMap();
|
||||
|
||||
if (occupiedMap != nullptr) {
|
||||
qDebug() << "Occupied map used :: " << *occupiedMap;
|
||||
}
|
||||
|
||||
QString prmScreenName = qGuiApp->primaryScreen()->name();
|
||||
QString prmScreenName = m_corona->screenPool()->primaryScreen()->name();
|
||||
|
||||
qDebug() << "PRIMARY SCREEN :: " << prmScreenName;
|
||||
qDebug() << "LATTEVIEWS MAP :: " << viewsMap;
|
||||
|
||||
//! add views
|
||||
for (const auto containment : m_containments) {
|
||||
int screenId = containment->screen();
|
||||
|
||||
if (!Layouts::Storage::isValid(screenId)) {
|
||||
screenId = containment->lastScreen();
|
||||
}
|
||||
|
||||
if (!latteViewExists(containment) && mapContainsId(&viewsMap, containment->id())) {
|
||||
qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << m_corona->screenPool()->connector(screenId);
|
||||
if (!hasLatteView(containment) && mapContainsId(&viewsMap, containment->id())) {
|
||||
qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << mapScreenName(&viewsMap, containment->id());
|
||||
addView(containment);
|
||||
}
|
||||
}
|
||||
@ -1430,7 +1357,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
|
||||
|
||||
for (auto view : m_latteViews) {
|
||||
auto containment = view->containment();
|
||||
if (containment && !mapContainsId(&viewsMap, containment->id())) {
|
||||
if (containment && view->isOriginal() && !mapContainsId(&viewsMap, containment->id())) {
|
||||
viewsToDelete << containment;
|
||||
}
|
||||
}
|
||||
@ -1445,7 +1372,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
|
||||
|
||||
//! reconsider views
|
||||
for (const auto view : m_latteViews) {
|
||||
if (view->containment() && mapContainsId(&viewsMap, view->containment()->id())) {
|
||||
if (view->containment() && view->isOriginal() && mapContainsId(&viewsMap, view->containment()->id())) {
|
||||
//! if the dock will not be deleted its a very good point to reconsider
|
||||
//! if the screen in which is running is the correct one
|
||||
qDebug() << "syncLatteViewsToScreens: view must consider its screen... for containment:" << view->containment()->id() << " at screen:" << view->positioner()->currentScreenName();
|
||||
@ -1607,7 +1534,7 @@ void GenericLayout::updateView(const Latte::Data::View &viewData)
|
||||
}
|
||||
|
||||
view->setName(viewData.name);
|
||||
view->positioner()->setNextLocation(nextactivelayoutname, scrName, viewData.edge, viewData.alignment);
|
||||
view->positioner()->setNextLocation(nextactivelayoutname, viewData.screensGroup, scrName, viewData.edge, viewData.alignment);
|
||||
return;
|
||||
} else {
|
||||
//! viewMustBeDeleted
|
||||
|
@ -55,12 +55,15 @@ public:
|
||||
|
||||
virtual const QStringList appliedActivities() = 0; // to move at an interface
|
||||
|
||||
virtual bool initCorona();
|
||||
void importToCorona();
|
||||
bool initToCorona(Latte::Corona *corona);
|
||||
bool initContainments();
|
||||
void setCorona(Latte::Corona *corona);
|
||||
|
||||
bool isActive() const; //! is loaded and running
|
||||
virtual bool isCurrent();
|
||||
bool isWritable() const;
|
||||
bool hasCorona() const;
|
||||
|
||||
virtual int viewsCount(int screen) const;
|
||||
virtual int viewsCount(QScreen *screen) const;
|
||||
@ -85,15 +88,16 @@ public:
|
||||
Plasma::Containment *containmentForId(uint id) const;
|
||||
QList<Plasma::Containment *> subContainmentsOf(uint id) const;
|
||||
|
||||
static bool viewAtLowerScreenPriority(Latte::View *test, Latte::View *base);
|
||||
static bool viewAtLowerScreenPriority(Latte::View *test, Latte::View *base, QScreen *primaryScreen);
|
||||
static bool viewAtLowerEdgePriority(Latte::View *test, Latte::View *base);
|
||||
static QList<Latte::View *> sortedLatteViews(QList<Latte::View *> views);
|
||||
static QList<Latte::View *> sortedLatteViews(QList<Latte::View *> views, QScreen *primaryScreen);
|
||||
|
||||
QList<Latte::View *> sortedLatteViews();
|
||||
virtual QList<Latte::View *> viewsWithPlasmaShortcuts();
|
||||
virtual QList<Latte::View *> latteViews();
|
||||
ViewsMap validViewsMap(ViewsMap *occupiedMap = nullptr);
|
||||
virtual void syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap = nullptr);
|
||||
virtual QList<Latte::View *> onlyOriginalViews();
|
||||
ViewsMap validViewsMap();
|
||||
virtual void syncLatteViewsToScreens();
|
||||
|
||||
void syncToLayoutFile(bool removeLayoutId = false);
|
||||
|
||||
@ -106,10 +110,10 @@ public:
|
||||
virtual void setLastConfigViewFor(Latte::View *view);
|
||||
virtual Latte::View *lastConfigViewFor();
|
||||
|
||||
//! this function needs the layout to have first set the corona through initToCorona() function
|
||||
virtual void addView(Plasma::Containment *containment, bool forceOnPrimary = false, int explicitScreen = -1, Layout::ViewsMap *occupied = nullptr);
|
||||
//! this function needs the layout to have first set the corona through setCorona() function
|
||||
virtual void addView(Plasma::Containment *containment);
|
||||
void recreateView(Plasma::Containment *containment, bool delayed = true);
|
||||
bool latteViewExists(Plasma::Containment *containment);
|
||||
bool hasLatteView(Plasma::Containment *containment);
|
||||
|
||||
bool newView(const QString &templateName);
|
||||
Data::View newView(const Latte::Data::View &nextViewData);
|
||||
@ -190,6 +194,7 @@ private:
|
||||
bool viewDataAtLowerStatePriority(const Latte::Data::View &test, const Latte::Data::View &base) const;
|
||||
|
||||
bool mapContainsId(const ViewsMap *map, uint viewId) const;
|
||||
QString mapScreenName(const ViewsMap *map, uint viewId) const;
|
||||
|
||||
QList<int> subContainmentsOf(Plasma::Containment *containment) const;
|
||||
|
||||
@ -199,7 +204,7 @@ private:
|
||||
|
||||
private:
|
||||
bool m_blockAutomaticLatteViewCreation{false};
|
||||
|
||||
bool m_hasInitializedContainments{false};
|
||||
QPointer<Latte::View> m_lastConfigViewFor;
|
||||
|
||||
QStringList m_unloadedContainmentsIds;
|
||||
|
@ -758,6 +758,38 @@ QString Importer::uniqueLayoutName(QString name)
|
||||
return name;
|
||||
}
|
||||
|
||||
Latte::MultipleLayouts::Status Importer::multipleLayoutsStatus()
|
||||
{
|
||||
QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
|
||||
if (!QFileInfo(linkedFilePath).exists()) {
|
||||
return Latte::MultipleLayouts::Uninitialized;
|
||||
}
|
||||
|
||||
KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
|
||||
KConfigGroup multipleSettings = KConfigGroup(filePtr, "MultipleLayoutsSettings");
|
||||
return static_cast<Latte::MultipleLayouts::Status>(multipleSettings.readEntry("status", (int)Latte::MultipleLayouts::Uninitialized));
|
||||
}
|
||||
|
||||
void Importer::setMultipleLayoutsStatus(const Latte::MultipleLayouts::Status &status)
|
||||
{
|
||||
QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
|
||||
|
||||
if (!QFileInfo(linkedFilePath).exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (multipleLayoutsStatus() == status) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << " MULTIPLE LAYOUTS changed status:" << status;
|
||||
|
||||
KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
|
||||
KConfigGroup multipleSettings = KConfigGroup(filePtr, "MultipleLayoutsSettings");
|
||||
multipleSettings.writeEntry("status", (int)(status));
|
||||
multipleSettings.sync();
|
||||
}
|
||||
|
||||
QStringList Importer::checkRepairMultipleLayoutsLinkedFile()
|
||||
{
|
||||
QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
|
||||
|
@ -8,6 +8,9 @@
|
||||
#ifndef IMPORTER_H
|
||||
#define IMPORTER_H
|
||||
|
||||
// local
|
||||
#include "../apptypes.h"
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
#include <QTemporaryDir>
|
||||
@ -107,6 +110,9 @@ public:
|
||||
//! close correctly, e.g. there was a crash.
|
||||
static QStringList checkRepairMultipleLayoutsLinkedFile();
|
||||
|
||||
static Latte::MultipleLayouts::Status multipleLayoutsStatus();
|
||||
static void setMultipleLayoutsStatus(const Latte::MultipleLayouts::Status &status);
|
||||
|
||||
signals:
|
||||
void newLayoutAdded(const QString &path);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "../data/generictable.h"
|
||||
#include "../layout/abstractlayout.h"
|
||||
#include "../layout/centrallayout.h"
|
||||
#include "../layouts/storage.h"
|
||||
#include "../settings/universalsettings.h"
|
||||
#include "../templates/templatesmanager.h"
|
||||
#include "../tools/commontools.h"
|
||||
@ -51,6 +52,10 @@ Manager::Manager(QObject *parent)
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
if (memoryUsage() == Latte::MemoryUsage::MultipleLayouts) {
|
||||
m_importer->setMultipleLayoutsStatus(Latte::MultipleLayouts::Paused);
|
||||
}
|
||||
|
||||
m_importer->deleteLater();
|
||||
m_syncedLaunchers->deleteLater();
|
||||
|
||||
@ -230,7 +235,7 @@ bool Manager::switchToLayout(QString layoutName, MemoryUsage::LayoutsMemory new
|
||||
|
||||
void Manager::loadLayoutOnStartup(QString layoutName)
|
||||
{
|
||||
QStringList layouts = m_importer->checkRepairMultipleLayoutsLinkedFile();
|
||||
/* QStringList layouts = m_importer->checkRepairMultipleLayoutsLinkedFile();
|
||||
|
||||
//! Latte didn't close correctly, maybe a crash
|
||||
if (layouts.size() > 0) {
|
||||
@ -254,7 +259,7 @@ void Manager::loadLayoutOnStartup(QString layoutName)
|
||||
KMessageBox::NoExec,
|
||||
QString());
|
||||
dialog->show();
|
||||
}
|
||||
}*/
|
||||
|
||||
m_synchronizer->switchToLayout(layoutName);
|
||||
}
|
||||
@ -332,6 +337,8 @@ void Manager::setOnActivities(QString layoutName, QStringList activities)
|
||||
|
||||
void Manager::cleanupOnStartup(QString path)
|
||||
{
|
||||
Layouts::Storage::self()->removeAllClonedViews(path);
|
||||
|
||||
KSharedConfigPtr filePtr = KSharedConfig::openConfig(path);
|
||||
|
||||
KConfigGroup actionGroups = KConfigGroup(filePtr, "ActionPlugins");
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "../lattecorona.h"
|
||||
#include "../screenpool.h"
|
||||
#include "../data/errordata.h"
|
||||
#include "../data/viewdata.h"
|
||||
#include "../layout/abstractlayout.h"
|
||||
#include "../view/view.h"
|
||||
|
||||
@ -99,13 +100,13 @@ bool Storage::isLatteContainment(const KConfigGroup &group) const
|
||||
return pluginId == QLatin1String("org.kde.latte.containment");
|
||||
}
|
||||
|
||||
bool Storage::isSubContainment(const Layout::GenericLayout *layout, const Plasma::Applet *applet) const
|
||||
bool Storage::isSubContainment(const Plasma::Corona *corona, const Plasma::Applet *applet) const
|
||||
{
|
||||
if (!layout || !applet) {
|
||||
if (!corona || !applet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto containment : *layout->containments()) {
|
||||
for (const auto containment : corona->containments()) {
|
||||
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
|
||||
if (parentApplet && parentApplet == applet) {
|
||||
return true;
|
||||
@ -178,14 +179,14 @@ int Storage::subIdentityIndex(const KConfigGroup &appletGroup) const
|
||||
return IDNULL;
|
||||
}
|
||||
|
||||
Plasma::Containment *Storage::subContainmentOf(const Layout::GenericLayout *layout, const Plasma::Applet *applet)
|
||||
Plasma::Containment *Storage::subContainmentOf(const Plasma::Corona *corona, const Plasma::Applet *applet)
|
||||
{
|
||||
if (!layout || !applet) {
|
||||
if (!corona || !applet) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (isSubContainment(layout, applet)) {
|
||||
for (const auto containment : *layout->containments()) {
|
||||
if (isSubContainment(corona, applet)) {
|
||||
for (const auto containment : corona->containments()) {
|
||||
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
|
||||
if (parentApplet && parentApplet == applet) {
|
||||
return containment;
|
||||
@ -224,6 +225,8 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
|
||||
//! Setting mutable for create a containment
|
||||
layout->corona()->setImmutability(Plasma::Types::Mutable);
|
||||
|
||||
removeAllClonedViews(layout->file());
|
||||
|
||||
QString temp1FilePath = m_storageTmpDir.path() + "/" + layout->name() + ".multiple.views";
|
||||
//! we need to copy first the layout file because the kde cache
|
||||
//! may not have yet been updated (KSharedConfigPtr)
|
||||
@ -240,8 +243,9 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
|
||||
tempLayoutFile.remove();
|
||||
}
|
||||
|
||||
if (copyFile.exists())
|
||||
if (copyFile.exists()) {
|
||||
copyFile.remove();
|
||||
}
|
||||
|
||||
layoutOriginalFile.copy(tempLayoutFilePath);
|
||||
|
||||
@ -329,7 +333,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
|
||||
QString currentdestinationname = destinationLayout->name();
|
||||
QString currentdestinationfile = "";
|
||||
|
||||
if (!destinationLayout->isActive()) {
|
||||
if (!destinationLayout->hasCorona()) {
|
||||
currentdestinationfile = destinationLayout->file();
|
||||
}
|
||||
|
||||
@ -344,7 +348,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
|
||||
//! BEGIN updating the ids in the temp file
|
||||
QStringList allIds;
|
||||
|
||||
if (destinationLayout->isActive()) {
|
||||
if (destinationLayout->hasCorona()) {
|
||||
allIds << destinationLayout->corona()->containmentsIds();
|
||||
allIds << destinationLayout->corona()->appletsIds();
|
||||
} else {
|
||||
@ -475,7 +479,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
|
||||
}
|
||||
}
|
||||
|
||||
if (destinationLayout->isActive() && destinationLayout->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
|
||||
if (destinationLayout->hasCorona() && destinationLayout->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
|
||||
//! will be added in main corona multiple layouts file
|
||||
investigate_conts.group(cId).writeEntry("layoutId", destinationLayout->name());
|
||||
} else {
|
||||
@ -560,6 +564,45 @@ void Storage::syncToLayoutFile(const Layout::GenericLayout *layout, bool removeL
|
||||
}
|
||||
|
||||
filePtr->reparseConfiguration();
|
||||
removeAllClonedViews(layout->file());
|
||||
}
|
||||
|
||||
void Storage::moveToLayoutFile(const QString &layoutName)
|
||||
{
|
||||
if (layoutName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString linkedFilePath = Importer::layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
|
||||
QString layoutFilePath = Importer::layoutUserFilePath(layoutName);
|
||||
|
||||
if (linkedFilePath.isEmpty() || layoutFilePath.isEmpty() || !QFileInfo(linkedFilePath).exists() || !QFileInfo(layoutFilePath).exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
KSharedConfigPtr layoutFilePtr = KSharedConfig::openConfig(layoutFilePath);
|
||||
KConfigGroup singleContainments = KConfigGroup(layoutFilePtr, "Containments");
|
||||
singleContainments.deleteGroup();
|
||||
|
||||
KSharedConfigPtr multiFilePtr = KSharedConfig::openConfig(linkedFilePath);
|
||||
KConfigGroup multiContainments = KConfigGroup(multiFilePtr, "Containments");
|
||||
|
||||
for(const auto &cId : multiContainments.groupList()) {
|
||||
QString cname = multiContainments.group(cId).readEntry("layoutId", QString());
|
||||
|
||||
if (!cname.isEmpty() && cname == layoutName) {
|
||||
multiContainments.group(cId).writeEntry("layoutId", "");
|
||||
KConfigGroup singleGroup = singleContainments.group(cId);
|
||||
multiContainments.group(cId).copyTo(&singleGroup);
|
||||
singleGroup.writeEntry("layoutId", "");
|
||||
singleGroup.sync();
|
||||
|
||||
multiContainments.group(cId).deleteGroup();
|
||||
}
|
||||
}
|
||||
|
||||
layoutFilePtr->reparseConfiguration();
|
||||
removeAllClonedViews(layoutFilePath);
|
||||
}
|
||||
|
||||
QList<Plasma::Containment *> Storage::importLayoutFile(const Layout::GenericLayout *layout, QString file)
|
||||
@ -567,13 +610,10 @@ QList<Plasma::Containment *> Storage::importLayoutFile(const Layout::GenericLayo
|
||||
KSharedConfigPtr filePtr = KSharedConfig::openConfig(file);
|
||||
auto newContainments = layout->corona()->importLayout(KConfigGroup(filePtr, ""));
|
||||
|
||||
qDebug() << " imported containments ::: " << newContainments.length();
|
||||
|
||||
QList<Plasma::Containment *> importedViews;
|
||||
|
||||
for (const auto containment : newContainments) {
|
||||
if (isLatteContainment(containment)) {
|
||||
qDebug() << "new latte containment id: " << containment->id();
|
||||
importedViews << containment;
|
||||
}
|
||||
}
|
||||
@ -609,7 +649,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
|
||||
|
||||
qDebug() << "new view for layout";
|
||||
|
||||
if (destinationLayout->isActive()) {
|
||||
if (destinationLayout->hasCorona()) {
|
||||
//! Setting mutable for create a containment
|
||||
destinationLayout->corona()->setImmutability(Plasma::Types::Mutable);
|
||||
}
|
||||
@ -650,7 +690,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
|
||||
return Data::View();
|
||||
}
|
||||
|
||||
if (destinationLayout->isActive()) {
|
||||
if (destinationLayout->hasCorona()) {
|
||||
//! import views for active layout
|
||||
QList<Plasma::Containment *> importedViews = importLayoutFile(destinationLayout, temp2File);
|
||||
|
||||
@ -732,6 +772,7 @@ bool Storage::exportTemplate(const QString &originFile, const QString &destinati
|
||||
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
|
||||
clearExportedLayoutSettings(layoutSettingsGrp);
|
||||
destFilePtr->reparseConfiguration();
|
||||
removeAllClonedViews(destinationFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -828,6 +869,7 @@ bool Storage::exportTemplate(const Layout::GenericLayout *layout, Plasma::Contai
|
||||
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
|
||||
clearExportedLayoutSettings(layoutSettingsGrp);
|
||||
destFilePtr->reparseConfiguration();
|
||||
removeAllClonedViews(destinationFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1271,7 +1313,7 @@ Data::AppletsTable Storage::plugins(const Layout::GenericLayout *layout, const i
|
||||
}
|
||||
|
||||
for (auto applet : containment->applets()) {
|
||||
if (isSubContainment(layout, applet)) {
|
||||
if (isSubContainment(layout->corona(), applet)) {
|
||||
validcontainmentids << subContainmentId(applet->config());
|
||||
}
|
||||
}
|
||||
@ -1426,6 +1468,51 @@ bool Storage::hasContainment(const Layout::GenericLayout *layout, const int &id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::isClonedView(const Plasma::Containment *containment) const
|
||||
{
|
||||
if (!containment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isClonedView(containment->config());
|
||||
}
|
||||
|
||||
bool Storage::isClonedView(const KConfigGroup &containmentGroup) const
|
||||
{
|
||||
if (!isLatteContainment(containmentGroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int isClonedFrom = containmentGroup.readEntry("isClonedFrom", Data::View::ISCLONEDNULL);
|
||||
return (isClonedFrom != IDNULL);
|
||||
}
|
||||
|
||||
void Storage::removeAllClonedViews(const QString &filepath)
|
||||
{
|
||||
KSharedConfigPtr lFile = KSharedConfig::openConfig(filepath);
|
||||
KConfigGroup containmentGroups = KConfigGroup(lFile, "Containments");
|
||||
|
||||
QList<Data::View> clones;
|
||||
|
||||
for (const auto &contId : containmentGroups.groupList()) {
|
||||
if (isClonedView(containmentGroups.group(contId))) {
|
||||
clones << view(containmentGroups.group(contId));
|
||||
}
|
||||
}
|
||||
|
||||
if (clones.size() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clones.count()>0) {
|
||||
qDebug() << "org.kde.layout :: Removing clones from file: " << filepath;
|
||||
}
|
||||
|
||||
for (const auto &clonedata : clones) {
|
||||
qDebug() << "org.kde.layout :: Removing clone:" << clonedata.id << " and its subcontainments:" << clonedata.subcontainments;
|
||||
removeView(filepath, clonedata);
|
||||
}
|
||||
}
|
||||
|
||||
Data::GenericTable<Data::Generic> Storage::subcontainments(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const
|
||||
{
|
||||
@ -1505,8 +1592,10 @@ Data::View Storage::view(const KConfigGroup &containmentGroup)
|
||||
vdata.id = containmentGroup.name();
|
||||
vdata.name = containmentGroup.readEntry("name", QString());
|
||||
vdata.isActive = false;
|
||||
vdata.screensGroup = static_cast<Latte::Types::ScreensGroup>(containmentGroup.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
|
||||
vdata.onPrimary = containmentGroup.readEntry("onPrimary", true);
|
||||
vdata.screen = containmentGroup.readEntry("lastScreen", IDNULL);
|
||||
vdata.isClonedFrom = containmentGroup.readEntry("isClonedFrom", Data::View::ISCLONEDNULL);
|
||||
vdata.screenEdgeMargin = containmentGroup.group("General").readEntry("screenEdgeMargin", (int)-1);
|
||||
|
||||
int location = containmentGroup.readEntry("location", (int)Plasma::Types::BottomEdge);
|
||||
@ -1530,7 +1619,9 @@ void Storage::updateView(KConfigGroup viewGroup, const Data::View &viewData)
|
||||
}
|
||||
|
||||
viewGroup.writeEntry("name", viewData.name);
|
||||
viewGroup.writeEntry("screensGroup", (int)viewData.screensGroup);
|
||||
viewGroup.writeEntry("onPrimary", viewData.onPrimary);
|
||||
viewGroup.writeEntry("isClonedFrom", viewData.isClonedFrom);
|
||||
viewGroup.writeEntry("lastScreen", viewData.screen);
|
||||
viewGroup.group("General").writeEntry("screenEdgeMargin", viewData.screenEdgeMargin);
|
||||
viewGroup.writeEntry("location", (int)viewData.edge);
|
||||
@ -1602,6 +1693,30 @@ void Storage::removeContainment(const QString &filepath, const QString &containm
|
||||
lFile->reparseConfiguration();
|
||||
}
|
||||
|
||||
QStringList Storage::storedLayoutsInMultipleFile()
|
||||
{
|
||||
QStringList layouts;
|
||||
QString linkedFilePath = Importer::layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
|
||||
|
||||
if (linkedFilePath.isEmpty() || !QFileInfo(linkedFilePath).exists()) {
|
||||
return layouts;
|
||||
}
|
||||
|
||||
KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
|
||||
KConfigGroup linkedContainments = KConfigGroup(filePtr, "Containments");
|
||||
|
||||
for(const auto &cId : linkedContainments.groupList()) {
|
||||
QString layoutName = linkedContainments.group(cId).readEntry("layoutId", QString());
|
||||
|
||||
if (!layoutName.isEmpty() && !layouts.contains(layoutName)) {
|
||||
layouts << layoutName;
|
||||
}
|
||||
}
|
||||
|
||||
return layouts;
|
||||
}
|
||||
|
||||
|
||||
QString Storage::storedView(const Layout::GenericLayout *layout, const int &containmentId)
|
||||
{
|
||||
//! make sure that layout and containmentId are valid
|
||||
@ -1677,6 +1792,38 @@ QString Storage::storedView(const Layout::GenericLayout *layout, const int &cont
|
||||
return nextTmpStoredViewAbsolutePath;
|
||||
}
|
||||
|
||||
int Storage::expectedViewScreenId(const Latte::Corona *corona, const KConfigGroup &containmentGroup) const
|
||||
{
|
||||
return expectedViewScreenId(corona, self()->view(containmentGroup));
|
||||
}
|
||||
|
||||
int Storage::expectedViewScreenId(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const
|
||||
{
|
||||
if (!layout || !layout->corona()) {
|
||||
return Latte::ScreenPool::NOSCREENID;
|
||||
}
|
||||
|
||||
return expectedViewScreenId(layout->corona(), self()->view(layout, lattecontainment));
|
||||
}
|
||||
|
||||
int Storage::expectedViewScreenId(const Latte::Corona *corona, const Data::View &view) const
|
||||
{
|
||||
if (!corona || !view.isValid()) {
|
||||
return Latte::ScreenPool::NOSCREENID;
|
||||
}
|
||||
|
||||
if (view.screensGroup == Latte::Types::SingleScreenGroup || view.isCloned()) {
|
||||
return view.onPrimary ? corona->screenPool()->primaryScreenId() : view.screen;
|
||||
} else if (view.screensGroup == Latte::Types::AllScreensGroup) {
|
||||
return corona->screenPool()->primaryScreenId();
|
||||
} else if (view.screensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
QList<int> secondaryscreens = corona->screenPool()->secondaryScreenIds();
|
||||
return secondaryscreens.contains(view.screen) || secondaryscreens.isEmpty() ? view.screen : secondaryscreens[0];
|
||||
}
|
||||
|
||||
return Latte::ScreenPool::NOSCREENID;
|
||||
}
|
||||
|
||||
Data::ViewsTable Storage::views(const Layout::GenericLayout *layout)
|
||||
{
|
||||
Data::ViewsTable vtable;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <Plasma/Containment>
|
||||
|
||||
namespace Latte {
|
||||
class Corona;
|
||||
namespace Layout {
|
||||
class GenericLayout;
|
||||
}
|
||||
@ -51,14 +52,18 @@ public:
|
||||
bool isWritable(const Layout::GenericLayout *layout) const;
|
||||
bool isLatteContainment(const Plasma::Containment *containment) const;
|
||||
bool isLatteContainment(const KConfigGroup &group) const;
|
||||
bool isSubContainment(const Layout::GenericLayout *layout, const Plasma::Applet *applet) const;
|
||||
bool isSubContainment(const Plasma::Corona *corona, const Plasma::Applet *applet) const;
|
||||
|
||||
bool hasContainment(const Layout::GenericLayout *layout, const int &id);
|
||||
bool containsView(const QString &filepath, const int &viewId);
|
||||
|
||||
bool isClonedView(const Plasma::Containment *containment) const;
|
||||
bool isClonedView(const KConfigGroup &containmentGroup) const;
|
||||
void removeAllClonedViews(const QString &filepath);
|
||||
|
||||
int subContainmentId(const KConfigGroup &appletGroup) const;
|
||||
|
||||
Plasma::Containment *subContainmentOf(const Layout::GenericLayout *layout, const Plasma::Applet *applet);
|
||||
Plasma::Containment *subContainmentOf(const Plasma::Corona *corona, const Plasma::Applet *applet);
|
||||
|
||||
void lock(const Layout::GenericLayout *layout); //! make it only read-only
|
||||
void unlock(const Layout::GenericLayout *layout); //! make it writable which it should be the default
|
||||
@ -72,17 +77,23 @@ public:
|
||||
void updateView(KConfigGroup viewGroup, const Data::View &viewData);
|
||||
QString storedView(const Layout::GenericLayout *layout, const int &containmentId); //returns temp filepath containing all view data
|
||||
|
||||
void moveToLayoutFile(const QString &layoutName);
|
||||
QStringList storedLayoutsInMultipleFile();
|
||||
|
||||
void removeContainment(const QString &filepath, const QString &containmentId);
|
||||
|
||||
bool exportTemplate(const QString &originFile, const QString &destinationFile, const Data::AppletsTable &approvedApplets);
|
||||
bool exportTemplate(const Layout::GenericLayout *layout, Plasma::Containment *containment, const QString &destinationFile, const Data::AppletsTable &approvedApplets);
|
||||
|
||||
int expectedViewScreenId(const Latte::Corona *corona, const Data::View &view) const;
|
||||
int expectedViewScreenId(const Latte::Corona *corona, const KConfigGroup &containmentGroup) const;
|
||||
int expectedViewScreenId(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const;
|
||||
|
||||
/// STATIC
|
||||
//! Check if an applet config group is valid or belongs to removed applet
|
||||
static bool appletGroupIsValid(const KConfigGroup &appletGroup);
|
||||
static bool isValid(const int &id);
|
||||
|
||||
|
||||
//! AppletsData Information
|
||||
Data::Applet metadata(const QString &pluginId);
|
||||
Data::AppletsTable plugins(const Layout::GenericLayout *layout, const int containmentid = IDNULL);
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "syncedlaunchers.h"
|
||||
|
||||
// local
|
||||
#include <coretypes.h>
|
||||
#include "../lattecorona.h"
|
||||
#include "../layout/centrallayout.h"
|
||||
#include "../layouts/manager.h"
|
||||
@ -63,36 +62,61 @@ void SyncedLaunchers::removeClientObject(QObject *obj)
|
||||
}
|
||||
}
|
||||
|
||||
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName)
|
||||
QQuickItem *SyncedLaunchers::client(const int &id)
|
||||
{
|
||||
if (id <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for(const auto client: m_clients) {
|
||||
int clientid = client->property("clientId").toInt();
|
||||
if (clientid == id) {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName, QString groupId)
|
||||
{
|
||||
QList<QQuickItem *> items;
|
||||
|
||||
if (!layoutName.isEmpty()) {
|
||||
for(const auto client: m_clients) {
|
||||
QString cLayoutName = client->property("layoutName").toString();
|
||||
if (cLayoutName == layoutName) {
|
||||
items << client;
|
||||
}
|
||||
for(const auto client: m_clients) {
|
||||
QString cLayoutName = layoutName.isEmpty() ? QString() : client->property("layoutName").toString();
|
||||
QString gid = client->property("syncedGroupId").toString();
|
||||
if (cLayoutName == layoutName && gid == groupId) {
|
||||
items << client;
|
||||
}
|
||||
} else {
|
||||
items = m_clients;
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void SyncedLaunchers::addLauncher(QString layoutName, int launcherGroup, QString launcher)
|
||||
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName, uint senderId, Latte::Types::LaunchersGroup launcherGroup, QString launcherGroupId)
|
||||
{
|
||||
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
|
||||
QList<QQuickItem *> temclients;
|
||||
|
||||
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
|
||||
return;
|
||||
if (launcherGroup == Types::UniqueLaunchers && launcherGroupId.isEmpty()) {
|
||||
//! on its own, single taskmanager
|
||||
auto c = client(senderId);
|
||||
if (c) {
|
||||
temclients << client(senderId);
|
||||
}
|
||||
} else {
|
||||
temclients << clients(layoutName, launcherGroupId);
|
||||
}
|
||||
|
||||
return temclients;
|
||||
}
|
||||
|
||||
void SyncedLaunchers::addLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher)
|
||||
{
|
||||
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
|
||||
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
|
||||
|
||||
for(const auto client : clients(lName)) {
|
||||
if (auto *metaObject = client->metaObject()) {
|
||||
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
|
||||
if (auto *metaObject = c->metaObject()) {
|
||||
int methodIndex = metaObject->indexOfMethod("addSyncedLauncher(QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
@ -101,23 +125,18 @@ void SyncedLaunchers::addLauncher(QString layoutName, int launcherGroup, QString
|
||||
}
|
||||
|
||||
QMetaMethod method = metaObject->method(methodIndex);
|
||||
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
|
||||
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SyncedLaunchers::removeLauncher(QString layoutName, int launcherGroup, QString launcher)
|
||||
void SyncedLaunchers::removeLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher)
|
||||
{
|
||||
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
|
||||
|
||||
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
|
||||
|
||||
for(const auto client : clients(lName)) {
|
||||
if (auto *metaObject = client->metaObject()) {
|
||||
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
|
||||
if (auto *metaObject = c->metaObject()) {
|
||||
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncher(QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
@ -126,23 +145,18 @@ void SyncedLaunchers::removeLauncher(QString layoutName, int launcherGroup, QStr
|
||||
}
|
||||
|
||||
QMetaMethod method = metaObject->method(methodIndex);
|
||||
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
|
||||
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SyncedLaunchers::addLauncherToActivity(QString layoutName, int launcherGroup, QString launcher, QString activity)
|
||||
void SyncedLaunchers::addLauncherToActivity(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher, QString activity)
|
||||
{
|
||||
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
|
||||
|
||||
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
|
||||
|
||||
for(const auto client : clients(lName)) {
|
||||
if (auto *metaObject = client->metaObject()) {
|
||||
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
|
||||
if (auto *metaObject = c->metaObject()) {
|
||||
int methodIndex = metaObject->indexOfMethod("addSyncedLauncherToActivity(QVariant,QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
@ -151,23 +165,18 @@ void SyncedLaunchers::addLauncherToActivity(QString layoutName, int launcherGrou
|
||||
}
|
||||
|
||||
QMetaMethod method = metaObject->method(methodIndex);
|
||||
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
|
||||
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, int launcherGroup, QString launcher, QString activity)
|
||||
void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher, QString activity)
|
||||
{
|
||||
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
|
||||
|
||||
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
|
||||
|
||||
for(const auto client : clients(lName)) {
|
||||
if (auto *metaObject = client->metaObject()) {
|
||||
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
|
||||
if (auto *metaObject = c->metaObject()) {
|
||||
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncherFromActivity(QVariant,QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
@ -176,23 +185,18 @@ void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, int launche
|
||||
}
|
||||
|
||||
QMetaMethod method = metaObject->method(methodIndex);
|
||||
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
|
||||
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SyncedLaunchers::urlsDropped(QString layoutName, int launcherGroup, QStringList urls)
|
||||
void SyncedLaunchers::urlsDropped(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList urls)
|
||||
{
|
||||
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
|
||||
|
||||
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
|
||||
|
||||
for(const auto client : clients(lName)) {
|
||||
if (auto *metaObject = client->metaObject()) {
|
||||
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
|
||||
if (auto *metaObject = c->metaObject()) {
|
||||
int methodIndex = metaObject->indexOfMethod("dropSyncedUrls(QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
@ -201,26 +205,21 @@ void SyncedLaunchers::urlsDropped(QString layoutName, int launcherGroup, QString
|
||||
}
|
||||
|
||||
QMetaMethod method = metaObject->method(methodIndex);
|
||||
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, urls));
|
||||
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, urls));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QStringList launchers)
|
||||
void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList launchers)
|
||||
{
|
||||
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
|
||||
|
||||
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
|
||||
|
||||
for(const auto client : clients(lName)) {
|
||||
uint clientId = client->property("clientId").toUInt();
|
||||
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
|
||||
auto tc = client(senderId);
|
||||
|
||||
if (clientId != senderId) {
|
||||
if (auto *metaObject = client->metaObject()) {
|
||||
if (c != tc) {
|
||||
if (auto *metaObject = c->metaObject()) {
|
||||
int methodIndex = metaObject->indexOfMethod("validateSyncedLaunchersOrder(QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
@ -229,7 +228,7 @@ void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId,
|
||||
}
|
||||
|
||||
QMetaMethod method = metaObject->method(methodIndex);
|
||||
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launchers));
|
||||
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launchers));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,9 @@
|
||||
#ifndef SYNCEDLAUNCHERS_H
|
||||
#define SYNCEDLAUNCHERS_H
|
||||
|
||||
// local
|
||||
#include <coretypes.h>
|
||||
|
||||
// Qt
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
@ -42,15 +45,17 @@ public slots:
|
||||
Q_INVOKABLE void addAbilityClient(QQuickItem *client);
|
||||
Q_INVOKABLE void removeAbilityClient(QQuickItem *client);
|
||||
|
||||
Q_INVOKABLE void addLauncher(QString layoutName, int launcherGroup, QString launcher);
|
||||
Q_INVOKABLE void removeLauncher(QString layoutName, int launcherGroup, QString launcher);
|
||||
Q_INVOKABLE void addLauncherToActivity(QString layoutName, int launcherGroup, QString launcher, QString activity);
|
||||
Q_INVOKABLE void removeLauncherFromActivity(QString layoutName, int launcherGroup, QString launcher, QString activity);
|
||||
Q_INVOKABLE void urlsDropped(QString layoutName, int launcherGroup, QStringList urls);
|
||||
Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QStringList launchers);
|
||||
Q_INVOKABLE void addLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher);
|
||||
Q_INVOKABLE void removeLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher);
|
||||
Q_INVOKABLE void addLauncherToActivity(QString layoutName, uint senderId, int launcherGroup,QString launcherGroupId, QString launcher, QString activity);
|
||||
Q_INVOKABLE void removeLauncherFromActivity(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher, QString activity);
|
||||
Q_INVOKABLE void urlsDropped(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList urls);
|
||||
Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList launchers);
|
||||
|
||||
private:
|
||||
QList<QQuickItem *> clients(QString layoutName = QString());
|
||||
QList<QQuickItem *> clients(QString layoutName, QString groupId);
|
||||
QList<QQuickItem *> clients(QString layoutName, uint senderId, Latte::Types::LaunchersGroup launcherGroup, QString launcherGroupId);
|
||||
QQuickItem *client(const int &id);
|
||||
|
||||
private slots:
|
||||
void removeClientObject(QObject *obj);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "importer.h"
|
||||
#include "manager.h"
|
||||
#include "../apptypes.h"
|
||||
#include "../screenpool.h"
|
||||
#include "../data/layoutdata.h"
|
||||
#include "../lattecorona.h"
|
||||
#include "../layout/centrallayout.h"
|
||||
@ -191,7 +192,9 @@ QStringList Synchronizer::centralLayoutsNames()
|
||||
QStringList names;
|
||||
|
||||
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) {
|
||||
names << m_centralLayouts.at(0)->name();
|
||||
if (m_centralLayouts.count() > 0) {
|
||||
names << m_centralLayouts.at(0)->name();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < m_centralLayouts.size(); ++i) {
|
||||
CentralLayout *layout = m_centralLayouts.at(i);
|
||||
@ -357,6 +360,17 @@ QList<Latte::View *> Synchronizer::currentViews() const
|
||||
return views;
|
||||
}
|
||||
|
||||
QList<Latte::View *> Synchronizer::currentOriginalViews() const
|
||||
{
|
||||
QList<Latte::View *> views;
|
||||
|
||||
for(auto layout : currentLayouts()) {
|
||||
views << layout->onlyOriginalViews();
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const
|
||||
{
|
||||
QList<Latte::View *> views;
|
||||
@ -370,9 +384,12 @@ QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const
|
||||
|
||||
QList<Latte::View *> Synchronizer::sortedCurrentViews() const
|
||||
{
|
||||
QList<Latte::View *> views = currentViews();
|
||||
return Layout::GenericLayout::sortedLatteViews(currentViews(), m_manager->corona()->screenPool()->primaryScreen());
|
||||
}
|
||||
|
||||
return Layout::GenericLayout::sortedLatteViews(views);
|
||||
QList<Latte::View *> Synchronizer::sortedCurrentOriginalViews() const
|
||||
{
|
||||
return Layout::GenericLayout::sortedLatteViews(currentOriginalViews(), m_manager->corona()->screenPool()->primaryScreen());
|
||||
}
|
||||
|
||||
QList<Latte::View *> Synchronizer::viewsBasedOnActivityId(const QString &id) const
|
||||
@ -436,7 +453,6 @@ void Synchronizer::addLayout(CentralLayout *layout)
|
||||
{
|
||||
if (!m_centralLayouts.contains(layout)) {
|
||||
m_centralLayouts.append(layout);
|
||||
layout->initToCorona(m_manager->corona());
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,14 +556,14 @@ void Synchronizer::unloadCentralLayout(CentralLayout *layout)
|
||||
if (pos>=0) {
|
||||
CentralLayout *central = m_centralLayouts.takeAt(pos);
|
||||
|
||||
if (m_multipleModeInitialized) {
|
||||
if (m_multipleModeInitialized && !m_manager->corona()->inQuit()) {
|
||||
central->syncToLayoutFile(true);
|
||||
}
|
||||
|
||||
central->unloadLatteViews();
|
||||
central->unloadContainments();
|
||||
|
||||
if (m_multipleModeInitialized) {
|
||||
if (m_multipleModeInitialized && !m_manager->corona()->inQuit()) {
|
||||
m_manager->clearUnloadedContainmentsFromLinkedFile(central->unloadedContainmentsIds(), true);
|
||||
}
|
||||
|
||||
@ -619,6 +635,24 @@ void Synchronizer::unloadLayouts()
|
||||
m_multipleModeInitialized = false;
|
||||
}
|
||||
|
||||
void Synchronizer::unloadPreloadedLayouts()
|
||||
{
|
||||
QStringList currentnames;
|
||||
QStringList preloadednames = Layouts::Storage::self()->storedLayoutsInMultipleFile();
|
||||
|
||||
for(auto l : m_centralLayouts) {
|
||||
if (l) {
|
||||
currentnames << l->name();
|
||||
}
|
||||
}
|
||||
|
||||
for(auto lname : preloadednames) {
|
||||
if (!currentnames.contains(lname)) {
|
||||
Layouts::Storage::self()->moveToLayoutFile(lname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Synchronizer::memoryInitialized() const
|
||||
{
|
||||
return ((m_manager->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.size()>0)
|
||||
@ -642,13 +676,23 @@ bool Synchronizer::initSingleMode(QString layoutName)
|
||||
//! Tasks plasmoid case that triggers layouts switching through its context menu
|
||||
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutName, layoutpath]() {
|
||||
qDebug() << " ... initializing layout in single mode : " << layoutName << " - " << layoutpath;
|
||||
unloadPreloadedLayouts();
|
||||
unloadLayouts();
|
||||
|
||||
//! load the main layout/corona file
|
||||
//! load the main single layout/corona file
|
||||
CentralLayout *newLayout = new CentralLayout(this, layoutpath, layoutName);
|
||||
addLayout(newLayout);
|
||||
|
||||
m_manager->loadLatteLayout(layoutpath);
|
||||
//! Order of initialization steps is very important and guarantees correct startup initialization
|
||||
//! Step1: corona is set for the layout
|
||||
//! Step2: containments from file are loaded into main corona
|
||||
//! Step3: layout connects to corona signals and slots
|
||||
//! Step4: layout is added in manager and is accesible for others to find
|
||||
//! Step5: layout is attaching its initial containmens and is now considered ACTIVE
|
||||
newLayout->setCorona(m_manager->corona()); //step1
|
||||
m_manager->loadLatteLayout(layoutpath); //step2
|
||||
newLayout->initCorona(); //step3
|
||||
addLayout(newLayout); //step4
|
||||
newLayout->initContainments(); //step5
|
||||
|
||||
emit centralLayoutsChanged();
|
||||
|
||||
@ -664,7 +708,7 @@ bool Synchronizer::initSingleMode(QString layoutName)
|
||||
}
|
||||
|
||||
m_manager->corona()->universalSettings()->setSingleModeLayoutName(layoutName);
|
||||
|
||||
m_manager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Uninitialized);
|
||||
emit initializationFinished();
|
||||
});
|
||||
|
||||
@ -687,6 +731,9 @@ bool Synchronizer::initMultipleMode(QString layoutName)
|
||||
qDebug() << " ... initializing layout in multiple mode : " << layoutName ;
|
||||
unloadLayouts();
|
||||
|
||||
QStringList layoutsinmultiplestorage = Layouts::Storage::self()->storedLayoutsInMultipleFile();
|
||||
qDebug() << "Preloaded Multiple Layouts in Storage :: " << layoutsinmultiplestorage;
|
||||
|
||||
m_manager->loadLatteLayout(layoutPath(QString(Layout::MULTIPLELAYOUTSHIDDENNAME)));
|
||||
|
||||
m_multipleModeInitialized = true;
|
||||
@ -697,8 +744,8 @@ bool Synchronizer::initMultipleMode(QString layoutName)
|
||||
switchToLayoutInMultipleModeBasedOnActivities(layoutName);
|
||||
}
|
||||
|
||||
syncMultipleLayoutsToActivities();
|
||||
|
||||
syncMultipleLayoutsToActivities(layoutsinmultiplestorage);
|
||||
m_manager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Running);
|
||||
emit initializationFinished();
|
||||
});
|
||||
|
||||
@ -878,7 +925,7 @@ bool Synchronizer::switchToLayout(QString layoutName, MemoryUsage::LayoutsMemory
|
||||
}
|
||||
}
|
||||
|
||||
void Synchronizer::syncMultipleLayoutsToActivities()
|
||||
void Synchronizer::syncMultipleLayoutsToActivities(QStringList preloadedLayouts)
|
||||
{
|
||||
qDebug() << " ---- --------- ------ syncMultipleLayoutsToActivities ------- ";
|
||||
qDebug() << " ---- --------- ------ ------------------------------- ------- ";
|
||||
@ -899,14 +946,6 @@ void Synchronizer::syncMultipleLayoutsToActivities()
|
||||
|
||||
//! discover layouts assigned to explicit activities based on running activities
|
||||
for (const auto &activity : runningActivities()) {
|
||||
#if KF5_VERSION_MINOR < 81
|
||||
if (KWindowSystem::isPlatformWayland() && (m_activitiesController->currentActivity() != activity)){
|
||||
//! Wayland Protection: Plasma wayland does not support Activities for windows before kde frameworks 5.81
|
||||
//! In that scenario we can load the layouts that belong OnAllActivities + (ForFreeActivities OR SpecificActivity)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_assignedLayouts.contains(activity)) {
|
||||
layoutNamesToLoad << m_assignedLayouts[activity];
|
||||
}
|
||||
@ -919,6 +958,12 @@ void Synchronizer::syncMultipleLayoutsToActivities()
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto lname : preloadedLayouts) {
|
||||
if (!layoutNamesToLoad.contains(lname)) {
|
||||
layoutNamesToUnload << lname;
|
||||
}
|
||||
}
|
||||
|
||||
QString defaultForcedLayout;
|
||||
|
||||
//! Safety
|
||||
@ -939,8 +984,20 @@ void Synchronizer::syncMultipleLayoutsToActivities()
|
||||
|
||||
if (newLayout) {
|
||||
qDebug() << "ACTIVATING LAYOUT ::::: " << layoutname;
|
||||
addLayout(newLayout);
|
||||
newLayout->importToCorona();
|
||||
|
||||
//! Order of initialization steps is very important and guarantees correct startup initialization
|
||||
//! Step1: corona is set for the layout
|
||||
//! Step2: containments from the layout file are adjusted and are imported into main corona
|
||||
//! Step3: layout connects to corona signals and slots
|
||||
//! Step4: layout is added in manager and is accesible for others to find
|
||||
//! Step5: layout is attaching its initial containmens and is now considered ACTIVE
|
||||
newLayout->setCorona(m_manager->corona()); //step1
|
||||
if (!preloadedLayouts.contains(layoutname)) {
|
||||
newLayout->importToCorona(); //step2
|
||||
}
|
||||
newLayout->initCorona(); //step3
|
||||
addLayout(newLayout); //step4
|
||||
newLayout->initContainments(); //step5
|
||||
|
||||
if (!defaultForcedLayout.isEmpty() && defaultForcedLayout == layoutname) {
|
||||
emit newLayoutAdded(newLayout->data());
|
||||
@ -967,8 +1024,8 @@ void Synchronizer::syncMultipleLayoutsToActivities()
|
||||
emit currentLayoutIsSwitching(layoutname);
|
||||
}
|
||||
|
||||
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutNamesToUnload]() {
|
||||
unloadLayouts(layoutNamesToUnload);
|
||||
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutNamesToUnload, preloadedLayouts]() {
|
||||
unloadLayouts(layoutNamesToUnload, preloadedLayouts);
|
||||
});
|
||||
}
|
||||
|
||||
@ -980,7 +1037,7 @@ void Synchronizer::syncMultipleLayoutsToActivities()
|
||||
}
|
||||
}
|
||||
|
||||
void Synchronizer::unloadLayouts(const QStringList &layoutNames)
|
||||
void Synchronizer::unloadLayouts(const QStringList &layoutNames, const QStringList &preloadedLayouts)
|
||||
{
|
||||
if (layoutNames.isEmpty()) {
|
||||
return;
|
||||
@ -995,11 +1052,19 @@ void Synchronizer::unloadLayouts(const QStringList &layoutNames)
|
||||
qDebug() << "REMOVING LAYOUT ::::: " << layoutname;
|
||||
m_centralLayouts.removeAt(posLayout);
|
||||
|
||||
layout->syncToLayoutFile(true);
|
||||
if (!m_manager->corona()->inQuit()) {
|
||||
layout->syncToLayoutFile(true);
|
||||
}
|
||||
|
||||
layout->unloadContainments();
|
||||
layout->unloadLatteViews();
|
||||
m_manager->clearUnloadedContainmentsFromLinkedFile(layout->unloadedContainmentsIds());
|
||||
if (!m_manager->corona()->inQuit()) {
|
||||
m_manager->clearUnloadedContainmentsFromLinkedFile(layout->unloadedContainmentsIds());
|
||||
}
|
||||
delete layout;
|
||||
} else if (preloadedLayouts.contains(layoutname)) {
|
||||
Layouts::Storage::self()->moveToLayoutFile(layoutname);
|
||||
//! just make sure that
|
||||
}
|
||||
}
|
||||
|
||||
@ -1017,7 +1082,7 @@ void Synchronizer::updateKWinDisabledBorders()
|
||||
if (!m_manager->corona()->universalSettings()->canDisableBorders()) {
|
||||
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(false);
|
||||
} else {
|
||||
if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
|
||||
if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.size() > 0) {
|
||||
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(m_centralLayouts.at(0)->disableBordersForMaximizedWindows());
|
||||
} else if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
|
||||
QList<CentralLayout *> centrals = centralLayoutsForActivity(m_manager->corona()->activitiesConsumer()->currentActivity());
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QTimer>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
namespace Latte {
|
||||
@ -65,7 +66,7 @@ public:
|
||||
void pauseLayout(QString layoutName);
|
||||
void syncActiveLayoutsToOriginalFiles();
|
||||
void syncLatteViewsToScreens();
|
||||
void syncMultipleLayoutsToActivities();
|
||||
void syncMultipleLayoutsToActivities(QStringList preloadedLayouts = QStringList());
|
||||
|
||||
//! In that case single layout file must be removed after loading the new layout
|
||||
void setIsSingleLayoutInDeprecatedRenaming(const bool &enabled);
|
||||
@ -95,7 +96,9 @@ public:
|
||||
QList<CentralLayout *> currentLayouts() const;
|
||||
QList<Latte::View *> currentViews() const;
|
||||
QList<Latte::View *> currentViewsWithPlasmaShortcuts() const;
|
||||
QList<Latte::View *> currentOriginalViews() const;
|
||||
QList<Latte::View *> sortedCurrentViews() const;
|
||||
QList<Latte::View *> sortedCurrentOriginalViews() const;
|
||||
QList<Latte::View *> viewsBasedOnActivityId(const QString &id) const;
|
||||
|
||||
CentralLayout *centralLayout(QString layoutname) const;
|
||||
@ -130,13 +133,14 @@ private slots:
|
||||
void onActivityRemoved(const QString &activityid);
|
||||
void onLayoutAdded(const QString &layoutpath);
|
||||
|
||||
void unloadPreloadedLayouts();
|
||||
void reloadAssignedLayouts();
|
||||
void updateBorderlessMaximizedAfterTimer();
|
||||
|
||||
private:
|
||||
void addLayout(CentralLayout *layout);
|
||||
void unloadCentralLayout(CentralLayout *layout);
|
||||
void unloadLayouts(const QStringList &layoutNames);
|
||||
void unloadLayouts(const QStringList &layoutNames, const QStringList &preloadedLayouts);
|
||||
|
||||
bool initSingleMode(QString layoutName);
|
||||
bool initMultipleMode(QString layoutName);
|
||||
|
36
app/main.cpp
36
app/main.cpp
@ -25,9 +25,11 @@
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QLockFile>
|
||||
#include <QSessionManager>
|
||||
#include <QSharedMemory>
|
||||
#include <QTextStream>
|
||||
|
||||
// KDE
|
||||
#include <KCrash>
|
||||
@ -50,6 +52,7 @@ inline void detectPlatform(int argc, char **argv);
|
||||
inline void filterDebugMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||
|
||||
QString filterDebugMessageText;
|
||||
QString filterDebugLogFile;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -70,9 +73,11 @@ int main(int argc, char **argv)
|
||||
|
||||
QQuickWindow::setDefaultAlphaBuffer(true);
|
||||
|
||||
qputenv("QT_WAYLAND_DISABLE_FIXED_POSITIONS", {});
|
||||
const bool qpaVariable = qEnvironmentVariableIsSet("QT_QPA_PLATFORM");
|
||||
detectPlatform(argc, argv);
|
||||
QApplication app(argc, argv);
|
||||
qunsetenv("QT_WAYLAND_DISABLE_FIXED_POSITIONS");
|
||||
|
||||
if (!qpaVariable) {
|
||||
// don't leak the env variable to processes we start
|
||||
@ -171,6 +176,12 @@ int main(int argc, char **argv)
|
||||
filterDebugEventSinkMask.setDescription(QStringLiteral("Show visual indicators for areas of EventsSink."));
|
||||
filterDebugEventSinkMask.setFlags(QCommandLineOption::HiddenFromHelp);
|
||||
parser.addOption(filterDebugEventSinkMask);
|
||||
|
||||
QCommandLineOption filterDebugLogCmd(QStringList() << QStringLiteral("log-file"));
|
||||
filterDebugLogCmd.setDescription(QStringLiteral("Forward debug output in a log text file."));
|
||||
filterDebugLogCmd.setFlags(QCommandLineOption::HiddenFromHelp);
|
||||
filterDebugLogCmd.setValueName(i18nc("command line: log-filepath", "filter_log_filepath"));
|
||||
parser.addOption(filterDebugLogCmd);
|
||||
//! END: Hidden options
|
||||
|
||||
parser.process(app);
|
||||
@ -398,6 +409,11 @@ int main(int argc, char **argv)
|
||||
filterDebugMessageText = parser.value(QStringLiteral("debug-text"));
|
||||
}
|
||||
|
||||
//! log file for debug output
|
||||
if (parser.isSet(QStringLiteral("log-file")) && !parser.value(QStringLiteral("log-file")).isEmpty()) {
|
||||
filterDebugLogFile = parser.value(QStringLiteral("log-file"));
|
||||
}
|
||||
|
||||
//! debug/mask options
|
||||
if (parser.isSet(QStringLiteral("debug")) || parser.isSet(QStringLiteral("mask")) || parser.isSet(QStringLiteral("debug-text"))) {
|
||||
qInstallMessageHandler(filterDebugMessageOutput);
|
||||
@ -406,7 +422,6 @@ int main(int argc, char **argv)
|
||||
qInstallMessageHandler(noMessageOutput);
|
||||
}
|
||||
|
||||
|
||||
auto signal_handler = [](int) {
|
||||
qGuiApp->exit();
|
||||
};
|
||||
@ -467,14 +482,21 @@ inline void filterDebugMessageOutput(QtMsgType type, const QMessageLogContext &c
|
||||
TypeColor = CRED;
|
||||
} else {
|
||||
TypeColor = CIGREEN;
|
||||
|
||||
}
|
||||
|
||||
qDebug().nospace() << TypeColor << "[" << typeStr.toStdString().c_str() << " : " << CGREEN << QTime::currentTime().toString("h:mm:ss.zz").toStdString().c_str() << TypeColor << "]" << CNORMAL
|
||||
#ifndef QT_NO_DEBUG
|
||||
<< CIRED << " [" << CCYAN << function << CIRED << ":" << CCYAN << context.line << CIRED << "]"
|
||||
#endif
|
||||
<< CICYAN << " - " << CNORMAL << msg;
|
||||
if (filterDebugLogFile.isEmpty()) {
|
||||
qDebug().nospace() << TypeColor << "[" << typeStr.toStdString().c_str() << " : " << CGREEN << QTime::currentTime().toString("h:mm:ss.zz").toStdString().c_str() << TypeColor << "]" << CNORMAL
|
||||
#ifndef QT_NO_DEBUG
|
||||
<< CIRED << " [" << CCYAN << function << CIRED << ":" << CCYAN << context.line << CIRED << "]"
|
||||
#endif
|
||||
<< CICYAN << " - " << CNORMAL << msg;
|
||||
} else {
|
||||
QFile logfile(filterDebugLogFile);
|
||||
logfile.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||
QTextStream logts(&logfile);
|
||||
logts << "[" << typeStr.toStdString().c_str() << " : " << QTime::currentTime().toString("h:mm:ss.zz").toStdString().c_str() << "]"
|
||||
<< " - " << msg << Qt::endl;
|
||||
}
|
||||
}
|
||||
|
||||
inline void configureAboutData()
|
||||
|
@ -4,7 +4,6 @@
|
||||
<extends>org.kde.plasmashell</extends>
|
||||
<name>Latte</name>
|
||||
<name xml:lang="ar">لاتيه</name>
|
||||
<name xml:lang="ast">Latte</name>
|
||||
<name xml:lang="az">Latte</name>
|
||||
<name xml:lang="ca">Latte</name>
|
||||
<name xml:lang="ca-valencia">Latte</name>
|
||||
@ -13,6 +12,7 @@
|
||||
<name xml:lang="de">Latte</name>
|
||||
<name xml:lang="el">Latte</name>
|
||||
<name xml:lang="en-GB">Latte</name>
|
||||
<name xml:lang="eo">Latte</name>
|
||||
<name xml:lang="es">Latte</name>
|
||||
<name xml:lang="et">Latte</name>
|
||||
<name xml:lang="eu">Latte</name>
|
||||
@ -22,6 +22,7 @@
|
||||
<name xml:lang="ia">Latte</name>
|
||||
<name xml:lang="id">Latte</name>
|
||||
<name xml:lang="it">Latte</name>
|
||||
<name xml:lang="ka">Latte</name>
|
||||
<name xml:lang="ko">Latte</name>
|
||||
<name xml:lang="lt">Latte</name>
|
||||
<name xml:lang="nl">Latte</name>
|
||||
@ -40,7 +41,6 @@
|
||||
<name xml:lang="zh-TW">Latte</name>
|
||||
<summary>Dock for the masses</summary>
|
||||
<summary xml:lang="ar">رصيف للأمور الكبيرة</summary>
|
||||
<summary xml:lang="ast">Árees d'anclaxe pa les mases</summary>
|
||||
<summary xml:lang="az">Hər kəs üçün Dok panel</summary>
|
||||
<summary xml:lang="ca">Acoblador per a les masses</summary>
|
||||
<summary xml:lang="ca-valencia">Acoblador per a les masses</summary>
|
||||
@ -49,6 +49,7 @@
|
||||
<summary xml:lang="de">Dock für die Massen</summary>
|
||||
<summary xml:lang="el">Πίνακες εφαρμογών για όλον τον κόσμο</summary>
|
||||
<summary xml:lang="en-GB">Dock for the masses</summary>
|
||||
<summary xml:lang="eo">Doko por la amasoj</summary>
|
||||
<summary xml:lang="es">Un dock para las masas</summary>
|
||||
<summary xml:lang="et">Dokk massidele</summary>
|
||||
<summary xml:lang="eu">Jendartearen kaia</summary>
|
||||
@ -68,33 +69,33 @@
|
||||
<summary xml:lang="sk">Dok pre masy</summary>
|
||||
<summary xml:lang="sl">Dok za množice</summary>
|
||||
<summary xml:lang="sv">Dockningsfönster för alla</summary>
|
||||
<summary xml:lang="tr">Kitleler için kilitleme</summary>
|
||||
<summary xml:lang="tr">Kitleler için rıhtım</summary>
|
||||
<summary xml:lang="uk">Панель для усіх</summary>
|
||||
<summary xml:lang="x-test">xxDock for the massesxx</summary>
|
||||
<summary xml:lang="zh-CN">给大众使用的停靠栏</summary>
|
||||
<summary xml:lang="zh-CN">符合大多数人使用习惯的停靠栏程序</summary>
|
||||
<summary xml:lang="zh-TW">給大眾使用的 Dock</summary>
|
||||
<description>
|
||||
<p>Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.</p>
|
||||
<p xml:lang="ar">«لاتيه» هو رصيف مبنيّ على أُطر عمل «بلازما» حيث يقدّم تجربة أنيقة وبدهيّة لمهامك والبلازمويد لديك. يعمل الرّصيف على إنشاء حركة للمحتويات باستخدام تأثير تقريب القطع المكافئ، ويحاول أن يكون بمتناول يديك عند حاجتك إليه فقط.</p>
|
||||
<p xml:lang="ast">Latte ye un área d'anclaxe basáu nos frameworks de Plasma qu'apurren una esperiencia elegante ya intuitiva pa xeres y plasmoides. Anima'l so conteníu usando l'efeutu de zoom parabólicu y tenta d'amosase namás cuando se precisa.</p>
|
||||
<p xml:lang="az">Latte, plasma iş çərçivələrinə əsaslanan, tapşırıq və plasmoid'ləriniz üçün rahat istifadə oluna bilən, zərif və intiutiv bir Dok Panelidir. O tərkibində yerləşən nişanları parabolik böyütmə effekti ilə canlandırır və yalnız lazım olduqda görünməyə çalışır.</p>
|
||||
<p xml:lang="ca">El Latte és un acoblador basat en els Frameworks del Plasma que proporciona una experiència elegant i intuïtiva per a les vostres tasques i els plasmoides. Anima els seus continguts usant un efecte de zoom parabòlic i intenta mostrar-se només quan cal.</p>
|
||||
<p xml:lang="ca-valencia">El Latte és un acoblador basat en els Frameworks del Plasma que proporciona una experiència elegant i intuïtiva per a les vostres tasques i els plasmoides. Anima els seus continguts usant un efecte de zoom parabòlic i intenta mostrar-se només quan cal.</p>
|
||||
<p xml:lang="ca-valencia">Latte és un acoblador basat en els Frameworks de Plasma que proporciona una experiència elegant i intuïtiva per a les vostres tasques i els plasmoides. Anima els seus continguts utilitzant un efecte de zoom parabòlic i intenta mostrar-se només quan cal.</p>
|
||||
<p xml:lang="da">Latte er en dok som er baseret på plasma-frameworks som giver en elegant og intuitiv oplevelse til dine opgaver og plasmoids. Den animerer dens indhold med parabolsk zoom og prøver på kun at være der når der er brug for det.</p>
|
||||
<p xml:lang="de">Latte-Dock ist ein auf Plasma-Framework-Technologie basierendes Dock für Anwendungen und Plasmoide, das ein elegantes und intuitives Nutzererlebnis bietet.Seine Inhalte werden mithilfe parabolischer Zoom-Effekte animiert. Latte versucht, immer zur Stelle zu sein, wenn es benötigt wird.</p>
|
||||
<p xml:lang="el">Το Latte είναι ένας πίνακας εφαρμογών βασισμένος στις βιβλιοθήκες plasma που εστιάζει στην καλαισθησία και παρέχει ένα όμορφο περιβάλλον για τις εργασίες και τα γραφικά συστατικά σας. Χρησιμοποιεί το παραβολικό εφέ έτσι ώστε να απεικονίσει τα περιεχόμενα του και προσπαθεί να είναι εκεί μόνο όταν το χρειάζεστε.</p>
|
||||
<p xml:lang="en-GB">Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.</p>
|
||||
<p xml:lang="eo">Latte estas doko bazita sur plasma-frameworks kiu provizas elegantan kaj intuician sperton por viaj taskoj kaj plasmoidoj. Ĝi animas sian enhavon uzante parabolan zomefikon kaj provas esti tie nur kiam ĝi estas bezonata.</p>
|
||||
<p xml:lang="es">Latte es un dock basado en la infraestructura plasma que proporciona una experiencia intuitiva y elegante para sus tareas y plasmoides. Anima sus contenidos usando un efecto de zoom parabólico e intenta estar presente solo cuando se le necesita.</p>
|
||||
<p xml:lang="et">Latte on Plasma raamistikul põhinev dokk, mis pakub elegantset ja loomupärast kogemust ülesannete ja plasmoididega majandamisel. Sisu animeeritakse paraboolse suurenduse efekti abil ning dokk püüab olla alati sinu käsutuses, kui sa seda vajad.</p>
|
||||
<p xml:lang="eu">Plasma frameworks-en oinarritutako kaia da Latte, bizipen eder eta intuitiboa hornitzen duena zure ataza eta aplikaziotxoentzat. Honek bere edukiak animatzen ditu zoom parabolikoaren efektua erabiliz eta bertan behar denean bakarrik egoten saiatzen da.</p>
|
||||
<p xml:lang="fi">Latte on Plasma Frameworksiin perustuva telakka, joka tarjoaa tyylikkään ja intuitiivisen tehtävä- ja sovelmakäyttöliittymän. Se animoi sisältönsä parabolisella lähennystehosteella ja yrittää pysyä poissa, kunnes sitä tarvitaan.</p>
|
||||
<p xml:lang="fr">Latte est une barre des tâches conçue à partir de l'environnement de développement de Plasma. Il propose une expérience élégante et intuitive pour vos tâches et pour vos composants graphiques. Son contenu est animé grâce à l'utilisation d'un effet de zoom parabolique. Il n'essaie d'être là que lorsque cela est nécessaire.</p>
|
||||
<p xml:lang="gl">Latte é unha doca construída coas infraestruturas de Plasma que fornece unha experiencia elegante e intuitiva para as súas tarefas e plasmoides. Anima o seu contido usando o efecto de ampliación parabólico e intenta estar aí só cando se necesita.</p>
|
||||
<p xml:lang="gl">Latte é unha doca construída coas infraestruturas de Plasma que fornece unha experiencia elegante e intuitiva para as súas tarefas e trebellos. Anima o seu contido usando o efecto de ampliación parabólico e intenta estar aí só cando se necesita.</p>
|
||||
<p xml:lang="id">Latte adalah dock berdasarkan kerangka kerja plasma yang memberikan pengalaman yang elegan dan intuitif untuk tugas dan plasmoid kamu. Ini menganimasikan konten dengan menggunakan efek zoom parabola dan mencoba untuk berada di sana hanya ketika diperlukan.</p>
|
||||
<p xml:lang="it">Latte è un'area di aggancio basata su plasma frameworks. Offre ai tuoi processi e ai tuoi plasmoidi un'esperienza elegante ed intuitiva, animando il loro contenuto con un effetto zoom parabolico e facendosi trovare solo quando necessario.</p>
|
||||
<p xml:lang="ko">Latte는 플라즈마 프레임워크를 기반으로 한 도구집으로 작업 및 plasmoids에 대한 우아하고 직관적인 경험을 제공합니다. 포물선 모양의 확대/축소 효과를 사용하여 내용을 애니메이션화하고 필요할 때만 도구집을 표시됩니다.</p>
|
||||
<p xml:lang="lt">Latte yra Plasma karkasu pagrįstas dokas, kuris teikia elegantišką ir intuityvų jūsų užduočių ir Plasma įskiepių patyrimą. Jis animuoja savo turinį naudodamas parabolinį mastelio efektą ir stengiasi pasirodyti tik tuomet, kai jo reikia.</p>
|
||||
<p xml:lang="nl">Latte is een dock gebaseerd op plasma frameworks die een elegante en intuïtieve ervaring voor uw taken en plasmoids is. Het animeert zijn inhoud door een parabolisch zoomeffect te gebruiken en probeert er alleen te zijn wanneer nodig.</p>
|
||||
<p xml:lang="nl">Latte voorziet uw desktop van Docks of Panelen met behulp waarvan u uw taken en widgets op een elegante en eenvoudige manier kunt beheren. Latte animeert de inhoud m.b.v. parabolische effecten in macOS-stijl en probeert er alleen te zijn wanneer dat nodig is. </p>
|
||||
<p xml:lang="nn">Latte er ei dokk basert på Plasma-rammeverket og som gjev elegant og intuitiv tilgang til program/oppgåver og skjermelement. Innhaldet vert animerte med parabolske forstørringseffektar og programmet prøver å ikkje vera i vegen når det ikkje trengst.</p>
|
||||
<p xml:lang="pl">Latte jest dokiem opartym na szkieletach plazmy, który zapewnia przyjemne i intuicyjne odczucia w pracy z zadaniami i plazmoidami. Animuje swoją zawartośc przy użyciu efektu przybliżenia parabolicznego i próbuje być widocznym tylko wtedy, gdy jest potrzebny.</p>
|
||||
<p xml:lang="pt">O Latte é uma área acoplável baseada nas plataformas do Plasma que oferece uma experiência elegante e intuitiva para as suas tarefas e plasmóides. Ele anima o seu conteúdo, usando um efeito de ampliação parabólico e tenta estar apenas onde for necessário.</p>
|
||||
@ -103,14 +104,13 @@
|
||||
<p xml:lang="sk">Latte je dok založený na frameworkoch plasma, ktorý poskytuje elegantné a intuitívne rozhranie pre vaše úlohy a plazmoidy. Animuje svoj obsah použitím parabolického efektu priblíženia a snaží sa by tam len vtedy, keď je to treba.</p>
|
||||
<p xml:lang="sl">Latte je dok, ki temelji v okolju Plasma Frameworka, ki zagotavlja elegantno in intuitivno izkušnjo za vaše naloge in plazmoide. Svojo vsebino animiraz uporabo učinka paraboličnega povečevanja in poskuša biti tam le, kadar je to potrebno.</p>
|
||||
<p xml:lang="sv">Latte är ett dockningsfönster baserat på Plasma ramverk som erbjuder en elegant och intuitiv upplevelse för aktiviteter och Plasmoider. Det animerar innehållet genom att använda en paraboleffekt för zoomning, och försöker bara vara där när det behövs.</p>
|
||||
<p xml:lang="tr">Latte, görevleriniz ve plasmoidleriniz için zarif ve sezgisel bir deneyim sağlayan plazma çerçevelerine dayalı bir yuvadır. İçeriğini parabolik yakınlaştırma efekti kullanarak canlandırır ve sadece ihtiyaç duyulduğunda orada olmaya çalışır.</p>
|
||||
<p xml:lang="tr">Latte, görevleriniz ve Plasmoid'leriniz için zarif ve sezgisel bir deneyim sağlayan Plasma kod kitaplıklarını kullanan bir rıhtımdır. İçeriğini parabolik yakınlaştırma efekti kullanarak canlandırır ve yalnızca gereksinim duyulduğunda orada olmaya çalışır.</p>
|
||||
<p xml:lang="uk">Латте — панель на основі бібліотек Плазми, яка забезпечує елегантний і інтуїтивно зрозумілий доступ до ваших завдань та плазмоїдів. Вміст панелі анімується за допомогою ефекту параболічного збільшення і показується лише тоді, коли це потрібно.</p>
|
||||
<p xml:lang="x-test">xxLatte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.xx</p>
|
||||
<p xml:lang="zh-CN">Latte 是一个基于 plasma 框架的停靠栏,它为您的任务及 plasmoid 提供了优雅直观的体验。它为它的内容赋予抛物线缩放动画效果,并尽可能仅在它被需要时出现。</p>
|
||||
<p xml:lang="zh-CN">Latte 是一款基于 Plasma 框架的停靠栏程序,它为您的任务和 Plasma 小程序提供了简洁优雅、直观易懂的使用体验。它能够以抛物线缩放动效显示其内容,并尽可能在不需要的时候降低存在感,减少对用户的干扰。</p>
|
||||
<p xml:lang="zh-TW">Latte 是一個基於 Plasma 框架並提供您的工作與 plasmoid 優雅與直觀體驗的 dock。它使用拋物線縮放效果來讓您的內容動畫化,並試著只在您需要它時出現。</p>
|
||||
<p> "Art In Coffee" </p>
|
||||
<p xml:lang="ar">”الفنّ في القهوة“</p>
|
||||
<p xml:lang="ast">«Arte nel café»</p>
|
||||
<p xml:lang="az">"Qəhvədə İncəsənət"</p>
|
||||
<p xml:lang="ca">«Art al cafè»</p>
|
||||
<p xml:lang="ca-valencia">«Art al cafè»</p>
|
||||
@ -119,6 +119,7 @@
|
||||
<p xml:lang="de">„Art In Coffee“</p>
|
||||
<p xml:lang="el">"Τέχνη στον Καφέ"</p>
|
||||
<p xml:lang="en-GB">"Art In Coffee"</p>
|
||||
<p xml:lang="eo">"Arto En Kafo"</p>
|
||||
<p xml:lang="es">"El arte en el café"</p>
|
||||
<p xml:lang="et">"Kohvikunst"</p>
|
||||
<p xml:lang="eu">"Artea kafean"</p>
|
||||
@ -127,6 +128,7 @@
|
||||
<p xml:lang="gl">«Arte en café».</p>
|
||||
<p xml:lang="id">"Art In Coffee"</p>
|
||||
<p xml:lang="it">«Art In Coffee»</p>
|
||||
<p xml:lang="ka">"ხელოვნება ყავაში"</p>
|
||||
<p xml:lang="ko">"커피 안의 예술"</p>
|
||||
<p xml:lang="lt">"Menas kavoje"</p>
|
||||
<p xml:lang="nl">"Kunst in koffie"</p>
|
||||
@ -152,7 +154,7 @@
|
||||
<url type="bugtracker">@BUG_ADDRESS@</url>
|
||||
<url type="faq">@FAQS@</url>
|
||||
<developer_name>Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="ast">Michail Vourlakos y Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="ar">ميخائيل فورلاكوس، يوهان سميث أجوديلو رودريجيز</developer_name>
|
||||
<developer_name xml:lang="az">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="ca">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="ca-valencia">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
@ -160,6 +162,7 @@
|
||||
<developer_name xml:lang="de">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="el">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="en-GB">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="eo">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="es">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="et">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="eu">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
@ -169,6 +172,7 @@
|
||||
<developer_name xml:lang="ia">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="id">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="it">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="ka">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="ko">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="lt">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
<developer_name xml:lang="nl">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
|
||||
|
@ -1,39 +1,42 @@
|
||||
[Desktop Entry]
|
||||
Name=Latte
|
||||
Name[ast]=Latte
|
||||
Name[az]=Latte
|
||||
Name[ca]=Latte
|
||||
Name[ca@valencia]=Latte
|
||||
Name[cs]=Latte
|
||||
Name[da]=Latte
|
||||
Name[de]=Latte
|
||||
Name[el]=Latte
|
||||
Name[en_GB]=Latte
|
||||
Name[es]=Latte
|
||||
Name[et]=Latte
|
||||
Name[eu]=Latte
|
||||
Name[fi]=Latte
|
||||
Name[fr]=Latte
|
||||
Name[gl]=Latte
|
||||
Name[hsb]=Latte
|
||||
Name[id]=Latte
|
||||
Name[it]=Latte
|
||||
Name[ko]=Latte
|
||||
Name[lt]=Latte
|
||||
Name[nl]=Latte
|
||||
Name[nn]=Latte
|
||||
Name[pl]=Latte
|
||||
Name[pt]=Latte
|
||||
Name[pt_BR]=Latte
|
||||
Name[ru]=Latte
|
||||
Name[sk]=Latte
|
||||
Name[sl]=Latte
|
||||
Name[sv]=Latte
|
||||
Name[uk]=Латте
|
||||
Name[x-test]=xxLattexx
|
||||
Name[zh_CN]=Latte
|
||||
Name[zh_TW]=Latte
|
||||
Name=Latte Dock
|
||||
Name[ar]=رصيف لاتيه
|
||||
Name[az]=Latte Dok Paneli
|
||||
Name[ca]=Acoblador Latte
|
||||
Name[ca@valencia]=Acoblador Latte
|
||||
Name[cs]=Dok Latte
|
||||
Name[da]=Latte-dok
|
||||
Name[de]=Latte-Dock
|
||||
Name[el]=Latte Dock
|
||||
Name[en_GB]=Latte Dock
|
||||
Name[eo]=Latte Doko
|
||||
Name[es]=Latte Dock
|
||||
Name[et]=Latte dokk
|
||||
Name[eu]=Latte Dock
|
||||
Name[fi]=Latte-telakka
|
||||
Name[fr]=Barre des tâches de Latte
|
||||
Name[gl]=Doca Latte
|
||||
Name[hsb]=Latte pas
|
||||
Name[id]=Dock Latte
|
||||
Name[it]=Latte Dock
|
||||
Name[ko]=Latte 독
|
||||
Name[lt]=Latte dokas
|
||||
Name[nl]=Latte Dock
|
||||
Name[nn]=Latte-dokk
|
||||
Name[pl]=Dok Latte
|
||||
Name[pt]=Área Acoplável do Latte
|
||||
Name[pt_BR]=Latte Dock
|
||||
Name[ru]=Latte Dock
|
||||
Name[sk]=Dok Latte
|
||||
Name[sl]=Latte Dock
|
||||
Name[sv]=Latte dockningsfönster
|
||||
Name[tr]=Latte Rıhtım
|
||||
Name[uk]=Панель Латте
|
||||
Name[x-test]=xxLatte Dockxx
|
||||
Name[zh_CN]=Latte 停靠栏
|
||||
Name[zh_TW]=Latte Dock
|
||||
Comment=Dock for the masses
|
||||
Comment[ar]=رصيف للأمور الكبيرة
|
||||
Comment[az]=Hər kəs üçün Dok panel
|
||||
Comment[ca]=Acoblador per a les masses
|
||||
Comment[ca@valencia]=Acoblador per a les masses
|
||||
@ -42,6 +45,7 @@ Comment[da]=Dok til masserene
|
||||
Comment[de]=Dock für die Massen
|
||||
Comment[el]=Διαχειριστής εργασιών για όλον τον κόσμο
|
||||
Comment[en_GB]=Dock for the masses
|
||||
Comment[eo]=Doko por la masoj
|
||||
Comment[es]=Un dock para las masas
|
||||
Comment[et]=Dokk massidele
|
||||
Comment[eu]=Jendartearen kaia
|
||||
@ -51,6 +55,7 @@ Comment[gl]=Doca para as masas.
|
||||
Comment[hsb]=Pas za wšěch
|
||||
Comment[id]=Dock untuk mengumpulkan
|
||||
Comment[it]=Area di aggancio per le masse
|
||||
Comment[ja]=人々のためのドック
|
||||
Comment[ko]=모두를 위한 독
|
||||
Comment[lt]=Dokas masėms
|
||||
Comment[nl]=Dock voor de massa
|
||||
@ -62,11 +67,13 @@ Comment[ru]=Док для всех
|
||||
Comment[sk]=Dok pre davy ľudí
|
||||
Comment[sl]=Dok za množice
|
||||
Comment[sv]=Dockningsfönster för alla
|
||||
Comment[tr]=Kitleler için rıhtım
|
||||
Comment[uk]=Панель для усіх
|
||||
Comment[x-test]=xxDock for the massesxx
|
||||
Comment[zh_CN]=给大众使用的停靠栏
|
||||
Comment[zh_TW]=給大眾使用的 Dock
|
||||
GenericName=Dock
|
||||
GenericName[ar]=مرسى
|
||||
GenericName[az]=Dok
|
||||
GenericName[ca]=Acobla
|
||||
GenericName[ca@valencia]=Acobla
|
||||
@ -75,6 +82,7 @@ GenericName[da]=Dok
|
||||
GenericName[de]=Dock
|
||||
GenericName[el]=Dock
|
||||
GenericName[en_GB]=Dock
|
||||
GenericName[eo]=Doko
|
||||
GenericName[es]=Dock
|
||||
GenericName[et]=Dokk
|
||||
GenericName[eu]=Kaia
|
||||
@ -85,6 +93,8 @@ GenericName[hsb]=Pas
|
||||
GenericName[ia]=Bassino
|
||||
GenericName[id]=Dok
|
||||
GenericName[it]=Aggancio
|
||||
GenericName[ja]=ドック
|
||||
GenericName[ka]=მიმაგრება
|
||||
GenericName[ko]=독
|
||||
GenericName[lt]=Dokas
|
||||
GenericName[nl]=Dock
|
||||
@ -96,6 +106,7 @@ GenericName[ru]=Док
|
||||
GenericName[sk]=Dok
|
||||
GenericName[sl]=Dok
|
||||
GenericName[sv]=Dockningsfönster
|
||||
GenericName[tr]=Rıhtım
|
||||
GenericName[uk]=Панель
|
||||
GenericName[x-test]=xxDockxx
|
||||
GenericName[zh_CN]=停靠栏
|
||||
|
@ -1,8 +1,5 @@
|
||||
set(indicator_SRCS
|
||||
indicatorpackage.cpp
|
||||
)
|
||||
|
||||
add_library(latte_packagestructure_indicator MODULE ${indicator_SRCS})
|
||||
kcoreaddons_add_plugin(latte_packagestructure_indicator SOURCES indicatorpackage.cpp INSTALL_NAMESPACE kpackage/packagestructure)
|
||||
set_target_properties(latte_packagestructure_indicator PROPERTIES OUTPUT_NAME latte_indicator)
|
||||
|
||||
target_link_libraries(latte_packagestructure_indicator
|
||||
KF5::Declarative
|
||||
@ -10,7 +7,4 @@ target_link_libraries(latte_packagestructure_indicator
|
||||
KF5::Package
|
||||
)
|
||||
|
||||
kcoreaddons_desktop_to_json(latte_packagestructure_indicator latte-packagestructure-indicator.desktop)
|
||||
|
||||
install(TARGETS latte_packagestructure_indicator DESTINATION ${KDE_INSTALL_PLUGINDIR}/kpackage/packagestructure)
|
||||
install(FILES latte-indicator.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR})
|
||||
|
@ -19,10 +19,6 @@ IndicatorPackage::IndicatorPackage(QObject *parent, const QVariantList &args)
|
||||
{
|
||||
}
|
||||
|
||||
IndicatorPackage::~IndicatorPackage()
|
||||
{
|
||||
}
|
||||
|
||||
void IndicatorPackage::initPackage(KPackage::Package *package)
|
||||
{
|
||||
package->setDefaultPackageRoot(QStringLiteral("latte/indicators"));
|
||||
@ -36,6 +32,6 @@ void IndicatorPackage::initPackage(KPackage::Package *package)
|
||||
|
||||
}
|
||||
|
||||
K_EXPORT_KPACKAGE_PACKAGE_WITH_JSON(Latte::IndicatorPackage, "latte-packagestructure-indicator.json")
|
||||
K_PLUGIN_CLASS_WITH_JSON(Latte::IndicatorPackage, "latte-packagestructure-indicator.json")
|
||||
|
||||
#include "indicatorpackage.moc"
|
||||
|
@ -19,11 +19,9 @@ class IndicatorPackage : public KPackage::PackageStructure
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit IndicatorPackage(QObject *parent = 0, const QVariantList &args = QVariantList());
|
||||
~IndicatorPackage() override;
|
||||
explicit IndicatorPackage(QObject *parent, const QVariantList &args );
|
||||
|
||||
void initPackage(KPackage::Package *package) override;
|
||||
//void pathChanged(KPackage::Package *package) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -3,21 +3,24 @@ Type=ServiceType
|
||||
X-KDE-ServiceType=Latte/Indicator
|
||||
|
||||
Comment=Latte indicator
|
||||
Comment[ar]=مؤشرات لاتيه
|
||||
Comment[az]=Latte İndikatoru
|
||||
Comment[ca]=Indicador del Latte
|
||||
Comment[ca@valencia]=Indicador del Latte
|
||||
Comment[ca@valencia]=Indicador de Latte
|
||||
Comment[cs]=Ukazatel Latte
|
||||
Comment[el]=Δείκτης Latte
|
||||
Comment[en_GB]=Latte indicator
|
||||
Comment[eo]=Latte indikilo
|
||||
Comment[es]=Indicador Latte
|
||||
Comment[et]=Latte indikaator
|
||||
Comment[eu]=Latte adierazlea
|
||||
Comment[fi]=Latte-ilmaisin
|
||||
Comment[fr]=Indicateur de Latte
|
||||
Comment[gl]=Indicador de Latte
|
||||
Comment[gl]=Indicador de Latte.
|
||||
Comment[hsb]=Latte pokazowak
|
||||
Comment[id]=Indikator latte
|
||||
Comment[it]=Indicatore Latte
|
||||
Comment[ja]=Latte インジケータ
|
||||
Comment[ko]=Latte 표시기
|
||||
Comment[lt]=Latte indikatorius
|
||||
Comment[nl]=Indicator van Latte
|
||||
@ -29,6 +32,7 @@ Comment[ru]=Индикатор Latte
|
||||
Comment[sk]=Latte indicator
|
||||
Comment[sl]=Kazalnik Latte
|
||||
Comment[sv]=Latte indikator
|
||||
Comment[tr]=Latte göstergesi
|
||||
Comment[uk]=Індикатор Латте
|
||||
Comment[x-test]=xxLatte indicatorxx
|
||||
Comment[zh_CN]=Latte 任务指示器
|
||||
|
@ -1,40 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Indicator
|
||||
Name[az]=İndikator
|
||||
Name[ca]=Indicador
|
||||
Name[ca@valencia]=Indicador
|
||||
Name[cs]=Ukazatel
|
||||
Name[el]=Δείκτης
|
||||
Name[en_GB]=Indicator
|
||||
Name[es]=Indicador
|
||||
Name[et]=Indikaator
|
||||
Name[eu]=Adierazlea
|
||||
Name[fi]=Ilmaisin
|
||||
Name[fr]=Indicateur
|
||||
Name[gl]=Indicador
|
||||
Name[hsb]=Pokazowak
|
||||
Name[id]=Indikator
|
||||
Name[it]=Indicatore
|
||||
Name[ko]=표시기
|
||||
Name[lt]=Indikatorius
|
||||
Name[nl]=Indicator
|
||||
Name[nn]=Markør
|
||||
Name[pl]=Wskaźnik
|
||||
Name[pt]=Indicador
|
||||
Name[pt_BR]=Indicador
|
||||
Name[ru]=Индикатор
|
||||
Name[sk]=Indikátor
|
||||
Name[sl]=Kazalnik
|
||||
Name[sv]=Indikator
|
||||
Name[uk]=Індикатор
|
||||
Name[x-test]=xxIndicatorxx
|
||||
Name[zh_CN]=任务指示器
|
||||
Name[zh_TW]=指示器
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=KPackage/PackageStructure
|
||||
X-KDE-Library=latte_packagestructure_indicator
|
||||
X-KDE-PluginInfo-Author=Michail Vourlakos
|
||||
X-KDE-PluginInfo-Email=mvourlakos@gmail.com
|
||||
X-KDE-PluginInfo-Name=Latte/Indicator
|
||||
X-KDE-PluginInfo-Version=1
|
||||
X-KDE-ParentApp=org.kde.latte-dock
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"KPackageStructure": "Latte/Indicator",
|
||||
"X-KDE-ParentApp": "org.kde.latte-dock"
|
||||
}
|
@ -52,6 +52,7 @@ BackgroundCache::BackgroundCache(QObject *parent)
|
||||
|
||||
if (!m_pool) {
|
||||
m_pool = new ScreenPool(this);
|
||||
connect(m_pool, &ScreenPool::idsChanged, this, &BackgroundCache::reload);
|
||||
}
|
||||
|
||||
reload();
|
||||
|
@ -122,11 +122,7 @@ void PanelBackground::updateMaxOpacity(Plasma::Svg *svg)
|
||||
QImage center = svg->image(QSize(CENTERWIDTH, CENTERHEIGHT), element(svg, "center"));
|
||||
|
||||
if (center.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
center.convertTo(QImage::Format_ARGB32_Premultiplied);
|
||||
#else
|
||||
center = center.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
#endif
|
||||
}
|
||||
|
||||
float alphasum{0};
|
||||
@ -144,6 +140,12 @@ void PanelBackground::updateMaxOpacity(Plasma::Svg *svg)
|
||||
|
||||
m_maxOpacity = alphasum / (float)(2 * CENTERWIDTH);
|
||||
|
||||
//! minimum acceptable panel background opacity is 1%. Such is a case is when
|
||||
//! panel background is fully transparent but it provides a border. In such case
|
||||
//! previous approach was identifying as background max opacity 0% and in such case
|
||||
//! all the upcoming calculations where returning a fully transparent plasma svg to the user
|
||||
m_maxOpacity = qMax(0.01f, m_maxOpacity);
|
||||
|
||||
emit maxOpacityChanged();
|
||||
}
|
||||
|
||||
@ -173,11 +175,7 @@ void PanelBackground::updateRoundnessFromMask(Plasma::Svg *svg)
|
||||
QImage corner = svg->image(svg->elementSize(cornerId), cornerId);
|
||||
|
||||
if (corner.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
corner.convertTo(QImage::Format_ARGB32_Premultiplied);
|
||||
#else
|
||||
corner = corner.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
#endif
|
||||
}
|
||||
|
||||
int baseRow = (topLeftCorner ? corner.height()-1 : 0);
|
||||
@ -345,11 +343,7 @@ void PanelBackground::updateRoundnessFromShadows(Plasma::Svg *svg)
|
||||
QImage corner = svg->image(svg->elementSize(cornerId), cornerId);
|
||||
|
||||
if (corner.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
corner.convertTo(QImage::Format_ARGB32_Premultiplied);
|
||||
#else
|
||||
corner = corner.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
#endif
|
||||
}
|
||||
|
||||
int baseRow = (topLeftCorner ? corner.height()-1 : 0);
|
||||
@ -510,11 +504,7 @@ void PanelBackground::updateRoundnessFallback(Plasma::Svg *svg)
|
||||
QImage corner = svg->image(svg->elementSize(cornerId), cornerId);
|
||||
|
||||
if (corner.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
corner.convertTo(QImage::Format_ARGB32_Premultiplied);
|
||||
#else
|
||||
corner = corner.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
#endif
|
||||
}
|
||||
|
||||
int discovRow = (m_location == Plasma::Types::LeftEdge ? corner.height()-1 : 0);
|
||||
@ -586,11 +576,7 @@ void PanelBackground::updateShadow(Plasma::Svg *svg)
|
||||
QImage border = svg->image(svg->elementSize(borderId), borderId);
|
||||
|
||||
if (border.format() != QImage::Format_ARGB32_Premultiplied) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
border.convertTo(QImage::Format_ARGB32_Premultiplied);
|
||||
#else
|
||||
border = border.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
#endif
|
||||
}
|
||||
|
||||
//! find shadow size through, plasma theme
|
||||
|
@ -139,15 +139,16 @@ void ScreenGeometries::setPlasmaAvailableScreenRegion(const QString &screenName,
|
||||
|
||||
QVariant regionvariant;
|
||||
|
||||
QList<QRect> rects;
|
||||
if (!region.isNull()) {
|
||||
//! transorm QRegion to QList<QRect> in order to be sent through dbus
|
||||
QList<QRect> rects;
|
||||
foreach (const QRect &rect, region) {
|
||||
rects << rect;
|
||||
}
|
||||
|
||||
regionvariant = QVariant::fromValue(rects);
|
||||
} else {
|
||||
rects << QRect();
|
||||
}
|
||||
regionvariant = QVariant::fromValue(rects);
|
||||
|
||||
QVariantList args;
|
||||
|
||||
@ -189,6 +190,8 @@ void ScreenGeometries::updateGeometries()
|
||||
|
||||
qDebug() << " PLASMA SCREEN GEOMETRIES, LAST AVAILABLE SCREEN RECTS :: " << m_lastAvailableRect;
|
||||
|
||||
QStringList clearedScreenNames;
|
||||
|
||||
//! check for available geometries changes
|
||||
for (QScreen *screen : qGuiApp->screens()) {
|
||||
QString scrName = screen->name();
|
||||
@ -211,17 +214,23 @@ void ScreenGeometries::updateGeometries()
|
||||
true,
|
||||
true);
|
||||
|
||||
//! Disable checks because of the workaround concerning plasma desktop behavior
|
||||
if (!m_lastAvailableRect.contains(scrName) || m_lastAvailableRect[scrName] != availableRect) {
|
||||
m_lastAvailableRect[scrName] = availableRect;
|
||||
setPlasmaAvailableScreenRect(scrName, availableRect);
|
||||
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE RECT :: " << screen->name() << " : " << availableRect;
|
||||
}
|
||||
bool clearedScreen = (availableRect == screen->geometry());
|
||||
|
||||
if (!m_lastAvailableRegion.contains(scrName) || m_lastAvailableRegion[scrName] != availableRegion) {
|
||||
m_lastAvailableRegion[scrName] = availableRegion;
|
||||
setPlasmaAvailableScreenRegion(scrName, availableRegion);
|
||||
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE REGION :: " << screen->name() << " : " << availableRegion;
|
||||
if (!clearedScreen) {
|
||||
//! Disable checks because of the workaround concerning plasma desktop behavior
|
||||
if (!m_lastAvailableRect.contains(scrName) || m_lastAvailableRect[scrName] != availableRect) {
|
||||
m_lastAvailableRect[scrName] = availableRect;
|
||||
setPlasmaAvailableScreenRect(scrName, availableRect);
|
||||
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE RECT :: " << screen->name() << " : " << availableRect;
|
||||
}
|
||||
|
||||
if (!m_lastAvailableRegion.contains(scrName) || m_lastAvailableRegion[scrName] != availableRegion) {
|
||||
m_lastAvailableRegion[scrName] = availableRegion;
|
||||
setPlasmaAvailableScreenRegion(scrName, availableRegion);
|
||||
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE REGION :: " << screen->name() << " : " << availableRegion;
|
||||
}
|
||||
} else {
|
||||
clearedScreenNames << scrName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,14 +239,21 @@ void ScreenGeometries::updateGeometries()
|
||||
|
||||
//! check for inactive screens that were published previously
|
||||
for (QString &lastScrName : m_lastScreenNames) {
|
||||
if (!screenIsActive(lastScrName)) {
|
||||
bool scractive = screenIsActive(lastScrName);
|
||||
|
||||
if (!scractive || clearedScreenNames.contains(lastScrName)) {
|
||||
//! screen became inactive and its geometries could be unpublished
|
||||
setPlasmaAvailableScreenRect(lastScrName, QRect());
|
||||
setPlasmaAvailableScreenRegion(lastScrName, QRegion());
|
||||
|
||||
m_lastAvailableRect.remove(lastScrName);
|
||||
m_lastAvailableRegion.remove(lastScrName);
|
||||
}
|
||||
|
||||
if (!scractive) {
|
||||
qDebug() << " PLASMA SCREEN GEOMETRIES, INACTIVE SCREEN :: " << lastScrName;
|
||||
} else if (clearedScreenNames.contains(lastScrName)) {
|
||||
qDebug() << " PLASMA SCREEN GEOMETRIES, CLEARED SCREEN :: " << lastScrName;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "screenpool.h"
|
||||
|
||||
// local
|
||||
#include "../../primaryoutputwatcher.h"
|
||||
#include "../../tools/commontools.h"
|
||||
|
||||
// Qt
|
||||
@ -25,10 +26,11 @@ namespace Latte {
|
||||
namespace PlasmaExtended {
|
||||
|
||||
ScreenPool::ScreenPool(QObject *parent)
|
||||
: QObject(parent)
|
||||
: QObject(parent),
|
||||
m_primaryWatcher(new PrimaryOutputWatcher(this))
|
||||
{
|
||||
KSharedConfigPtr plasmaPtr = KSharedConfig::openConfig(PLASMARC);
|
||||
m_screensGroup = KConfigGroup(plasmaPtr, "ScreenConnectors");
|
||||
m_plasmarcConfig = KSharedConfig::openConfig(PLASMARC);
|
||||
m_screensGroup = KConfigGroup(m_plasmarcConfig, "ScreenConnectors");
|
||||
|
||||
load();
|
||||
|
||||
@ -62,12 +64,14 @@ void ScreenPool::load()
|
||||
m_connectorForId.clear();
|
||||
m_idForConnector.clear();
|
||||
|
||||
m_plasmarcConfig->reparseConfiguration();
|
||||
|
||||
bool updated{false};
|
||||
|
||||
for (const auto &screenId : m_screensGroup.keyList()) {
|
||||
QString screenName = m_screensGroup.readEntry(screenId, QString());
|
||||
if (screenId != 0) {
|
||||
int scrId = screenId.toInt();
|
||||
int scrId = screenId.toInt();
|
||||
if (scrId != 0) {
|
||||
insertScreenMapping(scrId, screenName);
|
||||
|
||||
if (!connectorForId.contains(scrId) || connectorForId[scrId] != m_connectorForId[scrId]) {
|
||||
@ -106,7 +110,7 @@ int ScreenPool::id(const QString &connector) const
|
||||
{
|
||||
if (!m_idForConnector.contains(connector)) {
|
||||
//! return 0 for primary screen, -1 for not found
|
||||
return qGuiApp->primaryScreen()->name() == connector ? 0 : -1;
|
||||
return m_primaryWatcher->primaryScreen()->name() == connector ? 0 : -1;
|
||||
}
|
||||
|
||||
return m_idForConnector.value(connector);
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KSharedConfig>
|
||||
|
||||
class PrimaryOutputWatcher;
|
||||
|
||||
namespace Latte {
|
||||
namespace PlasmaExtended {
|
||||
@ -42,7 +45,10 @@ private:
|
||||
QMap<int, QString> m_connectorForId;
|
||||
QHash<QString, int> m_idForConnector;
|
||||
|
||||
KSharedConfig::Ptr m_plasmarcConfig;
|
||||
KConfigGroup m_screensGroup;
|
||||
|
||||
PrimaryOutputWatcher *m_primaryWatcher;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -433,8 +433,8 @@ const CornerRegions &Theme::cornersMask(const int &radius)
|
||||
int axis = (2 * radius) + 2;
|
||||
QImage cornerimage(axis, axis, QImage::Format_ARGB32);
|
||||
QPainter painter(&cornerimage);
|
||||
//!does not provide valid masks
|
||||
//painter.setRenderHints(QPainter::Antialiasing);
|
||||
//!does not provide valid masks ?
|
||||
painter.setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
QPen pen(Qt::black);
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
@ -454,7 +454,7 @@ const CornerRegions &Theme::cornersMask(const int &radius)
|
||||
for(int x=0; x<radius; ++x) {
|
||||
QRgb point = line[x];
|
||||
|
||||
if (QColor(point) == Qt::black) {
|
||||
if (QColor(point) != Qt::white) {
|
||||
bits = bits + "1 ";
|
||||
width = qMax(0, x);
|
||||
break;
|
||||
@ -541,13 +541,8 @@ void Theme::saveConfig()
|
||||
|
||||
void Theme::qmlRegisterTypes()
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
qmlRegisterType<Latte::PlasmaExtended::Theme>();
|
||||
qmlRegisterType<Latte::PlasmaExtended::PanelBackground>();
|
||||
#else
|
||||
qmlRegisterAnonymousType<Latte::PlasmaExtended::Theme>("latte-dock", 1);
|
||||
qmlRegisterAnonymousType<Latte::PlasmaExtended::PanelBackground>("latte-dock", 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
166
app/primaryoutputwatcher.cpp
Normal file
166
app/primaryoutputwatcher.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "primaryoutputwatcher.h"
|
||||
|
||||
#include <KWindowSystem>
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
||||
#include "qwayland-kde-primary-output-v1.h"
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/registry.h>
|
||||
|
||||
#include <config-latte.h>
|
||||
#if HAVE_X11
|
||||
#include <QTimer> //Used only in x11 case
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <private/qtx11extras_p.h>
|
||||
#else
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_event.h>
|
||||
#endif
|
||||
|
||||
class WaylandPrimaryOutput : public QObject, public QtWayland::kde_primary_output_v1
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WaylandPrimaryOutput(struct ::wl_registry *registry, int id, int version, QObject *parent)
|
||||
: QObject(parent)
|
||||
, QtWayland::kde_primary_output_v1(registry, id, version)
|
||||
{
|
||||
}
|
||||
|
||||
void kde_primary_output_v1_primary_output(const QString &outputName) override
|
||||
{
|
||||
Q_EMIT primaryOutputChanged(outputName);
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void primaryOutputChanged(const QString &outputName);
|
||||
};
|
||||
|
||||
PrimaryOutputWatcher::PrimaryOutputWatcher(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (KWindowSystem::isPlatformX11()) {
|
||||
m_primaryOutputName = qGuiApp->primaryScreen()->name();
|
||||
qGuiApp->installNativeEventFilter(this);
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(QX11Info::connection(), &xcb_randr_id);
|
||||
m_xrandrExtensionOffset = reply->first_event;
|
||||
setPrimaryOutputName(qGuiApp->primaryScreen()->name());
|
||||
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, [this](QScreen *newPrimary) {
|
||||
setPrimaryOutputName(newPrimary->name());
|
||||
});
|
||||
}
|
||||
#endif
|
||||
if (KWindowSystem::isPlatformWayland()) {
|
||||
setupRegistry();
|
||||
}
|
||||
}
|
||||
|
||||
void PrimaryOutputWatcher::setPrimaryOutputName(const QString &newOutputName)
|
||||
{
|
||||
if (newOutputName != m_primaryOutputName) {
|
||||
const QString oldOutputName = m_primaryOutputName;
|
||||
m_primaryOutputName = newOutputName;
|
||||
Q_EMIT primaryOutputNameChanged(oldOutputName, newOutputName);
|
||||
}
|
||||
}
|
||||
|
||||
void PrimaryOutputWatcher::setupRegistry()
|
||||
{
|
||||
auto m_connection = KWayland::Client::ConnectionThread::fromApplication(this);
|
||||
if (!m_connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Asking for primaryOutputName() before this happened, will return qGuiApp->primaryScreen()->name() anyways, so set it so the primaryOutputNameChange will
|
||||
// have parameters that are coherent
|
||||
m_primaryOutputName = qGuiApp->primaryScreen()->name();
|
||||
m_registry = new KWayland::Client::Registry(this);
|
||||
connect(m_registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this](const QByteArray &interface, quint32 name, quint32 version) {
|
||||
if (interface == WaylandPrimaryOutput::interface()->name) {
|
||||
auto m_outputManagement = new WaylandPrimaryOutput(m_registry->registry(), name, version, this);
|
||||
connect(m_outputManagement, &WaylandPrimaryOutput::primaryOutputChanged, this, [this](const QString &outputName) {
|
||||
m_primaryOutputWayland = outputName;
|
||||
// Only set the outputName when there's a QScreen attached to it
|
||||
if (screenForName(outputName)) {
|
||||
setPrimaryOutputName(outputName);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// In case the outputName was received before Qt reported the screen
|
||||
connect(qGuiApp, &QGuiApplication::screenAdded, this, [this](QScreen *screen) {
|
||||
if (screen->name() == m_primaryOutputWayland) {
|
||||
setPrimaryOutputName(m_primaryOutputWayland);
|
||||
}
|
||||
});
|
||||
|
||||
m_registry->create(m_connection);
|
||||
m_registry->setup();
|
||||
}
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
bool PrimaryOutputWatcher::nativeEventFilter(const QByteArray &eventType, void *message, long int *result)
|
||||
#else
|
||||
bool PrimaryOutputWatcher::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
|
||||
#endif
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
#if HAVE_X11
|
||||
// a particular edge case: when we switch the only enabled screen
|
||||
// we don't have any signal about it, the primary screen changes but we have the same old QScreen* getting recycled
|
||||
// see https://bugs.kde.org/show_bug.cgi?id=373880
|
||||
// if this slot will be invoked many times, their//second time on will do nothing as name and primaryOutputName will be the same by then
|
||||
if (eventType[0] != 'x') {
|
||||
return false;
|
||||
}
|
||||
|
||||
xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
|
||||
|
||||
const auto responseType = XCB_EVENT_RESPONSE_TYPE(ev);
|
||||
|
||||
if (responseType == m_xrandrExtensionOffset + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
|
||||
QTimer::singleShot(0, this, [this]() {
|
||||
setPrimaryOutputName(qGuiApp->primaryScreen()->name());
|
||||
});
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
QScreen *PrimaryOutputWatcher::screenForName(const QString &outputName) const
|
||||
{
|
||||
const auto screens = qGuiApp->screens();
|
||||
for (auto screen : screens) {
|
||||
if (screen->name() == outputName) {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QScreen *PrimaryOutputWatcher::primaryScreen() const
|
||||
{
|
||||
auto screen = screenForName(m_primaryOutputName);
|
||||
if (!screen) {
|
||||
qDebug() << "PrimaryOutputWatcher: Could not find primary screen:" << m_primaryOutputName;
|
||||
return qGuiApp->primaryScreen();
|
||||
}
|
||||
return screen;
|
||||
}
|
||||
|
||||
#include "primaryoutputwatcher.moc"
|
||||
|
58
app/primaryoutputwatcher.h
Normal file
58
app/primaryoutputwatcher.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PRIMARYOUTPUTWATCHER_H
|
||||
#define PRIMARYOUTPUTWATCHER_H
|
||||
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QObject>
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class Registry;
|
||||
class ConnectionThread;
|
||||
}
|
||||
}
|
||||
|
||||
class QScreen;
|
||||
|
||||
class PrimaryOutputWatcher : public QObject, public QAbstractNativeEventFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PrimaryOutputWatcher(QObject *parent);
|
||||
QScreen *primaryScreen() const;
|
||||
QScreen *screenForName(const QString &outputName) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void primaryOutputNameChanged(const QString &oldOutputName, const QString &newOutputName);
|
||||
|
||||
protected:
|
||||
friend class WaylandOutputDevice;
|
||||
void setPrimaryOutputName(const QString &outputName);
|
||||
|
||||
private:
|
||||
void setupRegistry();
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
|
||||
#else
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
|
||||
#endif
|
||||
|
||||
// All
|
||||
QString m_primaryOutputName;
|
||||
|
||||
// Wayland
|
||||
KWayland::Client::Registry *m_registry = nullptr;
|
||||
QString m_primaryOutputWayland;
|
||||
|
||||
// Xrandr
|
||||
int m_xrandrExtensionOffset;
|
||||
};
|
||||
|
||||
#endif // PRIMARYOUTPUTWATCHER_H
|
@ -8,6 +8,7 @@
|
||||
|
||||
// local
|
||||
#include <config-latte.h>
|
||||
#include "primaryoutputwatcher.h"
|
||||
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
@ -17,6 +18,7 @@
|
||||
|
||||
// KDE
|
||||
#include <KLocalizedString>
|
||||
#include <KWindowSystem>
|
||||
|
||||
// X11
|
||||
#if HAVE_X11
|
||||
@ -32,10 +34,9 @@ const int ScreenPool::FIRSTSCREENID;
|
||||
|
||||
ScreenPool::ScreenPool(KSharedConfig::Ptr config, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_configGroup(KConfigGroup(config, QStringLiteral("ScreenConnectors")))
|
||||
m_configGroup(KConfigGroup(config, QStringLiteral("ScreenConnectors"))),
|
||||
m_primaryWatcher(new PrimaryOutputWatcher(this))
|
||||
{
|
||||
qApp->installNativeEventFilter(this);
|
||||
|
||||
m_configSaveTimer.setSingleShot(true);
|
||||
connect(&m_configSaveTimer, &QTimer::timeout, this, [this]() {
|
||||
m_configGroup.sync();
|
||||
@ -52,15 +53,8 @@ ScreenPool::~ScreenPool()
|
||||
|
||||
void ScreenPool::load()
|
||||
{
|
||||
m_lastPrimaryConnector = QString();
|
||||
m_screensTable.clear();
|
||||
|
||||
QScreen *primary = qGuiApp->primaryScreen();
|
||||
|
||||
if (primary) {
|
||||
m_lastPrimaryConnector = primary->name();
|
||||
}
|
||||
|
||||
//restore the known ids to connector mappings
|
||||
for (const QString &key : m_configGroup.keyList()) {
|
||||
if (key.toInt() <= 0) {
|
||||
@ -94,6 +88,20 @@ void ScreenPool::load()
|
||||
|
||||
onScreenAdded(screen);
|
||||
}
|
||||
|
||||
if (KWindowSystem::isPlatformX11()) {
|
||||
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &ScreenPool::primaryScreenChanged, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
connect(m_primaryWatcher, &PrimaryOutputWatcher::primaryOutputNameChanged, this, &ScreenPool::onPrimaryOutputNameChanged, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void ScreenPool::onPrimaryOutputNameChanged(const QString &oldOutputName, const QString &newOutputName)
|
||||
{
|
||||
Q_UNUSED(oldOutputName);
|
||||
Q_UNUSED(newOutputName);
|
||||
|
||||
emit primaryScreenChanged(m_primaryWatcher->primaryScreen());
|
||||
}
|
||||
|
||||
void ScreenPool::onScreenAdded(const QScreen *screen)
|
||||
@ -165,7 +173,24 @@ void ScreenPool::removeScreens(const Latte::Data::ScreensTable &obsoleteScreens)
|
||||
|
||||
int ScreenPool::primaryScreenId() const
|
||||
{
|
||||
return id(qGuiApp->primaryScreen()->name());
|
||||
return id(primaryScreen()->name());
|
||||
}
|
||||
|
||||
QList<int> ScreenPool::secondaryScreenIds() const
|
||||
{
|
||||
QList<int> secondaryscreens;
|
||||
|
||||
QScreen *primary{primaryScreen()};
|
||||
|
||||
for (const auto scr : qGuiApp->screens()) {
|
||||
if (scr == primary) {
|
||||
continue;
|
||||
}
|
||||
|
||||
secondaryscreens << id(scr->name());
|
||||
}
|
||||
|
||||
return secondaryscreens;
|
||||
}
|
||||
|
||||
void ScreenPool::save()
|
||||
@ -214,7 +239,7 @@ void ScreenPool::insertScreenMapping(const QString &connector)
|
||||
int ScreenPool::id(const QString &connector) const
|
||||
{
|
||||
QString screenId = m_screensTable.idForName(connector);
|
||||
return screenId.isEmpty() ? -1 : screenId.toInt();
|
||||
return screenId.isEmpty() ? NOSCREENID : screenId.toInt();
|
||||
}
|
||||
|
||||
QString ScreenPool::connector(int id) const
|
||||
@ -259,10 +284,15 @@ bool ScreenPool::isScreenActive(int screenId) const
|
||||
return false;
|
||||
}
|
||||
|
||||
QScreen *ScreenPool::primaryScreen() const
|
||||
{
|
||||
return m_primaryWatcher->primaryScreen();
|
||||
}
|
||||
|
||||
QScreen *ScreenPool::screenForId(int id)
|
||||
{
|
||||
const auto screens = qGuiApp->screens();
|
||||
QScreen *screen{qGuiApp->primaryScreen()};
|
||||
QScreen *screen{primaryScreen()};
|
||||
|
||||
if (hasScreenId(id)) {
|
||||
QString scrName = connector(id);
|
||||
@ -277,41 +307,4 @@ QScreen *ScreenPool::screenForId(int id)
|
||||
return screen;
|
||||
}
|
||||
|
||||
bool ScreenPool::nativeEventFilter(const QByteArray &eventType, void *message, long int *result)
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
#if HAVE_X11
|
||||
|
||||
// a particular edge case: when we switch the only enabled screen
|
||||
// we don't have any signal about it, the primary screen changes but we have the same old QScreen* getting recycled
|
||||
// see https://bugs.kde.org/show_bug.cgi?id=373880
|
||||
// if this slot will be invoked many times, their//second time on will do nothing as name and primaryconnector will be the same by then
|
||||
if (eventType != "xcb_generic_event_t") {
|
||||
return false;
|
||||
}
|
||||
|
||||
xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
|
||||
|
||||
const auto responseType = XCB_EVENT_RESPONSE_TYPE(ev);
|
||||
|
||||
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(QX11Info::connection(), &xcb_randr_id);
|
||||
|
||||
if (responseType == reply->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
|
||||
if (qGuiApp->primaryScreen()->name() != m_lastPrimaryConnector) {
|
||||
//new screen?
|
||||
if (id(qGuiApp->primaryScreen()->name()) < 0) {
|
||||
insertScreenMapping(qGuiApp->primaryScreen()->name());
|
||||
}
|
||||
|
||||
m_lastPrimaryConnector = qGuiApp->primaryScreen()->name();
|
||||
emit primaryPoolChanged();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_screenpool.cpp"
|
||||
|
@ -16,28 +16,32 @@
|
||||
#include <QScreen>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
// KDE
|
||||
#include <KConfigGroup>
|
||||
#include <KSharedConfig>
|
||||
|
||||
class PrimaryOutputWatcher;
|
||||
|
||||
namespace Latte {
|
||||
|
||||
class ScreenPool : public QObject, public QAbstractNativeEventFilter
|
||||
class ScreenPool : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static const int FIRSTSCREENID = 10;
|
||||
static const int NOSCREENID = -1;
|
||||
|
||||
ScreenPool(KSharedConfig::Ptr config, QObject *parent = nullptr);
|
||||
void load();
|
||||
~ScreenPool() override;
|
||||
|
||||
void load();
|
||||
|
||||
bool hasScreenId(int screenId) const;
|
||||
bool isScreenActive(int screenId) const;
|
||||
int primaryScreenId() const;
|
||||
QList<int> secondaryScreenIds() const;
|
||||
|
||||
void insertScreenMapping(const QString &connector);
|
||||
void reload(QString path);
|
||||
@ -48,20 +52,20 @@ public:
|
||||
QString connector(int id) const;
|
||||
|
||||
QScreen *screenForId(int id);
|
||||
QScreen *primaryScreen() const;
|
||||
|
||||
Latte::Data::ScreensTable screensTable();
|
||||
|
||||
signals:
|
||||
void primaryPoolChanged();
|
||||
void primaryScreenChanged(QScreen *screen);
|
||||
void screenGeometryChanged();
|
||||
|
||||
protected:
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
||||
|
||||
int firstAvailableId() const;
|
||||
|
||||
private slots:
|
||||
void updateScreenGeometry(const QScreen *screen);
|
||||
void onPrimaryOutputNameChanged(const QString &oldOutputName, const QString &newOutputName);
|
||||
void onScreenAdded(const QScreen *screen);
|
||||
void onScreenRemoved(const QScreen *screen);
|
||||
|
||||
@ -73,10 +77,10 @@ private:
|
||||
Latte::Data::ScreensTable m_screensTable;
|
||||
|
||||
KConfigGroup m_configGroup;
|
||||
//! used to workaround a bug under X11 when primary screen changes and no screenChanged signal is emitted
|
||||
QString m_lastPrimaryConnector;
|
||||
|
||||
QTimer m_configSaveTimer;
|
||||
|
||||
PrimaryOutputWatcher *m_primaryWatcher;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
#ifndef COLORSMODEL_H
|
||||
#define COLROSMODEL_H
|
||||
#define COLORSMODEL_H
|
||||
|
||||
// local
|
||||
#include "../../lattecorona.h"
|
||||
|
@ -193,7 +193,7 @@ void ExportTemplateHandler::chooseFileDialog()
|
||||
});
|
||||
|
||||
chooseFileDlg->open();
|
||||
chooseFileDlg->selectFile(currentFile.baseName());
|
||||
chooseFileDlg->selectFile(currentFile.fileName());
|
||||
}
|
||||
|
||||
void ExportTemplateHandler::onExport()
|
||||
|
@ -502,7 +502,7 @@ int screenMaxLength(const QStyleOption &option, const int &maxIconSize)
|
||||
return scr_maxlength;
|
||||
}
|
||||
|
||||
QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSize)
|
||||
QRect remainedFromScreenDrawing(const QStyleOption &option, bool drawMultipleScreens, const int &maxIconSize)
|
||||
{
|
||||
int total_length = screenMaxLength(option, maxIconSize) + MARGIN * 2 + 1;
|
||||
|
||||
@ -512,7 +512,7 @@ QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSi
|
||||
return optionRemainedRect;
|
||||
}
|
||||
|
||||
QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeometry, const int &maxIconSize, const float brushOpacity)
|
||||
QRect drawScreen(QPainter *painter, const QStyleOption &option, bool drawMultipleScreens, QRect screenGeometry, const int &maxIconSize, const float brushOpacity)
|
||||
{
|
||||
float scr_ratio = (float)screenGeometry.width() / (float)screenGeometry.height();
|
||||
bool isVertical = (scr_ratio < 1.0);
|
||||
@ -565,13 +565,24 @@ QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeom
|
||||
painter->setPen(pen);
|
||||
painter->drawRect(screenRect);
|
||||
|
||||
//! draw screen base
|
||||
pen.setWidth(1);
|
||||
painter->setPen(pen);
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
//! draw multiple
|
||||
if (drawMultipleScreens) {
|
||||
int multiplemargin = 3;
|
||||
int curx = screenRect.x()-multiplemargin;
|
||||
painter->drawLine(screenRect.x() - multiplemargin, screenRect.y() - multiplemargin,
|
||||
screenRect.x() - multiplemargin, screenRect.y() - multiplemargin + screenRect.height());
|
||||
painter->drawLine(screenRect.x() - multiplemargin, screenRect.y() - multiplemargin,
|
||||
screenRect.x() - multiplemargin + screenRect.width(), screenRect.y() - multiplemargin);
|
||||
}
|
||||
|
||||
int basex = screenRect.x() + (screenRect.width()/2) - 4;
|
||||
int basey = screenRect.y() + screenRect.height() + 2;
|
||||
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
painter->drawLine(basex , basey, basex + 8, basey);
|
||||
|
||||
// debug screen maximum available rect
|
||||
|
@ -60,8 +60,8 @@ QRect remainedFromCheckBox(const QStyleOptionButton &option, Qt::AlignmentFlag a
|
||||
void drawCheckBox(QPainter *painter, const QStyleOptionButton &option, Qt::AlignmentFlag alignment = Qt::AlignLeft, const QWidget *widget = nullptr);
|
||||
|
||||
//! screen icon
|
||||
QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSize = -1);
|
||||
QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeometry, const int &maxIconSize = -1, const float brushOpacity = 1.0); // returns screen available rect
|
||||
QRect remainedFromScreenDrawing(const QStyleOption &option, bool drawMultipleScreens, const int &maxIconSize = -1);
|
||||
QRect drawScreen(QPainter *painter, const QStyleOption &option, bool drawMultipleScreens, QRect screenGeometry, const int &maxIconSize = -1, const float brushOpacity = 1.0); // returns screen available rect
|
||||
|
||||
int screenMaxLength(const QStyleOption &option, const int &maxIconSize = -1);
|
||||
|
||||
|
@ -111,8 +111,8 @@ void CheckBox::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
|
||||
|
||||
//! screen
|
||||
int maxiconsize = -1; //disabled
|
||||
remainedrect = Latte::remainedFromScreenDrawing(adjustedOption, maxiconsize);
|
||||
Latte::drawScreen(painter, adjustedOption, screen.geometry, maxiconsize);
|
||||
remainedrect = Latte::remainedFromScreenDrawing(adjustedOption, false, maxiconsize);
|
||||
Latte::drawScreen(painter, adjustedOption, false, screen.geometry, maxiconsize);
|
||||
adjustedOption.rect = remainedrect;
|
||||
|
||||
//! screen id
|
||||
|
@ -236,7 +236,7 @@ const Latte::Data::ViewsTable Layouts::selectedLayoutViews()
|
||||
central = new CentralLayout(this, selectedCurrentData.id);
|
||||
}
|
||||
|
||||
selectedCurrentData.views = central->viewsTable();
|
||||
selectedCurrentData.views = central->viewsTable().onlyOriginals();
|
||||
selectedCurrentData.views.isInitialized = true;
|
||||
|
||||
if (!islayoutactive) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@
|
||||
#include "../../layout/centrallayout.h"
|
||||
#include "../../layouts/importer.h"
|
||||
#include "../../layouts/manager.h"
|
||||
#include "../../layouts/storage.h"
|
||||
#include "../../templates/templatesmanager.h"
|
||||
#include "../../tools/commontools.h"
|
||||
|
||||
@ -513,8 +514,6 @@ void TabLayouts::removeLayout()
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_layoutsController->removeSelected();
|
||||
}
|
||||
|
||||
@ -660,6 +659,9 @@ void TabLayouts::exportLayoutForBackup()
|
||||
QFile(file).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther);
|
||||
}
|
||||
|
||||
// cleanup clones from exported file
|
||||
Latte::Layouts::Storage::self()->removeAllClonedViews(file);
|
||||
|
||||
CentralLayout layoutS(this, file);
|
||||
layoutS.setActivities(QStringList());
|
||||
layoutS.clearLastUsedActivity();
|
||||
@ -714,7 +716,7 @@ void TabLayouts::exportLayoutForBackup()
|
||||
});
|
||||
|
||||
exportFileDialog->open();
|
||||
exportFileDialog->selectFile(selectedLayout.name);
|
||||
exportFileDialog->selectFile(selectedLayout.name + ".layout.latte");
|
||||
}
|
||||
|
||||
void TabLayouts::showDetailsDialog()
|
||||
|
@ -33,21 +33,39 @@ TabPreferences::TabPreferences(Latte::Settings::Dialog::SettingsDialog *parent)
|
||||
|
||||
void TabPreferences::initUi()
|
||||
{
|
||||
//! exclusive group
|
||||
m_mouseSensitivityButtons = new QButtonGroup(this);
|
||||
m_mouseSensitivityButtons->addButton(m_ui->lowSensitivityBtn, Latte::Settings::LowMouseSensitivity);
|
||||
m_mouseSensitivityButtons->addButton(m_ui->mediumSensitivityBtn, Latte::Settings::MediumMouseSensitivity);
|
||||
m_mouseSensitivityButtons->addButton(m_ui->highSensitivityBtn, Latte::Settings::HighMouseSensitivity);
|
||||
m_mouseSensitivityButtons->setExclusive(true);
|
||||
//! exclusive groups
|
||||
m_parabolicSpreadButtons = new QButtonGroup(this);
|
||||
m_parabolicSpreadButtons->addButton(m_ui->smallParabolicBtn, Data::Preferences::PARABOLICSPREAD);
|
||||
m_parabolicSpreadButtons->addButton(m_ui->mediumParabolicBtn, 5);
|
||||
m_parabolicSpreadButtons->addButton(m_ui->largeParabolicBtn, 7);
|
||||
m_parabolicSpreadButtons->setExclusive(true);
|
||||
|
||||
m_thicknessMarginInfluenceButtons = new QButtonGroup(this);
|
||||
m_thicknessMarginInfluenceButtons->addButton(m_ui->noMarginInfluenceBtn, 0); // 0%
|
||||
m_thicknessMarginInfluenceButtons->addButton(m_ui->halfMarginInfluenceBtn, 50); // 50%
|
||||
m_thicknessMarginInfluenceButtons->addButton(m_ui->fullMarginInfluenceBtn, 100); // 100%
|
||||
m_thicknessMarginInfluenceButtons->setExclusive(true);
|
||||
|
||||
m_ui->noMarginInfluenceBtn->setText(i18nc("number in percentage, e.g. 85%","%1%").arg(0));
|
||||
m_ui->halfMarginInfluenceBtn->setText(i18nc("number in percentage, e.g. 85%","%1%").arg(50));
|
||||
m_ui->fullMarginInfluenceBtn->setText(i18nc("number in percentage, e.g. 85%","%1%").arg(100));
|
||||
|
||||
//! Buttons
|
||||
connect(m_ui->contextMenuActionsBtn, &QPushButton::clicked, this, &TabPreferences::onActionsBtnPressed);
|
||||
|
||||
//! signals
|
||||
connect(m_mouseSensitivityButtons, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
|
||||
connect(m_parabolicSpreadButtons, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
|
||||
[ = ](int id, bool checked) {
|
||||
if (checked) {
|
||||
m_preferences.mouseSensitivity = static_cast<Latte::Settings::MouseSensitivity>(id);
|
||||
m_preferences.parabolicSpread = id;
|
||||
emit dataChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_thicknessMarginInfluenceButtons, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
|
||||
[ = ](int id, bool checked) {
|
||||
if (checked) {
|
||||
m_preferences.thicknessMarginInfluence = (id / 100.0f);
|
||||
emit dataChanged();
|
||||
}
|
||||
});
|
||||
@ -110,7 +128,8 @@ void TabPreferences::initSettings()
|
||||
o_preferences.metaPressForAppLauncher = m_corona->universalSettings()->kwin_metaForwardedToLatte();
|
||||
o_preferences.metaHoldForBadges = m_corona->universalSettings()->metaPressAndHoldEnabled();
|
||||
o_preferences.borderlessMaximized = m_corona->universalSettings()->canDisableBorders();
|
||||
o_preferences.mouseSensitivity = m_corona->universalSettings()->sensitivity();
|
||||
o_preferences.parabolicSpread = m_corona->universalSettings()->parabolicSpread();
|
||||
o_preferences.thicknessMarginInfluence = m_corona->universalSettings()->thicknessMarginInfluence();
|
||||
o_preferences.screensDelay = m_corona->universalSettings()->screenTrackerInterval();
|
||||
|
||||
m_preferences = o_preferences;
|
||||
@ -145,12 +164,20 @@ void TabPreferences::updateUi()
|
||||
m_ui->noBordersForMaximizedChkBox->setChecked(m_preferences.borderlessMaximized);
|
||||
m_ui->screenTrackerSpinBox->setValue(m_preferences.screensDelay);
|
||||
|
||||
if (m_preferences.mouseSensitivity == Settings::LowMouseSensitivity) {
|
||||
m_ui->lowSensitivityBtn->setChecked(true);
|
||||
} else if (m_preferences.mouseSensitivity == Settings::MediumMouseSensitivity) {
|
||||
m_ui->mediumSensitivityBtn->setChecked(true);
|
||||
} else if (m_preferences.mouseSensitivity == Settings::HighMouseSensitivity) {
|
||||
m_ui->highSensitivityBtn->setChecked(true);
|
||||
if (m_preferences.parabolicSpread == Data::Preferences::PARABOLICSPREAD) {
|
||||
m_ui->smallParabolicBtn->setChecked(true);
|
||||
} else if (m_preferences.parabolicSpread == 5) {
|
||||
m_ui->mediumParabolicBtn->setChecked(true);
|
||||
} else if (m_preferences.parabolicSpread == 7) {
|
||||
m_ui->largeParabolicBtn->setChecked(true);
|
||||
}
|
||||
|
||||
if (m_preferences.thicknessMarginInfluence == 0.0f) {
|
||||
m_ui->noMarginInfluenceBtn->setChecked(true);
|
||||
} else if (m_preferences.thicknessMarginInfluence == 0.5f) {
|
||||
m_ui->halfMarginInfluenceBtn->setChecked(true);
|
||||
} else if (m_preferences.thicknessMarginInfluence == Data::Preferences::THICKNESSMARGININFLUENCE) {
|
||||
m_ui->fullMarginInfluenceBtn->setChecked(true);
|
||||
}
|
||||
|
||||
emit dataChanged();
|
||||
@ -186,7 +213,6 @@ void TabPreferences::resetDefaults()
|
||||
|
||||
void TabPreferences::save()
|
||||
{
|
||||
m_corona->universalSettings()->setSensitivity(m_preferences.mouseSensitivity);
|
||||
m_corona->universalSettings()->setAutostart(m_preferences.autostart);
|
||||
m_corona->universalSettings()->setBadges3DStyle(m_preferences.badgeStyle3D);
|
||||
m_corona->universalSettings()->setContextMenuActionsAlwaysShown(m_preferences.contextMenuAlwaysActions);
|
||||
@ -195,6 +221,8 @@ void TabPreferences::save()
|
||||
m_corona->universalSettings()->setMetaPressAndHoldEnabled(m_preferences.metaHoldForBadges);
|
||||
m_corona->universalSettings()->setShowInfoWindow(m_preferences.layoutsInformationWindow);
|
||||
m_corona->universalSettings()->setCanDisableBorders(m_preferences.borderlessMaximized);
|
||||
m_corona->universalSettings()->setParabolicSpread(m_preferences.parabolicSpread);
|
||||
m_corona->universalSettings()->setThicknessMarginInfluence(m_preferences.thicknessMarginInfluence);
|
||||
m_corona->universalSettings()->setScreenTrackerInterval(m_preferences.screensDelay);
|
||||
|
||||
o_preferences = m_preferences;
|
||||
|
@ -69,7 +69,8 @@ private:
|
||||
Ui::SettingsDialog *m_ui{nullptr};
|
||||
Latte::Corona *m_corona{nullptr};
|
||||
|
||||
QButtonGroup *m_mouseSensitivityButtons;
|
||||
QButtonGroup *m_parabolicSpreadButtons;
|
||||
QButtonGroup *m_thicknessMarginInfluenceButtons;
|
||||
|
||||
//! current data
|
||||
Data::Preferences m_preferences;
|
||||
|
@ -46,14 +46,17 @@ UniversalSettings::UniversalSettings(KSharedConfig::Ptr config, QObject *parent)
|
||||
connect(this, &UniversalSettings::badges3DStyleChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::canDisableBordersChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::inAdvancedModeForEditSettingsChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::inConfigureAppletsModeChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::isAvailableGeometryBroadcastedToPlasmaChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::launchersChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::layoutsMemoryUsageChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::metaPressAndHoldEnabledChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::parabolicSpreadChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::sensitivityChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::screenTrackerIntervalChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::showInfoWindowChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::singleModeLayoutNameChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::thicknessMarginInfluenceChanged, this, &UniversalSettings::saveConfig);
|
||||
connect(this, &UniversalSettings::versionChanged, this, &UniversalSettings::saveConfig);
|
||||
|
||||
connect(this, &UniversalSettings::screenScalesChanged, this, &UniversalSettings::saveScalesConfig);
|
||||
@ -131,6 +134,21 @@ void UniversalSettings::setInAdvancedModeForEditSettings(const bool &inAdvanced)
|
||||
emit inAdvancedModeForEditSettingsChanged();
|
||||
}
|
||||
|
||||
bool UniversalSettings::inConfigureAppletsMode() const
|
||||
{
|
||||
return m_inConfigureAppletsMode;
|
||||
}
|
||||
|
||||
void UniversalSettings::setInConfigureAppletsMode(const bool enabled)
|
||||
{
|
||||
if (m_inConfigureAppletsMode == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_inConfigureAppletsMode = enabled;
|
||||
emit inConfigureAppletsModeChanged();
|
||||
}
|
||||
|
||||
bool UniversalSettings::isAvailableGeometryBroadcastedToPlasma() const
|
||||
{
|
||||
return m_isAvailableGeometryBroadcastedToPlasma;
|
||||
@ -193,6 +211,36 @@ void UniversalSettings::setScreenTrackerInterval(int duration)
|
||||
emit screenTrackerIntervalChanged();
|
||||
}
|
||||
|
||||
int UniversalSettings::parabolicSpread() const
|
||||
{
|
||||
return m_parabolicSpread;
|
||||
}
|
||||
|
||||
void UniversalSettings::setParabolicSpread(const int &spread)
|
||||
{
|
||||
if (m_parabolicSpread == spread) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_parabolicSpread = spread;
|
||||
emit parabolicSpreadChanged();
|
||||
}
|
||||
|
||||
float UniversalSettings::thicknessMarginInfluence() const
|
||||
{
|
||||
return m_thicknessMarginInfluence;
|
||||
}
|
||||
|
||||
void UniversalSettings::setThicknessMarginInfluence(const float &influence)
|
||||
{
|
||||
if (m_thicknessMarginInfluence == influence) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_thicknessMarginInfluence = influence;
|
||||
emit thicknessMarginInfluenceChanged();
|
||||
}
|
||||
|
||||
QString UniversalSettings::singleModeLayoutName() const
|
||||
{
|
||||
return m_singleModeLayoutName;
|
||||
@ -434,7 +482,9 @@ void UniversalSettings::setLayoutsMemoryUsage(MemoryUsage::LayoutsMemory layouts
|
||||
|
||||
Settings::MouseSensitivity UniversalSettings::sensitivity()
|
||||
{
|
||||
return m_sensitivity;
|
||||
//! return always default option as the users have not shown any interest in that option
|
||||
return Latte::Settings::HighMouseSensitivity;
|
||||
// return m_sensitivity;
|
||||
}
|
||||
|
||||
void UniversalSettings::setSensitivity(Settings::MouseSensitivity sense)
|
||||
@ -444,7 +494,7 @@ void UniversalSettings::setSensitivity(Settings::MouseSensitivity sense)
|
||||
}
|
||||
|
||||
m_sensitivity = sense;
|
||||
emit sensitivityChanged();
|
||||
// emit sensitivityChanged();
|
||||
}
|
||||
|
||||
float UniversalSettings::screenWidthScale(QString screenName) const
|
||||
@ -521,14 +571,17 @@ void UniversalSettings::loadConfig()
|
||||
m_canDisableBorders = m_universalGroup.readEntry("canDisableBorders", false);
|
||||
m_contextMenuActionsAlwaysShown = m_universalGroup.readEntry("contextMenuActionsAlwaysShown", Latte::Data::ContextMenu::ACTIONSALWAYSVISIBLE);
|
||||
m_inAdvancedModeForEditSettings = m_universalGroup.readEntry("inAdvancedModeForEditSettings", false);
|
||||
m_inConfigureAppletsMode = m_universalGroup.readEntry("inConfigureAppletsMode", false);
|
||||
m_isAvailableGeometryBroadcastedToPlasma = m_universalGroup.readEntry("isAvailableGeometryBroadcastedToPlasma", true);
|
||||
m_launchers = m_universalGroup.readEntry("launchers", QStringList());
|
||||
m_metaPressAndHoldEnabled = m_universalGroup.readEntry("metaPressAndHoldEnabled", true);
|
||||
m_screenTrackerInterval = m_universalGroup.readEntry("screenTrackerInterval", 2500);
|
||||
m_showInfoWindow = m_universalGroup.readEntry("showInfoWindow", true);
|
||||
m_singleModeLayoutName = m_universalGroup.readEntry("singleModeLayoutName", QString());
|
||||
m_parabolicSpread = m_universalGroup.readEntry("parabolicSpread", Data::Preferences::PARABOLICSPREAD);
|
||||
m_thicknessMarginInfluence = m_universalGroup.readEntry("parabolicThicknessMarginInfluence", Data::Preferences::THICKNESSMARGININFLUENCE);
|
||||
m_memoryUsage = static_cast<MemoryUsage::LayoutsMemory>(m_universalGroup.readEntry("memoryUsage", (int)MemoryUsage::SingleLayout));
|
||||
m_sensitivity = static_cast<Settings::MouseSensitivity>(m_universalGroup.readEntry("mouseSensitivity", (int)Settings::HighMouseSensitivity));
|
||||
//m_sensitivity = static_cast<Settings::MouseSensitivity>(m_universalGroup.readEntry("mouseSensitivity", (int)Settings::HighMouseSensitivity));
|
||||
|
||||
loadScalesConfig();
|
||||
|
||||
@ -544,14 +597,17 @@ void UniversalSettings::saveConfig()
|
||||
m_universalGroup.writeEntry("canDisableBorders", m_canDisableBorders);
|
||||
m_universalGroup.writeEntry("contextMenuActionsAlwaysShown", m_contextMenuActionsAlwaysShown);
|
||||
m_universalGroup.writeEntry("inAdvancedModeForEditSettings", m_inAdvancedModeForEditSettings);
|
||||
m_universalGroup.writeEntry("inConfigureAppletsMode", m_inConfigureAppletsMode);
|
||||
m_universalGroup.writeEntry("isAvailableGeometryBroadcastedToPlasma", m_isAvailableGeometryBroadcastedToPlasma);
|
||||
m_universalGroup.writeEntry("launchers", m_launchers);
|
||||
m_universalGroup.writeEntry("metaPressAndHoldEnabled", m_metaPressAndHoldEnabled);
|
||||
m_universalGroup.writeEntry("screenTrackerInterval", m_screenTrackerInterval);
|
||||
m_universalGroup.writeEntry("showInfoWindow", m_showInfoWindow);
|
||||
m_universalGroup.writeEntry("singleModeLayoutName", m_singleModeLayoutName);
|
||||
m_universalGroup.writeEntry("parabolicSpread", m_parabolicSpread);
|
||||
m_universalGroup.writeEntry("parabolicThicknessMarginInfluence", m_thicknessMarginInfluence);
|
||||
m_universalGroup.writeEntry("memoryUsage", (int)m_memoryUsage);
|
||||
m_universalGroup.writeEntry("mouseSensitivity", (int)m_sensitivity);
|
||||
//m_universalGroup.writeEntry("mouseSensitivity", (int)m_sensitivity);
|
||||
syncSettings();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <coretypes.h>
|
||||
#include "../apptypes.h"
|
||||
#include "../lattecorona.h"
|
||||
#include "../data/preferencesdata.h"
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
@ -44,9 +45,13 @@ class UniversalSettings : public QObject
|
||||
Q_PROPERTY(bool autostart READ autostart WRITE setAutostart NOTIFY autostartChanged)
|
||||
Q_PROPERTY(bool badges3DStyle READ badges3DStyle WRITE setBadges3DStyle NOTIFY badges3DStyleChanged)
|
||||
Q_PROPERTY(bool inAdvancedModeForEditSettings READ inAdvancedModeForEditSettings WRITE setInAdvancedModeForEditSettings NOTIFY inAdvancedModeForEditSettingsChanged)
|
||||
Q_PROPERTY(bool inConfigureAppletsMode READ inConfigureAppletsMode WRITE setInConfigureAppletsMode NOTIFY inConfigureAppletsModeChanged)
|
||||
Q_PROPERTY(bool colorsScriptIsPresent READ colorsScriptIsPresent NOTIFY colorsScriptIsPresentChanged)
|
||||
Q_PROPERTY(bool showInfoWindow READ showInfoWindow WRITE setShowInfoWindow NOTIFY showInfoWindowChanged)
|
||||
|
||||
Q_PROPERTY(int parabolicSpread READ parabolicSpread WRITE setParabolicSpread NOTIFY parabolicSpreadChanged)
|
||||
Q_PROPERTY(float thicknessMarginInfluence READ thicknessMarginInfluence WRITE setThicknessMarginInfluence NOTIFY thicknessMarginInfluenceChanged)
|
||||
|
||||
Q_PROPERTY(QString singleModeLayoutName READ singleModeLayoutName WRITE setSingleModeLayoutName NOTIFY singleModeLayoutNameChanged)
|
||||
|
||||
Q_PROPERTY(QStringList launchers READ launchers WRITE setLaunchers NOTIFY launchersChanged)
|
||||
@ -76,6 +81,9 @@ public:
|
||||
bool inAdvancedModeForEditSettings() const;
|
||||
void setInAdvancedModeForEditSettings(const bool &inAdvanced);
|
||||
|
||||
bool inConfigureAppletsMode() const;
|
||||
void setInConfigureAppletsMode(const bool enabled);
|
||||
|
||||
bool isAvailableGeometryBroadcastedToPlasma() const;
|
||||
void setIsAvailableGeometryBroadcastedToPlasma(const bool &isBroadcasted);
|
||||
|
||||
@ -91,12 +99,18 @@ public:
|
||||
bool showInfoWindow() const;
|
||||
void setShowInfoWindow(bool show);
|
||||
|
||||
int parabolicSpread() const;
|
||||
void setParabolicSpread(const int &spread);
|
||||
|
||||
int version() const;
|
||||
void setVersion(int ver);
|
||||
|
||||
int screenTrackerInterval() const;
|
||||
void setScreenTrackerInterval(int duration);
|
||||
|
||||
float thicknessMarginInfluence() const;
|
||||
void setThicknessMarginInfluence(const float &influence);
|
||||
|
||||
QString singleModeLayoutName() const;
|
||||
void setSingleModeLayoutName(QString layoutName);
|
||||
|
||||
@ -132,18 +146,21 @@ signals:
|
||||
void colorsScriptIsPresentChanged();
|
||||
void downloadWindowSizeChanged();
|
||||
void inAdvancedModeForEditSettingsChanged();
|
||||
void inConfigureAppletsModeChanged();
|
||||
void layoutsColumnWidthsChanged();
|
||||
void layoutsWindowSizeChanged();
|
||||
void launchersChanged();
|
||||
void layoutsMemoryUsageChanged();
|
||||
void isAvailableGeometryBroadcastedToPlasmaChanged();
|
||||
void metaPressAndHoldEnabledChanged();
|
||||
void parabolicSpreadChanged();
|
||||
void sensitivityChanged();
|
||||
void screensCountChanged();
|
||||
void screenScalesChanged();
|
||||
void screenTrackerIntervalChanged();
|
||||
void showInfoWindowChanged();
|
||||
void singleModeLayoutNameChanged();
|
||||
void thicknessMarginInfluenceChanged();
|
||||
void versionChanged();
|
||||
|
||||
private slots:
|
||||
@ -170,6 +187,7 @@ private:
|
||||
bool m_canDisableBorders{false};
|
||||
bool m_colorsScriptIsPresent{false};
|
||||
bool m_inAdvancedModeForEditSettings{false};
|
||||
bool m_inConfigureAppletsMode{false};
|
||||
bool m_isAvailableGeometryBroadcastedToPlasma{true};
|
||||
bool m_metaPressAndHoldEnabled{true};
|
||||
bool m_showInfoWindow{true};
|
||||
@ -182,6 +200,8 @@ private:
|
||||
int m_version{1};
|
||||
|
||||
int m_screenTrackerInterval{2500};
|
||||
int m_parabolicSpread{Data::Preferences::PARABOLICSPREAD};
|
||||
float m_thicknessMarginInfluence{Data::Preferences::THICKNESSMARGININFLUENCE};
|
||||
|
||||
QString m_singleModeLayoutName;
|
||||
|
||||
|
@ -89,8 +89,8 @@ void CustomMenuItemWidget::paintEvent(QPaintEvent* e)
|
||||
|
||||
if (!m_screen.id.isEmpty()) {
|
||||
int maxiconsize = 26;
|
||||
remained = Latte::remainedFromScreenDrawing(opt, maxiconsize);
|
||||
QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.geometry, maxiconsize);
|
||||
remained = Latte::remainedFromScreenDrawing(opt, m_screen.isScreensGroup(), maxiconsize);
|
||||
QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.isScreensGroup(), m_screen.geometry, maxiconsize);
|
||||
|
||||
if (!m_view.id.isEmpty()) {
|
||||
Latte::drawView(&painter, opt, m_view, availableScreenRect);
|
||||
|
@ -27,7 +27,7 @@ NameDelegate::NameDelegate(QObject *parent)
|
||||
|
||||
void NameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
editor->setGeometry(Latte::remainedFromScreenDrawing(option));
|
||||
editor->setGeometry(Latte::remainedFromScreenDrawing(option, false));
|
||||
}
|
||||
|
||||
void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
@ -90,8 +90,8 @@ void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
|
||||
// draw screen icon
|
||||
int maxiconsize = -1; //disabled
|
||||
remainedrect = Latte::remainedFromScreenDrawing(myOptions, maxiconsize);
|
||||
QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.geometry, maxiconsize, textopacity);
|
||||
remainedrect = Latte::remainedFromScreenDrawing(myOptions, screen.isScreensGroup(), maxiconsize);
|
||||
QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.isScreensGroup(), screen.geometry, maxiconsize, textopacity);
|
||||
Latte::drawView(painter, myOptions, view, availableScreenRect, textopacity);
|
||||
|
||||
myOptions.rect = remainedrect;
|
||||
|
@ -31,12 +31,8 @@
|
||||
// KDE
|
||||
#include <KMessageWidget>
|
||||
#include <KSharedConfig>
|
||||
|
||||
#if KF5_VERSION_MINOR >= 71
|
||||
#include <KIO/OpenUrlJob>
|
||||
#else
|
||||
#include <KRun>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Latte {
|
||||
namespace Settings {
|
||||
@ -604,12 +600,8 @@ void Views::showDefaultPersistentErrorWarningInlineMessage(const QString &messag
|
||||
QString file = openlayoutaction->data().toString();
|
||||
|
||||
if (!file.isEmpty()) {
|
||||
#if KF5_VERSION_MINOR >= 71
|
||||
auto job = new KIO::OpenUrlJob(QUrl::fromLocalFile(file), QStringLiteral("text/plain"), this);
|
||||
job->start();
|
||||
#else
|
||||
KRun::runUrl(QUrl::fromLocalFile(file), QStringLiteral("text/plain"), m_view);
|
||||
#endif
|
||||
showDefaultInlineMessageValidator();
|
||||
}
|
||||
});
|
||||
|
@ -424,16 +424,26 @@ Latte::Data::Screen Views::screenData(const QString &viewId) const
|
||||
return Latte::Data::Screen();
|
||||
}
|
||||
|
||||
QString primaryid = QString::number(m_corona->screenPool()->primaryScreenId());
|
||||
// QString primaryid = QString::number(m_corona->screenPool()->primaryScreenId());
|
||||
QString explicitid = QString::number(m_viewsTable[row].screen);
|
||||
|
||||
if (m_viewsTable[row].onPrimary && s_screens.containsId(primaryid)) {
|
||||
return s_screens[primaryid];
|
||||
Data::Screen scrData = s_screens[0]; //default
|
||||
|
||||
if (m_viewsTable[row].onPrimary || (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup)) {
|
||||
scrData = s_screens[0]; //primary, allscreens
|
||||
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
scrData = s_screens[2]; //allsecondaryscreens
|
||||
} else if (!m_viewsTable[row].onPrimary && s_screens.containsId(explicitid)) {
|
||||
return s_screens[explicitid];
|
||||
scrData = s_screens[explicitid]; //explicit
|
||||
}
|
||||
|
||||
return Latte::Data::Screen();
|
||||
if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
|
||||
scrData.id = QString::number(Data::Screen::ONALLSCREENSID);
|
||||
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
scrData.id = QString::number(Data::Screen::ONALLSECONDARYSCREENSID);
|
||||
}
|
||||
|
||||
return scrData;
|
||||
}
|
||||
|
||||
Latte::Data::ViewsTable Views::alteredViews() const
|
||||
@ -486,14 +496,21 @@ void Views::clearErrorsAndWarnings()
|
||||
void Views::populateScreens()
|
||||
{
|
||||
s_screens.clear();
|
||||
Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID),
|
||||
i18nc("primary screen", " - Follow Primary Screen - "));
|
||||
Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID), i18n(" - On Primary Screen - "));
|
||||
Data::Screen allscreens(QString::number(Data::Screen::ONALLSCREENSID), i18n(" - On All Screens - "));
|
||||
Data::Screen allsecscreens(QString::number(Data::Screen::ONALLSECONDARYSCREENSID), i18n(" - On All Secondary Screens - "));
|
||||
|
||||
primary.isActive = true;
|
||||
allscreens.isActive = true;
|
||||
allsecscreens.isActive = (m_corona->screenPool()->secondaryScreenIds().count() > 0);
|
||||
|
||||
primary.isActive = true;
|
||||
s_screens << primary;
|
||||
s_screens << allscreens;
|
||||
s_screens << allsecscreens;
|
||||
int defcount = s_screens.rowCount();
|
||||
s_screens << m_corona->screenPool()->screensTable();
|
||||
|
||||
for (int i=1; i<s_screens.rowCount(); ++i) {
|
||||
for (int i=defcount; i<s_screens.rowCount(); ++i) {
|
||||
s_screens[i].isActive = m_corona->screenPool()->isScreenActive(s_screens[i].id.toInt());
|
||||
}
|
||||
}
|
||||
@ -662,22 +679,30 @@ bool Views::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
if (role == Qt::UserRole) {
|
||||
int screen = value.toString().toInt();
|
||||
bool onprimary = (screen == Latte::Data::Screen::ONPRIMARYID);
|
||||
|
||||
if ((m_viewsTable[row].onPrimary == onprimary) && (m_viewsTable[row].screen == screen)) {
|
||||
return false;
|
||||
}
|
||||
bool onallscreens = (screen == Latte::Data::Screen::ONALLSCREENSID);
|
||||
bool onallsecscreens = (screen == Latte::Data::Screen::ONALLSECONDARYSCREENSID);
|
||||
|
||||
if (onprimary) {
|
||||
m_viewsTable[row].onPrimary = true;
|
||||
m_viewsTable[row].screensGroup = Latte::Types::SingleScreenGroup;
|
||||
} else if (onallscreens) {
|
||||
m_viewsTable[row].onPrimary = true;
|
||||
m_viewsTable[row].screensGroup = Latte::Types::AllScreensGroup;
|
||||
} else if (onallsecscreens) {
|
||||
m_viewsTable[row].onPrimary = false;
|
||||
m_viewsTable[row].screensGroup = Latte::Types::AllSecondaryScreensGroup;
|
||||
} else {
|
||||
m_viewsTable[row].onPrimary = false;
|
||||
m_viewsTable[row].screensGroup = Latte::Types::SingleScreenGroup;
|
||||
m_viewsTable[row].screen = screen;
|
||||
}
|
||||
|
||||
if (onprimary || onallscreens || onallsecscreens) {
|
||||
if (o_viewsTable.containsId(m_viewsTable[row].id)) {
|
||||
//! we need to update screen also in order to not show that there are changes even though
|
||||
//! they are not any
|
||||
m_viewsTable[row].screen = o_viewsTable[m_viewsTable[row].id].screen;
|
||||
}
|
||||
} else {
|
||||
m_viewsTable[row].onPrimary = false;
|
||||
m_viewsTable[row].screen = screen;
|
||||
}
|
||||
|
||||
emit dataChanged(this->index(row, NAMECOLUMN), this->index(row, ALIGNMENTCOLUMN), roles);
|
||||
@ -759,7 +784,7 @@ QVariant Views::data(const QModelIndex &index, int role) const
|
||||
|
||||
if (!m_viewsTable[row].onPrimary && !currentScreens.containsId(QString::number(m_viewsTable[row].screen))) {
|
||||
Data::Screen explicitScr(QString::number(m_viewsTable[row].screen),
|
||||
i18nc("unknown screen", "Unknown : [%1]", explicitScr.id));
|
||||
i18nc("unknown screen", "Unknown: [%1]", explicitScr.id));
|
||||
currentScreens.insertBasedOnId(explicitScr);
|
||||
}
|
||||
|
||||
@ -838,18 +863,30 @@ QVariant Views::data(const QModelIndex &index, int role) const
|
||||
break;
|
||||
case SCREENCOLUMN:
|
||||
if (role == Qt::DisplayRole){
|
||||
if (m_viewsTable[row].onPrimary) {
|
||||
if (m_viewsTable[row].screensGroup == Latte::Types::SingleScreenGroup && m_viewsTable[row].onPrimary) {
|
||||
return i18nc("primary screen", "Primary");
|
||||
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
|
||||
return i18n("All Screens");
|
||||
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
return i18n("Secondary Screens");
|
||||
} else {
|
||||
QString scrId = QString::number(m_viewsTable[row].screen);
|
||||
if (s_screens.containsId(scrId)) {
|
||||
return s_screens[scrId].name;
|
||||
} else {
|
||||
return i18nc("unknown screen", "Unknown : [%1]", scrId);
|
||||
return i18nc("unknown screen", "Unknown: [%1]", scrId);
|
||||
}
|
||||
}
|
||||
} else if (role == Qt::UserRole) {
|
||||
return m_viewsTable[row].onPrimary ? QString::number(Data::Screen::ONPRIMARYID) : QString::number(m_viewsTable[row].screen);
|
||||
if (m_viewsTable[row].screensGroup == Latte::Types::SingleScreenGroup && m_viewsTable[row].onPrimary) {
|
||||
return QString::number(Data::Screen::ONPRIMARYID);
|
||||
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
|
||||
return QString::number(Data::Screen::ONALLSCREENSID);
|
||||
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
return QString::number(Data::Screen::ONALLSECONDARYSCREENSID);
|
||||
} else {
|
||||
return QString::number(m_viewsTable[row].screen);
|
||||
}
|
||||
} else if (role == ISCHANGEDROLE) {
|
||||
return (isNewView
|
||||
|| (m_viewsTable[row].onPrimary != o_viewsTable[origviewid].onPrimary)
|
||||
|
@ -103,8 +103,8 @@ void GlobalShortcuts::init()
|
||||
//show the layouts editor
|
||||
QAction *layoutsAction = generalActions->addAction(QStringLiteral("show latte global settings"));
|
||||
layoutsAction->setText(i18n("Show Latte Global Settings"));
|
||||
layoutsAction->setShortcut(QKeySequence(Qt::META + Qt::Key_W));
|
||||
KGlobalAccel::setGlobalShortcut(layoutsAction, QKeySequence(Qt::META + Qt::Key_W));
|
||||
layoutsAction->setShortcut(QKeySequence());
|
||||
KGlobalAccel::setGlobalShortcut(layoutsAction, QKeySequence());
|
||||
connect(layoutsAction, &QAction::triggered, this, [this]() {
|
||||
m_modifierTracker->cancelMetaPressed();
|
||||
m_corona->layoutsManager()->showLatteSettingsDialog(Settings::Dialog::PreferencesPage, true);
|
||||
@ -487,7 +487,7 @@ bool GlobalShortcuts::viewsToHideAreValid()
|
||||
|
||||
void GlobalShortcuts::showSettings()
|
||||
{
|
||||
QList<Latte::View *> sortedViews = m_corona->layoutsManager()->synchronizer()->sortedCurrentViews();
|
||||
QList<Latte::View *> sortedViews = m_corona->layoutsManager()->synchronizer()->sortedCurrentOriginalViews();
|
||||
|
||||
//! find which is the next view to show its settings
|
||||
if (sortedViews.count() > 0) {
|
||||
|
@ -214,10 +214,10 @@ QString Manager::proposedTemplateAbsolutePath(QString templateFilename)
|
||||
QString tempfilename = templateFilename;
|
||||
|
||||
if (tempfilename.endsWith(".layout.latte")) {
|
||||
QString clearedname = QFileInfo(tempfilename).baseName();
|
||||
QString clearedname = tempfilename.chopped(QString(".layout.latte").size());
|
||||
tempfilename = uniqueLayoutTemplateName(clearedname) + ".layout.latte";
|
||||
} else if (tempfilename.endsWith(".view.latte")) {
|
||||
QString clearedname = QFileInfo(tempfilename).baseName();
|
||||
QString clearedname = tempfilename.chopped(QString(".view.latte").size());
|
||||
tempfilename = uniqueViewTemplateName(clearedname) + ".view.latte";
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
set(lattedock-app_SRCS
|
||||
${lattedock-app_SRCS}
|
||||
${lattedock-app_SRCS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/clonedview.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/containmentinterface.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/contextmenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/effects.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/eventssink.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/panelshadows.cpp
|
||||
@ -9,6 +9,7 @@ set(lattedock-app_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/positioner.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tasksmodel.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/view.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/originalview.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/visibilitymanager.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
357
app/view/clonedview.cpp
Normal file
357
app/view/clonedview.cpp
Normal file
@ -0,0 +1,357 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "clonedview.h"
|
||||
#include "containmentinterface.h"
|
||||
#include "visibilitymanager.h"
|
||||
#include "../data/viewdata.h"
|
||||
#include "../layouts/storage.h"
|
||||
|
||||
namespace Latte {
|
||||
|
||||
const int ClonedView::ERRORAPPLETID;
|
||||
|
||||
QStringList ClonedView::CONTAINMENTMANUALSYNCEDPROPERTIES = QStringList()
|
||||
<< QString("appletOrder")
|
||||
<< QString("lockedZoomApplets")
|
||||
<< QString("userBlocksColorizingApplets");
|
||||
|
||||
ClonedView::ClonedView(Plasma::Corona *corona, Latte::OriginalView *originalView, QScreen *targetScreen, bool byPassX11WM)
|
||||
: View(corona, targetScreen, byPassX11WM),
|
||||
m_originalView(originalView)
|
||||
{
|
||||
m_originalView->addClone(this);
|
||||
initSync();
|
||||
}
|
||||
|
||||
ClonedView::~ClonedView()
|
||||
{
|
||||
}
|
||||
|
||||
void ClonedView::initSync()
|
||||
{
|
||||
connect(m_originalView, &View::containmentChanged, this, &View::groupIdChanged);
|
||||
|
||||
//! Update Visibility From Original
|
||||
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::modeChanged, this, [&]() {
|
||||
visibility()->setMode(m_originalView->visibility()->mode());
|
||||
});
|
||||
|
||||
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnDesktopChanged, this, [&]() {
|
||||
visibility()->setRaiseOnDesktop(m_originalView->visibility()->raiseOnDesktop());
|
||||
});
|
||||
|
||||
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnActivityChanged, this, [&]() {
|
||||
visibility()->setRaiseOnActivity(m_originalView->visibility()->raiseOnActivity());
|
||||
});
|
||||
|
||||
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::enableKWinEdgesChanged, this, [&]() {
|
||||
visibility()->setEnableKWinEdges(m_originalView->visibility()->enableKWinEdges());
|
||||
});
|
||||
|
||||
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerShowChanged, this, [&]() {
|
||||
visibility()->setTimerShow(m_originalView->visibility()->timerShow());
|
||||
});
|
||||
|
||||
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerHideChanged, this, [&]() {
|
||||
visibility()->setTimerHide(m_originalView->visibility()->timerHide());
|
||||
});
|
||||
|
||||
|
||||
//! Update Applets from Clone -> OriginalView
|
||||
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::updateOriginalAppletConfigProperty);
|
||||
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::initializationCompleted, this, &ClonedView::updateAppletIdsHash);
|
||||
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::updateAppletIdsHash);
|
||||
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
|
||||
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this, [&](const QString &pluginId) {
|
||||
m_originalView->addApplet(pluginId, containment()->id());
|
||||
});
|
||||
|
||||
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this, [&](QObject *data, int x, int y) {
|
||||
m_originalView->addApplet(data, x, y, containment()->id());
|
||||
});
|
||||
|
||||
//! Update Applets and Containment from OrigalView -> Clone
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::containmentConfigPropertyChanged, this, &ClonedView::updateContainmentConfigProperty);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::onOriginalAppletConfigPropertyChanged);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletInScheduledDestructionChanged, this, &ClonedView::onOriginalAppletInScheduledDestructionChanged);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletRemoved, this, &ClonedView::onOriginalAppletRemoved);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::onOriginalAppletsOrderChanged);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsInLockedZoomChanged, this, &ClonedView::onOriginalAppletsInLockedZoomChanged);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsDisabledColoringChanged, this, &ClonedView::onOriginalAppletsDisabledColoringChanged);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this->extendedInterface(), [&](const QString &pluginId) {
|
||||
extendedInterface()->addApplet(pluginId);
|
||||
});
|
||||
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this->extendedInterface(), [&](QObject *data, int x, int y) {
|
||||
extendedInterface()->addApplet(data, x, y);
|
||||
});
|
||||
|
||||
//! Indicator
|
||||
connect(m_originalView, &Latte::View::indicatorChanged, this, &ClonedView::indicatorChanged);
|
||||
}
|
||||
|
||||
bool ClonedView::isSingle() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClonedView::isOriginal() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClonedView::isCloned() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClonedView::isPreferredForShortcuts() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int ClonedView::groupId() const
|
||||
{
|
||||
if (!m_originalView->containment()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_originalView->containment()->id();
|
||||
}
|
||||
|
||||
Latte::Types::ScreensGroup ClonedView::screensGroup() const
|
||||
{
|
||||
return Latte::Types::SingleScreenGroup;
|
||||
}
|
||||
|
||||
ViewPart::Indicator *ClonedView::indicator() const
|
||||
{
|
||||
return m_originalView->indicator();
|
||||
}
|
||||
|
||||
|
||||
bool ClonedView::hasOriginalAppletId(const int &clonedid)
|
||||
{
|
||||
if (clonedid < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
|
||||
while (i != m_currentAppletIds.constEnd()) {
|
||||
if (i.value() == clonedid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ClonedView::originalAppletId(const int &clonedid)
|
||||
{
|
||||
if (clonedid < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
|
||||
while (i != m_currentAppletIds.constEnd()) {
|
||||
if (i.value() == clonedid) {
|
||||
return i.key();
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool ClonedView::isTranslatableToClonesOrder(const QList<int> &originalOrder)
|
||||
{
|
||||
for(int i=0; i<originalOrder.count(); ++i) {
|
||||
int oid = originalOrder[i];
|
||||
if (oid < 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_currentAppletIds.contains(oid)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Latte::Data::View ClonedView::data() const
|
||||
{
|
||||
Latte::Data::View vdata = View::data();
|
||||
vdata.isClonedFrom = m_originalView->containment()->id();
|
||||
return vdata;
|
||||
}
|
||||
|
||||
void ClonedView::updateAppletIdsHash()
|
||||
{
|
||||
QList<int> originalids = m_originalView->extendedInterface()->appletsOrder();
|
||||
QList<int> clonedids = extendedInterface()->appletsOrder();
|
||||
|
||||
for (int i=0; i<originalids.count(); ++i) {
|
||||
int oid = originalids[i];
|
||||
if (oid < 0 || (m_currentAppletIds.contains(oid) && m_currentAppletIds[oid] > 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int oindex = m_originalView->extendedInterface()->indexOfApplet(oid);
|
||||
ViewPart::AppletInterfaceData originalapplet = m_originalView->extendedInterface()->appletDataForId(oid);
|
||||
ViewPart::AppletInterfaceData clonedapplet = extendedInterface()->appletDataAtIndex(oindex);
|
||||
|
||||
bool registeredclonedid = (originalAppletId(clonedapplet.id) > 0);
|
||||
|
||||
if (originalapplet.id>0 && clonedapplet.id>0 && originalapplet.plugin == clonedapplet.plugin && !registeredclonedid) {
|
||||
m_currentAppletIds[originalapplet.id] = clonedapplet.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<int> ClonedView::translateToClonesOrder(const QList<int> &originalIds)
|
||||
{
|
||||
QList<int> ids;
|
||||
|
||||
for (int i=0; i<originalIds.count(); ++i) {
|
||||
int originalid = originalIds[i];
|
||||
if (originalid < 0 ) {
|
||||
ids << originalid;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_currentAppletIds.contains(originalid)) {
|
||||
ids << m_currentAppletIds[originalid];
|
||||
} else {
|
||||
ids << ERRORAPPLETID; //error
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
void ClonedView::showConfigurationInterface(Plasma::Applet *applet)
|
||||
{
|
||||
Plasma::Containment *c = qobject_cast<Plasma::Containment *>(applet);
|
||||
|
||||
if (Layouts::Storage::self()->isLatteContainment(c)) {
|
||||
m_originalView->showSettingsWindow();
|
||||
} else {
|
||||
View::showConfigurationInterface(applet);
|
||||
}
|
||||
}
|
||||
|
||||
void ClonedView::onOriginalAppletRemoved(const int &id)
|
||||
{
|
||||
if (!m_currentAppletIds.contains(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
extendedInterface()->removeApplet(m_currentAppletIds[id]);
|
||||
m_currentAppletIds.remove(id);
|
||||
}
|
||||
|
||||
void ClonedView::onOriginalAppletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value)
|
||||
{
|
||||
if (!m_currentAppletIds.contains(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
extendedInterface()->updateAppletConfigProperty(m_currentAppletIds[id], key, value);
|
||||
}
|
||||
|
||||
void ClonedView::onOriginalAppletInScheduledDestructionChanged(const int &id, const bool &enabled)
|
||||
{
|
||||
if (!m_currentAppletIds.contains(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
extendedInterface()->setAppletInScheduledDestruction(m_currentAppletIds[id], enabled);
|
||||
}
|
||||
|
||||
void ClonedView::updateContainmentConfigProperty(const QString &key, const QVariant &value)
|
||||
{
|
||||
if (!CONTAINMENTMANUALSYNCEDPROPERTIES.contains(key)) {
|
||||
extendedInterface()->updateContainmentConfigProperty(key, value);
|
||||
} else {
|
||||
//qDebug() << "org.kde.sync :: containment config value syncing blocked :: " << key;
|
||||
}
|
||||
}
|
||||
|
||||
void ClonedView::updateOriginalAppletConfigProperty(const int &clonedid, const QString &key, const QVariant &value)
|
||||
{
|
||||
if (!hasOriginalAppletId(clonedid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_originalView->extendedInterface()->updateAppletConfigProperty(originalAppletId(clonedid), key, value);
|
||||
}
|
||||
|
||||
void ClonedView::onOriginalAppletsOrderChanged()
|
||||
{
|
||||
updateAppletIdsHash();
|
||||
QList<int> originalorder = m_originalView->extendedInterface()->appletsOrder();
|
||||
|
||||
if (originalorder.count() != extendedInterface()->appletsOrder().count()) {
|
||||
//probably an applet was removed or added and clone has not been updated yet
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isTranslatableToClonesOrder(originalorder)) {
|
||||
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
|
||||
return;
|
||||
}
|
||||
|
||||
QList<int> newclonesorder = translateToClonesOrder(originalorder);
|
||||
|
||||
if (newclonesorder.contains(ERRORAPPLETID)) {
|
||||
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
|
||||
return;
|
||||
}
|
||||
|
||||
extendedInterface()->setAppletsOrder(newclonesorder);
|
||||
}
|
||||
|
||||
void ClonedView::onOriginalAppletsInLockedZoomChanged(const QList<int> &originalapplets)
|
||||
{
|
||||
if (!isTranslatableToClonesOrder(originalapplets)) {
|
||||
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
|
||||
return;
|
||||
}
|
||||
|
||||
QList<int> newclonesorder = translateToClonesOrder(originalapplets);
|
||||
|
||||
if (newclonesorder.contains(ERRORAPPLETID)) {
|
||||
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
|
||||
return;
|
||||
}
|
||||
|
||||
extendedInterface()->setAppletsInLockedZoom(newclonesorder);
|
||||
}
|
||||
|
||||
void ClonedView::onOriginalAppletsDisabledColoringChanged(const QList<int> &originalapplets)
|
||||
{
|
||||
if (!isTranslatableToClonesOrder(originalapplets)) {
|
||||
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
|
||||
return;
|
||||
}
|
||||
|
||||
QList<int> newclonesorder = translateToClonesOrder(originalapplets);
|
||||
|
||||
if (newclonesorder.contains(ERRORAPPLETID)) {
|
||||
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
|
||||
return;
|
||||
}
|
||||
|
||||
extendedInterface()->setAppletsDisabledColoring(newclonesorder);
|
||||
}
|
||||
|
||||
|
||||
}
|
72
app/view/clonedview.h
Normal file
72
app/view/clonedview.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef CLONEDVIEW_H
|
||||
#define CLONEDVIEW_H
|
||||
|
||||
// local
|
||||
#include <coretypes.h>
|
||||
#include "originalview.h"
|
||||
#include "indicator/indicator.h"
|
||||
#include "view.h"
|
||||
|
||||
namespace Latte {
|
||||
|
||||
class ClonedView : public View
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static const int ERRORAPPLETID = -999;
|
||||
|
||||
ClonedView(Plasma::Corona *corona, Latte::OriginalView *originalView, QScreen *targetScreen = nullptr, bool byPassX11WM = false);
|
||||
~ClonedView();
|
||||
|
||||
bool isOriginal() const override;
|
||||
bool isCloned() const override;
|
||||
bool isSingle() const override;
|
||||
|
||||
bool isPreferredForShortcuts() const override;
|
||||
int groupId() const override;
|
||||
|
||||
Latte::Types::ScreensGroup screensGroup() const override;
|
||||
|
||||
ViewPart::Indicator *indicator() const override;
|
||||
Latte::Data::View data() const override;
|
||||
|
||||
protected:
|
||||
void showConfigurationInterface(Plasma::Applet *applet) override;
|
||||
|
||||
private slots:
|
||||
void initSync();
|
||||
void onOriginalAppletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value);
|
||||
void onOriginalAppletInScheduledDestructionChanged(const int &id, const bool &enabled);
|
||||
void onOriginalAppletRemoved(const int &id);
|
||||
void onOriginalAppletsOrderChanged();
|
||||
void onOriginalAppletsInLockedZoomChanged(const QList<int> &originalapplets);
|
||||
void onOriginalAppletsDisabledColoringChanged(const QList<int> &originalapplets);
|
||||
|
||||
void updateContainmentConfigProperty(const QString &key, const QVariant &value);
|
||||
void updateOriginalAppletConfigProperty(const int &clonedid, const QString &key, const QVariant &value);
|
||||
|
||||
void updateAppletIdsHash();
|
||||
private:
|
||||
bool isTranslatableToClonesOrder(const QList<int> &originalOrder);
|
||||
|
||||
bool hasOriginalAppletId(const int &clonedid);
|
||||
int originalAppletId(const int &clonedid);
|
||||
|
||||
QList<int> translateToClonesOrder(const QList<int> &originalIds);
|
||||
|
||||
private:
|
||||
static QStringList CONTAINMENTMANUALSYNCEDPROPERTIES;
|
||||
|
||||
QPointer<Latte::OriginalView> m_originalView;
|
||||
QHash<int, int> m_currentAppletIds;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -9,11 +9,13 @@
|
||||
#include "view.h"
|
||||
#include "../lattecorona.h"
|
||||
#include "../layout/genericlayout.h"
|
||||
#include "../layouts/importer.h"
|
||||
#include "../layouts/storage.h"
|
||||
#include "../settings/universalsettings.h"
|
||||
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QLatin1String>
|
||||
|
||||
// Plasma
|
||||
@ -25,6 +27,7 @@
|
||||
#include <KDesktopFile>
|
||||
#include <KLocalizedString>
|
||||
#include <KPluginMetaData>
|
||||
#include <KDeclarative/ConfigPropertyMap>
|
||||
|
||||
namespace Latte {
|
||||
namespace ViewPart {
|
||||
@ -41,13 +44,16 @@ ContainmentInterface::ContainmentInterface(Latte::View *parent)
|
||||
m_appletsExpandedConnectionsTimer.setInterval(2000);
|
||||
m_appletsExpandedConnectionsTimer.setSingleShot(true);
|
||||
|
||||
m_appletDelayedConfigurationTimer.setInterval(1000);
|
||||
m_appletDelayedConfigurationTimer.setSingleShot(true);
|
||||
connect(&m_appletDelayedConfigurationTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletDelayedConfiguration);
|
||||
|
||||
connect(&m_appletsExpandedConnectionsTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletsTracking);
|
||||
|
||||
connect(m_view, &View::containmentChanged
|
||||
, this, [&]() {
|
||||
if (m_view->containment()) {
|
||||
connect(m_view->containment(), &Plasma::Containment::appletAdded, this, &ContainmentInterface::onAppletAdded);
|
||||
|
||||
m_appletsExpandedConnectionsTimer.start();
|
||||
}
|
||||
});
|
||||
@ -423,7 +429,7 @@ bool ContainmentInterface::appletIsExpandable(const int id) const
|
||||
|
||||
for (const auto applet : m_view->containment()->applets()) {
|
||||
if (applet && applet->id() == (uint)id) {
|
||||
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) {
|
||||
if (Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -446,7 +452,7 @@ bool ContainmentInterface::appletIsExpandable(PlasmaQuick::AppletQuickItem *appl
|
||||
|
||||
return ((appletQuickItem->fullRepresentation() != nullptr
|
||||
&& appletQuickItem->preferredRepresentation() != appletQuickItem->fullRepresentation())
|
||||
|| Latte::Layouts::Storage::self()->isSubContainment(m_view->layout(), appletQuickItem->applet()));
|
||||
|| Latte::Layouts::Storage::self()->isSubContainment(m_view->corona(), appletQuickItem->applet()));
|
||||
}
|
||||
|
||||
bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const
|
||||
@ -457,7 +463,7 @@ bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const
|
||||
|
||||
for (const auto applet : m_view->containment()->applets()) {
|
||||
if (applet && applet->id() == (uint)id) {
|
||||
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) {
|
||||
if (Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -487,6 +493,148 @@ bool ContainmentInterface::hasPlasmaTasks() const
|
||||
return (m_plasmaTasksModel->count() > 0);
|
||||
}
|
||||
|
||||
int ContainmentInterface::indexOfApplet(const int &id)
|
||||
{
|
||||
if (m_appletOrder.contains(id)) {
|
||||
return m_appletOrder.indexOf(id);
|
||||
} else if (m_appletData.contains(id)) {
|
||||
return m_appletData[id].lastValidIndex;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ViewPart::AppletInterfaceData ContainmentInterface::appletDataAtIndex(const int &index)
|
||||
{
|
||||
ViewPart::AppletInterfaceData data;
|
||||
|
||||
if (index<0 || (index > (m_appletOrder.count()-1))) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return m_appletData[m_appletOrder[index]];
|
||||
}
|
||||
|
||||
ViewPart::AppletInterfaceData ContainmentInterface::appletDataForId(const int &id)
|
||||
{
|
||||
ViewPart::AppletInterfaceData data;
|
||||
|
||||
if (!m_appletData.contains(id)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return m_appletData[id];
|
||||
}
|
||||
|
||||
QObject *ContainmentInterface::plasmoid() const
|
||||
{
|
||||
return m_plasmoid;
|
||||
}
|
||||
|
||||
void ContainmentInterface::setPlasmoid(QObject *plasmoid)
|
||||
{
|
||||
if (m_plasmoid == plasmoid) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_plasmoid = plasmoid;
|
||||
|
||||
if (m_plasmoid) {
|
||||
m_configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>(m_plasmoid->property("configuration").value<QObject *>());
|
||||
|
||||
if (m_configuration) {
|
||||
connect(m_configuration, &QQmlPropertyMap::valueChanged, this, &ContainmentInterface::containmentConfigPropertyChanged);
|
||||
}
|
||||
}
|
||||
|
||||
emit plasmoidChanged();
|
||||
}
|
||||
|
||||
QObject *ContainmentInterface::layoutManager() const
|
||||
{
|
||||
return m_layoutManager;
|
||||
}
|
||||
|
||||
void ContainmentInterface::setLayoutManager(QObject *manager)
|
||||
{
|
||||
if (m_layoutManager == manager) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_layoutManager = manager;
|
||||
|
||||
// applets order
|
||||
int metaorderindex = m_layoutManager->metaObject()->indexOfProperty("order");
|
||||
if (metaorderindex >= 0) {
|
||||
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
|
||||
if (metaorder.hasNotifySignal()) {
|
||||
QMetaMethod metaorderchanged = metaorder.notifySignal();
|
||||
QMetaMethod metaupdateappletorder = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsOrder()"));
|
||||
connect(m_layoutManager, metaorderchanged, this, metaupdateappletorder);
|
||||
updateAppletsOrder();
|
||||
}
|
||||
}
|
||||
|
||||
// applets in locked zoom
|
||||
metaorderindex = m_layoutManager->metaObject()->indexOfProperty("lockedZoomApplets");
|
||||
if (metaorderindex >= 0) {
|
||||
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
|
||||
if (metaorder.hasNotifySignal()) {
|
||||
QMetaMethod metaorderchanged = metaorder.notifySignal();
|
||||
QMetaMethod metaupdateapplets = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsInLockedZoom()"));
|
||||
connect(m_layoutManager, metaorderchanged, this, metaupdateapplets);
|
||||
updateAppletsInLockedZoom();
|
||||
}
|
||||
}
|
||||
|
||||
// applets disabled their autocoloring
|
||||
metaorderindex = m_layoutManager->metaObject()->indexOfProperty("userBlocksColorizingApplets");
|
||||
if (metaorderindex >= 0) {
|
||||
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
|
||||
if (metaorder.hasNotifySignal()) {
|
||||
QMetaMethod metaorderchanged = metaorder.notifySignal();
|
||||
QMetaMethod metaupdateapplets = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsDisabledColoring()"));
|
||||
connect(m_layoutManager, metaorderchanged, this, metaupdateapplets);
|
||||
updateAppletsDisabledColoring();
|
||||
}
|
||||
}
|
||||
|
||||
emit layoutManagerChanged();
|
||||
}
|
||||
|
||||
void ContainmentInterface::addApplet(const QString &pluginId)
|
||||
{
|
||||
if (pluginId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList paths = Latte::Layouts::Importer::standardPaths();
|
||||
QString pluginpath;
|
||||
|
||||
for(int i=0; i<paths.count(); ++i) {
|
||||
QString cpath = paths[i] + "/plasma/plasmoids/" + pluginId;
|
||||
|
||||
if (QDir(cpath).exists()) {
|
||||
pluginpath = cpath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pluginpath.isEmpty()) {
|
||||
m_view->containment()->createApplet(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentInterface::addApplet(QObject *metadata, int x, int y)
|
||||
{
|
||||
int processmimedataindex = m_plasmoid->metaObject()->indexOfMethod("processMimeData(QObject*,int,int)");
|
||||
QMetaMethod processmethod = m_plasmoid->metaObject()->method(processmimedataindex);
|
||||
processmethod.invoke(m_plasmoid,
|
||||
Q_ARG(QObject *, metadata),
|
||||
Q_ARG(int, x),
|
||||
Q_ARG(int, y));
|
||||
}
|
||||
|
||||
void ContainmentInterface::addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem)
|
||||
{
|
||||
if (appletQuickItem && m_expandedAppletIds.contains(appletQuickItem) && appletIsExpandable(appletQuickItem)) {
|
||||
@ -555,6 +703,68 @@ void ContainmentInterface::onAppletExpandedChanged()
|
||||
}
|
||||
}
|
||||
|
||||
QList<int> ContainmentInterface::appletsOrder() const
|
||||
{
|
||||
return m_appletOrder;
|
||||
}
|
||||
|
||||
void ContainmentInterface::updateAppletsOrder()
|
||||
{
|
||||
if (!m_layoutManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<int> neworder = m_layoutManager->property("order").value<QList<int>>();
|
||||
|
||||
if (m_appletOrder == neworder) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_appletOrder = neworder;
|
||||
|
||||
//! update applets last recorded index, this is needed for example when an applet is removed
|
||||
//! to know in which index was located before the removal
|
||||
for(const auto &id: m_appletOrder) {
|
||||
if (m_appletData.contains(id)) {
|
||||
m_appletData[id].lastValidIndex = m_appletOrder.indexOf(id);
|
||||
}
|
||||
}
|
||||
|
||||
emit appletsOrderChanged();
|
||||
}
|
||||
|
||||
void ContainmentInterface::updateAppletsInLockedZoom()
|
||||
{
|
||||
if (!m_layoutManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<int> appletslockedzoom = m_layoutManager->property("lockedZoomApplets").value<QList<int>>();
|
||||
|
||||
if (m_appletsInLockedZoom == appletslockedzoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_appletsInLockedZoom = appletslockedzoom;
|
||||
emit appletsInLockedZoomChanged(m_appletsInLockedZoom);
|
||||
}
|
||||
|
||||
void ContainmentInterface::updateAppletsDisabledColoring()
|
||||
{
|
||||
if (!m_layoutManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<int> appletsdisabledcoloring = m_layoutManager->property("userBlocksColorizingApplets").value<QList<int>>();
|
||||
|
||||
if (m_appletsDisabledColoring == appletsdisabledcoloring) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_appletsDisabledColoring = appletsdisabledcoloring;
|
||||
emit appletsDisabledColoringChanged(appletsdisabledcoloring);
|
||||
}
|
||||
|
||||
void ContainmentInterface::onLatteTasksCountChanged()
|
||||
{
|
||||
if ((m_hasLatteTasks && m_latteTasksModel->count()>0)
|
||||
@ -589,7 +799,7 @@ void ContainmentInterface::toggleAppletExpanded(const int id)
|
||||
}
|
||||
|
||||
for (const auto applet : m_view->containment()->applets()) {
|
||||
if (applet->id() == (uint)id && !Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)/*block for sub-containments*/) {
|
||||
if (applet->id() == (uint)id && !Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)/*block for sub-containments*/) {
|
||||
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
if (ai) {
|
||||
@ -599,6 +809,78 @@ void ContainmentInterface::toggleAppletExpanded(const int id)
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentInterface::removeApplet(const int &id)
|
||||
{
|
||||
if (!m_appletData.contains(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto applet = m_appletData[id].applet;
|
||||
emit applet->appletDeleted(applet); //! this signal should be part of Plasma Frameworks AppletPrivate::destroy() function...
|
||||
applet->destroy();
|
||||
}
|
||||
|
||||
|
||||
void ContainmentInterface::setAppletsOrder(const QList<int> &order)
|
||||
{
|
||||
QMetaObject::invokeMethod(m_layoutManager,
|
||||
"requestAppletsOrder",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(QList<int>, order));
|
||||
|
||||
}
|
||||
|
||||
void ContainmentInterface::setAppletsInLockedZoom(const QList<int> &applets)
|
||||
{
|
||||
QMetaObject::invokeMethod(m_layoutManager,
|
||||
"requestAppletsInLockedZoom",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(QList<int>, applets));
|
||||
}
|
||||
|
||||
void ContainmentInterface::setAppletsDisabledColoring(const QList<int> &applets)
|
||||
{
|
||||
QMetaObject::invokeMethod(m_layoutManager,
|
||||
"requestAppletsDisabledColoring",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(QList<int>, applets));
|
||||
}
|
||||
|
||||
void ContainmentInterface::setAppletInScheduledDestruction(const int &id, const bool &enabled)
|
||||
{
|
||||
QMetaObject::invokeMethod(m_layoutManager,
|
||||
"setAppletInScheduledDestruction",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(int, id),
|
||||
Q_ARG(bool, enabled));
|
||||
}
|
||||
|
||||
void ContainmentInterface::updateContainmentConfigProperty(const QString &key, const QVariant &value)
|
||||
{
|
||||
if (!m_configuration || !m_configuration->keys().contains(key)) {
|
||||
|
||||
}
|
||||
|
||||
if (m_configuration->keys().contains(key)
|
||||
&& (*m_configuration)[key] != value) {
|
||||
m_configuration->insert(key, value);
|
||||
emit m_configuration->valueChanged(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentInterface::updateAppletConfigProperty(const int &id, const QString &key, const QVariant &value)
|
||||
{
|
||||
if (!m_appletData.contains(id) || !m_appletData[id].configuration || !m_appletData[id].configuration->keys().contains(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_appletData[id].configuration->keys().contains(key)
|
||||
&& (*m_appletData[id].configuration)[key] != value) {
|
||||
m_appletData[id].configuration->insert(key, value);
|
||||
emit m_appletData[id].configuration->valueChanged(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentInterface::updateAppletsTracking()
|
||||
{
|
||||
if (!m_view->containment()) {
|
||||
@ -608,6 +890,69 @@ void ContainmentInterface::updateAppletsTracking()
|
||||
for (const auto applet : m_view->containment()->applets()) {
|
||||
onAppletAdded(applet);
|
||||
}
|
||||
|
||||
emit initializationCompleted();
|
||||
}
|
||||
|
||||
void ContainmentInterface::updateAppletDelayedConfiguration()
|
||||
{
|
||||
for (const auto id : m_appletData.keys()) {
|
||||
if (!m_appletData[id].configuration) {
|
||||
m_appletData[id].configuration = appletConfiguration(m_appletData[id].applet);
|
||||
|
||||
if (m_appletData[id].configuration) {
|
||||
qDebug() << "org.kde.sync delayed applet configuration was successful for : " << id;
|
||||
initAppletConfigurationSignals(id, m_appletData[id].configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentInterface::initAppletConfigurationSignals(const int &id, KDeclarative::ConfigPropertyMap *configuration)
|
||||
{
|
||||
if (!configuration) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(configuration, &QQmlPropertyMap::valueChanged,
|
||||
this, [&, id](const QString &key, const QVariant &value) {
|
||||
//qDebug() << "org.kde.sync applet property changed : " << currentAppletId << " __ " << m_appletData[currentAppletId].plugin << " __ " << key << " __ " << value;
|
||||
emit appletConfigPropertyChanged(id, key, value);
|
||||
});
|
||||
}
|
||||
|
||||
KDeclarative::ConfigPropertyMap *ContainmentInterface::appletConfiguration(const Plasma::Applet *applet)
|
||||
{
|
||||
if (!m_view->containment() || !applet) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
bool isSubContainment = Layouts::Storage::self()->isSubContainment(m_view->corona(), applet); //we use corona() to make sure that returns true even when it is first created from user
|
||||
int currentAppletId = applet->id();
|
||||
KDeclarative::ConfigPropertyMap *configuration{nullptr};
|
||||
|
||||
//! set configuration object properly for applets and subcontainments
|
||||
if (!isSubContainment) {
|
||||
int metaconfigindex = ai->metaObject()->indexOfProperty("configuration");
|
||||
if (metaconfigindex >=0 ){
|
||||
configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>((ai->property("configuration")).value<QObject *>());
|
||||
}
|
||||
} else {
|
||||
Plasma::Containment *subcontainment = Layouts::Storage::self()->subContainmentOf(m_view->corona(), applet);
|
||||
if (subcontainment) {
|
||||
PlasmaQuick::AppletQuickItem *subcai = subcontainment->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
if (subcai) {
|
||||
int metaconfigindex = subcai->metaObject()->indexOfProperty("configuration");
|
||||
if (metaconfigindex >=0 ){
|
||||
configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>((subcai->property("configuration")).value<QObject *>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
|
||||
@ -616,10 +961,15 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
|
||||
return;
|
||||
}
|
||||
|
||||
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) {
|
||||
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
bool isSubContainment = Layouts::Storage::self()->isSubContainment(m_view->corona(), applet); //we use corona() to make sure that returns true even when it is first created from user
|
||||
int currentAppletId = applet->id();
|
||||
|
||||
//! Track expanded/able applets and Tasks applets
|
||||
if (isSubContainment) {
|
||||
//! internal containment case
|
||||
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->layout(), applet);
|
||||
PlasmaQuick::AppletQuickItem *contAi = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->corona(), applet);
|
||||
PlasmaQuick::AppletQuickItem *contAi = ai;
|
||||
|
||||
if (contAi && !m_appletsExpandedConnections.contains(contAi)) {
|
||||
m_appletsExpandedConnections[contAi] = connect(contAi, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::onAppletExpandedChanged);
|
||||
@ -642,13 +992,7 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
if (!ai) {
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (ai) {
|
||||
KPluginMetaData meta = applet->kPackage().metadata();
|
||||
const auto &provides = KPluginMetaData::readStringList(meta.rawData(), QStringLiteral("X-Plasma-Provides"));
|
||||
|
||||
@ -668,6 +1012,56 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
|
||||
}
|
||||
}
|
||||
|
||||
//! Track All Applets, for example to support syncing between different docks and panels
|
||||
if (ai) {
|
||||
bool initializing{!m_appletData.contains(currentAppletId)};
|
||||
|
||||
KPluginMetaData meta = applet->kPackage().metadata();
|
||||
ViewPart::AppletInterfaceData data;
|
||||
data.id = currentAppletId;
|
||||
data.plugin = meta.pluginId();
|
||||
data.applet = applet;
|
||||
data.plasmoid = ai;
|
||||
data.lastValidIndex = m_appletOrder.indexOf(data.id);
|
||||
//! set configuration object properly for applets and subcontainments
|
||||
data.configuration = appletConfiguration(applet);
|
||||
|
||||
//! track property changes in applets
|
||||
if (data.configuration) {
|
||||
initAppletConfigurationSignals(data.id, data.configuration);
|
||||
} else {
|
||||
qDebug() << "org.kde.sync Unfortunately configuration syncing for :: " << currentAppletId << " was not established, configuration object was missing!";
|
||||
m_appletDelayedConfigurationTimer.start();
|
||||
}
|
||||
|
||||
if (initializing) {
|
||||
//! track applet destroyed flag
|
||||
connect(applet, &Plasma::Applet::destroyedChanged, this, [&, currentAppletId](bool destroyed) {
|
||||
emit appletInScheduledDestructionChanged(currentAppletId, destroyed);
|
||||
});
|
||||
|
||||
//! remove on applet destruction
|
||||
connect(applet, &QObject::destroyed, this, [&, data](){
|
||||
emit appletRemoved(data.id);
|
||||
//qDebug() << "org.kde.sync: removing applet ::: " << data.id << " __ " << data.plugin << " remained : " << m_appletData.keys();
|
||||
m_appletData.remove(data.id);
|
||||
});
|
||||
}
|
||||
|
||||
m_appletData[data.id] = data;
|
||||
emit appletDataCreated(data.id);
|
||||
}
|
||||
}
|
||||
|
||||
QList<int> ContainmentInterface::toIntList(const QVariantList &list)
|
||||
{
|
||||
QList<int> converted;
|
||||
|
||||
for(const QVariant &item: list) {
|
||||
converted << item.toInt();
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include "tasksmodel.h"
|
||||
|
||||
// Qt
|
||||
#include <QMetaMethod>
|
||||
#include <QHash>
|
||||
#include <QMetaMethod>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QQuickItem>
|
||||
@ -26,6 +26,10 @@ namespace PlasmaQuick {
|
||||
class AppletQuickItem;
|
||||
}
|
||||
|
||||
namespace KDeclarative {
|
||||
class ConfigPropertyMap;
|
||||
}
|
||||
|
||||
namespace Latte {
|
||||
class Corona;
|
||||
class View;
|
||||
@ -34,6 +38,16 @@ class View;
|
||||
namespace Latte {
|
||||
namespace ViewPart {
|
||||
|
||||
struct AppletInterfaceData
|
||||
{
|
||||
int id{-1};
|
||||
QString plugin;
|
||||
int lastValidIndex{-1};
|
||||
Plasma::Applet *applet{nullptr};
|
||||
PlasmaQuick::AppletQuickItem *plasmoid{nullptr};
|
||||
KDeclarative::ConfigPropertyMap *configuration{nullptr};
|
||||
};
|
||||
|
||||
class ContainmentInterface: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -41,9 +55,14 @@ class ContainmentInterface: public QObject
|
||||
Q_PROPERTY(bool hasLatteTasks READ hasLatteTasks NOTIFY hasLatteTasksChanged)
|
||||
Q_PROPERTY(bool hasPlasmaTasks READ hasPlasmaTasks NOTIFY hasPlasmaTasksChanged)
|
||||
|
||||
Q_PROPERTY(QObject *plasmoid READ plasmoid() WRITE setPlasmoid NOTIFY plasmoidChanged)
|
||||
|
||||
Q_PROPERTY(QAbstractListModel *latteTasksModel READ latteTasksModel() NOTIFY latteTasksModelChanged)
|
||||
Q_PROPERTY(QAbstractListModel *plasmaTasksModel READ plasmaTasksModel() NOTIFY plasmaTasksModelChanged)
|
||||
|
||||
//! specified from containment qml side
|
||||
Q_PROPERTY(QObject* layoutManager READ layoutManager WRITE setLayoutManager NOTIFY layoutManagerChanged)
|
||||
|
||||
public:
|
||||
ContainmentInterface(Latte::View *parent);
|
||||
virtual ~ContainmentInterface();
|
||||
@ -73,6 +92,17 @@ public:
|
||||
int applicationLauncherId() const;
|
||||
int appletIdForVisualIndex(const int index);
|
||||
|
||||
int indexOfApplet(const int &id);
|
||||
QList<int> appletsOrder() const;
|
||||
ViewPart::AppletInterfaceData appletDataAtIndex(const int &index);
|
||||
ViewPart::AppletInterfaceData appletDataForId(const int &id);
|
||||
|
||||
QObject *plasmoid() const;
|
||||
void setPlasmoid(QObject *plasmoid);
|
||||
|
||||
QObject *layoutManager() const;
|
||||
void setLayoutManager(QObject *manager);
|
||||
|
||||
QAbstractListModel *latteTasksModel() const;
|
||||
QAbstractListModel *plasmaTasksModel() const;
|
||||
|
||||
@ -86,13 +116,39 @@ public slots:
|
||||
|
||||
Q_INVOKABLE bool isApplication(const QUrl &url) const;
|
||||
|
||||
void addApplet(const QString &pluginId);
|
||||
void addApplet(QObject *metadata, int x, int y);
|
||||
void removeApplet(const int &id);
|
||||
void setAppletsOrder(const QList<int> &order);
|
||||
void setAppletsInLockedZoom(const QList<int> &applets);
|
||||
void setAppletsDisabledColoring(const QList<int> &applets);
|
||||
void setAppletInScheduledDestruction(const int &id, const bool &enabled);
|
||||
void updateContainmentConfigProperty(const QString &key, const QVariant &value);
|
||||
void updateAppletConfigProperty(const int &id, const QString &key, const QVariant &value);
|
||||
|
||||
signals:
|
||||
void expandedAppletStateChanged();
|
||||
void hasExpandedAppletChanged();
|
||||
void hasLatteTasksChanged();
|
||||
void hasPlasmaTasksChanged();
|
||||
void initializationCompleted();
|
||||
void latteTasksModelChanged();
|
||||
void layoutManagerChanged();
|
||||
void plasmaTasksModelChanged();
|
||||
void plasmoidChanged();
|
||||
|
||||
//! syncing signals
|
||||
void appletRemoved(const int &id);
|
||||
|
||||
void appletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value);
|
||||
void appletCreated(const QString &pluginId);
|
||||
void appletDataCreated(const int &id);
|
||||
void appletDropped(QObject *data, int x, int y);
|
||||
void containmentConfigPropertyChanged(const QString &key, const QVariant &value);
|
||||
void appletsOrderChanged();
|
||||
void appletsInLockedZoomChanged(const QList<int> &applets);
|
||||
void appletsDisabledColoringChanged(const QList<int> &applets);
|
||||
void appletInScheduledDestructionChanged(const int &id, const bool &enabled);
|
||||
|
||||
void appletRequestedVisualIndicator(const int &plasmoidId);
|
||||
|
||||
@ -100,7 +156,12 @@ private slots:
|
||||
void identifyShortcutsHost();
|
||||
void identifyMethods();
|
||||
|
||||
void updateAppletsOrder();
|
||||
void updateAppletsInLockedZoom();
|
||||
void updateAppletsDisabledColoring();
|
||||
void updateAppletsTracking();
|
||||
void updateAppletDelayedConfiguration();
|
||||
|
||||
void onAppletAdded(Plasma::Applet *applet);
|
||||
void onAppletExpandedChanged();
|
||||
void onLatteTasksCountChanged();
|
||||
@ -109,9 +170,14 @@ private slots:
|
||||
private:
|
||||
void addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem);
|
||||
void removeExpandedApplet(PlasmaQuick::AppletQuickItem *appletQuickItem);
|
||||
void initAppletConfigurationSignals(const int &id, KDeclarative::ConfigPropertyMap *configuration);
|
||||
|
||||
bool appletIsExpandable(PlasmaQuick::AppletQuickItem *appletQuickItem) const;
|
||||
|
||||
KDeclarative::ConfigPropertyMap *appletConfiguration(const Plasma::Applet *applet);
|
||||
|
||||
QList<int> toIntList(const QVariantList &list);
|
||||
|
||||
private:
|
||||
bool m_hasLatteTasks{false};
|
||||
bool m_hasPlasmaTasks{false};
|
||||
@ -132,9 +198,21 @@ private:
|
||||
TasksModel *m_latteTasksModel;
|
||||
TasksModel *m_plasmaTasksModel;
|
||||
|
||||
//!follow containment plasmoid
|
||||
QPointer<QObject> m_plasmoid;
|
||||
QPointer<QObject> m_layoutManager;
|
||||
QPointer<KDeclarative::ConfigPropertyMap> m_configuration;
|
||||
|
||||
//!keep record of applet ids and avoid crashes when trying to access ids for already destroyed applets
|
||||
QHash<PlasmaQuick::AppletQuickItem *, int> m_expandedAppletIds;
|
||||
QHash<PlasmaQuick::AppletQuickItem *, QMetaObject::Connection> m_appletsExpandedConnections;
|
||||
|
||||
//!all applet data
|
||||
QList<int> m_appletOrder; //includes justify splitters
|
||||
QList<int> m_appletsInLockedZoom;
|
||||
QList<int> m_appletsDisabledColoring;
|
||||
QHash<int, ViewPart::AppletInterfaceData> m_appletData;
|
||||
QTimer m_appletDelayedConfigurationTimer;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,584 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2018 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "contextmenu.h"
|
||||
|
||||
// local
|
||||
#include "view.h"
|
||||
#include "visibilitymanager.h"
|
||||
#include "../lattecorona.h"
|
||||
#include "../layouts/storage.h"
|
||||
|
||||
// Qt
|
||||
#include <QMouseEvent>
|
||||
#include <QVersionNumber>
|
||||
#include <QLatin1String>
|
||||
|
||||
// KDE
|
||||
#include <KActionCollection>
|
||||
#include <KAuthorized>
|
||||
#include <KLocalizedString>
|
||||
|
||||
// Plasma
|
||||
#include <Plasma/Applet>
|
||||
#include <Plasma/Containment>
|
||||
#include <Plasma/ContainmentActions>
|
||||
#include <Plasma/Corona>
|
||||
#include <PlasmaQuick/AppletQuickItem>
|
||||
|
||||
#define BLOCKHIDINGTYPE "View::contextMenu()"
|
||||
|
||||
namespace Latte {
|
||||
namespace ViewPart {
|
||||
|
||||
ContextMenu::ContextMenu(Latte::View *view) :
|
||||
QObject(view),
|
||||
m_latteView(view)
|
||||
{
|
||||
}
|
||||
|
||||
ContextMenu::~ContextMenu()
|
||||
{
|
||||
}
|
||||
|
||||
QMenu *ContextMenu::menu()
|
||||
{
|
||||
return m_contextMenu;
|
||||
}
|
||||
|
||||
void ContextMenu::menuAboutToHide()
|
||||
{
|
||||
if (!m_latteView) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_contextMenu = 0;
|
||||
|
||||
emit menuChanged();
|
||||
}
|
||||
|
||||
QPoint ContextMenu::popUpRelevantToParent(const QRect &parentItem, const QRect popUpRect)
|
||||
{
|
||||
QPoint resultPoint;
|
||||
|
||||
if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
resultPoint.setX(parentItem.left());
|
||||
resultPoint.setY(parentItem.bottom());
|
||||
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
resultPoint.setX(parentItem.left());
|
||||
resultPoint.setY(parentItem.top() - popUpRect.height() - 1);
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
resultPoint.setX(parentItem.right());
|
||||
resultPoint.setY(parentItem.top());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
resultPoint.setX(parentItem.left() - popUpRect.width());
|
||||
resultPoint.setY(parentItem.top());
|
||||
}
|
||||
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
QPoint ContextMenu::popUpRelevantToGlobalPoint(const QRect &parentItem, const QRect popUpRect)
|
||||
{
|
||||
QPoint resultPoint;
|
||||
|
||||
if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
resultPoint.setX(popUpRect.x());
|
||||
resultPoint.setY(popUpRect.y() + 1);
|
||||
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
resultPoint.setX(popUpRect.x());
|
||||
resultPoint.setY(popUpRect.y() - popUpRect.height() - 1);
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
resultPoint.setX(popUpRect.x() + 1);
|
||||
resultPoint.setY(popUpRect.y());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
resultPoint.setX(popUpRect.x() - popUpRect.width() - 1);
|
||||
resultPoint.setY(popUpRect.y());
|
||||
}
|
||||
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
QPoint ContextMenu::popUpTopLeft(Plasma::Applet *applet, const QRect popUpRect)
|
||||
{
|
||||
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
QRect globalItemRect = m_latteView->absoluteGeometry();
|
||||
|
||||
if (ai && applet != m_latteView->containment()) {
|
||||
QPointF appletGlobalTopLeft = ai->mapToGlobal(QPointF(ai->x(), ai->y()));
|
||||
globalItemRect = QRect(appletGlobalTopLeft.x(), appletGlobalTopLeft.y(), ai->width(), ai->height());
|
||||
}
|
||||
|
||||
int itemLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? globalItemRect.width() : globalItemRect.height());
|
||||
int menuLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? popUpRect.width() : popUpRect.height());
|
||||
|
||||
if ((itemLength > menuLength)
|
||||
|| (applet == m_latteView->containment())
|
||||
|| (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->layout(), applet)) ) {
|
||||
return popUpRelevantToGlobalPoint(globalItemRect, popUpRect);
|
||||
} else {
|
||||
return popUpRelevantToParent(globalItemRect, popUpRect);
|
||||
}
|
||||
}
|
||||
|
||||
bool ContextMenu::mousePressEventForContainmentMenu(QQuickView *view, QMouseEvent *event)
|
||||
{
|
||||
if (!event || !view || !m_latteView->containment()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_contextMenu) {
|
||||
m_contextMenu->close();
|
||||
m_contextMenu = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString trigger = Plasma::ContainmentActions::eventToString(event);
|
||||
|
||||
if (trigger == QLatin1String("RightButton;NoModifier")) {
|
||||
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
|
||||
|
||||
if (!plugin || plugin->contextualActions().isEmpty()) {
|
||||
event->setAccepted(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_latteView->containment()) {
|
||||
QMenu *desktopMenu = new QMenu;
|
||||
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
if (desktopMenu->winId()) {
|
||||
desktopMenu->windowHandle()->setTransientParent(m_latteView);
|
||||
}
|
||||
|
||||
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_contextMenu = desktopMenu;
|
||||
emit menuChanged();
|
||||
|
||||
auto ungrabMouseHack = [this]() {
|
||||
if (m_latteView->mouseGrabberItem()) {
|
||||
m_latteView->mouseGrabberItem()->ungrabMouse();
|
||||
}
|
||||
};
|
||||
|
||||
if (QVersionNumber::fromString(qVersion()) > QVersionNumber(5, 8, 0)) {
|
||||
QTimer::singleShot(0, this, ungrabMouseHack);
|
||||
} else {
|
||||
ungrabMouseHack();
|
||||
}
|
||||
|
||||
emit m_latteView->containment()->contextualActionsAboutToShow();
|
||||
addContainmentActions(desktopMenu, event);
|
||||
|
||||
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
QPoint globalPos = event->globalPos();
|
||||
desktopMenu->adjustSize();
|
||||
|
||||
QRect popUpRect(globalPos.x(), globalPos.y(), desktopMenu->width(), desktopMenu->height());
|
||||
|
||||
globalPos = popUpRelevantToGlobalPoint(QRect(0,0,0,0), popUpRect);
|
||||
|
||||
if (desktopMenu->isEmpty()) {
|
||||
delete desktopMenu;
|
||||
event->accept();
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
|
||||
|
||||
desktopMenu->popup(globalPos);
|
||||
event->setAccepted(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ContextMenu::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
//qDebug() << "Step -1 ...";
|
||||
|
||||
if (!event || !m_latteView->containment()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//qDebug() << "Step 0...";
|
||||
|
||||
//even if the menu is executed synchronously, other events may be processed
|
||||
//by the qml incubator when plasma is loading, so we need to guard there
|
||||
if (m_contextMenu) {
|
||||
//qDebug() << "Step 0.5 ...";
|
||||
m_contextMenu->close();
|
||||
m_contextMenu = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
//qDebug() << "1 ...";
|
||||
QString trigger = Plasma::ContainmentActions::eventToString(event);
|
||||
|
||||
if (trigger == QLatin1String("RightButton;NoModifier")) {
|
||||
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
|
||||
|
||||
if (!plugin || plugin->contextualActions().isEmpty()) {
|
||||
event->setAccepted(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
//qDebug() << "2 ...";
|
||||
//the plugin can be a single action or a context menu
|
||||
//Don't have an action list? execute as single action
|
||||
//and set the event position as action data
|
||||
/*if (plugin->contextualActions().length() == 1) {
|
||||
QAction *action = plugin->contextualActions().at(0);
|
||||
action->setData(event->pos());
|
||||
action->trigger();
|
||||
event->accept();
|
||||
return;
|
||||
}*/
|
||||
//FIXME: very inefficient appletAt() implementation
|
||||
Plasma::Applet *applet = 0;
|
||||
bool inSystray = false;
|
||||
|
||||
//! initialize the appletContainsMethod on the first right click
|
||||
if (!m_appletContainsMethod.isValid()) {
|
||||
updateAppletContainsMethod();
|
||||
}
|
||||
|
||||
for (const Plasma::Applet *appletTemp : m_latteView->containment()->applets()) {
|
||||
PlasmaQuick::AppletQuickItem *ai = appletTemp->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
bool appletContainsMouse = false;
|
||||
|
||||
if (m_appletContainsMethod.isValid()) {
|
||||
QVariant retVal;
|
||||
m_appletContainsMethod.invoke(m_appletContainsMethodItem, Qt::DirectConnection, Q_RETURN_ARG(QVariant, retVal)
|
||||
, Q_ARG(QVariant, appletTemp->id()), Q_ARG(QVariant, event->pos()));
|
||||
appletContainsMouse = retVal.toBool();
|
||||
} else {
|
||||
appletContainsMouse = ai->contains(ai->mapFromItem(m_latteView->contentItem(), event->pos()));
|
||||
}
|
||||
|
||||
if (ai && ai->isVisible() && appletContainsMouse) {
|
||||
applet = ai->applet();
|
||||
|
||||
if (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->layout(), applet)) {
|
||||
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_latteView->layout(), applet);
|
||||
|
||||
if (subContainment) {
|
||||
Plasma::Applet *internalApplet{nullptr};
|
||||
|
||||
for (const Plasma::Applet *appletCont : subContainment->applets()) {
|
||||
PlasmaQuick::AppletQuickItem *ai2 = appletCont->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
|
||||
|
||||
if (ai2 && ai2->isVisible() && ai2->contains(ai2->mapFromItem(m_latteView->contentItem(), event->pos()))) {
|
||||
internalApplet = ai2->applet();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!internalApplet) {
|
||||
return true;
|
||||
} else {
|
||||
applet = internalApplet;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
ai = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!applet && !inSystray) {
|
||||
applet = m_latteView->containment();
|
||||
}
|
||||
|
||||
//qDebug() << "3 ...";
|
||||
|
||||
if (applet) {
|
||||
const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides"));
|
||||
|
||||
//qDebug() << "3.5 ...";
|
||||
|
||||
if (!provides.contains(QLatin1String("org.kde.plasma.multitasking"))) {
|
||||
//qDebug() << "4...";
|
||||
QMenu *desktopMenu = new QMenu;
|
||||
|
||||
//this is a workaround where Qt now creates the menu widget
|
||||
//in .exec before oxygen can polish it and set the following attribute
|
||||
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
|
||||
//end workaround
|
||||
|
||||
if (desktopMenu->winId()) {
|
||||
desktopMenu->windowHandle()->setTransientParent(m_latteView);
|
||||
}
|
||||
|
||||
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_contextMenu = desktopMenu;
|
||||
emit menuChanged();
|
||||
|
||||
//! deprecated old code that can be removed if the following plasma approach doesn't
|
||||
//! create any issues with context menu creation in Latte
|
||||
/*if (m_latteView->mouseGrabberItem()) {
|
||||
//workaround, this fixes for me most of the right click menu behavior
|
||||
m_latteView->mouseGrabberItem()->ungrabMouse();
|
||||
return;
|
||||
}*/
|
||||
|
||||
//!plasma official code
|
||||
//this is a workaround where Qt will fail to realize a mouse has been released
|
||||
|
||||
// this happens if a window which does not accept focus spawns a new window that takes focus and X grab
|
||||
// whilst the mouse is depressed
|
||||
// https://bugreports.qt.io/browse/QTBUG-59044
|
||||
// this causes the next click to go missing
|
||||
|
||||
//by releasing manually we avoid that situation
|
||||
auto ungrabMouseHack = [this]() {
|
||||
if (m_latteView->mouseGrabberItem()) {
|
||||
m_latteView->mouseGrabberItem()->ungrabMouse();
|
||||
}
|
||||
};
|
||||
|
||||
//pre 5.8.0 QQuickWindow code is "item->grabMouse(); sendEvent(item, mouseEvent)"
|
||||
//post 5.8.0 QQuickWindow code is sendEvent(item, mouseEvent); item->grabMouse()
|
||||
if (QVersionNumber::fromString(qVersion()) > QVersionNumber(5, 8, 0)) {
|
||||
QTimer::singleShot(0, this, ungrabMouseHack);
|
||||
} else {
|
||||
ungrabMouseHack();
|
||||
}
|
||||
|
||||
//end workaround
|
||||
//!end of plasma official code(workaround)
|
||||
|
||||
//qDebug() << "5 ...";
|
||||
|
||||
if (applet && applet != m_latteView->containment()) {
|
||||
//qDebug() << "5.3 ...";
|
||||
emit applet->contextualActionsAboutToShow();
|
||||
addAppletActions(desktopMenu, applet, event);
|
||||
} else {
|
||||
//qDebug() << "5.6 ...";
|
||||
emit m_latteView->containment()->contextualActionsAboutToShow();
|
||||
addContainmentActions(desktopMenu, event);
|
||||
}
|
||||
|
||||
//this is a workaround where Qt now creates the menu widget
|
||||
//in .exec before oxygen can polish it and set the following attribute
|
||||
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
|
||||
//end workaround
|
||||
QPoint globalPos = event->globalPos();
|
||||
desktopMenu->adjustSize();
|
||||
|
||||
QRect popUpRect(globalPos.x(), globalPos.y(), desktopMenu->width(), desktopMenu->height());
|
||||
|
||||
if (applet) {
|
||||
globalPos = popUpTopLeft(applet, popUpRect);
|
||||
} else {
|
||||
globalPos = popUpRelevantToGlobalPoint(QRect(0,0,0,0), popUpRect);
|
||||
}
|
||||
|
||||
//qDebug() << "7...";
|
||||
|
||||
if (desktopMenu->isEmpty()) {
|
||||
//qDebug() << "7.5 ...";
|
||||
delete desktopMenu;
|
||||
event->accept();
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
|
||||
|
||||
desktopMenu->popup(globalPos);
|
||||
event->setAccepted(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
//qDebug() << "8 ...";
|
||||
}
|
||||
|
||||
//qDebug() << "9 ...";
|
||||
}
|
||||
|
||||
//qDebug() << "10 ...";
|
||||
return true;
|
||||
// PlasmaQuick::ContainmentView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
//! update the appletContainsPos method from Panel view
|
||||
void ContextMenu::updateAppletContainsMethod()
|
||||
{
|
||||
for (QQuickItem *item : m_latteView->contentItem()->childItems()) {
|
||||
if (auto *metaObject = item->metaObject()) {
|
||||
// not using QMetaObject::invokeMethod to avoid warnings when calling
|
||||
// this on applets that don't have it or other child items since this
|
||||
// is pretty much trial and error.
|
||||
// Also, "var" arguments are treated as QVariant in QMetaObject
|
||||
|
||||
int methodIndex = metaObject->indexOfMethod("appletContainsPos(QVariant,QVariant)");
|
||||
|
||||
if (methodIndex == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_appletContainsMethod = metaObject->method(methodIndex);
|
||||
m_appletContainsMethodItem = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContextMenu::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event)
|
||||
{
|
||||
if (!m_latteView->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
desktopMenu->addSection(applet->pluginMetaData().name());
|
||||
|
||||
for (QAction *action : applet->contextualActions()) {
|
||||
if (action) {
|
||||
desktopMenu->addAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
if (!applet->failedToLaunch()) {
|
||||
QAction *runAssociatedApplication = applet->actions()->action(QStringLiteral("run associated application"));
|
||||
|
||||
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
|
||||
desktopMenu->addAction(runAssociatedApplication);
|
||||
}
|
||||
|
||||
QAction *configureApplet = applet->actions()->action(QStringLiteral("configure"));
|
||||
|
||||
if (configureApplet && configureApplet->isEnabled()) {
|
||||
desktopMenu->addAction(configureApplet);
|
||||
}
|
||||
|
||||
QAction *appletAlternatives = applet->actions()->action(QStringLiteral("alternatives"));
|
||||
|
||||
if (appletAlternatives && appletAlternatives->isEnabled() && m_latteView->containment()->isUserConfiguring()) {
|
||||
desktopMenu->addAction(appletAlternatives);
|
||||
}
|
||||
}
|
||||
|
||||
QAction *containmentAction = desktopMenu->menuAction();
|
||||
containmentAction->setText(i18nc("%1 is the name of the containment", "%1 Options", m_latteView->containment()->title()));
|
||||
|
||||
addContainmentActions(containmentAction->menu(), event);
|
||||
|
||||
if (!containmentAction->menu()->isEmpty()) {
|
||||
int enabled = 0;
|
||||
//count number of real actions
|
||||
QListIterator<QAction *> actionsIt(containmentAction->menu()->actions());
|
||||
|
||||
while (enabled < 3 && actionsIt.hasNext()) {
|
||||
QAction *action = actionsIt.next();
|
||||
|
||||
if (action->isVisible() && !action->isSeparator()) {
|
||||
++enabled;
|
||||
}
|
||||
}
|
||||
|
||||
desktopMenu->addSeparator();
|
||||
|
||||
if (enabled) {
|
||||
//if there is only one, don't create a submenu
|
||||
// if (enabled < 2) {
|
||||
for (QAction *action : containmentAction->menu()->actions()) {
|
||||
if (action && action->isVisible()) {
|
||||
desktopMenu->addAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
// } else {
|
||||
// desktopMenu->addMenu(containmentMenu);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
if (m_latteView->containment()->immutability() == Plasma::Types::Mutable &&
|
||||
(m_latteView->containment()->containmentType() != Plasma::Types::PanelContainment || m_latteView->containment()->isUserConfiguring())) {
|
||||
QAction *closeApplet = applet->actions()->action(QStringLiteral("remove"));
|
||||
|
||||
//qDebug() << "checking for removal" << closeApplet;
|
||||
if (closeApplet) {
|
||||
if (!desktopMenu->isEmpty()) {
|
||||
desktopMenu->addSeparator();
|
||||
}
|
||||
|
||||
//qDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
|
||||
desktopMenu->addAction(closeApplet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContextMenu::addContainmentActions(QMenu *desktopMenu, QEvent *event)
|
||||
{
|
||||
if (!m_latteView->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_latteView->containment()->corona()->immutability() != Plasma::Types::Mutable &&
|
||||
!KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) {
|
||||
//qDebug() << "immutability";
|
||||
return;
|
||||
}
|
||||
|
||||
//this is what ContainmentPrivate::prepareContainmentActions was
|
||||
const QString trigger = Plasma::ContainmentActions::eventToString(event);
|
||||
//"RightButton;NoModifier"
|
||||
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
|
||||
|
||||
if (!plugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin->containment() != m_latteView->containment()) {
|
||||
plugin->setContainment(m_latteView->containment());
|
||||
// now configure it
|
||||
KConfigGroup cfg(m_latteView->containment()->corona()->config(), "ActionPlugins");
|
||||
cfg = KConfigGroup(&cfg, QString::number(m_latteView->containment()->containmentType()));
|
||||
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
|
||||
plugin->restore(pluginConfig);
|
||||
}
|
||||
|
||||
QList<QAction *> actions = plugin->contextualActions();
|
||||
|
||||
for (const QAction *act : actions) {
|
||||
if (act->menu()) {
|
||||
//this is a workaround where Qt now creates the menu widget
|
||||
//in .exec before oxygen can polish it and set the following attribute
|
||||
act->menu()->setAttribute(Qt::WA_TranslucentBackground);
|
||||
//end workaround
|
||||
|
||||
if (act->menu()->winId()) {
|
||||
act->menu()->windowHandle()->setTransientParent(m_latteView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
desktopMenu->addActions(actions);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Plasma::Containment *ContextMenu::containmentById(uint id)
|
||||
{
|
||||
for (const auto containment : m_latteView->corona()->containments()) {
|
||||
if (id == containment->id()) {
|
||||
return containment;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -40,6 +40,7 @@ Effects::~Effects()
|
||||
void Effects::init()
|
||||
{
|
||||
connect(this, &Effects::backgroundOpacityChanged, this, &Effects::updateEffects);
|
||||
connect(this, &Effects::backgroundOpacityChanged, this, &Effects::updateBackgroundContrastValues);
|
||||
connect(this, &Effects::backgroundCornersMaskChanged, this, &Effects::updateEffects);
|
||||
connect(this, &Effects::backgroundRadiusEnabledChanged, this, &Effects::updateEffects);
|
||||
connect(this, &Effects::drawEffectsChanged, this, &Effects::updateEffects);
|
||||
@ -91,17 +92,6 @@ void Effects::init()
|
||||
connect(m_view, &Latte::View::layoutChanged, this, &Effects::onPopUpMarginChanged);
|
||||
|
||||
connect(&m_theme, &Plasma::Theme::themeChanged, this, [&]() {
|
||||
auto background = m_background;
|
||||
m_background = new Plasma::FrameSvg(this);
|
||||
|
||||
if (background) {
|
||||
background->deleteLater();
|
||||
}
|
||||
|
||||
if (m_background->imagePath() != "widgets/panel-background") {
|
||||
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
|
||||
}
|
||||
|
||||
updateBackgroundContrastValues();
|
||||
updateEffects();
|
||||
});
|
||||
@ -353,6 +343,21 @@ void Effects::setAppletsLayoutGeometry(const QRect &geom)
|
||||
emit appletsLayoutGeometryChanged();
|
||||
}
|
||||
|
||||
QQuickItem *Effects::panelBackgroundSvg() const
|
||||
{
|
||||
return m_panelBackgroundSvg;
|
||||
}
|
||||
|
||||
void Effects::setPanelBackgroundSvg(QQuickItem *quickitem)
|
||||
{
|
||||
if (m_panelBackgroundSvg == quickitem) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_panelBackgroundSvg = quickitem;
|
||||
emit panelBackgroundSvgChanged();
|
||||
}
|
||||
|
||||
void Effects::onPopUpMarginChanged()
|
||||
{
|
||||
m_view->setProperty("_applets_popup_margin", QVariant(popUpMargin()));
|
||||
@ -360,14 +365,6 @@ void Effects::onPopUpMarginChanged()
|
||||
|
||||
void Effects::forceMaskRedraw()
|
||||
{
|
||||
if (m_background) {
|
||||
delete m_background;
|
||||
}
|
||||
|
||||
m_background = new Plasma::FrameSvg(this);
|
||||
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
|
||||
m_background->setEnabledBorders(m_enabledBorders);
|
||||
|
||||
updateMask();
|
||||
}
|
||||
|
||||
@ -461,7 +458,7 @@ QRegion Effects::maskCombinedRegion()
|
||||
|
||||
void Effects::updateBackgroundCorners()
|
||||
{
|
||||
if (m_backgroundRadius<=0) {
|
||||
if (m_backgroundRadius<0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -499,21 +496,14 @@ void Effects::updateMask()
|
||||
//! rounded corners to be shown correctly
|
||||
//! the enabledBorders check was added because there was cases
|
||||
//! that the mask region wasn't calculated correctly after location changes
|
||||
if (!m_background) {
|
||||
if (m_background && m_background->enabledBorders() != m_enabledBorders) {
|
||||
delete m_background;
|
||||
}
|
||||
|
||||
m_background = new Plasma::FrameSvg(this);
|
||||
if (!m_panelBackgroundSvg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_background->imagePath() != "widgets/panel-background") {
|
||||
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
|
||||
const QVariant maskProperty = m_panelBackgroundSvg->property("mask");
|
||||
if (static_cast<QMetaType::Type>(maskProperty.type()) == QMetaType::QRegion) {
|
||||
fixedMask = maskProperty.value<QRegion>();
|
||||
}
|
||||
|
||||
m_background->setEnabledBorders(m_enabledBorders);
|
||||
m_background->resizeFrame(maskRect.size());
|
||||
fixedMask = m_background->mask();
|
||||
}
|
||||
|
||||
fixedMask.translate(maskRect.x(), maskRect.y());
|
||||
@ -553,7 +543,7 @@ void Effects::updateEffects()
|
||||
|
||||
if (m_drawEffects) {
|
||||
if (!m_view->behaveAsPlasmaPanel()) {
|
||||
if (!m_rect.isNull() && !m_rect.isEmpty()) {
|
||||
if (!m_rect.isNull() && !m_rect.isEmpty() && m_rect != VisibilityManager::ISHIDDENMASK) {
|
||||
QRegion backMask;
|
||||
|
||||
if (m_backgroundRadiusEnabled) {
|
||||
@ -564,25 +554,23 @@ void Effects::updateEffects()
|
||||
//! this is used when compositing is disabled and provides
|
||||
//! the correct way for the mask to be painted in order for
|
||||
//! rounded corners to be shown correctly
|
||||
if (!m_background) {
|
||||
m_background = new Plasma::FrameSvg(this);
|
||||
if (!m_panelBackgroundSvg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_background->imagePath() != "widgets/panel-background") {
|
||||
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
|
||||
if (m_rect == VisibilityManager::ISHIDDENMASK) {
|
||||
clearEffects = true;
|
||||
} else {
|
||||
const QVariant maskProperty = m_panelBackgroundSvg->property("mask");
|
||||
if (static_cast<QMetaType::Type>(maskProperty.type()) == QMetaType::QRegion) {
|
||||
backMask = maskProperty.value<QRegion>();
|
||||
}
|
||||
}
|
||||
|
||||
m_background->setEnabledBorders(m_enabledBorders);
|
||||
m_background->resizeFrame(m_rect.size());
|
||||
|
||||
backMask = m_background->mask();
|
||||
}
|
||||
|
||||
//! adjust mask coordinates based on local coordinates
|
||||
int fX = m_rect.x(); int fY = m_rect.y();
|
||||
|
||||
|
||||
#if KF5_VERSION_MINOR >= 65
|
||||
//! Latte is now using GtkFrameExtents so Effects geometries must be adjusted
|
||||
//! windows that use GtkFrameExtents and apply Effects on them they take GtkFrameExtents
|
||||
//! as granted
|
||||
@ -593,7 +581,6 @@ void Effects::updateEffects()
|
||||
fX = qMax(0, fX - m_view->headThicknessGap());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//! There are cases that mask is NULL even though it should not
|
||||
//! Example: SidebarOnDemand from v0.10 that BEHAVEASPLASMAPANEL in EditMode
|
||||
@ -666,15 +653,21 @@ qreal Effects::currentMidValue(const qreal &max, const qreal &factor, const qrea
|
||||
void Effects::updateBackgroundContrastValues()
|
||||
{
|
||||
if (!m_theme.backgroundContrastEnabled()) {
|
||||
m_backEffectContrast = 1;
|
||||
m_backEffectIntesity = 1;
|
||||
m_backEffectSaturation = 1;
|
||||
m_backEffectContrast = 1.0;
|
||||
m_backEffectIntesity = 1.0;
|
||||
m_backEffectSaturation = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_backEffectContrast = currentMidValue(m_theme.backgroundContrast(), m_backgroundOpacity, 1);
|
||||
m_backEffectIntesity = currentMidValue(m_theme.backgroundIntensity(), m_backgroundOpacity, 1);
|
||||
m_backEffectSaturation = currentMidValue(m_theme.backgroundSaturation(), m_backgroundOpacity, 1);
|
||||
if (m_backgroundOpacity == -1 /*Default plasma opacity option*/) {
|
||||
m_backEffectContrast = m_theme.backgroundContrast();
|
||||
m_backEffectIntesity = m_theme.backgroundIntensity();
|
||||
m_backEffectSaturation = m_theme.backgroundSaturation();
|
||||
} else {
|
||||
m_backEffectContrast = currentMidValue(m_theme.backgroundContrast(), m_backgroundOpacity, 1);
|
||||
m_backEffectIntesity = currentMidValue(m_theme.backgroundIntensity(), m_backgroundOpacity, 1);
|
||||
m_backEffectSaturation = currentMidValue(m_theme.backgroundSaturation(), m_backgroundOpacity, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Effects::updateEnabledBorders()
|
||||
|
@ -52,6 +52,8 @@ class Effects: public QObject
|
||||
|
||||
Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged)
|
||||
|
||||
Q_PROPERTY(QQuickItem *panelBackgroundSvg READ panelBackgroundSvg WRITE setPanelBackgroundSvg NOTIFY panelBackgroundSvgChanged)
|
||||
|
||||
public:
|
||||
Effects(Latte::View *parent);
|
||||
virtual ~Effects();
|
||||
@ -102,6 +104,9 @@ public:
|
||||
|
||||
Plasma::FrameSvg::EnabledBorders enabledBorders() const;
|
||||
|
||||
QQuickItem *panelBackgroundSvg() const;
|
||||
void setPanelBackgroundSvg(QQuickItem *quickitem);
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE void forceMaskRedraw();
|
||||
Q_INVOKABLE void setSubtractedMaskRegion(const QString ®ionid, const QRegion ®ion);
|
||||
@ -130,6 +135,7 @@ signals:
|
||||
void maskChanged();
|
||||
void innerShadowChanged();
|
||||
void inputMaskChanged();
|
||||
void panelBackgroundSvgChanged();
|
||||
void popUpMarginChanged();
|
||||
void rectChanged();
|
||||
|
||||
@ -185,12 +191,13 @@ private:
|
||||
PlasmaExtended::CornerRegions m_cornersMaskRegion;
|
||||
|
||||
Plasma::Theme m_theme;
|
||||
//only for the mask on disabled compositing, not to actually paint
|
||||
Plasma::FrameSvg *m_background{nullptr};
|
||||
|
||||
//only for the mask, not to actually paint
|
||||
Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders};
|
||||
|
||||
//assigned from qml side in order to access the official panel background svg
|
||||
QQuickItem *m_panelBackgroundSvg{nullptr};
|
||||
|
||||
//! Subtracted and United Mask regions
|
||||
QHash<QString, QRegion> m_subtractedMaskRegions;
|
||||
QHash<QString, QRegion> m_unitedMaskRegions;
|
||||
|
@ -184,12 +184,7 @@ QEvent *EventsSink::onEvent(QEvent *e)
|
||||
|
||||
case QEvent::Wheel:
|
||||
if (auto we = dynamic_cast<QWheelEvent *>(e)) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QPoint pos = QPoint(we->x(), we->y());
|
||||
#else
|
||||
QPoint pos = we->position().toPoint();
|
||||
#endif
|
||||
|
||||
if (originSinksContain(pos)) {
|
||||
auto positionadjusted = positionAdjustedForDestination(pos);
|
||||
auto we2 = new QWheelEvent(positionadjusted,
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
#ifndef FLOATINGGAPWINDOW_H
|
||||
#define FLOATINGWINDOW_H
|
||||
#define FLOATINGGAPWINDOW_H
|
||||
|
||||
// local
|
||||
#include "subwindow.h"
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
// local
|
||||
#include "../view.h"
|
||||
#include "../positioner.h"
|
||||
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
@ -41,6 +42,8 @@ ScreenEdgeGhostWindow::ScreenEdgeGhostWindow(Latte::View *view) :
|
||||
|
||||
setColor(m_showColor);
|
||||
|
||||
connect(m_latteView->positioner(), &Latte::ViewPart::Positioner::slideOffsetChanged, this, &ScreenEdgeGhostWindow::updateGeometry);
|
||||
|
||||
//! this timer is used in order to avoid fast enter/exit signals during first
|
||||
//! appearing after edge activation
|
||||
m_delayedMouseTimer.setSingleShot(true);
|
||||
@ -72,7 +75,7 @@ void ScreenEdgeGhostWindow::updateGeometry()
|
||||
return;
|
||||
}
|
||||
|
||||
QRect newGeometry;
|
||||
QRect newGeometry = m_latteView->absoluteGeometry();
|
||||
|
||||
if (KWindowSystem::compositingActive()) {
|
||||
m_thickness = 6;
|
||||
@ -86,41 +89,42 @@ void ScreenEdgeGhostWindow::updateGeometry()
|
||||
if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
|
||||
//! set minimum length to be 25% of screen width
|
||||
length = qMax(m_latteView->screenGeometry().width()/4,qMin(m_latteView->absoluteGeometry().width(), m_latteView->screenGeometry().width() - 1));
|
||||
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().width());
|
||||
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().width()) / 2;
|
||||
} else {
|
||||
//! set minimum length to be 25% of screen height
|
||||
length = qMax(m_latteView->screenGeometry().height()/4,qMin(m_latteView->absoluteGeometry().height(), m_latteView->screenGeometry().height() - 1));
|
||||
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().height());
|
||||
}
|
||||
|
||||
if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left() - lengthDifference);
|
||||
newGeometry.moveLeft(xF);
|
||||
newGeometry.moveTop(m_latteView->screenGeometry().bottom() - m_thickness);
|
||||
} else if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left() - lengthDifference);
|
||||
newGeometry.moveLeft(xF);
|
||||
newGeometry.moveTop(m_latteView->screenGeometry().top());
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top() - lengthDifference);
|
||||
newGeometry.moveLeft(m_latteView->screenGeometry().left());
|
||||
newGeometry.moveTop(yF);
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top() - lengthDifference);
|
||||
newGeometry.moveLeft(m_latteView->screenGeometry().right() - m_thickness);
|
||||
newGeometry.moveTop(yF);
|
||||
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().height()) / 2;
|
||||
}
|
||||
|
||||
if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
|
||||
int leftF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left() - lengthDifference);
|
||||
int rightF = qMax(m_latteView->screenGeometry().left(), qMin(m_latteView->screenGeometry().right(), m_latteView->absoluteGeometry().right() + lengthDifference));
|
||||
newGeometry.setLeft(leftF);
|
||||
newGeometry.setRight(rightF);
|
||||
} else {
|
||||
int topF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top() - lengthDifference);
|
||||
int bottomF = qMax(m_latteView->screenGeometry().top(), qMin(m_latteView->screenGeometry().bottom(), m_latteView->absoluteGeometry().bottom() + lengthDifference));
|
||||
newGeometry.setTop(topF);
|
||||
newGeometry.setBottom(bottomF);
|
||||
}
|
||||
|
||||
if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
newGeometry.moveTop(m_latteView->screenGeometry().bottom() - m_thickness);
|
||||
} else if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
newGeometry.moveTop(m_latteView->screenGeometry().top());
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
newGeometry.moveLeft(m_latteView->screenGeometry().left());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
newGeometry.moveLeft(m_latteView->screenGeometry().right() - m_thickness);
|
||||
}
|
||||
|
||||
if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
|
||||
newGeometry.setWidth(length);
|
||||
newGeometry.setHeight(m_thickness + 1);
|
||||
} else {
|
||||
newGeometry.setWidth(m_thickness + 1);
|
||||
newGeometry.setHeight(length);
|
||||
}
|
||||
|
||||
m_calculatedGeometry = newGeometry;
|
||||
|
||||
emit calculatedGeometryChanged();
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
// Qt
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QLatin1String>
|
||||
|
||||
// KDE
|
||||
@ -243,9 +244,7 @@ void Indicator::load(QString type)
|
||||
|
||||
m_metadata = metadata;
|
||||
m_type = type;
|
||||
|
||||
QString path = m_metadata.fileName();
|
||||
m_pluginPath = path.remove("metadata.desktop");
|
||||
m_pluginPath = QFileInfo(m_metadata.fileName()).absolutePath();
|
||||
|
||||
if (m_corona && m_corona->indicatorFactory()->isCustomType(type)) {
|
||||
setCustomType(type);
|
||||
@ -271,7 +270,7 @@ void Indicator::updateComponent()
|
||||
QString uiPath = m_metadata.value("X-Latte-MainScript");
|
||||
|
||||
if (!uiPath.isEmpty()) {
|
||||
uiPath = m_pluginPath + "package/" + uiPath;
|
||||
uiPath = m_pluginPath + "/package/" + uiPath;
|
||||
m_component = new QQmlComponent(m_view->engine(), uiPath);
|
||||
}
|
||||
|
||||
@ -288,10 +287,7 @@ void Indicator::loadPlasmaComponent()
|
||||
QString uiPath = metadata.value("X-Latte-MainScript");
|
||||
|
||||
if (!uiPath.isEmpty()) {
|
||||
QString path = metadata.fileName();
|
||||
path = path.remove("metadata.desktop");
|
||||
|
||||
uiPath = path + "package/" + uiPath;
|
||||
uiPath = QFileInfo(metadata.fileName()).absolutePath() + "/package/" + uiPath;
|
||||
m_plasmaComponent = new QQmlComponent(m_view->engine(), uiPath);
|
||||
}
|
||||
|
||||
@ -315,7 +311,7 @@ void Indicator::updateScheme()
|
||||
QString xmlPath = m_metadata.value("X-Latte-ConfigXml");
|
||||
|
||||
if (!xmlPath.isEmpty()) {
|
||||
QFile file(m_pluginPath + "package/" + xmlPath);
|
||||
QFile file(m_pluginPath + "/package/" + xmlPath);
|
||||
m_configLoader = new KConfigLoader(m_view->containment()->config().group("Indicator").group(m_metadata.pluginId()), &file);
|
||||
m_configuration = new KDeclarative::ConfigPropertyMap(m_configLoader, this);
|
||||
} else {
|
||||
|
282
app/view/originalview.cpp
Normal file
282
app/view/originalview.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "originalview.h"
|
||||
#include "clonedview.h"
|
||||
#include "positioner.h"
|
||||
#include "../lattecorona.h"
|
||||
#include "../screenpool.h"
|
||||
#include "../layouts/storage.h"
|
||||
|
||||
// KDE
|
||||
#include <KLocalizedString>
|
||||
|
||||
namespace Latte {
|
||||
OriginalView::OriginalView(Plasma::Corona *corona, QScreen *targetScreen, bool byPassX11WM)
|
||||
: View(corona, targetScreen, byPassX11WM)
|
||||
{
|
||||
connect(this, &View::containmentChanged, this, [&]() {
|
||||
if (!this->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(containment(), &Plasma::Applet::destroyedChanged, this, &OriginalView::syncClonesToScreens);
|
||||
restoreConfig();
|
||||
});
|
||||
|
||||
connect(this, &View::layoutChanged, this, &OriginalView::syncClonesToScreens);
|
||||
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::syncClonesToScreens);
|
||||
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::saveConfig);
|
||||
}
|
||||
|
||||
OriginalView::~OriginalView()
|
||||
{
|
||||
cleanClones();
|
||||
}
|
||||
|
||||
bool OriginalView::isSingle() const
|
||||
{
|
||||
return m_screensGroup == Latte::Types::SingleScreenGroup;
|
||||
}
|
||||
|
||||
bool OriginalView::isOriginal() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OriginalView::isCloned() const
|
||||
{
|
||||
return !isOriginal();
|
||||
}
|
||||
|
||||
int OriginalView::clonesCount() const
|
||||
{
|
||||
return m_clones.count();
|
||||
}
|
||||
|
||||
int OriginalView::expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const
|
||||
{
|
||||
Data::View view = data();
|
||||
view.screensGroup = nextScreensGroup;
|
||||
return Latte::Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
|
||||
}
|
||||
|
||||
Latte::Types::ScreensGroup OriginalView::screensGroup() const
|
||||
{
|
||||
return m_screensGroup;
|
||||
}
|
||||
|
||||
void OriginalView::setScreensGroup(const Latte::Types::ScreensGroup &group)
|
||||
{
|
||||
if (m_screensGroup == group) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_screensGroup = group;
|
||||
emit screensGroupChanged();
|
||||
}
|
||||
|
||||
void OriginalView::addClone(Latte::ClonedView *view)
|
||||
{
|
||||
if (m_clones.contains(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_clones << view;
|
||||
m_waitingCreation.removeAll(view->positioner()->currentScreenId());
|
||||
}
|
||||
|
||||
void OriginalView::removeClone(Latte::ClonedView *view)
|
||||
{
|
||||
if (!m_clones.contains(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = m_clones.indexOf(view);
|
||||
auto cloned = m_clones.takeAt(idx);
|
||||
|
||||
if (!cloned->layout()) {
|
||||
return;
|
||||
}
|
||||
cloned->positioner()->slideOutDuringExit();
|
||||
cloned->layout()->removeView(cloned->data());
|
||||
}
|
||||
|
||||
void OriginalView::createClone(int screenId)
|
||||
{
|
||||
if (!layout() || !containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString templateFile = layout()->storedView(containment()->id());
|
||||
|
||||
if (templateFile.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Data::ViewsTable templateviews = Layouts::Storage::self()->views(templateFile);
|
||||
|
||||
if (templateviews.rowCount() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Data::View nextdata = templateviews[0];
|
||||
nextdata.name = i18nc("clone of original dock panel, name","Clone of %1", name());
|
||||
nextdata.onPrimary = false;
|
||||
nextdata.screensGroup = Latte::Types::SingleScreenGroup;
|
||||
nextdata.isClonedFrom = containment()->id();
|
||||
nextdata.screen = screenId;
|
||||
|
||||
nextdata.setState(Data::View::OriginFromViewTemplate, templateFile);
|
||||
|
||||
if (!m_waitingCreation.contains(screenId)) {
|
||||
m_waitingCreation << screenId;
|
||||
layout()->newView(nextdata);
|
||||
}
|
||||
}
|
||||
|
||||
void OriginalView::cleanClones()
|
||||
{
|
||||
if (m_clones.count()==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while(!m_clones.isEmpty()) {
|
||||
removeClone(m_clones[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void OriginalView::reconsiderScreen()
|
||||
{
|
||||
View::reconsiderScreen();
|
||||
syncClonesToScreens();
|
||||
}
|
||||
|
||||
void OriginalView::setNextLocationForClones(const QString layoutName, int edge, int alignment)
|
||||
{
|
||||
if (m_clones.count()==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto clone : m_clones) {
|
||||
clone->positioner()->setNextLocation(layoutName, Latte::Types::SingleScreenGroup, "", edge, alignment);
|
||||
}
|
||||
}
|
||||
|
||||
void OriginalView::addApplet(const QString &pluginId, const int &excludecloneid)
|
||||
{
|
||||
if (m_clones.count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add applet in original view
|
||||
extendedInterface()->addApplet(pluginId);
|
||||
|
||||
// add applet in clones and exclude the one that probably produced this triggering
|
||||
for(const auto clone: m_clones) {
|
||||
if (clone->containment()->id() == excludecloneid) {
|
||||
// this way we make sure that an applet will not be double added
|
||||
continue;
|
||||
}
|
||||
|
||||
clone->extendedInterface()->addApplet(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
void OriginalView::addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid)
|
||||
{
|
||||
if (m_clones.count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add applet in original view
|
||||
extendedInterface()->addApplet(mimedata, x, y);
|
||||
|
||||
// add applet in clones and exclude the one that probably produced this triggering
|
||||
for(const auto clone: m_clones) {
|
||||
if (clone->containment()->id() == excludecloneid) {
|
||||
// this way we make sure that an applet will not be double added
|
||||
continue;
|
||||
}
|
||||
|
||||
clone->extendedInterface()->addApplet(mimedata, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void OriginalView::syncClonesToScreens()
|
||||
{
|
||||
if (isSingle() || (containment() && containment()->destroyed())) {
|
||||
cleanClones();
|
||||
return;
|
||||
}
|
||||
|
||||
QList<int> secondaryscreens = m_corona->screenPool()->secondaryScreenIds();
|
||||
|
||||
for (const auto scrid : secondaryscreens) {
|
||||
if (m_waitingCreation.contains(scrid)) {
|
||||
secondaryscreens.removeAll(scrid);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_screensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
//! occuped screen from original view in "allsecondaryscreensgroup" must be ignored
|
||||
secondaryscreens.removeAll(expectedScreenIdFromScreenGroup(m_screensGroup));
|
||||
}
|
||||
|
||||
QList<Latte::ClonedView *> removable;
|
||||
|
||||
for (const auto clone : m_clones) {
|
||||
if (secondaryscreens.contains(clone->positioner()->currentScreenId())) {
|
||||
// do nothing valid clone
|
||||
secondaryscreens.removeAll(clone->positioner()->currentScreenId());
|
||||
} else {
|
||||
// must be removed the screen is not active
|
||||
removable << clone;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto scrid : secondaryscreens) {
|
||||
if (removable.count() > 0) {
|
||||
//! move deprecated and available clone to valid secondary screen
|
||||
auto clone = removable.takeFirst();
|
||||
clone->positioner()->setScreenToFollow(m_corona->screenPool()->screenForId(scrid));
|
||||
} else {
|
||||
//! create a new clone
|
||||
createClone(scrid);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto removableclone : removable) {
|
||||
//! remove deprecated clones
|
||||
removeClone(removableclone);
|
||||
}
|
||||
}
|
||||
|
||||
void OriginalView::saveConfig()
|
||||
{
|
||||
|
||||
if (!this->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto config = this->containment()->config();
|
||||
config.writeEntry("screensGroup", (int)m_screensGroup);
|
||||
}
|
||||
|
||||
void OriginalView::restoreConfig()
|
||||
{
|
||||
if (!this->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto config = this->containment()->config();
|
||||
m_screensGroup = static_cast<Latte::Types::ScreensGroup>(config.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
|
||||
|
||||
//! Send changed signals at the end in order to be sure that saveConfig
|
||||
//! wont rewrite default/invalid values
|
||||
emit screensGroupChanged();
|
||||
}
|
||||
|
||||
}
|
72
app/view/originalview.h
Normal file
72
app/view/originalview.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ORIGINALVIEW_H
|
||||
#define ORIGINALVIEW_H
|
||||
|
||||
// local
|
||||
#include <coretypes.h>
|
||||
#include "view.h"
|
||||
|
||||
// Qt
|
||||
#include <QList>
|
||||
|
||||
namespace Latte {
|
||||
|
||||
class ClonedView;
|
||||
|
||||
class OriginalView : public View
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Latte::Types::ScreensGroup screensGroup READ screensGroup NOTIFY screensGroupChanged)
|
||||
|
||||
public:
|
||||
OriginalView(Plasma::Corona *corona, QScreen *targetScreen = nullptr, bool byPassX11WM = false);
|
||||
~OriginalView();
|
||||
|
||||
bool isOriginal() const override;
|
||||
bool isCloned() const override;
|
||||
bool isSingle() const override;
|
||||
|
||||
int clonesCount() const;
|
||||
|
||||
int expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const;
|
||||
|
||||
Latte::Types::ScreensGroup screensGroup() const override;
|
||||
void setScreensGroup(const Latte::Types::ScreensGroup &group);
|
||||
|
||||
void addClone(Latte::ClonedView *view);
|
||||
void setNextLocationForClones(const QString layoutName, int edge, int alignment);
|
||||
void addApplet(const QString &pluginId, const int &excludecloneid);
|
||||
void addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid);
|
||||
|
||||
void reconsiderScreen() override;
|
||||
|
||||
public slots:
|
||||
void cleanClones();
|
||||
|
||||
signals:
|
||||
void screensGroupChanged();
|
||||
|
||||
private slots:
|
||||
void syncClonesToScreens();
|
||||
|
||||
void restoreConfig();
|
||||
void saveConfig();
|
||||
|
||||
private:
|
||||
void createClone(int screenId);
|
||||
void removeClone(Latte::ClonedView *view);
|
||||
|
||||
private:
|
||||
Latte::Types::ScreensGroup m_screensGroup{Latte::Types::SingleScreenGroup};
|
||||
QList<Latte::ClonedView *> m_clones;
|
||||
|
||||
QList<int> m_waitingCreation;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -6,98 +6,34 @@
|
||||
|
||||
#include "panelshadows_p.h"
|
||||
|
||||
#include <QWindow>
|
||||
#include <QPainter>
|
||||
|
||||
#include <config-latte.h>
|
||||
|
||||
#include <KWindowSystem>
|
||||
#if HAVE_X11
|
||||
#include <QX11Info>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <fixx11h.h>
|
||||
#endif
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <KWayland/Client/shadow.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
||||
#include <qdebug.h>
|
||||
#include <QDebug>
|
||||
#include <KWindowShadow>
|
||||
|
||||
class PanelShadows::Private
|
||||
{
|
||||
public:
|
||||
Private(PanelShadows *shadows)
|
||||
: q(shadows)
|
||||
#if HAVE_X11
|
||||
,_connection( nullptr ),
|
||||
_gc( 0x0 )
|
||||
, m_isX11(KWindowSystem::isPlatformX11())
|
||||
#endif
|
||||
{
|
||||
setupWaylandIntegration();
|
||||
}
|
||||
|
||||
~Private()
|
||||
{
|
||||
// Do not call clearPixmaps() from here: it creates new QPixmap(),
|
||||
// which causes a crash when application is stopping.
|
||||
freeX11Pixmaps();
|
||||
}
|
||||
|
||||
void freeX11Pixmaps();
|
||||
void freeWaylandBuffers();
|
||||
void clearPixmaps();
|
||||
void setupPixmaps();
|
||||
Qt::HANDLE createPixmap(const QPixmap& source);
|
||||
void initPixmap(const QString &element);
|
||||
QPixmap initEmptyPixmap(const QSize &size);
|
||||
void updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void clearShadow(const QWindow *window);
|
||||
void clearShadowX11(const QWindow *window);
|
||||
void clearShadowWayland(const QWindow *window);
|
||||
void clearTiles();
|
||||
void setupTiles();
|
||||
void initTile(const QString &element);
|
||||
void updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void clearShadow(QWindow *window);
|
||||
void updateShadows();
|
||||
void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders);
|
||||
bool hasShadows() const;
|
||||
|
||||
void setupWaylandIntegration();
|
||||
|
||||
PanelShadows *q;
|
||||
QList<QPixmap> m_shadowPixmaps;
|
||||
|
||||
QPixmap m_emptyCornerPix;
|
||||
QPixmap m_emptyCornerLeftPix;
|
||||
QPixmap m_emptyCornerTopPix;
|
||||
QPixmap m_emptyCornerRightPix;
|
||||
QPixmap m_emptyCornerBottomPix;
|
||||
QPixmap m_emptyVerticalPix;
|
||||
QPixmap m_emptyHorizontalPix;
|
||||
|
||||
#if HAVE_X11
|
||||
//! xcb connection
|
||||
xcb_connection_t* _connection;
|
||||
|
||||
//! graphical context
|
||||
xcb_gcontext_t _gc;
|
||||
bool m_isX11;
|
||||
#endif
|
||||
|
||||
struct Wayland {
|
||||
KWayland::Client::ShadowManager *manager = nullptr;
|
||||
KWayland::Client::ShmPool *shmPool = nullptr;
|
||||
|
||||
QList<KWayland::Client::Buffer::Ptr> shadowBuffers;
|
||||
};
|
||||
Wayland m_wayland;
|
||||
|
||||
QHash<Plasma::FrameSvg::EnabledBorders, QVector<unsigned long> > data;
|
||||
QHash<const QWindow *, Plasma::FrameSvg::EnabledBorders> m_windows;
|
||||
QHash<QWindow *, Plasma::FrameSvg::EnabledBorders> m_windows;
|
||||
QHash<QWindow *, KWindowShadow *> m_shadows;
|
||||
QVector<KWindowShadowTile::Ptr> m_tiles;
|
||||
};
|
||||
|
||||
class PanelShadowsSingleton
|
||||
@ -107,14 +43,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
PanelShadows self;
|
||||
PanelShadows self;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(PanelShadowsSingleton, privatePanelShadowsSelf)
|
||||
|
||||
PanelShadows::PanelShadows(QObject *parent, const QString &prefix)
|
||||
: Plasma::Svg(parent),
|
||||
d(new Private(this))
|
||||
: Plasma::Svg(parent)
|
||||
, d(new Private(this))
|
||||
{
|
||||
setImagePath(prefix);
|
||||
connect(this, &Plasma::Svg::repaintNeeded, this, [this]() {
|
||||
@ -132,7 +68,7 @@ PanelShadows *PanelShadows::self()
|
||||
return &privatePanelShadowsSelf->self;
|
||||
}
|
||||
|
||||
void PanelShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
void PanelShadows::addWindow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
@ -142,13 +78,14 @@ void PanelShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBor
|
||||
d->updateShadow(window, enabledBorders);
|
||||
connect(window, &QObject::destroyed, this, [this, window]() {
|
||||
d->m_windows.remove(window);
|
||||
d->clearShadow(window);
|
||||
if (d->m_windows.isEmpty()) {
|
||||
d->clearPixmaps();
|
||||
d->clearTiles();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PanelShadows::removeWindow(const QWindow *window)
|
||||
void PanelShadows::removeWindow(QWindow *window)
|
||||
{
|
||||
if (!d->m_windows.contains(window)) {
|
||||
return;
|
||||
@ -159,16 +96,11 @@ void PanelShadows::removeWindow(const QWindow *window)
|
||||
d->clearShadow(window);
|
||||
|
||||
if (d->m_windows.isEmpty()) {
|
||||
d->clearPixmaps();
|
||||
d->clearTiles();
|
||||
}
|
||||
}
|
||||
|
||||
bool PanelShadows::hasShadows() const
|
||||
{
|
||||
return hasElement(QStringLiteral("shadow-left"));
|
||||
}
|
||||
|
||||
void PanelShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
void PanelShadows::setEnabledBorders(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
if (!window || !d->m_windows.contains(window)) {
|
||||
return;
|
||||
@ -180,12 +112,12 @@ void PanelShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::En
|
||||
|
||||
void PanelShadows::Private::updateShadows()
|
||||
{
|
||||
const bool hadShadowsBefore = !m_shadowPixmaps.isEmpty();
|
||||
const bool hadShadowsBefore = !m_tiles.isEmpty();
|
||||
|
||||
// has shadows now?
|
||||
if (hasShadows()) {
|
||||
if (hadShadowsBefore) {
|
||||
clearPixmaps();
|
||||
clearTiles();
|
||||
}
|
||||
for (auto i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) {
|
||||
updateShadow(i.key(), i.value());
|
||||
@ -195,524 +127,162 @@ void PanelShadows::Private::updateShadows()
|
||||
for (auto i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) {
|
||||
clearShadow(i.key());
|
||||
}
|
||||
clearPixmaps();
|
||||
clearTiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qt::HANDLE PanelShadows::Private::createPixmap(const QPixmap& source)
|
||||
void PanelShadows::Private::initTile(const QString &element)
|
||||
{
|
||||
const QImage image = q->pixmap(element).toImage();
|
||||
|
||||
// do nothing for invalid pixmaps
|
||||
if( source.isNull() ) return nullptr;
|
||||
|
||||
/*
|
||||
in some cases, pixmap handle is invalid. This is the case notably
|
||||
when Qt uses to RasterEngine. In this case, we create an X11 Pixmap
|
||||
explicitly and draw the source pixmap on it.
|
||||
*/
|
||||
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check connection
|
||||
if( !_connection ) _connection = QX11Info::connection();
|
||||
|
||||
const int width( source.width() );
|
||||
const int height( source.height() );
|
||||
|
||||
// create X11 pixmap
|
||||
Pixmap pixmap = XCreatePixmap( QX11Info::display(), QX11Info::appRootWindow(), width, height, 32 );
|
||||
|
||||
// check gc
|
||||
if( !_gc )
|
||||
{
|
||||
_gc = xcb_generate_id( _connection );
|
||||
xcb_create_gc( _connection, _gc, pixmap, 0, nullptr );
|
||||
}
|
||||
|
||||
// // create explicitly shared QPixmap from it
|
||||
// QPixmap dest( QPixmap::fromX11Pixmap( pixmap, QPixmap::ExplicitlyShared ) );
|
||||
//
|
||||
// // create surface for pixmap
|
||||
// {
|
||||
// QPainter painter( &dest );
|
||||
// painter.setCompositionMode( QPainter::CompositionMode_Source );
|
||||
// painter.drawPixmap( 0, 0, source );
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return pixmap;
|
||||
QImage image( source.toImage() );
|
||||
xcb_put_image(
|
||||
_connection, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc,
|
||||
image.width(), image.height(), 0, 0,
|
||||
0, 32,
|
||||
image.byteCount(), image.constBits());
|
||||
|
||||
return (Qt::HANDLE)pixmap;
|
||||
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create();
|
||||
tile->setImage(image);
|
||||
|
||||
m_tiles << tile;
|
||||
}
|
||||
|
||||
void PanelShadows::Private::initPixmap(const QString &element)
|
||||
void PanelShadows::Private::setupTiles()
|
||||
{
|
||||
m_shadowPixmaps << q->pixmap(element);
|
||||
clearTiles();
|
||||
|
||||
initTile(QStringLiteral("shadow-top"));
|
||||
initTile(QStringLiteral("shadow-topright"));
|
||||
initTile(QStringLiteral("shadow-right"));
|
||||
initTile(QStringLiteral("shadow-bottomright"));
|
||||
initTile(QStringLiteral("shadow-bottom"));
|
||||
initTile(QStringLiteral("shadow-bottomleft"));
|
||||
initTile(QStringLiteral("shadow-left"));
|
||||
initTile(QStringLiteral("shadow-topleft"));
|
||||
}
|
||||
|
||||
QPixmap PanelShadows::Private::initEmptyPixmap(const QSize &size)
|
||||
void PanelShadows::Private::clearTiles()
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return QPixmap();
|
||||
}
|
||||
QPixmap tempEmptyPix(size);
|
||||
if (!size.isEmpty()) {
|
||||
tempEmptyPix.fill(Qt::transparent);
|
||||
}
|
||||
return tempEmptyPix;
|
||||
#else
|
||||
Q_UNUSED(size)
|
||||
return QPixmap();
|
||||
#endif
|
||||
m_tiles.clear();
|
||||
}
|
||||
|
||||
void PanelShadows::Private::setupPixmaps()
|
||||
{
|
||||
clearPixmaps();
|
||||
initPixmap(QStringLiteral("shadow-top"));
|
||||
initPixmap(QStringLiteral("shadow-topright"));
|
||||
initPixmap(QStringLiteral("shadow-right"));
|
||||
initPixmap(QStringLiteral("shadow-bottomright"));
|
||||
initPixmap(QStringLiteral("shadow-bottom"));
|
||||
initPixmap(QStringLiteral("shadow-bottomleft"));
|
||||
initPixmap(QStringLiteral("shadow-left"));
|
||||
initPixmap(QStringLiteral("shadow-topleft"));
|
||||
|
||||
m_emptyCornerPix = initEmptyPixmap(QSize(1,1));
|
||||
m_emptyCornerLeftPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-topleft")).width(), 1));
|
||||
m_emptyCornerTopPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-topleft")).height()));
|
||||
m_emptyCornerRightPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-bottomright")).width(), 1));
|
||||
m_emptyCornerBottomPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-bottomright")).height()));
|
||||
m_emptyVerticalPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-left")).height()));
|
||||
m_emptyHorizontalPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-top")).width(), 1));
|
||||
|
||||
if (m_wayland.shmPool) {
|
||||
for (auto it = m_shadowPixmaps.constBegin(); it != m_shadowPixmaps.constEnd(); ++it) {
|
||||
m_wayland.shadowBuffers << m_wayland.shmPool->createBuffer(it->toImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PanelShadows::Private::setupData(Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return;
|
||||
}
|
||||
//shadow-top
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[0]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
|
||||
}
|
||||
|
||||
//shadow-topright
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[1]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-right
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[2]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
|
||||
}
|
||||
|
||||
//shadow-bottomright
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[3]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-bottom
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[4]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
|
||||
}
|
||||
|
||||
//shadow-bottomleft
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[5]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-left
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[6]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
|
||||
}
|
||||
|
||||
//shadow-topleft
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[7]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
#endif
|
||||
|
||||
int left, top, right, bottom = 0;
|
||||
|
||||
QSize marginHint;
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
top = marginHint.height();
|
||||
} else {
|
||||
top = m_shadowPixmaps[0].height(); // top
|
||||
}
|
||||
} else {
|
||||
top = 1;
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
right = marginHint.width();
|
||||
} else {
|
||||
right = m_shadowPixmaps[2].width(); // right
|
||||
}
|
||||
} else {
|
||||
right = 1;
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
bottom = marginHint.height();
|
||||
} else {
|
||||
bottom = m_shadowPixmaps[4].height(); // bottom
|
||||
}
|
||||
} else {
|
||||
bottom = 1;
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
left = marginHint.width();
|
||||
} else {
|
||||
left = m_shadowPixmaps[6].width(); // left
|
||||
}
|
||||
} else {
|
||||
left = 1;
|
||||
}
|
||||
|
||||
data[enabledBorders] << top << right << bottom << left;
|
||||
}
|
||||
|
||||
void PanelShadows::Private::freeX11Pixmaps()
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *display = QX11Info::display();
|
||||
if (!display) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const QPixmap &pixmap, m_shadowPixmaps) {
|
||||
if (!pixmap.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(pixmap)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_emptyCornerPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix)));
|
||||
}
|
||||
if (!m_emptyCornerBottomPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix)));
|
||||
}
|
||||
if (!m_emptyCornerLeftPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix)));
|
||||
}
|
||||
if (!m_emptyCornerRightPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix)));
|
||||
}
|
||||
if (!m_emptyCornerTopPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix)));
|
||||
}
|
||||
if (!m_emptyVerticalPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix)));
|
||||
}
|
||||
if (!m_emptyHorizontalPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PanelShadows::Private::clearPixmaps()
|
||||
{
|
||||
#if HAVE_X11
|
||||
freeX11Pixmaps();
|
||||
|
||||
m_emptyCornerPix = QPixmap();
|
||||
m_emptyCornerBottomPix = QPixmap();
|
||||
m_emptyCornerLeftPix = QPixmap();
|
||||
m_emptyCornerRightPix = QPixmap();
|
||||
m_emptyCornerTopPix = QPixmap();
|
||||
m_emptyVerticalPix = QPixmap();
|
||||
m_emptyHorizontalPix = QPixmap();
|
||||
#endif
|
||||
freeWaylandBuffers();
|
||||
m_shadowPixmaps.clear();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void PanelShadows::Private::freeWaylandBuffers()
|
||||
{
|
||||
m_wayland.shadowBuffers.clear();
|
||||
}
|
||||
|
||||
void PanelShadows::Private::updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
void PanelShadows::Private::updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
if (!hasShadows()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if HAVE_X11
|
||||
if (m_isX11) {
|
||||
updateShadowX11(window, enabledBorders);
|
||||
}
|
||||
#endif
|
||||
if (m_wayland.manager) {
|
||||
updateShadowWayland(window, enabledBorders);
|
||||
}
|
||||
}
|
||||
|
||||
void PanelShadows::Private::updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (m_shadowPixmaps.isEmpty()) {
|
||||
setupPixmaps();
|
||||
if (m_tiles.isEmpty()) {
|
||||
setupTiles();
|
||||
}
|
||||
|
||||
if (!data.contains(enabledBorders)) {
|
||||
setupData(enabledBorders);
|
||||
KWindowShadow *&shadow = m_shadows[window];
|
||||
|
||||
if (!shadow) {
|
||||
shadow = new KWindowShadow(q);
|
||||
}
|
||||
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
|
||||
|
||||
// qDebug() << "going to set the shadow of" << window->winId() << "to" << data;
|
||||
XChangeProperty(dpy, window->winId(), atom, XA_CARDINAL, 32, PropModeReplace,
|
||||
reinterpret_cast<const unsigned char *>(data[enabledBorders].constData()), data[enabledBorders].size());
|
||||
#endif
|
||||
}
|
||||
|
||||
void PanelShadows::Private::updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
if (!m_wayland.shmPool) {
|
||||
return;
|
||||
if (shadow->isCreated()) {
|
||||
shadow->destroy();
|
||||
}
|
||||
if (m_wayland.shadowBuffers.isEmpty()) {
|
||||
setupPixmaps();
|
||||
}
|
||||
// TODO: check whether the surface already has a shadow
|
||||
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast<QWindow*>(window));
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
auto shadow = m_wayland.manager->createShadow(surface, surface);
|
||||
|
||||
//shadow-top
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
shadow->attachTop(m_wayland.shadowBuffers.at(0));
|
||||
shadow->setTopTile(m_tiles.at(0));
|
||||
} else {
|
||||
shadow->setTopTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-topright
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->attachTopRight(m_wayland.shadowBuffers.at(1));
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder && enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->setTopRightTile(m_tiles.at(1));
|
||||
} else {
|
||||
shadow->setTopRightTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-right
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->attachRight(m_wayland.shadowBuffers.at(2));
|
||||
shadow->setRightTile(m_tiles.at(2));
|
||||
} else {
|
||||
shadow->setRightTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-bottomright
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->attachBottomRight(m_wayland.shadowBuffers.at(3));
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder && enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->setBottomRightTile(m_tiles.at(3));
|
||||
} else {
|
||||
shadow->setBottomRightTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-bottom
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
shadow->attachBottom(m_wayland.shadowBuffers.at(4));
|
||||
shadow->setBottomTile(m_tiles.at(4));
|
||||
} else {
|
||||
shadow->setBottomTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-bottomleft
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->attachBottomLeft(m_wayland.shadowBuffers.at(5));
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder && enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->setBottomLeftTile(m_tiles.at(5));
|
||||
} else {
|
||||
shadow->setBottomLeftTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-left
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->attachLeft(m_wayland.shadowBuffers.at(6));
|
||||
shadow->setLeftTile(m_tiles.at(6));
|
||||
} else {
|
||||
shadow->setLeftTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-topleft
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->attachTopLeft(m_wayland.shadowBuffers.at(7));
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder && enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->setTopLeftTile(m_tiles.at(7));
|
||||
} else {
|
||||
shadow->setTopLeftTile(nullptr);
|
||||
}
|
||||
|
||||
QSize marginHint;
|
||||
QMarginsF margins;
|
||||
QMargins padding;
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setTop(marginHint.height());
|
||||
padding.setTop(marginHint.height());
|
||||
} else {
|
||||
margins.setTop(m_shadowPixmaps[0].height());
|
||||
padding.setTop(m_tiles[0]->image().height());
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setRight(marginHint.width());
|
||||
padding.setRight(marginHint.width());
|
||||
} else {
|
||||
margins.setRight(m_shadowPixmaps[2].width());
|
||||
padding.setRight(m_tiles[2]->image().width());
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setBottom(marginHint.height());
|
||||
padding.setBottom(marginHint.height());
|
||||
} else {
|
||||
margins.setBottom(m_shadowPixmaps[4].height());
|
||||
padding.setBottom(m_tiles[4]->image().height());
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setLeft(marginHint.width());
|
||||
padding.setLeft(marginHint.width());
|
||||
} else {
|
||||
margins.setLeft(m_shadowPixmaps[6].width());
|
||||
padding.setLeft(m_tiles[6]->image().width());
|
||||
}
|
||||
}
|
||||
|
||||
shadow->setOffsets(margins);
|
||||
shadow->commit();
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
}
|
||||
shadow->setPadding(padding);
|
||||
shadow->setWindow(window);
|
||||
|
||||
void PanelShadows::Private::clearShadow(const QWindow *window)
|
||||
{
|
||||
if (!static_cast<const QSurface*>(window)->surfaceHandle()) {
|
||||
qWarning() << "Cannot clear shadow from window without native surface!";
|
||||
return;
|
||||
}
|
||||
#if HAVE_X11
|
||||
if (m_isX11) {
|
||||
clearShadowX11(window);
|
||||
}
|
||||
#endif
|
||||
if (m_wayland.manager) {
|
||||
clearShadowWayland(window);
|
||||
if (!shadow->create()) {
|
||||
qDebug() << "Couldn't create KWindowShadow for" << window;
|
||||
}
|
||||
}
|
||||
|
||||
void PanelShadows::Private::clearShadowX11(const QWindow* window)
|
||||
void PanelShadows::Private::clearShadow(QWindow *window)
|
||||
{
|
||||
#if HAVE_X11
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
|
||||
XDeleteProperty(dpy, window->winId(), atom);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PanelShadows::Private::clearShadowWayland(const QWindow *window)
|
||||
{
|
||||
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast<QWindow*>(window));
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
m_wayland.manager->removeShadow(surface);
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
delete m_shadows.take(window);
|
||||
}
|
||||
|
||||
bool PanelShadows::Private::hasShadows() const
|
||||
{
|
||||
return q->hasShadows();
|
||||
}
|
||||
|
||||
void PanelShadows::Private::setupWaylandIntegration()
|
||||
{
|
||||
if (!KWindowSystem::isPlatformWayland()) {
|
||||
return;
|
||||
}
|
||||
using namespace KWayland::Client;
|
||||
ConnectionThread *connection = ConnectionThread::fromApplication(q);
|
||||
if (!connection) {
|
||||
return;
|
||||
}
|
||||
Registry *registry = new Registry(q);
|
||||
registry->create(connection);
|
||||
connect(registry, &Registry::shadowAnnounced, q,
|
||||
[this, registry] (quint32 name, quint32 version) {
|
||||
m_wayland.manager = registry->createShadowManager(name, version, q);
|
||||
updateShadows();
|
||||
}, Qt::QueuedConnection
|
||||
);
|
||||
connect(registry, &Registry::shmAnnounced, q,
|
||||
[this, registry] (quint32 name, quint32 version) {
|
||||
m_wayland.shmPool = registry->createShmPool(name, version, q);
|
||||
updateShadows();
|
||||
}, Qt::QueuedConnection
|
||||
);
|
||||
registry->setup();
|
||||
connection->roundtrip();
|
||||
return q->hasElement(QStringLiteral("shadow-left"));
|
||||
}
|
||||
|
||||
#include "moc_panelshadows_p.cpp"
|
||||
|
||||
|
@ -4,15 +4,13 @@
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef PANELSHADOWS_P_H
|
||||
#define PANELSHADOWS_P_H
|
||||
#pragma once
|
||||
|
||||
#include <QSet>
|
||||
|
||||
#include "plasma/framesvg.h"
|
||||
#include "plasma/svg.h"
|
||||
|
||||
|
||||
class PanelShadows : public Plasma::Svg
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -23,17 +21,12 @@ public:
|
||||
|
||||
static PanelShadows *self();
|
||||
|
||||
void addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
void removeWindow(const QWindow *window);
|
||||
void addWindow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
void removeWindow(QWindow *window);
|
||||
|
||||
void setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
|
||||
bool hasShadows() const;
|
||||
void setEnabledBorders(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private * const d;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
// local
|
||||
#include <coretypes.h>
|
||||
#include "effects.h"
|
||||
#include "originalview.h"
|
||||
#include "view.h"
|
||||
#include "visibilitymanager.h"
|
||||
#include "../lattecorona.h"
|
||||
@ -208,7 +209,7 @@ void Positioner::init()
|
||||
});
|
||||
|
||||
connect(qGuiApp, &QGuiApplication::screenAdded, this, &Positioner::onScreenChanged);
|
||||
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &Positioner::onScreenChanged);
|
||||
connect(m_corona->screenPool(), &ScreenPool::primaryScreenChanged, this, &Positioner::onScreenChanged);
|
||||
|
||||
connect(m_view, &Latte::View::visibilityChanged, this, &Positioner::initDelayedSignals);
|
||||
|
||||
@ -268,7 +269,7 @@ void Positioner::setInRelocationShowing(bool active)
|
||||
|
||||
bool Positioner::isOffScreen() const
|
||||
{
|
||||
return (m_validGeometry.x()<-500 || m_validGeometry.y()<-500);
|
||||
return (m_view->absoluteGeometry().x()<-500 || m_view->absoluteGeometry().y()<-500);
|
||||
}
|
||||
|
||||
int Positioner::currentScreenId() const
|
||||
@ -347,6 +348,7 @@ void Positioner::onStartupFinished()
|
||||
if (m_inStartup) {
|
||||
m_inStartup = false;
|
||||
syncGeometry();
|
||||
emit isOffScreenChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,11 +435,12 @@ void Positioner::reconsiderScreen()
|
||||
}
|
||||
|
||||
bool screenExists{false};
|
||||
QScreen *primaryScreen{m_corona->screenPool()->primaryScreen()};
|
||||
|
||||
//!check if the associated screen is running
|
||||
for (const auto scr : qGuiApp->screens()) {
|
||||
if (m_screenNameToFollow == scr->name()
|
||||
|| (m_view->onPrimary() && scr == qGuiApp->primaryScreen())) {
|
||||
|| (m_view->onPrimary() && scr == primaryScreen)) {
|
||||
screenExists = true;
|
||||
}
|
||||
}
|
||||
@ -445,12 +448,12 @@ void Positioner::reconsiderScreen()
|
||||
qDebug() << "dock screen exists ::: " << screenExists;
|
||||
|
||||
//! 1.a primary dock must be always on the primary screen
|
||||
if (m_view->onPrimary() && (m_screenNameToFollow != qGuiApp->primaryScreen()->name()
|
||||
|| m_screenToFollow != qGuiApp->primaryScreen()
|
||||
|| m_view->screen() != qGuiApp->primaryScreen())) {
|
||||
if (m_view->onPrimary() && (m_screenNameToFollow != primaryScreen->name()
|
||||
|| m_screenToFollow != primaryScreen
|
||||
|| m_view->screen() != primaryScreen)) {
|
||||
//! case 1
|
||||
qDebug() << "reached case 1: of updating dock primary screen...";
|
||||
setScreenToFollow(qGuiApp->primaryScreen());
|
||||
setScreenToFollow(primaryScreen);
|
||||
} else if (!m_view->onPrimary()) {
|
||||
//! 2.an explicit dock must be always on the correct associated screen
|
||||
//! there are cases that window manager misplaces the dock, this function
|
||||
@ -564,7 +567,10 @@ void Positioner::immediateSyncGeometry()
|
||||
freeRegion = latteCorona->availableScreenRegionWithCriteria(fixedScreen, activityid, ignoreModes, ignoreEdges);
|
||||
}
|
||||
|
||||
maximumRect = maximumNormalGeometry();
|
||||
//! On startup when offscreen use offscreen screen geometry.
|
||||
//! This way vertical docks and panels are not showing are shrinked that
|
||||
//! need to be expanded after sliding-in in startup
|
||||
maximumRect = maximumNormalGeometry(m_inStartup ? availableScreenRect : QRect());
|
||||
QRegion availableRegion = freeRegion.intersected(maximumRect);
|
||||
|
||||
availableScreenRect = freeRegion.intersected(maximumRect).boundingRect();
|
||||
@ -584,7 +590,6 @@ void Positioner::immediateSyncGeometry()
|
||||
}
|
||||
|
||||
validateTopBottomBorders(availableScreenRect, freeRegion);
|
||||
|
||||
m_lastAvailableScreenRegion = freeRegion;
|
||||
} else {
|
||||
m_view->effects()->setForceTopBorder(false);
|
||||
@ -634,23 +639,25 @@ void Positioner::setCanvasGeometry(const QRect &geometry)
|
||||
//! this is used mainly from vertical panels in order to
|
||||
//! to get the maximum geometry that can be used from the dock
|
||||
//! based on their alignment type and the location dock
|
||||
QRect Positioner::maximumNormalGeometry()
|
||||
QRect Positioner::maximumNormalGeometry(QRect screenGeometry)
|
||||
{
|
||||
QRect currentScrGeometry = screenGeometry.isEmpty() ? m_view->screen()->geometry() : screenGeometry;
|
||||
|
||||
int xPos = 0;
|
||||
int yPos = m_view->screen()->geometry().y();;
|
||||
int maxHeight = m_view->screen()->geometry().height();
|
||||
int yPos = currentScrGeometry.y();;
|
||||
int maxHeight = currentScrGeometry.height();
|
||||
int maxWidth = m_view->maxNormalThickness();
|
||||
QRect maxGeometry;
|
||||
maxGeometry.setRect(0, 0, maxWidth, maxHeight);
|
||||
|
||||
switch (m_view->location()) {
|
||||
case Plasma::Types::LeftEdge:
|
||||
xPos = m_view->screen()->geometry().x();
|
||||
xPos = currentScrGeometry.x();
|
||||
maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight);
|
||||
break;
|
||||
|
||||
case Plasma::Types::RightEdge:
|
||||
xPos = m_view->screen()->geometry().right() - maxWidth + 1;
|
||||
xPos = currentScrGeometry.right() - maxWidth + 1;
|
||||
maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight);
|
||||
break;
|
||||
|
||||
@ -669,7 +676,8 @@ void Positioner::validateTopBottomBorders(QRect availableScreenRect, QRegion ava
|
||||
|
||||
if (availableScreenRect.top() != m_view->screenGeometry().top()) {
|
||||
//! check top border
|
||||
QRegion fitInRegion = QRect(m_view->screenGeometry().x(), availableScreenRect.y()-1, edgeMargin, 1);
|
||||
int x = m_view->location() == Plasma::Types::LeftEdge ? m_view->screenGeometry().x() : m_view->screenGeometry().right() - edgeMargin + 1;
|
||||
QRegion fitInRegion = QRect(x, availableScreenRect.y()-1, edgeMargin, 1);
|
||||
QRegion subtracted = fitInRegion.subtracted(availableScreenRegion);
|
||||
|
||||
if (subtracted.isNull()) {
|
||||
@ -685,7 +693,8 @@ void Positioner::validateTopBottomBorders(QRect availableScreenRect, QRegion ava
|
||||
|
||||
if (availableScreenRect.bottom() != m_view->screenGeometry().bottom()) {
|
||||
//! check top border
|
||||
QRegion fitInRegion = QRect(m_view->screenGeometry().x(), availableScreenRect.bottom()+1, edgeMargin, 1);
|
||||
int x = m_view->location() == Plasma::Types::LeftEdge ? m_view->screenGeometry().x() : m_view->screenGeometry().right() - edgeMargin + 1;
|
||||
QRegion fitInRegion = QRect(x, availableScreenRect.bottom()+1, edgeMargin, 1);
|
||||
QRegion subtracted = fitInRegion.subtracted(availableScreenRegion);
|
||||
|
||||
if (subtracted.isNull()) {
|
||||
@ -966,10 +975,18 @@ void Positioner::initSignalingForLocationChangeSliding()
|
||||
|
||||
//! SCREEN
|
||||
connect(m_view, &QQuickView::screenChanged, this, [&]() {
|
||||
if (!m_view || !m_nextScreen) {
|
||||
return;
|
||||
}
|
||||
|
||||
//[1] if panels are not excluded from confirmed geometry check then they are stuck in sliding out end
|
||||
//and they do not switch to new screen geometry
|
||||
//[2] under wayland view geometry may be delayed to be updated even though the screen has been updated correctly
|
||||
bool confirmedgeometry = KWindowSystem::isPlatformWayland() || m_view->behaveAsPlasmaPanel() || (!m_view->behaveAsPlasmaPanel() && m_nextScreen->geometry().contains(m_view->geometry().center()));
|
||||
|
||||
if (m_nextScreen
|
||||
&& m_nextScreen == m_view->screen()
|
||||
&& m_nextScreen->geometry().contains(m_view->geometry().center())) {
|
||||
|
||||
&& confirmedgeometry) {
|
||||
bool isrelocationlastevent = isLastHidingRelocationEvent();
|
||||
m_nextScreen = nullptr;
|
||||
m_nextScreenName = "";
|
||||
@ -1014,7 +1031,7 @@ void Positioner::initSignalingForLocationChangeSliding()
|
||||
//! SCREEN
|
||||
if (!m_nextScreenName.isEmpty()) {
|
||||
bool nextonprimary = (m_nextScreenName == Latte::Data::Screen::ONPRIMARYNAME);
|
||||
m_nextScreen = qGuiApp->primaryScreen();
|
||||
m_nextScreen = m_corona->screenPool()->primaryScreen();
|
||||
|
||||
if (!nextonprimary) {
|
||||
for (const auto scr : qGuiApp->screens()) {
|
||||
@ -1039,6 +1056,12 @@ void Positioner::initSignalingForLocationChangeSliding()
|
||||
m_view->setAlignment(m_nextAlignment);
|
||||
m_nextAlignment = Latte::Types::NoneAlignment;
|
||||
}
|
||||
|
||||
//! SCREENSGROUP
|
||||
if (m_view->isOriginal()) {
|
||||
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
|
||||
originalview->setScreensGroup(m_nextScreensGroup);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1133,7 +1156,7 @@ bool Positioner::isLastHidingRelocationEvent() const
|
||||
return (events <= 1);
|
||||
}
|
||||
|
||||
void Positioner::setNextLocation(const QString layoutName, const QString screenName, int edge, int alignment)
|
||||
void Positioner::setNextLocation(const QString layoutName, const int screensGroup, QString screenName, int edge, int alignment)
|
||||
{
|
||||
bool isanimated{false};
|
||||
bool haschanges{false};
|
||||
@ -1158,6 +1181,30 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
|
||||
}
|
||||
}
|
||||
|
||||
//! SCREENSGROUP
|
||||
if (m_view->isOriginal()) {
|
||||
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
|
||||
//!initialize screens group
|
||||
m_nextScreensGroup = originalview->screensGroup();
|
||||
|
||||
if (m_nextScreensGroup != screensGroup) {
|
||||
haschanges = true;
|
||||
m_nextScreensGroup = static_cast<Latte::Types::ScreensGroup>(screensGroup);
|
||||
|
||||
if (m_nextScreensGroup == Latte::Types::AllScreensGroup) {
|
||||
screenName = Latte::Data::Screen::ONPRIMARYNAME;
|
||||
} else if (m_nextScreensGroup == Latte::Types::AllSecondaryScreensGroup) {
|
||||
int scrid = originalview->expectedScreenIdFromScreenGroup(m_nextScreensGroup);
|
||||
|
||||
if (scrid != Latte::ScreenPool::NOSCREENID) {
|
||||
screenName = m_corona->screenPool()->connector(scrid);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_nextScreensGroup = Latte::Types::SingleScreenGroup;
|
||||
}
|
||||
|
||||
//! SCREEN
|
||||
if (!screenName.isEmpty()) {
|
||||
bool nextonprimary = (screenName == Latte::Data::Screen::ONPRIMARYNAME);
|
||||
@ -1166,7 +1213,7 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
|
||||
|| (!m_view->onPrimary() && nextonprimary) /*explicit -> primary*/
|
||||
|| (!m_view->onPrimary() && !nextonprimary && screenName != currentScreenName()) ) { /*explicit -> new_explicit*/
|
||||
|
||||
QString nextscreenname = nextonprimary ? qGuiApp->primaryScreen()->name() : screenName;
|
||||
QString nextscreenname = nextonprimary ? m_corona->screenPool()->primaryScreen()->name() : screenName;
|
||||
|
||||
if (currentScreenName() == nextscreenname) {
|
||||
m_view->setOnPrimary(nextonprimary);
|
||||
@ -1194,6 +1241,11 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
|
||||
haschanges = true;
|
||||
}
|
||||
|
||||
if (haschanges && m_view->isOriginal()) {
|
||||
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
|
||||
originalview->setNextLocationForClones(layoutName, edge, alignment);
|
||||
}
|
||||
|
||||
m_repositionIsAnimated = isanimated;
|
||||
m_repositionFromViewSettingsWindow = m_view->settingsWindowIsShown();
|
||||
|
||||
|
@ -40,6 +40,7 @@ class Positioner: public QObject
|
||||
Q_PROPERTY(bool inRelocationShowing READ inRelocationShowing WRITE setInRelocationShowing NOTIFY inRelocationShowingChanged)
|
||||
Q_PROPERTY(bool inSlideAnimation READ inSlideAnimation WRITE setInSlideAnimation NOTIFY inSlideAnimationChanged)
|
||||
|
||||
Q_PROPERTY(bool isOffScreen READ isOffScreen NOTIFY isOffScreenChanged)
|
||||
Q_PROPERTY(bool isStickedOnTopEdge READ isStickedOnTopEdge WRITE setIsStickedOnTopEdge NOTIFY isStickedOnTopEdgeChanged)
|
||||
Q_PROPERTY(bool isStickedOnBottomEdge READ isStickedOnBottomEdge WRITE setIsStickedOnBottomEdge NOTIFY isStickedOnBottomEdgeChanged)
|
||||
|
||||
@ -90,7 +91,7 @@ public:
|
||||
Latte::WindowSystem::WindowId trackedWindowId();
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE void setNextLocation(const QString layoutName, const QString screenId, int edge, int alignment);
|
||||
Q_INVOKABLE void setNextLocation(const QString layoutName, const int screensGroup, QString screenName, int edge, int alignment);
|
||||
Q_INVOKABLE void slideInDuringStartup();
|
||||
|
||||
void syncGeometry();
|
||||
@ -126,6 +127,7 @@ signals:
|
||||
void inRelocationAnimationChanged();
|
||||
void inRelocationShowingChanged();
|
||||
void inSlideAnimationChanged();
|
||||
void isOffScreenChanged();
|
||||
void isStickedOnTopEdgeChanged();
|
||||
void isStickedOnBottomEdgeChanged();
|
||||
|
||||
@ -155,7 +157,7 @@ private:
|
||||
|
||||
bool isLastHidingRelocationEvent() const;
|
||||
|
||||
QRect maximumNormalGeometry();
|
||||
QRect maximumNormalGeometry(QRect screenGeometry = QRect());
|
||||
|
||||
WindowSystem::AbstractWindowInterface::Slide slideLocation(Plasma::Types::Location location);
|
||||
|
||||
@ -193,6 +195,7 @@ private:
|
||||
bool m_repositionIsAnimated{false};
|
||||
|
||||
QString m_nextLayoutName;
|
||||
Latte::Types::ScreensGroup m_nextScreensGroup{Latte::Types::SingleScreenGroup};
|
||||
QString m_nextScreenName;
|
||||
QScreen *m_nextScreen{nullptr};
|
||||
Plasma::Types::Location m_nextScreenEdge{Plasma::Types::Floating};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user