diff --git a/files/assets/images/watermark.png b/files/assets/images/watermark.png
index a7d29ed..f629108 100644
Binary files a/files/assets/images/watermark.png and b/files/assets/images/watermark.png differ
diff --git a/files/assets/splash/default-dark.jxl b/files/assets/splash/default-dark.jxl
index ae66f3e..e0411ad 100644
Binary files a/files/assets/splash/default-dark.jxl and b/files/assets/splash/default-dark.jxl differ
diff --git a/files/assets/splash/default.jxl b/files/assets/splash/default.jxl
index ae66f3e..e0411ad 100644
Binary files a/files/assets/splash/default.jxl and b/files/assets/splash/default.jxl differ
diff --git a/files/assets/wallpapers/jumping-jax--TfwQjOWEp8-unsplash.jpg b/files/assets/wallpapers/Miasma-Audio.jpg
similarity index 100%
rename from files/assets/wallpapers/jumping-jax--TfwQjOWEp8-unsplash.jpg
rename to files/assets/wallpapers/Miasma-Audio.jpg
diff --git a/files/assets/wallpapers/Miasma-Blue-Purple.jpg b/files/assets/wallpapers/Miasma-Blue-Purple.jpg
new file mode 100644
index 0000000..03f66fd
Binary files /dev/null and b/files/assets/wallpapers/Miasma-Blue-Purple.jpg differ
diff --git a/files/assets/wallpapers/blueredwave.jpg b/files/assets/wallpapers/Miasma-Blueredwave.jpg
similarity index 100%
rename from files/assets/wallpapers/blueredwave.jpg
rename to files/assets/wallpapers/Miasma-Blueredwave.jpg
diff --git a/files/assets/wallpapers/yassine-ait-tahit-uBqd-tGQI8o-unsplash.jpg b/files/assets/wallpapers/Miasma-Light.jpg
similarity index 100%
rename from files/assets/wallpapers/yassine-ait-tahit-uBqd-tGQI8o-unsplash.jpg
rename to files/assets/wallpapers/Miasma-Light.jpg
diff --git a/files/assets/wallpapers/boliviainteligente-1f5tMsTQGD8-unsplash.jpg b/files/assets/wallpapers/Miasma-Lines.jpg
similarity index 100%
rename from files/assets/wallpapers/boliviainteligente-1f5tMsTQGD8-unsplash.jpg
rename to files/assets/wallpapers/Miasma-Lines.jpg
diff --git a/files/assets/wallpapers/dmitry-dreyer-O_7jOtM_Hg0-unsplash.jpg b/files/assets/wallpapers/Miasma-Purple.jpg
similarity index 100%
rename from files/assets/wallpapers/dmitry-dreyer-O_7jOtM_Hg0-unsplash.jpg
rename to files/assets/wallpapers/Miasma-Purple.jpg
diff --git a/files/assets/wallpapers/blackwave.jpg b/files/assets/wallpapers/blackwave.jpg
deleted file mode 100644
index 5faa5d3..0000000
Binary files a/files/assets/wallpapers/blackwave.jpg and /dev/null differ
diff --git a/files/assets/wallpapers/bluewave.jpg b/files/assets/wallpapers/bluewave.jpg
deleted file mode 100644
index 67dadcf..0000000
Binary files a/files/assets/wallpapers/bluewave.jpg and /dev/null differ
diff --git a/files/assets/wallpapers/default.jpg b/files/assets/wallpapers/default.jpg
deleted file mode 100644
index 651ae67..0000000
Binary files a/files/assets/wallpapers/default.jpg and /dev/null differ
diff --git a/files/assets/wallpapers/dima-solomin-4fLZjleexow-unsplash.jpg b/files/assets/wallpapers/dima-solomin-4fLZjleexow-unsplash.jpg
deleted file mode 100644
index 5f81e4a..0000000
Binary files a/files/assets/wallpapers/dima-solomin-4fLZjleexow-unsplash.jpg and /dev/null differ
diff --git a/files/assets/wallpapers/martin-martz-JfwQ36wG7Uo-unsplash.jpg b/files/assets/wallpapers/martin-martz-JfwQ36wG7Uo-unsplash.jpg
deleted file mode 100644
index 490db04..0000000
Binary files a/files/assets/wallpapers/martin-martz-JfwQ36wG7Uo-unsplash.jpg and /dev/null differ
diff --git a/files/system/usr/etc/xdg/plasma-org.kde.plasma.desktop-appletsrc b/files/system/usr/etc/xdg/plasma-org.kde.plasma.desktop-appletsrc
index 4ee3123..e73aeba 100644
--- a/files/system/usr/etc/xdg/plasma-org.kde.plasma.desktop-appletsrc
+++ b/files/system/usr/etc/xdg/plasma-org.kde.plasma.desktop-appletsrc
@@ -5,4 +5,4 @@ Free=1,2
Container=1
[Applets][1][Configuration][General]
-Image=file:///usr/share/wallpapers/miasma/dmitry-dreyer-O_7jOtM_Hg0-unsplash.jpg
+Image=file:///usr/share/wallpapers/miasma/Miasma-Blue-Purple.jpg
diff --git a/files/system/usr/share/plasma/desktoptheme/Vapor/colors b/files/system/usr/share/plasma/desktoptheme/Vapor/colors
new file mode 100644
index 0000000..673d46a
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/Vapor/colors
@@ -0,0 +1,147 @@
+[ColorEffects:Disabled]
+Color=56,56,56
+ColorAmount=0
+ColorEffect=0
+ContrastAmount=0.65
+ContrastEffect=1
+IntensityAmount=0.1
+IntensityEffect=2
+
+[ColorEffects:Inactive]
+ChangeSelectionColor=true
+Color=112,111,110
+ColorAmount=0.025
+ColorEffect=2
+ContrastAmount=0.1
+ContrastEffect=2
+Enable=false
+IntensityAmount=0
+IntensityEffect=0
+
+[Colors:Button]
+BackgroundAlternate=77,77,77
+BackgroundNormal=36,39,44
+DecorationFocus=52,108,146
+DecorationHover=85,161,205
+ForegroundActive=61,174,233
+ForegroundInactive=189,195,199
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=199,130,61
+ForegroundNormal=239,240,241
+ForegroundPositive=126,166,75
+ForegroundVisited=127,140,141
+
+[Colors:Complementary]
+BackgroundAlternate=59,64,69
+BackgroundNormal=49,54,59
+DecorationFocus=30,146,255
+DecorationHover=61,174,230
+ForegroundActive=246,116,0
+ForegroundInactive=175,176,179
+ForegroundLink=61,174,230
+ForegroundNegative=237,21,21
+ForegroundNeutral=201,206,59
+ForegroundNormal=239,240,241
+ForegroundPositive=17,209,22
+ForegroundVisited=61,174,230
+
+[Colors:Selection]
+BackgroundAlternate=29,153,243
+BackgroundNormal=86,159,204
+DecorationFocus=52,108,146
+DecorationHover=85,161,205
+ForegroundActive=252,252,252
+ForegroundInactive=239,240,241
+ForegroundLink=253,188,75
+ForegroundNegative=218,68,83
+ForegroundNeutral=199,130,61
+ForegroundNormal=31,31,38
+ForegroundPositive=126,166,75
+ForegroundVisited=189,195,199
+
+[Colors:Tooltip]
+BackgroundAlternate=77,77,77
+BackgroundNormal=36,39,44
+DecorationFocus=52,108,146
+DecorationHover=85,161,205
+ForegroundActive=61,174,233
+ForegroundInactive=189,195,199
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=199,130,61
+ForegroundNormal=239,240,241
+ForegroundPositive=126,166,75
+ForegroundVisited=127,140,141
+
+[Colors:View]
+BackgroundAlternate=26,33,42
+BackgroundNormal=21,28,35
+DecorationFocus=52,108,146
+DecorationHover=85,161,205
+ForegroundActive=61,174,233
+ForegroundInactive=189,195,199
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=199,130,61
+ForegroundNormal=239,240,241
+ForegroundPositive=126,166,75
+ForegroundVisited=127,140,141
+
+[Colors:Window]
+BackgroundAlternate=77,77,77
+BackgroundNormal=36,39,44
+DecorationFocus=52,108,146
+DecorationHover=85,161,205
+ForegroundActive=61,174,233
+ForegroundInactive=189,195,199
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=199,130,61
+ForegroundNormal=241,241,242
+ForegroundPositive=126,166,75
+ForegroundVisited=127,140,141
+
+[Colors:Header]
+BackgroundAlternate=77,77,77
+BackgroundNormal=36,39,44
+DecorationFocus=52,108,146
+DecorationHover=85,161,205
+ForegroundActive=61,174,233
+ForegroundInactive=189,195,199
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=199,130,61
+ForegroundNormal=241,241,242
+ForegroundPositive=126,166,75
+ForegroundVisited=127,140,141
+
+[Colors:Header][Inactive]
+BackgroundAlternate=77,77,77
+BackgroundNormal=36,39,44
+DecorationFocus=52,108,146
+DecorationHover=85,161,205
+ForegroundActive=61,174,233
+ForegroundInactive=189,195,199
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=199,130,61
+ForegroundNormal=241,241,242
+ForegroundPositive=126,166,75
+ForegroundVisited=127,140,141
+
+[General]
+ColorScheme=Vapor
+Name=Vapor
+shadeSortColumn=true
+
+[KDE]
+contrast=4
+
+[WM]
+activeBackground=36,39,47
+activeBlend=255,255,255
+activeForeground=239,240,241
+inactiveBackground=36,39,44
+inactiveBlend=74,83,101
+inactiveForeground=127,140,141
diff --git a/files/system/usr/share/plasma/desktoptheme/Vapor/metadata.desktop b/files/system/usr/share/plasma/desktoptheme/Vapor/metadata.desktop
new file mode 100644
index 0000000..56286ab
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/Vapor/metadata.desktop
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Comment=Vapor - SteamOS Theme based on KDE Breeze and Breath
+Name=Vapor
+X-KDE-PluginInfo-Author=Valve
+X-KDE-PluginInfo-Category=Plasma Theme
+X-KDE-PluginInfo-Email=
+X-KDE-PluginInfo-EnabledByDefault=true
+X-KDE-PluginInfo-License=GPL version 3
+X-KDE-PluginInfo-Name=Vapor
+X-KDE-PluginInfo-Version=0.0.17
+X-KDE-PluginInfo-Website=
+X-Plasma-API=5.0
+
+[Wallpaper]
+defaultFileSuffix=.png
+defaultHeight=1080
+defaultWallpaperTheme=Vapor
+defaultWidth=1920
diff --git a/files/system/usr/share/plasma/desktoptheme/Vapor/plasmarc b/files/system/usr/share/plasma/desktoptheme/Vapor/plasmarc
new file mode 100644
index 0000000..28ccfae
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/Vapor/plasmarc
@@ -0,0 +1,2 @@
+[AdaptiveTransparency]
+enabled=true
diff --git a/files/system/usr/share/plasma/desktoptheme/Vapor/widgets/plasmoidheading.svg b/files/system/usr/share/plasma/desktoptheme/Vapor/widgets/plasmoidheading.svg
new file mode 100644
index 0000000..4d92847
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/Vapor/widgets/plasmoidheading.svg
@@ -0,0 +1,71 @@
+
+
diff --git a/files/system/usr/share/plasma/desktoptheme/breeze-dark/colors b/files/system/usr/share/plasma/desktoptheme/breeze-dark/colors
new file mode 100644
index 0000000..2c818ea
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/breeze-dark/colors
@@ -0,0 +1,123 @@
+[ColorEffects:Disabled]
+Color=56,56,56
+ColorAmount=0
+ColorEffect=0
+ContrastAmount=0.65
+ContrastEffect=1
+IntensityAmount=0.1
+IntensityEffect=2
+
+[ColorEffects:Inactive]
+ChangeSelectionColor=true
+Color=112,111,110
+ColorAmount=0.025
+ColorEffect=2
+ContrastAmount=0.1
+ContrastEffect=2
+Enable=false
+IntensityAmount=0
+IntensityEffect=0
+
+[Colors:Button]
+BackgroundAlternate=30,87,116
+BackgroundNormal=41,44,48
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Complementary]
+BackgroundAlternate=30,87,116
+BackgroundNormal=32,35,38
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Header]
+BackgroundAlternate=32,35,38
+BackgroundNormal=41,44,48
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Header][Inactive]
+BackgroundAlternate=41,44,48
+BackgroundNormal=32,35,38
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Selection]
+BackgroundAlternate=30,87,116
+ForegroundActive=252,252,252
+ForegroundInactive=161,169,177
+ForegroundLink=253,188,75
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Tooltip]
+BackgroundAlternate=32,35,38
+BackgroundNormal=41,44,48
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:View]
+BackgroundAlternate=29,31,34
+BackgroundNormal=20,22,24
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Window]
+BackgroundAlternate=41,44,48
+BackgroundNormal=32,35,38
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[General]
+ColorScheme=Breeze Dark
+Name=Breeze Dark
+shadeSortColumn=true
+
+[KDE]
+contrast=4
+
+[WM]
+activeBackground=39,44,49
+activeBlend=252,252,252
+activeForeground=252,252,252
+inactiveBackground=32,36,40
+inactiveBlend=161,169,177
+inactiveForeground=161,169,177
diff --git a/files/system/usr/share/plasma/desktoptheme/breeze-dark/metadata.json b/files/system/usr/share/plasma/desktoptheme/breeze-dark/metadata.json
new file mode 100644
index 0000000..6b0f39a
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/breeze-dark/metadata.json
@@ -0,0 +1,157 @@
+{
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "kde-artists@kde.org",
+ "Name": "KDE Visual Design Group",
+ "Name[ar]": "مجموعة التصميم المرئي لكِيدِي",
+ "Name[az]": "KDE Vizual Dizayn Qrupu",
+ "Name[be]": "Суполка візуальнага дызайну KDE",
+ "Name[bg]": "KDE Visual Design Group",
+ "Name[ca@valencia]": "Grup de disseny visual de KDE",
+ "Name[ca]": "Grup de disseny visual de KDE",
+ "Name[cs]": "Skupina vizuálního návrhu KDE",
+ "Name[da]": "KDE visuelle designgruppe",
+ "Name[de]": "KDE Visual Design Group",
+ "Name[el]": "Ομάδα οπτικού σχεδιασμού KDE",
+ "Name[en_GB]": "KDE Visual Design Group",
+ "Name[eo]": "KDE Vida Dezajna Grupo",
+ "Name[es]": "El grupo de diseño visual de KDE",
+ "Name[eu]": "KDE Diseinu bisualeko taldea",
+ "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä",
+ "Name[fr]": "Groupe de conception graphique de KDE « VDG » (Visual Design Group)",
+ "Name[gl]": "Grupo de deseño visual de KDE",
+ "Name[he]": "קבוצת העיצוב החזותי של KDE",
+ "Name[hi]": "केडीई विज़ुअल डिज़ाइन समूह",
+ "Name[hu]": "KDE Visual Design Group",
+ "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)",
+ "Name[id]": "Grup Desain Visual KDE",
+ "Name[is]": "Myndrænn hönnunarhópur KDE",
+ "Name[it]": "KDE Visual Design Group",
+ "Name[ka]": "KDE Visual Design Group",
+ "Name[ko]": "KDE 시각 디자인 그룹",
+ "Name[lt]": "KDE vaizdinio dizaino grupė",
+ "Name[lv]": "KDE Vizuālā dizaina grupa",
+ "Name[nb]": "KDE Visual Design Group",
+ "Name[nl]": "KDE Visuele ontwerpgroep",
+ "Name[nn]": "KDE Visual Design Group",
+ "Name[pl]": "Grupa oprawy graficznej KDE",
+ "Name[pt]": "Grupo de Desenho Visual do KDE",
+ "Name[pt_BR]": "Grupo de design visual do KDE (KDE VDG)",
+ "Name[ro]": "KDE Visual Design Group",
+ "Name[ru]": "Группа KDE Visual Design",
+ "Name[sa]": "KDE Visual Design Group",
+ "Name[sk]": "KDE Visual Design Group",
+ "Name[sl]": "Skupina vizualnega designa KDE",
+ "Name[sv]": "KDE:s visuella designgrupp",
+ "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு",
+ "Name[tr]": "KDE Görsel Tasarım Grubu",
+ "Name[uk]": "Група з візуального дизайну KDE",
+ "Name[vi]": "Đội Thiết kế Trực quan KDE",
+ "Name[zh_CN]": "KDE 视觉设计团队",
+ "Name[zh_TW]": "KDE VDG 視覺設計組"
+ }
+ ],
+ "Category": "",
+ "Description": "Breeze Dark by the KDE VDG",
+ "Description[ar]": "نسيم داكن من من مجموعة تصميم كِيدِي",
+ "Description[az]": "KDE VDG tərəfindən Breeze Qara",
+ "Description[be]": "Breeze Dark ад KDE VDG",
+ "Description[bg]": "Breeze Тъмен от KDE VDG",
+ "Description[ca@valencia]": "Brisa fosca, creat pel VDG de KDE",
+ "Description[ca]": "Brisa fosca, creat pel VDG del KDE",
+ "Description[cs]": "Breeze Dark od KDE VDG",
+ "Description[da]": "Breeze Mørk af KDE's visuelle designgruppe",
+ "Description[de]": "Breeze Dunkel von der KDE VDG",
+ "Description[el]": "Breeze σκοτεινό από το KDE VDG",
+ "Description[en_GB]": "Breeze Dark by the KDE VDG",
+ "Description[eo]": "Breeze Dark de la KDE VDG",
+ "Description[es]": "Brisa oscuro, por KDE VDG",
+ "Description[eu]": "Brisa iluna KDEren VDGk egina",
+ "Description[fi]": "Tumma Breeze KDE VDG:ltä",
+ "Description[fr]": "Breeze sombre par l'équipe « KDE VDG »",
+ "Description[gl]": "Brisa escura do KDE VDG.",
+ "Description[he]": "בריזה כהה מאת קבוצת העיצוב החזותי של KDE",
+ "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़ डार्क",
+ "Description[hu]": "Breeze Dark a KDE VDG-től",
+ "Description[ia]": "Breeze Dark (Brisa Obscure) per le KDE VDG",
+ "Description[id]": "Breeze Gelap oleh KDE VDG",
+ "Description[is]": "Breeze Dark frá KDE VDG",
+ "Description[it]": "Brezza scuro a cura del KDE VDG",
+ "Description[ka]": "Breeze Dark \"KDE VDG\"-სგან",
+ "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 어두운 Breeze",
+ "Description[lt]": "Breeze tamsus pagal KDE VDG",
+ "Description[lv]": "KDE VDG veidotā „Breeze Dark“",
+ "Description[nb]": "Breeze mørk fra KDE VDG",
+ "Description[nl]": "Breeze Dark door de KDE VDG",
+ "Description[nn]": "Breeze mørk frå KDE VDG",
+ "Description[pl]": "Ciemna Bryza autorstwa KDE VDG",
+ "Description[pt]": "Brisa Escuro da VDG do KDE",
+ "Description[pt_BR]": "Breeze pelo KDE VDG",
+ "Description[ro]": "Briză, întunecat, de KDE VDG",
+ "Description[ru]": "Тёмный вариант Breeze от KDE VDG",
+ "Description[sa]": "KDE VDG द्वारा Breeze Dark",
+ "Description[sk]": "Vánok Tmavý od KDE VDG",
+ "Description[sl]": "Temna sapica od KDE VDG",
+ "Description[sv]": "Breeze mörk av KDE:s visuella designgrupp",
+ "Description[ta]": "கே.டீ.யீ. VDG வழங்கும் கரும் பிரீஸ்",
+ "Description[tr]": "KDE VDG’den Esinti Koyu",
+ "Description[uk]": "Темна Breeze, автори — KDE VDG",
+ "Description[vi]": "Breeze Tối, do KDE VDG",
+ "Description[zh_CN]": "Breeze 微风深色主题,由 KDE VDG (视觉设计团队) 设计制作",
+ "Description[zh_TW]": "由 KDE VDG 設計的 Breeze Dark",
+ "EnabledByDefault": true,
+ "Id": "breeze-dark",
+ "License": "LGPL",
+ "Name": "Breeze Dark",
+ "Name[ar]": "نسيم داكن",
+ "Name[az]": "Breeze Qara",
+ "Name[be]": "Breeze Dark",
+ "Name[bg]": "Breeze Тъмен",
+ "Name[ca@valencia]": "Brisa fosca",
+ "Name[ca]": "Brisa fosca",
+ "Name[cs]": "Breeze Tmavé",
+ "Name[da]": "Breeze Mørk",
+ "Name[de]": "Breeze Dunkel",
+ "Name[el]": "Breeze σκοτεινό",
+ "Name[en_GB]": "Breeze Dark",
+ "Name[eo]": "Vento Malhela",
+ "Name[es]": "Brisa oscuro",
+ "Name[eu]": "Brisa iluna",
+ "Name[fi]": "Tumma Breeze",
+ "Name[fr]": "Breeze Sombre",
+ "Name[gl]": "Brisa escura",
+ "Name[he]": "בריזה כהה",
+ "Name[hi]": "ब्रीज़ डार्क",
+ "Name[hu]": "Breeze Dark",
+ "Name[ia]": "Brisa obscure",
+ "Name[id]": "Breeze Gelap",
+ "Name[is]": "Breeze Dark",
+ "Name[it]": "Brezza scuro",
+ "Name[ka]": "Breeze Dark",
+ "Name[ko]": "어두운 Breeze",
+ "Name[lt]": "Breeze tamsus",
+ "Name[lv]": "Breeze Dark",
+ "Name[nb]": "Breeze mørk",
+ "Name[nl]": "Breeze Dark",
+ "Name[nn]": "Breeze mørk",
+ "Name[pl]": "Ciemna Bryza",
+ "Name[pt]": "Brisa Escura",
+ "Name[pt_BR]": "Breeze Dark",
+ "Name[ro]": "Briză, întunecat",
+ "Name[ru]": "Breeze, тёмный вариант",
+ "Name[sa]": "Breeze Dark",
+ "Name[sk]": "Vánok Tmavý",
+ "Name[sl]": "Temna sapica",
+ "Name[sv]": "Breeze mörk",
+ "Name[ta]": "கரும் பிரீஸ்",
+ "Name[tr]": "Esinti Koyu",
+ "Name[uk]": "Темна Breeze",
+ "Name[vi]": "Breeze Tối",
+ "Name[zh_CN]": "Breeze 微风深色",
+ "Name[zh_TW]": "Breeze Dark",
+ "Version": "6.22.0",
+ "Website": "https://www.kde.org/"
+ },
+ "X-Plasma-API": "5.0"
+}
diff --git a/files/system/usr/share/plasma/desktoptheme/breeze-dark/plasmarc b/files/system/usr/share/plasma/desktoptheme/breeze-dark/plasmarc
new file mode 100644
index 0000000..d375649
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/breeze-dark/plasmarc
@@ -0,0 +1,13 @@
+[Wallpaper]
+defaultWallpaperTheme=Next
+defaultFileSuffix=.png
+defaultWidth=1920
+defaultHeight=1080
+
+[ContrastEffect]
+enabled=true
+contrast=1.0
+saturation=1.5
+
+[AdaptiveTransparency]
+enabled=true
diff --git a/files/system/usr/share/plasma/desktoptheme/breeze-light/colors b/files/system/usr/share/plasma/desktoptheme/breeze-light/colors
new file mode 100644
index 0000000..b6f24e3
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/breeze-light/colors
@@ -0,0 +1,122 @@
+[ColorEffects:Disabled]
+Color=56,56,56
+ColorAmount=0
+ColorEffect=0
+ContrastAmount=0.65
+ContrastEffect=1
+IntensityAmount=0.1
+IntensityEffect=2
+
+[ColorEffects:Inactive]
+ChangeSelectionColor=true
+Color=112,111,110
+ColorAmount=0.025
+ColorEffect=2
+ContrastAmount=0.1
+ContrastEffect=2
+Enable=false
+IntensityAmount=0
+IntensityEffect=0
+
+[Colors:Button]
+BackgroundAlternate=163,212,250
+BackgroundNormal=247,247,247
+ForegroundInactive=112,125,138
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=35,38,41
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Complementary]
+BackgroundAlternate=27,30,32
+BackgroundNormal=42,46,50
+ForegroundInactive=161,169,177
+ForegroundLink=29,153,243
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=252,252,252
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Header]
+BackgroundAlternate=239,240,241
+BackgroundNormal=222,224,226
+ForegroundInactive=112,125,138
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=35,38,41
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Header][Inactive]
+BackgroundAlternate=227,229,231
+BackgroundNormal=239,240,241
+ForegroundInactive=112,125,138
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=35,38,41
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Selection]
+BackgroundAlternate=163,212,250
+ForegroundInactive=112,125,138
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=255,255,255
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Tooltip]
+BackgroundAlternate=239,240,241
+BackgroundNormal=247,247,247
+ForegroundInactive=112,125,138
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=35,38,41
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:View]
+BackgroundAlternate=247,247,247
+BackgroundNormal=255,255,255
+ForegroundInactive=112,125,138
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=35,38,41
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[Colors:Window]
+BackgroundAlternate=227,229,231
+BackgroundNormal=239,240,241
+ForegroundInactive=112,125,138
+ForegroundLink=41,128,185
+ForegroundNegative=218,68,83
+ForegroundNeutral=246,116,0
+ForegroundNormal=35,38,41
+ForegroundPositive=39,174,96
+ForegroundVisited=155,89,182
+
+[General]
+ColorScheme=Breeze Light
+Name=Breeze Light
+shadeSortColumn=true
+
+[KDE]
+contrast=4
+
+[WM]
+activeBackground=227,229,231
+activeBlend=227,229,231
+activeForeground=35,38,41
+inactiveBackground=239,240,241
+inactiveBlend=239,240,241
+inactiveForeground=112,125,138
diff --git a/files/system/usr/share/plasma/desktoptheme/breeze-light/metadata.json b/files/system/usr/share/plasma/desktoptheme/breeze-light/metadata.json
new file mode 100644
index 0000000..8730075
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/breeze-light/metadata.json
@@ -0,0 +1,157 @@
+{
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "kde-artists@kde.org",
+ "Name": "KDE Visual Design Group",
+ "Name[ar]": "مجموعة التصميم المرئي لكِيدِي",
+ "Name[az]": "KDE Vizual Dizayn Qrupu",
+ "Name[be]": "Суполка візуальнага дызайну KDE",
+ "Name[bg]": "KDE Visual Design Group",
+ "Name[ca@valencia]": "Grup de disseny visual de KDE",
+ "Name[ca]": "Grup de disseny visual de KDE",
+ "Name[cs]": "Skupina vizuálního návrhu KDE",
+ "Name[da]": "KDE visuelle designgruppe",
+ "Name[de]": "KDE Visual Design Group",
+ "Name[el]": "Ομάδα οπτικού σχεδιασμού KDE",
+ "Name[en_GB]": "KDE Visual Design Group",
+ "Name[eo]": "KDE Vida Dezajna Grupo",
+ "Name[es]": "El grupo de diseño visual de KDE",
+ "Name[eu]": "KDE Diseinu bisualeko taldea",
+ "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä",
+ "Name[fr]": "Groupe de conception graphique de KDE « VDG » (Visual Design Group)",
+ "Name[gl]": "Grupo de deseño visual de KDE",
+ "Name[he]": "קבוצת העיצוב החזותי של KDE",
+ "Name[hi]": "केडीई विज़ुअल डिज़ाइन समूह",
+ "Name[hu]": "KDE Visual Design Group",
+ "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)",
+ "Name[id]": "Grup Desain Visual KDE",
+ "Name[is]": "Myndrænn hönnunarhópur KDE",
+ "Name[it]": "KDE Visual Design Group",
+ "Name[ka]": "KDE Visual Design Group",
+ "Name[ko]": "KDE 시각 디자인 그룹",
+ "Name[lt]": "KDE vaizdinio dizaino grupė",
+ "Name[lv]": "KDE Vizuālā dizaina grupa",
+ "Name[nb]": "KDE Visual Design Group",
+ "Name[nl]": "KDE Visuele ontwerpgroep",
+ "Name[nn]": "KDE Visual Design Group",
+ "Name[pl]": "Grupa oprawy graficznej KDE",
+ "Name[pt]": "Grupo de Desenho Visual do KDE",
+ "Name[pt_BR]": "Grupo de design visual do KDE (KDE VDG)",
+ "Name[ro]": "KDE Visual Design Group",
+ "Name[ru]": "Группа KDE Visual Design",
+ "Name[sa]": "KDE Visual Design Group",
+ "Name[sk]": "KDE Visual Design Group",
+ "Name[sl]": "Skupina vizualnega designa KDE",
+ "Name[sv]": "KDE:s visuella designgrupp",
+ "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு",
+ "Name[tr]": "KDE Görsel Tasarım Grubu",
+ "Name[uk]": "Група з візуального дизайну KDE",
+ "Name[vi]": "Đội Thiết kế Trực quan KDE",
+ "Name[zh_CN]": "KDE 视觉设计团队",
+ "Name[zh_TW]": "KDE VDG 視覺設計組"
+ }
+ ],
+ "Category": "",
+ "Description": "Breeze Light by the KDE VDG",
+ "Description[ar]": "نسيم فاتح من مجموعة تصميم كِيدِي",
+ "Description[az]": "Breeze -İşıqlı - KDE VDG tərəfindən",
+ "Description[be]": "Breeze Light ад KDE VDG",
+ "Description[bg]": "Breeze Светъл от KDE VDG",
+ "Description[ca@valencia]": "Brisa clara, creat pel VDG de KDE",
+ "Description[ca]": "Brisa clara, creat pel VDG del KDE",
+ "Description[cs]": "Breeze Light od KDE VDG",
+ "Description[da]": "Breeze Lys af KDE's visuelle designgruppe",
+ "Description[de]": "Breeze Hell von der KDE VDG",
+ "Description[el]": "Breeze φωτεινό από το KDE VDG",
+ "Description[en_GB]": "Breeze Light by the KDE VDG",
+ "Description[eo]": "Breeze Light de la KDE VDG",
+ "Description[es]": "Brisa claro, por KDE VDG",
+ "Description[eu]": "Brisa argia, KDE VDGk egina",
+ "Description[fi]": "Vaalea Breeze KDE VDG:ltä",
+ "Description[fr]": "Breeze clair par l'équipe « KDE VDG »",
+ "Description[gl]": "Brisa clara do KDE VDG.",
+ "Description[he]": "בריזה בהירה מאת קבוצת העיצוב החזותי של KDE",
+ "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़ लाइट",
+ "Description[hu]": "Breeze Light a KDE VDG-től",
+ "Description[ia]": "Brisa Ligier per KDE VDG",
+ "Description[id]": "Breeze Terang oleh KDE VDG",
+ "Description[is]": "Breeze Light frá KDE VDG",
+ "Description[it]": "Brezza chiaro a cura del VDG di KDE",
+ "Description[ka]": "Breeze-ის ღია ვარიანტი, KDE VDG-სგან",
+ "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 밝은 Breeze",
+ "Description[lt]": "Breeze šviesus pagal KDE VDG",
+ "Description[lv]": "KDE VDG veidotā „Breeze Light“",
+ "Description[nb]": "Breeze lys fra KDE VDG",
+ "Description[nl]": "Breeze Light door de KDE VDG",
+ "Description[nn]": "Breeze skumring frå KDE VDG",
+ "Description[pl]": "Jasna Bryza autorstwa KDE VDG",
+ "Description[pt]": "Brisa Claro da VDG do KDE",
+ "Description[pt_BR]": "Breeze Light pelo KDE VDG",
+ "Description[ro]": "Briză, luminos, de KDE VDG",
+ "Description[ru]": "Светлый вариант Breeze от KDE VDG",
+ "Description[sa]": "KDE VDG द्वारा Breeze Light",
+ "Description[sk]": "Vánok Svetlý od KDE VDG",
+ "Description[sl]": "Svetla sapica od KDE VDG",
+ "Description[sv]": "Breeze ljus av KDE:s visuella designgrupp",
+ "Description[ta]": "கே.டீ.யீ. VDG வழங்கும் வெளிர் பிரீஸ்",
+ "Description[tr]": "KDE VDG’den Esinti Açık",
+ "Description[uk]": "Світла Breeze, автори — KDE VDG",
+ "Description[vi]": "Breeze Sáng, do KDE VDG",
+ "Description[zh_CN]": "Breeze 微风浅色主题,由 KDE VDG (视觉设计团队) 设计制作",
+ "Description[zh_TW]": "由 KDE VDG 製作的 Breeze Light",
+ "EnabledByDefault": true,
+ "Id": "default",
+ "License": "LGPL",
+ "Name": "Breeze Light",
+ "Name[ar]": "نسيم فاتح",
+ "Name[az]": "Breeze - İşıqlı",
+ "Name[be]": "Breeze Light",
+ "Name[bg]": "Breeze Светъл",
+ "Name[ca@valencia]": "Brisa clara",
+ "Name[ca]": "Brisa clara",
+ "Name[cs]": "Breeze Světlé",
+ "Name[da]": "Breeze Lys",
+ "Name[de]": "Breeze Hell",
+ "Name[el]": "Breeze φωτεινό",
+ "Name[en_GB]": "Breeze Light",
+ "Name[eo]": "Briza Lumo",
+ "Name[es]": "Brisa claro",
+ "Name[eu]": "Brisa argia",
+ "Name[fi]": "Vaalea Breeze",
+ "Name[fr]": "Breeze clair",
+ "Name[gl]": "Brisa clara",
+ "Name[he]": "בריזה בהירה",
+ "Name[hi]": "ब्रीज़ लाइट",
+ "Name[hu]": "Breeze Light",
+ "Name[ia]": "Brisa Ligier",
+ "Name[id]": "Breeze Terang",
+ "Name[is]": "Breeze Light",
+ "Name[it]": "Brezza chiaro",
+ "Name[ka]": "ნიავი ღია",
+ "Name[ko]": "밝은 Breeze",
+ "Name[lt]": "Breeze šviesus",
+ "Name[lv]": "Breeze Light",
+ "Name[nb]": "Breeze lys",
+ "Name[nl]": "Breeze Light",
+ "Name[nn]": "Breeze lys",
+ "Name[pl]": "Jasna Bryza",
+ "Name[pt]": "Brisa Clara",
+ "Name[pt_BR]": "Breeze Light",
+ "Name[ro]": "Briză, luminos",
+ "Name[ru]": "Breeze, светлый вариант",
+ "Name[sa]": "Breeze Light",
+ "Name[sk]": "Vánok Svetlý",
+ "Name[sl]": "Svetla sapica",
+ "Name[sv]": "Breeze ljus",
+ "Name[ta]": "வெளிர் பிரீஸ்",
+ "Name[tr]": "Esinti Açık",
+ "Name[uk]": "Світла Breeze",
+ "Name[vi]": "Breeze Sáng",
+ "Name[zh_CN]": "Breeze 微风浅色",
+ "Name[zh_TW]": "Breeze Light",
+ "Version": "6.22.0",
+ "Website": "https://www.kde.org/"
+ },
+ "X-Plasma-API": "5.0"
+}
diff --git a/files/system/usr/share/plasma/desktoptheme/breeze-light/plasmarc b/files/system/usr/share/plasma/desktoptheme/breeze-light/plasmarc
new file mode 100644
index 0000000..d375649
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/breeze-light/plasmarc
@@ -0,0 +1,13 @@
+[Wallpaper]
+defaultWallpaperTheme=Next
+defaultFileSuffix=.png
+defaultWidth=1920
+defaultHeight=1080
+
+[ContrastEffect]
+enabled=true
+contrast=1.0
+saturation=1.5
+
+[AdaptiveTransparency]
+enabled=true
diff --git a/files/system/usr/share/plasma/desktoptheme/default/dialogs/background.svgz b/files/system/usr/share/plasma/desktoptheme/default/dialogs/background.svgz
new file mode 100644
index 0000000..ab2a5a6
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/dialogs/background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/akonadi.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/akonadi.svgz
new file mode 100644
index 0000000..26e17e0
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/akonadi.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/akregator.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/akregator.svgz
new file mode 100644
index 0000000..2cc37e0
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/akregator.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/amarok.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/amarok.svgz
new file mode 100644
index 0000000..3ec39aa
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/amarok.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/applications.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/applications.svgz
new file mode 100644
index 0000000..6fd0675
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/applications.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/apport.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/apport.svgz
new file mode 100644
index 0000000..24753d6
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/apport.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/audio.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/audio.svgz
new file mode 100644
index 0000000..71f258f
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/audio.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/battery.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/battery.svgz
new file mode 100644
index 0000000..a222c4b
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/battery.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/bookmarks.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/bookmarks.svgz
new file mode 100644
index 0000000..ad95bd2
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/bookmarks.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/cantata.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/cantata.svgz
new file mode 100644
index 0000000..4a57f2a
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/cantata.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/computer.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/computer.svgz
new file mode 100644
index 0000000..281b9b4
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/computer.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/configure.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/configure.svgz
new file mode 100644
index 0000000..c74f3e0
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/configure.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/device.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/device.svgz
new file mode 100644
index 0000000..1993d02
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/device.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/disk.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/disk.svgz
new file mode 100644
index 0000000..2f018fa
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/disk.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/distribute.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/distribute.svgz
new file mode 100644
index 0000000..689eb8b
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/distribute.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/document.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/document.svgz
new file mode 100644
index 0000000..da3ef9f
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/document.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/drive.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/drive.svgz
new file mode 100644
index 0000000..448391e
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/drive.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/edit.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/edit.svgz
new file mode 100644
index 0000000..361e13f
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/edit.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/fcitx.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/fcitx.svgz
new file mode 100644
index 0000000..8e2f07a
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/fcitx.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/go.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/go.svgz
new file mode 100644
index 0000000..f473fc4
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/go.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/ime.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/ime.svgz
new file mode 100644
index 0000000..578c35c
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/ime.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/input.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/input.svgz
new file mode 100644
index 0000000..34931c5
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/input.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kalarm.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kalarm.svgz
new file mode 100644
index 0000000..bc1d5a0
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kalarm.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kdeconnect.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kdeconnect.svgz
new file mode 100644
index 0000000..ddfa196
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kdeconnect.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/keyboard.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/keyboard.svgz
new file mode 100644
index 0000000..c3ed2ff
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/keyboard.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kget.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kget.svgz
new file mode 100644
index 0000000..c737183
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kget.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kgpg.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kgpg.svgz
new file mode 100644
index 0000000..fd0588c
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kgpg.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kleopatra.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kleopatra.svgz
new file mode 100644
index 0000000..39835a3
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kleopatra.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/klipper.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/klipper.svgz
new file mode 100644
index 0000000..c331ae5
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/klipper.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kmail.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kmail.svgz
new file mode 100644
index 0000000..1ed8492
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kmail.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/konv_message.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/konv_message.svgz
new file mode 100644
index 0000000..47dd526
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/konv_message.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/konversation.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/konversation.svgz
new file mode 100644
index 0000000..70406c5
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/konversation.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kopete.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kopete.svgz
new file mode 100644
index 0000000..6d17fa8
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kopete.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/korgac.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/korgac.svgz
new file mode 100644
index 0000000..ca61a31
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/korgac.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kpackagekit.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kpackagekit.svgz
new file mode 100644
index 0000000..22e894f
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kpackagekit.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kruler.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kruler.svgz
new file mode 100644
index 0000000..d5d69d9
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kruler.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kteatime.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kteatime.svgz
new file mode 100644
index 0000000..b515c8b
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kteatime.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/ktorrent.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/ktorrent.svgz
new file mode 100644
index 0000000..0cef8ef
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/ktorrent.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/kup.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/kup.svgz
new file mode 100644
index 0000000..81a9efe
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/kup.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/list.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/list.svgz
new file mode 100644
index 0000000..182df73
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/list.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/mail.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/mail.svgz
new file mode 100644
index 0000000..0d88643
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/mail.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/media.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/media.svgz
new file mode 100644
index 0000000..d250075
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/media.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/mobile.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/mobile.svgz
new file mode 100644
index 0000000..e44ad0f
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/mobile.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/network.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/network.svgz
new file mode 100644
index 0000000..de5f314
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/network.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/notification.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/notification.svgz
new file mode 100644
index 0000000..85575de
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/notification.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/osd.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/osd.svgz
new file mode 100644
index 0000000..cd9e569
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/osd.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/phone.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/phone.svgz
new file mode 100644
index 0000000..4d1e65b
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/phone.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/plasmavault.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/plasmavault.svgz
new file mode 100644
index 0000000..61f5a32
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/plasmavault.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/plasmavault_error.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/plasmavault_error.svgz
new file mode 100644
index 0000000..43b9d7a
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/plasmavault_error.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/preferences.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/preferences.svgz
new file mode 100644
index 0000000..2ee1f7d
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/preferences.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/printer.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/printer.svgz
new file mode 100644
index 0000000..7c786be
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/printer.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/quassel.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/quassel.svgz
new file mode 100644
index 0000000..3d3b678
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/quassel.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/search.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/search.svgz
new file mode 100644
index 0000000..76a2444
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/search.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/slc.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/slc.svgz
new file mode 100644
index 0000000..0a8cb18
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/slc.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/software.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/software.svgz
new file mode 100644
index 0000000..3af4b67
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/software.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/start.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/start.svgz
new file mode 100644
index 0000000..c2865ac
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/start.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/system.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/system.svgz
new file mode 100644
index 0000000..847fadf
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/system.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/touchpad.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/touchpad.svgz
new file mode 100644
index 0000000..2116b82
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/touchpad.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/user.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/user.svgz
new file mode 100644
index 0000000..01dc29e
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/user.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/video-card.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/video-card.svgz
new file mode 100644
index 0000000..1931b38
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/video-card.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/video.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/video.svgz
new file mode 100644
index 0000000..941e55e
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/video.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/view.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/view.svgz
new file mode 100644
index 0000000..c9f1147
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/view.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/vlc.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/vlc.svgz
new file mode 100644
index 0000000..a2f6a6c
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/vlc.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/wallet.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/wallet.svgz
new file mode 100644
index 0000000..4a34c67
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/wallet.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/window.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/window.svgz
new file mode 100644
index 0000000..2a183ca
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/window.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/yakuake.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/yakuake.svgz
new file mode 100644
index 0000000..d432446
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/yakuake.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/icons/zoom.svgz b/files/system/usr/share/plasma/desktoptheme/default/icons/zoom.svgz
new file mode 100644
index 0000000..9c6346d
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/icons/zoom.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/metadata.json b/files/system/usr/share/plasma/desktoptheme/default/metadata.json
new file mode 100644
index 0000000..b4d8b49
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/default/metadata.json
@@ -0,0 +1,157 @@
+{
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "kde-artists@kde.org",
+ "Name": "KDE Visual Design Group",
+ "Name[ar]": "مجموعة التصميم المرئي لكِيدِي",
+ "Name[az]": "KDE Vizual Dizayn Qrupu",
+ "Name[be]": "Суполка візуальнага дызайну KDE",
+ "Name[bg]": "KDE Visual Design Group",
+ "Name[ca@valencia]": "Grup de disseny visual de KDE",
+ "Name[ca]": "Grup de disseny visual de KDE",
+ "Name[cs]": "Skupina vizuálního návrhu KDE",
+ "Name[da]": "KDE visuelle designgruppe",
+ "Name[de]": "KDE Visual Design Group",
+ "Name[el]": "Ομάδα οπτικού σχεδιασμού KDE",
+ "Name[en_GB]": "KDE Visual Design Group",
+ "Name[eo]": "KDE Vida Dezajna Grupo",
+ "Name[es]": "El grupo de diseño visual de KDE",
+ "Name[eu]": "KDE Diseinu bisualeko taldea",
+ "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä",
+ "Name[fr]": "Groupe de conception graphique de KDE « VDG » (Visual Design Group)",
+ "Name[gl]": "Grupo de deseño visual de KDE",
+ "Name[he]": "קבוצת העיצוב החזותי של KDE",
+ "Name[hi]": "केडीई विज़ुअल डिज़ाइन समूह",
+ "Name[hu]": "KDE Visual Design Group",
+ "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)",
+ "Name[id]": "Grup Desain Visual KDE",
+ "Name[is]": "Myndrænn hönnunarhópur KDE",
+ "Name[it]": "KDE Visual Design Group",
+ "Name[ka]": "KDE Visual Design Group",
+ "Name[ko]": "KDE 시각 디자인 그룹",
+ "Name[lt]": "KDE vaizdinio dizaino grupė",
+ "Name[lv]": "KDE Vizuālā dizaina grupa",
+ "Name[nb]": "KDE Visual Design Group",
+ "Name[nl]": "KDE Visuele ontwerpgroep",
+ "Name[nn]": "KDE Visual Design Group",
+ "Name[pl]": "Grupa oprawy graficznej KDE",
+ "Name[pt]": "Grupo de Desenho Visual do KDE",
+ "Name[pt_BR]": "Grupo de design visual do KDE (KDE VDG)",
+ "Name[ro]": "KDE Visual Design Group",
+ "Name[ru]": "Группа KDE Visual Design",
+ "Name[sa]": "KDE Visual Design Group",
+ "Name[sk]": "KDE Visual Design Group",
+ "Name[sl]": "Skupina vizualnega designa KDE",
+ "Name[sv]": "KDE:s visuella designgrupp",
+ "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு",
+ "Name[tr]": "KDE Görsel Tasarım Grubu",
+ "Name[uk]": "Група з візуального дизайну KDE",
+ "Name[vi]": "Đội Thiết kế Trực quan KDE",
+ "Name[zh_CN]": "KDE 视觉设计团队",
+ "Name[zh_TW]": "KDE VDG 視覺設計組"
+ }
+ ],
+ "Category": "",
+ "Description": "Breeze by the KDE VDG",
+ "Description[ar]": "نسيم من مجموعة تصميم كِيدِي",
+ "Description[az]": "KDE VDG tərəfindən Breeze İş mühiti görünüşü",
+ "Description[be]": "Breeze ад KDE VDG",
+ "Description[bg]": "Breeze от KDE VDG",
+ "Description[ca@valencia]": "Brisa, creat pel VDG de KDE",
+ "Description[ca]": "Brisa, creat pel VDG del KDE",
+ "Description[cs]": "Breeze od KDE VDG",
+ "Description[da]": "Breeze af KDE's visuelle designgruppe",
+ "Description[de]": "Breeze von der KDE VDG",
+ "Description[el]": "Breeze από το KDE VDG",
+ "Description[en_GB]": "Breeze by the KDE VDG",
+ "Description[eo]": "Brizo de la KDE VDG",
+ "Description[es]": "Brisa, por KDE VDG",
+ "Description[eu]": "Brisa KDEren VDGk egina",
+ "Description[fi]": "Breeze KDE VDG:ltä",
+ "Description[fr]": "Breeze par l'équipe « KDE VDG »",
+ "Description[gl]": "Brisa do KDE VDG.",
+ "Description[he]": "בריזה מאת קבוצת העיצוב החזותי של KDE",
+ "Description[hi]": "केडीई वीडीजी द्वारा हवा",
+ "Description[hu]": "Breeze a KDE VDG-től",
+ "Description[ia]": "Breeze (Brisa) per le KDE VDG",
+ "Description[id]": "Breeze oleh KDE VDG",
+ "Description[is]": "Breeze frá KDE VDG",
+ "Description[it]": "Brezza a cura del KDE VDG",
+ "Description[ka]": "Breeze KDE VDG-სგან",
+ "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 Breeze",
+ "Description[lt]": "Breeze pagal KDE VDG",
+ "Description[lv]": "KDE VDG veidotā „Breeze“",
+ "Description[nb]": "Breeze fra KDE VDG",
+ "Description[nl]": "Breeze door de KDE VDG",
+ "Description[nn]": "Breeze frå KDE VDG",
+ "Description[pl]": "Bryza autorstwa KDE VDG",
+ "Description[pt]": "Brisa da VDG do KDE",
+ "Description[pt_BR]": "Breeze pelo KDE VDG",
+ "Description[ro]": "Briză, de KDE VDG",
+ "Description[ru]": "Оформление рабочей среды Breeze от KDE VDG",
+ "Description[sa]": "KDE VDG द्वारा Breeze",
+ "Description[sk]": "Vánok od KDE VDG",
+ "Description[sl]": "Sapica od KDE VDG",
+ "Description[sv]": "Breeze av KDE:s visuella designgrupp",
+ "Description[ta]": "கே.டீ.யீ. VDG வழங்கும் பிரீஸ்",
+ "Description[tr]": "KDE VDG’den Esinti",
+ "Description[uk]": "Breeze, автори — KDE VDG",
+ "Description[vi]": "Breeze, do KDE VDG",
+ "Description[zh_CN]": "Breeze 微风主题,由 KDE VDG (视觉设计团队) 设计制作",
+ "Description[zh_TW]": "由 KDE VDG 設計的 Breeze",
+ "EnabledByDefault": true,
+ "Id": "default",
+ "License": "LGPL",
+ "Name": "Breeze",
+ "Name[ar]": "نسيم",
+ "Name[az]": "Breeze",
+ "Name[be]": "Breeze",
+ "Name[bg]": "Breeze",
+ "Name[ca@valencia]": "Brisa",
+ "Name[ca]": "Brisa",
+ "Name[cs]": "Breeze",
+ "Name[da]": "Breeze",
+ "Name[de]": "Breeze",
+ "Name[el]": "Breeze",
+ "Name[en_GB]": "Breeze",
+ "Name[eo]": "Vento",
+ "Name[es]": "Brisa",
+ "Name[eu]": "Brisa",
+ "Name[fi]": "Breeze",
+ "Name[fr]": "Breeze",
+ "Name[gl]": "Brisa",
+ "Name[he]": "בריזה",
+ "Name[hi]": "हवा",
+ "Name[hu]": "Breeze",
+ "Name[ia]": "Brisa",
+ "Name[id]": "Breeze",
+ "Name[is]": "Breeze",
+ "Name[it]": "Brezza",
+ "Name[ka]": "ნიავი",
+ "Name[ko]": "Breeze",
+ "Name[lt]": "Breeze",
+ "Name[lv]": "Breeze",
+ "Name[nb]": "Breeze",
+ "Name[nl]": "Breeze",
+ "Name[nn]": "Breeze",
+ "Name[pl]": "Bryza",
+ "Name[pt]": "Brisa",
+ "Name[pt_BR]": "Breeze",
+ "Name[ro]": "Briză",
+ "Name[ru]": "Breeze",
+ "Name[sa]": "Breeze",
+ "Name[sk]": "Vánok",
+ "Name[sl]": "Sapica",
+ "Name[sv]": "Breeze",
+ "Name[ta]": "பிரீஸ்",
+ "Name[tr]": "Esinti",
+ "Name[uk]": "Breeze",
+ "Name[vi]": "Breeze",
+ "Name[zh_CN]": "Breeze 微风",
+ "Name[zh_TW]": "Breeze",
+ "Version": "6.22.0",
+ "Website": "https://www.kde.org/"
+ },
+ "X-Plasma-API": "5.0"
+}
diff --git a/files/system/usr/share/plasma/desktoptheme/default/opaque/dialogs/background.svgz b/files/system/usr/share/plasma/desktoptheme/default/opaque/dialogs/background.svgz
new file mode 100644
index 0000000..95371eb
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/opaque/dialogs/background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/opaque/widgets/panel-background.svgz b/files/system/usr/share/plasma/desktoptheme/default/opaque/widgets/panel-background.svgz
new file mode 100644
index 0000000..bafa330
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/opaque/widgets/panel-background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/opaque/widgets/tooltip.svgz b/files/system/usr/share/plasma/desktoptheme/default/opaque/widgets/tooltip.svgz
new file mode 100644
index 0000000..088e11f
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/opaque/widgets/tooltip.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/plasmarc b/files/system/usr/share/plasma/desktoptheme/default/plasmarc
new file mode 100644
index 0000000..d375649
--- /dev/null
+++ b/files/system/usr/share/plasma/desktoptheme/default/plasmarc
@@ -0,0 +1,13 @@
+[Wallpaper]
+defaultWallpaperTheme=Next
+defaultFileSuffix=.png
+defaultWidth=1920
+defaultHeight=1080
+
+[ContrastEffect]
+enabled=true
+contrast=1.0
+saturation=1.5
+
+[AdaptiveTransparency]
+enabled=true
diff --git a/files/system/usr/share/plasma/desktoptheme/default/solid/dialogs/background.svgz b/files/system/usr/share/plasma/desktoptheme/default/solid/dialogs/background.svgz
new file mode 100644
index 0000000..b787c2c
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/solid/dialogs/background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/background.svgz b/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/background.svgz
new file mode 100644
index 0000000..2b6b4f8
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/panel-background.svgz b/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/panel-background.svgz
new file mode 100644
index 0000000..0f66937
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/panel-background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/tooltip.svgz b/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/tooltip.svgz
new file mode 100644
index 0000000..4713a1c
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/solid/widgets/tooltip.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/translucent/dialogs/background.svgz b/files/system/usr/share/plasma/desktoptheme/default/translucent/dialogs/background.svgz
new file mode 100644
index 0000000..cd725f1
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/translucent/dialogs/background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/background.svgz b/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/background.svgz
new file mode 100644
index 0000000..635ede7
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/panel-background.svgz b/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/panel-background.svgz
new file mode 100644
index 0000000..035b914
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/panel-background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/tooltip.svgz b/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/tooltip.svgz
new file mode 100644
index 0000000..4ec55be
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/translucent/widgets/tooltip.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/weather/wind-arrows.svgz b/files/system/usr/share/plasma/desktoptheme/default/weather/wind-arrows.svgz
new file mode 100644
index 0000000..666ec85
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/weather/wind-arrows.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/action-overlays.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/action-overlays.svgz
new file mode 100644
index 0000000..bc22be5
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/action-overlays.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/actionbutton.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/actionbutton.svgz
new file mode 100644
index 0000000..017d891
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/actionbutton.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/analog_meter.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/analog_meter.svgz
new file mode 100644
index 0000000..1576ca3
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/analog_meter.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/arrows.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/arrows.svgz
new file mode 100644
index 0000000..b1b2870
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/arrows.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/background.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/background.svgz
new file mode 100644
index 0000000..070096a
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/bar_meter_horizontal.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/bar_meter_horizontal.svgz
new file mode 100644
index 0000000..45b6185
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/bar_meter_horizontal.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/bar_meter_vertical.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/bar_meter_vertical.svgz
new file mode 100644
index 0000000..f77c80e
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/bar_meter_vertical.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/branding.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/branding.svgz
new file mode 100644
index 0000000..c06df31
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/branding.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/busywidget.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/busywidget.svgz
new file mode 100644
index 0000000..f603483
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/busywidget.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/button.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/button.svgz
new file mode 100644
index 0000000..eeef942
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/button.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/calendar.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/calendar.svgz
new file mode 100644
index 0000000..288d790
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/calendar.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/checkmarks.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/checkmarks.svgz
new file mode 100644
index 0000000..2b9a521
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/checkmarks.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/clock.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/clock.svgz
new file mode 100644
index 0000000..77425a8
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/clock.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/configuration-icons.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/configuration-icons.svgz
new file mode 100644
index 0000000..284dfff
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/configuration-icons.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/containment-controls.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/containment-controls.svgz
new file mode 100644
index 0000000..4981130
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/containment-controls.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/dragger.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/dragger.svgz
new file mode 100644
index 0000000..19d0ed6
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/dragger.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/frame.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/frame.svgz
new file mode 100644
index 0000000..304ffb6
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/frame.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/glowbar.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/glowbar.svgz
new file mode 100644
index 0000000..8a96d79
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/glowbar.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/line.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/line.svgz
new file mode 100644
index 0000000..dd6c8c6
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/line.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/lineedit.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/lineedit.svgz
new file mode 100644
index 0000000..8203370
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/lineedit.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/listitem.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/listitem.svgz
new file mode 100644
index 0000000..25eca3f
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/listitem.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/margins-highlight.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/margins-highlight.svgz
new file mode 100644
index 0000000..34503d0
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/margins-highlight.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/media-delegate.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/media-delegate.svgz
new file mode 100644
index 0000000..616f897
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/media-delegate.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/menubaritem.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/menubaritem.svgz
new file mode 100644
index 0000000..ae60c2b
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/menubaritem.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/monitor.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/monitor.svgz
new file mode 100644
index 0000000..21498e4
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/monitor.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/notes.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/notes.svgz
new file mode 100644
index 0000000..854f817
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/notes.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/pager.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/pager.svgz
new file mode 100644
index 0000000..b616c4d
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/pager.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/panel-background.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/panel-background.svgz
new file mode 100644
index 0000000..dd3268b
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/panel-background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/picker.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/picker.svgz
new file mode 100644
index 0000000..871e012
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/picker.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/plasmoidheading.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/plasmoidheading.svgz
new file mode 100644
index 0000000..0569a42
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/plasmoidheading.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/plot-background.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/plot-background.svgz
new file mode 100644
index 0000000..5195628
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/plot-background.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/radiobutton.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/radiobutton.svgz
new file mode 100644
index 0000000..c0477af
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/radiobutton.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/scrollbar.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/scrollbar.svgz
new file mode 100644
index 0000000..a55666d
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/scrollbar.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/scrollwidget.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/scrollwidget.svgz
new file mode 100644
index 0000000..ffc4f39
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/scrollwidget.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/slider.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/slider.svgz
new file mode 100644
index 0000000..08f2319
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/slider.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/switch.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/switch.svgz
new file mode 100644
index 0000000..98bdfb9
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/switch.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/tabbar.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/tabbar.svgz
new file mode 100644
index 0000000..7dbdd2b
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/tabbar.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/tasks.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/tasks.svgz
new file mode 100644
index 0000000..26d44ec
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/tasks.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/timer.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/timer.svgz
new file mode 100644
index 0000000..68c81c5
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/timer.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/toolbar.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/toolbar.svgz
new file mode 100644
index 0000000..eb8471c
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/toolbar.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/tooltip.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/tooltip.svgz
new file mode 100644
index 0000000..0a4ac7e
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/tooltip.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/translucentbackground.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/translucentbackground.svgz
new file mode 100644
index 0000000..d1ddfc4
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/translucentbackground.svgz differ
diff --git a/files/system/usr/share/plasma/desktoptheme/default/widgets/viewitem.svgz b/files/system/usr/share/plasma/desktoptheme/default/widgets/viewitem.svgz
new file mode 100644
index 0000000..c2e8d63
Binary files /dev/null and b/files/system/usr/share/plasma/desktoptheme/default/widgets/viewitem.svgz differ
diff --git a/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.appmenubar/contents/layout.js b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.appmenubar/contents/layout.js
new file mode 100644
index 0000000..9f41581
--- /dev/null
+++ b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.appmenubar/contents/layout.js
@@ -0,0 +1,5 @@
+var panel = new Panel
+panel.location = "top";
+panel.height = Math.round(gridUnit * 1.5);
+
+panel.addWidget("org.kde.plasma.appmenu");
diff --git a/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.appmenubar/metadata.json b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.appmenubar/metadata.json
new file mode 100644
index 0000000..2518274
--- /dev/null
+++ b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.appmenubar/metadata.json
@@ -0,0 +1,175 @@
+{
+ "KPackageStructure": "Plasma/LayoutTemplate",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "kde@privat.broulik.de",
+ "Name": "Kai Uwe Broulik",
+ "Name[ar]": "كاي أووي بروتيك",
+ "Name[az]": "Kai Uwe Broulik",
+ "Name[be]": "Kai Uwe Broulik",
+ "Name[bg]": "Kai Uwe Broulik",
+ "Name[ca@valencia]": "Kai Uwe Broulik",
+ "Name[ca]": "Kai Uwe Broulik",
+ "Name[cs]": "Kai Uwe Broulik",
+ "Name[da]": "Kai Uwe Broulik",
+ "Name[de]": "Kai Uwe Broulik",
+ "Name[el]": "Kai Uwe Broulik",
+ "Name[en_GB]": "Kai Uwe Broulik",
+ "Name[eo]": "Kai Uwe Broulik",
+ "Name[es]": "Kai Uwe Broulik",
+ "Name[et]": "Kai Uwe Broulik",
+ "Name[eu]": "Kai Uwe Broulik",
+ "Name[fi]": "Kai Uwe Broulik",
+ "Name[fr]": "Kai Uwe Broulik",
+ "Name[ga]": "Kai Uwe Broulik",
+ "Name[gl]": "Kai Uwe Broulik",
+ "Name[he]": "קאי או ברוליק",
+ "Name[hu]": "Kai Uwe Broulik",
+ "Name[ia]": "Kai Uwe Broulik",
+ "Name[id]": "Kai Uwe Broulik",
+ "Name[ie]": "Kai Uwe Broulik",
+ "Name[is]": "Kai Uwe Broulik",
+ "Name[it]": "Kai Uwe Broulik",
+ "Name[ja]": "Kai Uwe Broulik",
+ "Name[ka]": "კაი უვე ბროულიკი",
+ "Name[ko]": "Kai Uwe Broulik",
+ "Name[lt]": "Kai Uwe Broulik",
+ "Name[lv]": "Kai Uwe Broulik",
+ "Name[nb]": "Kai Uwe Broulik",
+ "Name[nl]": "Kai Uwe Broulik",
+ "Name[nn]": "Kai Uwe Broulik",
+ "Name[pl]": "Kai Uwe Broulik",
+ "Name[pt]": "Kai Uwe Broulik",
+ "Name[pt_BR]": "Kai Uwe Broulik",
+ "Name[ro]": "Kai Uwe Broulik",
+ "Name[ru]": "Kai Uwe Broulik",
+ "Name[sa]": "कै उवे ब्रौलिक",
+ "Name[sk]": "Kai Uwe Broulik",
+ "Name[sl]": "Kai Uwe Broulik",
+ "Name[sv]": "Kai Uwe Broulik",
+ "Name[ta]": "காய் ஊவே புரோலிக்",
+ "Name[tr]": "Kai Uwe Broulik",
+ "Name[uk]": "Kai Uwe Broulik",
+ "Name[vi]": "Kai Uwe Broulik",
+ "Name[zh_CN]": "Kai Uwe Broulik",
+ "Name[zh_TW]": "Kai Uwe Broulik"
+ }
+ ],
+ "Category": "",
+ "Description": "Panel containing the global menu applet",
+ "Description[ar]": "لوحة تحوي بريمج القائمة العالمية",
+ "Description[az]": "Qlobal menyu əlavəsindən ibarət panel",
+ "Description[be]": "Панэль змяшчае аплет глабальнага меню",
+ "Description[bg]": "Панел с аплет на глобалното меню",
+ "Description[ca@valencia]": "Quadro que conté la miniaplicació del menú global",
+ "Description[ca]": "Plafó que conté la miniaplicació del menú global",
+ "Description[cs]": "Panel obsahující applet pro globální nabídku",
+ "Description[da]": "Panel med appletten global menu",
+ "Description[de]": "Kontrollleiste mit dem Miniprogramm für das Globale Menü",
+ "Description[el]": "Πίνακας που περιέχει την εφαρμογή του παγκόσμιου μενού",
+ "Description[en_GB]": "Panel containing the global menu applet",
+ "Description[eo]": "Panel enhavanta la globalan menu-aplkiaĵon",
+ "Description[es]": "Panel que contiene la miniaplicación del menú global",
+ "Description[et]": "Globaalse menüü apletti sisaldav paneel",
+ "Description[eu]": "Menu orokorraren aplikaziotxoa duen panela",
+ "Description[fi]": "Työpöydänlaajuisen valikkosovelman sisältävä paneeli",
+ "Description[fr]": "Panneau contenant l'applet du menu global",
+ "Description[ga]": "Painéal ina bhfuil an feidhmchláirín roghchláir dhomhanda",
+ "Description[gl]": "Panel que contén o trebello de menú global.",
+ "Description[he]": "לוח שמכיל את יישומון התפריט המקיף",
+ "Description[hu]": "A globális menü kisalkalmazást tartalmazó panel",
+ "Description[ia]": "Pannello continente le applet de menu global",
+ "Description[id]": "Panel berisi applet menu global",
+ "Description[is]": "Skjáborðsstika með almenna valmyndarsmáforritið",
+ "Description[it]": "Pannello contenente l'applet del menu globale",
+ "Description[ja]": "グローバルメニューウィジェットを含むパネル",
+ "Description[ka]": "პანელი, რომელიც გლობალური მენიუს აპლეტს შეიცავს",
+ "Description[ko]": "전역 메뉴 애플릿이 있는 패널",
+ "Description[lt]": "Skydelis su visuotinio meniu programėle",
+ "Description[lv]": "Panelis, kas satur globālās izvēlnes sīklietotni",
+ "Description[nb]": "Panel som inneholder global meny",
+ "Description[nl]": "Panel met de applet met het globale menu",
+ "Description[nn]": "Panel som inneheld global meny",
+ "Description[pa]": "ਪੈਨਲ ਵਿੱਚ ਗਲੋਬਲ ਮੇਨੂ ਐਪਲਿਟ ਹੈ",
+ "Description[pl]": "Panel zawierający aplet globalnego menu",
+ "Description[pt]": "Painel que contém a 'applet' do menu global",
+ "Description[pt_BR]": "Painel contendo o miniaplicativo de menu global",
+ "Description[ro]": "Panou ce conține miniaplicația de meniu global",
+ "Description[ru]": "Панель, содержащая виджет «Меню приложения»",
+ "Description[sa]": "वैश्विकमेनू एप्लेट् युक्तं पटलम्",
+ "Description[sk]": "Panel obsahujúci applet globálnej ponuky",
+ "Description[sl]": "Plošča, ki vsebuje aplet s splošnim menijem",
+ "Description[sv]": "Panel som innehåller miniprogrammet med den globala menyn",
+ "Description[ta]": "பொதுவான பட்டியை கொண்டிருக்கும் பலகை",
+ "Description[tr]": "Global menü uygulamacığını barındıran panel",
+ "Description[uk]": "Панель із аплетом загального меню",
+ "Description[vi]": "Bảng chứa tiểu ứng dụng trình đơn toàn cục",
+ "Description[zh_CN]": "包含全局菜单小程序的面板",
+ "Description[zh_TW]": "包含全域選單小程式的面板",
+ "EnabledByDefault": true,
+ "Id": "org.kde.plasma.desktop.appmenubar",
+ "License": "LGPLv2+",
+ "Name": "Application Menu Bar",
+ "Name[ar]": "شريط قائمة التّطبيقات",
+ "Name[az]": "Tətbiq menyu çubuğu",
+ "Name[be]": "Панэль меню праграм",
+ "Name[bg]": "Панел с меню на приложения",
+ "Name[ca@valencia]": "Barra de menús de l'aplicació",
+ "Name[ca]": "Barra de menús de l'aplicació",
+ "Name[cs]": "Panel s nabídkou aplikace",
+ "Name[da]": "Menulinje til programmer",
+ "Name[de]": "Anwendungsmenüleiste",
+ "Name[el]": "Γραμμή μενού εφαρμογής",
+ "Name[en_GB]": "Application Menu Bar",
+ "Name[eo]": "Aplikaĵa Menubreto",
+ "Name[es]": "Barra de menú de la aplicación",
+ "Name[et]": "Rakenduste menüüriba",
+ "Name[eu]": "Aplikazioen menu-barra",
+ "Name[fi]": "Sovellusvalikkopalkki",
+ "Name[fr]": "Barre de menus des applications",
+ "Name[ga]": "Barra Roghchláir an Fheidhmchláir",
+ "Name[gl]": "Barra de menú das aplicacións",
+ "Name[he]": "סרגל תפריט יישומים",
+ "Name[hu]": "Alkalmazás-menüsáv",
+ "Name[ia]": "Barra de Menu de application",
+ "Name[id]": "Bilah Menu Aplikasi",
+ "Name[ie]": "Singul menú de applicationes",
+ "Name[is]": "Valmyndastika forrita",
+ "Name[it]": "Barra del menu delle applicazioni",
+ "Name[ja]": "アプリケーションメニューバー",
+ "Name[ka]": "აპლიკაციის მენიუს ზოლი",
+ "Name[ko]": "앱 메뉴 표시줄",
+ "Name[lt]": "Programų meniu juosta",
+ "Name[lv]": "Programmas izvēlnes josla",
+ "Name[nb]": "Programmenylinje",
+ "Name[nl]": "Menubalk Toepassingen",
+ "Name[nn]": "Programmenylinje",
+ "Name[pa]": "ਐਪਲੀਕੇਸ਼ਨ ਮੇਨੂ ਪੱਟੀ",
+ "Name[pl]": "Pasek menu programów",
+ "Name[pt]": "Barra do Menu da Aplicação",
+ "Name[pt_BR]": "Menu de aplicativos",
+ "Name[ro]": "Bara de meniu a aplicației",
+ "Name[ru]": "Строка меню приложения",
+ "Name[sa]": "अनुप्रयोग मेनू पट्टी",
+ "Name[sk]": "Ponuka aplikácie",
+ "Name[sl]": "Menijska vrstico programa",
+ "Name[sr@ijekavian]": "Трака менија програма",
+ "Name[sr@ijekavianlatin]": "Traka menija programa",
+ "Name[sr@latin]": "Traka menija programa",
+ "Name[sr]": "Трака менија програма",
+ "Name[sv]": "Programmenyrad",
+ "Name[ta]": "செயலி பட்டிப் பட்டை",
+ "Name[tg]": "Навори феҳристи барномаҳо",
+ "Name[tr]": "Uygulama Menüsü Çubuğu",
+ "Name[uk]": "Смужка меню програми",
+ "Name[vi]": "Thanh trình đơn ứng dụng",
+ "Name[zh_CN]": "应用程序菜单栏",
+ "Name[zh_TW]": "應用程式選單列",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-ContainmentCategories": [
+ "panel"
+ ],
+ "X-Plasma-Shell": "plasmashell"
+}
diff --git a/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.defaultPanel/contents/layout.js b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.defaultPanel/contents/layout.js
new file mode 100644
index 0000000..bb19953
--- /dev/null
+++ b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.defaultPanel/contents/layout.js
@@ -0,0 +1,106 @@
+var panel = new Panel
+var panelScreen = panel.screen
+
+// No need to set panel.location as ShellCorona::addPanel will automatically pick one available edge
+
+// For an Icons-Only Task Manager on the bottom, *3 is too much, *2 is too little
+// Round up to next highest even number since the Panel size widget only displays
+// even numbers
+panel.height = 2 * Math.ceil(gridUnit * 2.5 / 2)
+
+// Restrict horizontal panel to a maximum size of a 21:9 monitor
+const maximumAspectRatio = 21/9;
+if (panel.formFactor === "horizontal") {
+ const geo = screenGeometry(panelScreen);
+ const maximumWidth = Math.ceil(geo.height * maximumAspectRatio);
+
+ if (geo.width > maximumWidth) {
+ panel.alignment = "center";
+ panel.minimumLength = maximumWidth;
+ panel.maximumLength = maximumWidth;
+ }
+}
+
+panel.addWidget("org.kde.plasma.kickoff")
+//panel.addWidget("org.kde.plasma.showActivityManager")
+panel.addWidget("org.kde.plasma.pager")
+panel.addWidget("org.kde.plasma.icontasks")
+panel.addWidget("org.kde.plasma.marginsseparator")
+
+/* Next up is determining whether to add the Input Method Panel
+ * widget to the panel or not. This is done based on whether
+ * the system locale's language id is a member of the following
+ * white list of languages which are known to pull in one of
+ * our supported IME backends when chosen during installation
+ * of common distributions. */
+
+var langIds = ["as", // Assamese
+ "bn", // Bengali
+ "bo", // Tibetan
+ "brx", // Bodo
+ "doi", // Dogri
+ "gu", // Gujarati
+ "hi", // Hindi
+ "ja", // Japanese
+ "kn", // Kannada
+ "ko", // Korean
+ "kok", // Konkani
+ "ks", // Kashmiri
+ "lep", // Lepcha
+ "mai", // Maithili
+ "ml", // Malayalam
+ "mni", // Manipuri
+ "mr", // Marathi
+ "ne", // Nepali
+ "or", // Odia
+ "pa", // Punjabi
+ "sa", // Sanskrit
+ "sat", // Santali
+ "sd", // Sindhi
+ "si", // Sinhala
+ "ta", // Tamil
+ "te", // Telugu
+ "th", // Thai
+ "ur", // Urdu
+ "vi", // Vietnamese
+ "zh_CN", // Simplified Chinese
+ "zh_TW"] // Traditional Chinese
+
+if (langIds.indexOf(languageId) != -1) {
+ panel.addWidget("org.kde.plasma.kimpanel");
+}
+
+panel.addWidget("org.kde.plasma.systemtray")
+panel.addWidget("org.kde.plasma.digitalclock")
+panel.addWidget("org.kde.plasma.showdesktop")
+
+const allPanels = panels();
+
+for (let i = 0; i < allPanels.length; ++i) {
+ const panel = allPanels[i];
+ const widgets = panel.widgets();
+
+ for (let j = 0; j < widgets.length; ++j) {
+ const widget = widgets[j];
+
+ if (widget.type === "org.kde.plasma.icontasks") {
+ widget.currentConfigGroup = ["General"];
+
+ // Read the current launchers value
+ const currentLaunchers = widget.readConfig("launchers", "");
+
+ // Only set our default if launchers is empty
+ if (!currentLaunchers || currentLaunchers.trim() === "") {
+ widget.writeConfig("launchers", [
+ "preferred://browser",
+ "applications:Alacritty.desktop",
+ "applications:io.github.kolunmi.Bazaar.desktop",
+ "preferred://filemanager",
+ "cockos-reaper.desktop"
+ ]);
+ widget.reloadConfig();
+ }
+ }
+ }
+}
+
diff --git a/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.defaultPanel/metadata.json b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.defaultPanel/metadata.json
new file mode 100644
index 0000000..998c3b8
--- /dev/null
+++ b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.defaultPanel/metadata.json
@@ -0,0 +1,178 @@
+{
+ "KPackageStructure": "Plasma/LayoutTemplate",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "aseigo@kde.org",
+ "Name": "Aaron Seigo",
+ "Name[ar]": "آرون سيغو",
+ "Name[az]": "Aaron Seigo",
+ "Name[be]": "Aaron Seigo",
+ "Name[bg]": "Aaron Seigo",
+ "Name[ca@valencia]": "Aaron Seigo",
+ "Name[ca]": "Aaron Seigo",
+ "Name[cs]": "Aaron Seigo",
+ "Name[da]": "Aaron Seigo",
+ "Name[de]": "Aaron Seigo",
+ "Name[el]": "Aaron Seigo",
+ "Name[en_GB]": "Aaron Seigo",
+ "Name[eo]": "Aaron Seigo",
+ "Name[es]": "Aaron Seigo",
+ "Name[et]": "Aaron Seigo",
+ "Name[eu]": "Aaron Seigo",
+ "Name[fi]": "Aaron Seigo",
+ "Name[fr]": "Aaron Seigo",
+ "Name[ga]": "Aaron Seigo",
+ "Name[gl]": "Aaron Seigo",
+ "Name[he]": "אהרון סייגו",
+ "Name[hu]": "Aaron Seigo",
+ "Name[ia]": "Aaron Seigo",
+ "Name[id]": "Aaron Seigo",
+ "Name[ie]": "Aaron Seigo",
+ "Name[is]": "Aaron Seigo",
+ "Name[it]": "Aaron Seigo",
+ "Name[ja]": "Aaron Seigo",
+ "Name[ka]": "აარონ სეიგო",
+ "Name[ko]": "Aaron Seigo",
+ "Name[lt]": "Aaron Seigo",
+ "Name[lv]": "Aaron Seigo",
+ "Name[nb]": "Aaron Seigo",
+ "Name[nl]": "Aaron Seigo",
+ "Name[nn]": "Aaron Seigo",
+ "Name[pl]": "Aaron Seigo",
+ "Name[pt]": "Aaron Seigo",
+ "Name[pt_BR]": "Aaron Seigo",
+ "Name[ro]": "Aaron Seigo",
+ "Name[ru]": "Aaron Seigo",
+ "Name[sa]": "एरोन् सेइगो",
+ "Name[sk]": "Aaron Seigo",
+ "Name[sl]": "Aaron Seigo",
+ "Name[sv]": "Aaron Seigo",
+ "Name[ta]": "ஆரோன் சீகோ",
+ "Name[tr]": "Aaron Seigo",
+ "Name[uk]": "Aaron Seigo",
+ "Name[vi]": "Aaron Seigo",
+ "Name[zh_CN]": "Aaron Seigo",
+ "Name[zh_TW]": "Aaron Seigo"
+ }
+ ],
+ "Category": "",
+ "Description": "Default panel featuring application launcher, task manager and system tray",
+ "Description[ar]": "لوحة مبدئية تحوي مطلق تطبيقات و مدير مهام و صينية نظام",
+ "Description[az]": "Tətbiq başlatma menyusundan, tapşırıq panelindən və Sistem trey-dən ibarət standart panel",
+ "Description[be]": "Прадвызначаная панэль са сродкам запуску праграм, кіраўніком задач і прасторай апавяшчэнняў",
+ "Description[bg]": "Стандартен панел, съдържащ стартер на приложение, диспечер на задачи и системна област",
+ "Description[ca@valencia]": "Quadro predeterminat amb l'iniciador d'aplicacions, el gestor de tasques i la safata del sistema",
+ "Description[ca]": "Plafó predeterminat amb el llançador d'aplicacions, el gestor de tasques i la safata del sistema",
+ "Description[cs]": "Výchozí panel se spouštěčem aplikací, správcem úloh a systémovou částí",
+ "Description[da]": "Standardpanel med programstarter, opgavelinje og statusområde",
+ "Description[de]": "Standardkontrollleiste mit dem Anwendungsstarter, Fensterleiste und dem Systemabschnitt der Kontrollleiste",
+ "Description[el]": "Προεπιλεγμένος πίνακας με εκκινητή εφαρμογών, διαχειριστή εργασιών και πλαίσιο συστήματος",
+ "Description[en_GB]": "Default panel featuring application launcher, task manager and system tray",
+ "Description[eo]": "Defaŭlta panelo kun aplikaĵlanĉilo, taskadministrilo kaj sistempleto",
+ "Description[es]": "Panel por defecto que contiene un lanzador de aplicaciones, un gestor de tareas y la bandeja del sistema",
+ "Description[et]": "Vaikimisi paneel rakenduste käivitaja, ülesannete halduri ja süsteemisalvega",
+ "Description[eu]": "Lehenetsitako panela, aplikazio abiarazlea, ataza kudeatzailea eta sistemaren erretilua dituena",
+ "Description[fi]": "Oletuspaneeli, jossa sovelluskäynnistin, tehtävänhallinta ja ilmoitusalue",
+ "Description[fr]": "Panneau par défaut contenant le lanceur d'application, le gestionnaire de tâches et la boite à miniatures.",
+ "Description[ga]": "Painéal réamhshocraithe ina bhfuil lainseálaí feidhmchlár, bainisteoir tascanna agus tráidire córais",
+ "Description[gl]": "Panel predeterminado que contén un iniciador de aplicacións, un xestor de tarefas e unha área de notificación.",
+ "Description[he]": "לוח ברירת מחדל שמציג משגר חלונות, מנהל משימות ומגש מערכת",
+ "Description[hu]": "Az alapértelmezett panel, amely tartalmazza az alkalmazásindítót, a feladatkezelőt és a rendszertálcát",
+ "Description[ia]": "Pannello predefinite con lanceator de application, administrator de carga e tabuliero de systema ",
+ "Description[id]": "Perfituran panel baku peluncur aplikasi, pengelola tugas dan baki sistem",
+ "Description[is]": "Sjálfgefin skjáborðsstika með forritaræsi, verkefnastjóra og kerfisbakka",
+ "Description[it]": "Pannello p che offre un avviatore di applicazioni, un gestore dei processi e un vassoio di sistema",
+ "Description[ja]": "アプリケーションランチャー、タスクマネージャ、システムトレイを含む標準のパネル",
+ "Description[ka]": "ნაგულისხმევი პანელი, რომელიც აპლიკაციების გამშვებს, აპლიკაციების მმართველს და საათს შეიცავს",
+ "Description[ko]": "앱 실행기, 작업 관리자, 시스템 트레이가 있는 기본 패널",
+ "Description[lt]": "Numatytasis skydelis su programų paleidykle, užduočių tvarkytuve ir sistemos dėklu",
+ "Description[lv]": "Noklusējuma panelis, kas satur lietotņu palaidēju, uzdevumu pārvaldnieku un sistēmas ikonu joslu",
+ "Description[nb]": "Standardpanel med programstarter, oppgavebehandler og systemkurv",
+ "Description[nl]": "Standaard paneel met starter van toepassingen, taakbeheerder en systeemvak",
+ "Description[nn]": "Standardpanel med programstartar, oppgåvehandsamar og systemtrau",
+ "Description[pa]": "ਡਿਫਾਲਟ ਪੈਨਲ ਵਿੱਚ ਐਪਲੀਕੇਸ਼ਨ ਲਾਂਚਰ, ਟਾਸਕ ਮੈਨੇਜਰ ਅਤੇ ਸਿਸਟਮ ਟਰੇ ਹੁੰਦੇ ਹਨ",
+ "Description[pl]": "Domyślny panel zawierający uruchamiacza programów, pasek zadań i tackę systemową",
+ "Description[pt]": "O painel predefinido, que possui o lançador de aplicações, o gestor de tarefas e a bandeja do sistema",
+ "Description[pt_BR]": "Painel padrão contendo o lançador de aplicativos, gerenciador de tarefas e área de notificação",
+ "Description[ro]": "Panou implicit cu lansator de aplicații, gestionar de sarcini și tavă de sistem",
+ "Description[ru]": "Стандартная панель, содержащая меню запуска приложений, панель задач и системный лоток",
+ "Description[sa]": "पूर्वनिर्धारितं पटलं यत्र अनुप्रयोगप्रक्षेपकः, कार्यप्रबन्धकः, प्रणालीट्रे च सन्ति",
+ "Description[sk]": "Predvolený panel obsahuje spúšťač aplikácií, správcu úloh a systémovú lištu",
+ "Description[sl]": "Privzeta plošča, ki vsebuje zaganjalnik programov, upravljalnik opravil in sistemsko vrstico",
+ "Description[sv]": "Standardpanel med funktionerna programstart, aktivitetshanterare och systembricka",
+ "Description[ta]": "செயலி ஏவி, பணி மேலாளர், மற்றும் கணினி தட்டை கொண்ட இயல்பிருப்பு பலகை",
+ "Description[tr]": "Uygulama başlatıcısını, görev yöneticisini ve sistem tepsisini sunan öntanımlı panel",
+ "Description[uk]": "Типова панель із засобом запуску програм, панеллю керування задачами та системним лотком",
+ "Description[vi]": "Bảng mặc định chứa trình khởi chạy ứng dụng, trình quản lí tác vụ và khay hệ thống",
+ "Description[zh_CN]": "带有应用程序启动器、任务管理器和系统托盘的默认面板",
+ "Description[zh_TW]": "擁有應用程式啟動器、工作管理員與系統匣的面板。",
+ "EnabledByDefault": true,
+ "Id": "org.kde.plasma.desktop.defaultPanel",
+ "License": "LGPLv2+",
+ "Name": "Default Panel",
+ "Name[ar]": "اللوحة المبدئية",
+ "Name[az]": "Əsas Panel",
+ "Name[be]": "Прадвызначаная панэль",
+ "Name[bg]": "Стандартен панел",
+ "Name[bs]": "Podrazumijevani panel",
+ "Name[ca@valencia]": "Quadro predeterminat",
+ "Name[ca]": "Plafó predeterminat",
+ "Name[cs]": "Výchozí panel",
+ "Name[da]": "Standardpanel",
+ "Name[de]": "Standard-Kontrollleiste",
+ "Name[el]": "Προεπιλεγμένος πίνακας",
+ "Name[en_GB]": "Default Panel",
+ "Name[eo]": "Defaŭlta Panelo",
+ "Name[es]": "Panel por omisión",
+ "Name[et]": "Vaikimisi paneel",
+ "Name[eu]": "Panel lehenetsia",
+ "Name[fi]": "Oletuspaneeli",
+ "Name[fr]": "Tableau de bord par défaut",
+ "Name[ga]": "Painéal Réamhshocraithe",
+ "Name[gl]": "Panel predeterminado",
+ "Name[he]": "לוחות ברירת מחדל",
+ "Name[hu]": "Alapértelmezett panel",
+ "Name[ia]": "Pannello predefinite",
+ "Name[id]": "Panel Bawaan",
+ "Name[ie]": "Predefinit panel",
+ "Name[is]": "Sjálfgefin skjáborðsstika",
+ "Name[it]": "Pannello predefinito",
+ "Name[ja]": "標準のパネル",
+ "Name[ka]": "ნაგულისხმევი პანელი",
+ "Name[ko]": "기본 패널",
+ "Name[lt]": "Numatytasis skydelis",
+ "Name[lv]": "Noklusētais panelis",
+ "Name[mr]": "मूलभूत पटल",
+ "Name[nb]": "Standardpanel",
+ "Name[nds]": "Standardpaneel",
+ "Name[nl]": "Standaard paneel",
+ "Name[nn]": "Standardpanel",
+ "Name[pa]": "ਡਿਫਾਲਟ ਪੈਨਲ",
+ "Name[pl]": "Domyślny panel",
+ "Name[pt]": "Painel Predefinido",
+ "Name[pt_BR]": "Painel padrão",
+ "Name[ro]": "Panou implicit",
+ "Name[ru]": "Стандартная панель",
+ "Name[sa]": "पूर्वनिर्धारित पटल",
+ "Name[sk]": "Štandardný panel",
+ "Name[sl]": "Privzeti pult",
+ "Name[sr@ijekavian]": "Подразумијевани панел",
+ "Name[sr@ijekavianlatin]": "Podrazumijevani panel",
+ "Name[sr@latin]": "Podrazumevani panel",
+ "Name[sr]": "Подразумевани панел",
+ "Name[sv]": "Standardpanel",
+ "Name[ta]": "இயல்பிருப்பு பலகை",
+ "Name[tg]": "Лавҳаи стандартӣ",
+ "Name[tr]": "Öntanımlı Pano",
+ "Name[uk]": "Типова панель",
+ "Name[vi]": "Bảng mặc định",
+ "Name[zh_CN]": "默认面板",
+ "Name[zh_TW]": "預設面板",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-ContainmentCategories": [
+ "panel"
+ ],
+ "X-Plasma-Shell": "plasmashell"
+}
diff --git a/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.emptyPanel/contents/layout.js b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.emptyPanel/contents/layout.js
new file mode 100644
index 0000000..23e5c68
--- /dev/null
+++ b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.emptyPanel/contents/layout.js
@@ -0,0 +1,28 @@
+var panel = new Panel
+var panelScreen = panel.screen
+var freeEdges = {"bottom": true, "top": true, "left": true, "right": true}
+
+for (i = 0; i < panelIds.length; ++i) {
+ var tmpPanel = panelById(panelIds[i])
+ if (tmpPanel.screen == panelScreen) {
+ // Ignore the new panel
+ if (tmpPanel.id != panel.id) {
+ freeEdges[tmpPanel.location] = false;
+ }
+ }
+}
+
+if (freeEdges["bottom"] == true) {
+ panel.location = "bottom";
+} else if (freeEdges["top"] == true) {
+ panel.location = "top";
+} else if (freeEdges["left"] == true) {
+ panel.location = "left";
+} else if (freeEdges["right"] == true) {
+ panel.location = "right";
+} else {
+ // There is no free edge, so leave the default value
+ panel.location = "top";
+}
+
+panel.height = gridUnit * 2
diff --git a/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.emptyPanel/metadata.json b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.emptyPanel/metadata.json
new file mode 100644
index 0000000..812a279
--- /dev/null
+++ b/files/system/usr/share/plasma/layout-templates/org.kde.plasma.desktop.emptyPanel/metadata.json
@@ -0,0 +1,181 @@
+{
+ "KPackageStructure": "Plasma/LayoutTemplate",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "davidedmundson@kde.org",
+ "Name": "David Edmundson",
+ "Name[ar]": "ديفيد إدموندسون",
+ "Name[az]": "David Edmundson",
+ "Name[be]": "David Edmundson",
+ "Name[bg]": "David Edmundson",
+ "Name[ca@valencia]": "David Edmundson",
+ "Name[ca]": "David Edmundson",
+ "Name[cs]": "David Edmundson",
+ "Name[da]": "David Edmundson",
+ "Name[de]": "David Edmundson",
+ "Name[el]": "David Edmundson",
+ "Name[en_GB]": "David Edmundson",
+ "Name[eo]": "David Edmundson",
+ "Name[es]": "David Edmundson",
+ "Name[et]": "David Edmundson",
+ "Name[eu]": "David Edmundson",
+ "Name[fi]": "David Edmundson",
+ "Name[fr]": "David Edmundson",
+ "Name[ga]": "David Edmundson",
+ "Name[gl]": "David Edmundson",
+ "Name[he]": "דיויד אדמונדסון",
+ "Name[hu]": "David Edmundson",
+ "Name[ia]": "David Edmundson",
+ "Name[id]": "David Edmundson",
+ "Name[ie]": "David Edmundson",
+ "Name[is]": "David Edmundson",
+ "Name[it]": "David Edmundson",
+ "Name[ja]": "David Edmundson",
+ "Name[ka]": "დავიდ ედმუნდსონი",
+ "Name[ko]": "David Edmundson",
+ "Name[lt]": "David Edmundson",
+ "Name[lv]": "David Edmundson",
+ "Name[nb]": "David Edmundson",
+ "Name[nl]": "David Edmundson",
+ "Name[nn]": "David Edmundson",
+ "Name[pl]": "David Edmundson",
+ "Name[pt]": "David Edmundson",
+ "Name[pt_BR]": "David Edmundson",
+ "Name[ro]": "David Edmundson",
+ "Name[ru]": "David Edmundson",
+ "Name[sa]": "डेविड् एडमण्ड्सनः",
+ "Name[sk]": "David Edmundson",
+ "Name[sl]": "David Edmundson",
+ "Name[sv]": "David Edmundson",
+ "Name[ta]": "டேவிட் எட்மண்டுஸன்",
+ "Name[tr]": "David Edmundson",
+ "Name[uk]": "David Edmundson",
+ "Name[vi]": "David Edmundson",
+ "Name[zh_CN]": "David Edmundson",
+ "Name[zh_TW]": "David Edmundson"
+ }
+ ],
+ "Category": "",
+ "Description": "Empty panel",
+ "Description[ar]": "لوحة فارغة",
+ "Description[az]": "Boş Panel",
+ "Description[be]": "Пустая панэль",
+ "Description[bg]": "Празен панел",
+ "Description[ca@valencia]": "Quadro buit",
+ "Description[ca]": "Plafó buit",
+ "Description[cs]": "Prázdný panel",
+ "Description[da]": "Tomt panel",
+ "Description[de]": "Leere Kontrollleiste",
+ "Description[el]": "Κενός πίνακας",
+ "Description[en_GB]": "Empty panel",
+ "Description[eo]": "Panelo",
+ "Description[es]": "Panel vacío",
+ "Description[et]": "Tühi paneel",
+ "Description[eu]": "Panel hutsik",
+ "Description[fi]": "Tyhjä paneeli",
+ "Description[fr]": "Panneau vide",
+ "Description[ga]": "Painéal folamh",
+ "Description[gl]": "Panel baleiro.",
+ "Description[he]": "לוח ריק",
+ "Description[hu]": "Üres panel",
+ "Description[ia]": "Pannello vacue",
+ "Description[id]": "Panel kosong",
+ "Description[ie]": "Vacui panel",
+ "Description[is]": "Auð skjáborðsstika",
+ "Description[it]": "Pannello vuoto",
+ "Description[ja]": "空のパネル",
+ "Description[ka]": "ცარიელი პანელი",
+ "Description[ko]": "빈 패널",
+ "Description[lt]": "Tuščias skydelis",
+ "Description[lv]": "Tukšs panelis",
+ "Description[nb]": "Tomt panel",
+ "Description[nl]": "Leeg paneel",
+ "Description[nn]": "Tomt panel",
+ "Description[pa]": "ਖਾਲੀ ਪੈਨਲ",
+ "Description[pl]": "Pusty panel",
+ "Description[pt]": "Painel vazio",
+ "Description[pt_BR]": "Painel vazio",
+ "Description[ro]": "Panou gol",
+ "Description[ru]": "Пустая панель",
+ "Description[sa]": "रिक्तं पटलम्",
+ "Description[sk]": "Prázdny panel",
+ "Description[sl]": "Prazna plošča",
+ "Description[sv]": "Tom panel",
+ "Description[ta]": "காலியான பலகை",
+ "Description[tr]": "Boş panel",
+ "Description[uk]": "Порожня панель",
+ "Description[vi]": "Bảng trống",
+ "Description[zh_CN]": "空面板",
+ "Description[zh_TW]": "空白面板",
+ "EnabledByDefault": true,
+ "Id": "org.kde.plasma.desktop.emptyPanel",
+ "License": "LGPLv2+",
+ "Name": "Empty Panel",
+ "Name[ar]": "لوحة فارغة",
+ "Name[az]": "Boş Panel",
+ "Name[be]": "Пустая панэль",
+ "Name[bg]": "Празен панел",
+ "Name[bs]": "Prazan panel",
+ "Name[ca@valencia]": "Quadro buit",
+ "Name[ca]": "Plafó buit",
+ "Name[cs]": "Prázdný panel",
+ "Name[da]": "Tomt panel",
+ "Name[de]": "Leere Kontrollleiste",
+ "Name[el]": "Κενός πίνακας",
+ "Name[en_GB]": "Empty Panel",
+ "Name[eo]": "Malplena Panelo",
+ "Name[es]": "Panel vacío",
+ "Name[et]": "Tühi paneel",
+ "Name[eu]": "Panel hutsa",
+ "Name[fi]": "Tyhjä paneeli",
+ "Name[fr]": "Tableau de bord vide",
+ "Name[ga]": "Painéal Folamh",
+ "Name[gl]": "Panel baleiro",
+ "Name[he]": "לוח ריק",
+ "Name[hr]": "Prazan panel",
+ "Name[hu]": "Üres panel",
+ "Name[ia]": "Pannello vacue",
+ "Name[id]": "Panel Kosong",
+ "Name[ie]": "Vacui panel",
+ "Name[is]": "Auð skjáborðsstika",
+ "Name[it]": "Pannello vuoto",
+ "Name[ja]": "空のパネル",
+ "Name[ka]": "ცარიელი პანელი",
+ "Name[kn]": "ಖಾಲಿ ಪುಟೀಪು (ಪ್ಯಾನಲ್)",
+ "Name[ko]": "빈 패널",
+ "Name[lt]": "Tuščias skydelis",
+ "Name[lv]": "Tukšs panelis",
+ "Name[mr]": "रिकामे पटल",
+ "Name[nb]": "Tomt panel",
+ "Name[nds]": "Leddig Paneel",
+ "Name[nl]": "Leeg paneel",
+ "Name[nn]": "Tomt panel",
+ "Name[pa]": "ਖਾਲੀ ਪੈਨਲ",
+ "Name[pl]": "Pusty panel",
+ "Name[pt]": "Painel Vazio",
+ "Name[pt_BR]": "Painel vazio",
+ "Name[ro]": "Panou gol",
+ "Name[ru]": "Пустая панель",
+ "Name[sa]": "रिक्त पटल",
+ "Name[sk]": "Prázdny panel",
+ "Name[sl]": "Prazen pult",
+ "Name[sr@ijekavian]": "празан панел",
+ "Name[sr@ijekavianlatin]": "prazan panel",
+ "Name[sr@latin]": "prazan panel",
+ "Name[sr]": "празан панел",
+ "Name[sv]": "Tom panel",
+ "Name[ta]": "காலியான பலகை",
+ "Name[tg]": "Лавҳаи холӣ",
+ "Name[tr]": "Boş Panel",
+ "Name[uk]": "Порожня панель",
+ "Name[vi]": "Bảng trống",
+ "Name[zh_CN]": "空面板",
+ "Name[zh_TW]": "空白面板",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-ContainmentCategories": [
+ "panel"
+ ],
+ "X-Plasma-Shell": "plasmashell"
+}
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/defaults b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/defaults
new file mode 100644
index 0000000..a14fa3f
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/defaults
@@ -0,0 +1,26 @@
+[kdeglobals][KDE]
+widgetStyle=Breeze
+
+[kdeglobals][General]
+ColorScheme=Vapor
+
+[kdeglobals][Icons]
+Theme=breeze-dark
+
+[plasmarc][Theme]
+name=Vapor
+
+[kcminputrc][Mouse]
+cursorTheme=breeze_cursors
+
+[kwinrc][WindowSwitcher]
+LayoutName=org.kde.breeze.desktop
+
+[kwinrc][DesktopSwitcher]
+LayoutName=org.kde.breeze.desktop
+
+[kwinrc][org.kde.kdecoration2]
+library=org.kde.breeze
+
+[KSplash]
+Theme=com.valve.vapor
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/icons/deck_icon.png b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/icons/deck_icon.png
new file mode 100644
index 0000000..7e596c0
Binary files /dev/null and b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/icons/deck_icon.png differ
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.folder.js b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.folder.js
new file mode 100644
index 0000000..8cfef49
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.folder.js
@@ -0,0 +1,4 @@
+applet.wallpaperPlugin = 'org.kde.image'
+applet.currentConfigGroup = ["Wallpaper", "org.kde.image", "General"]
+applet.writeConfig("Image", "/usr/share/wallpapers/miasma-default.jxl")
+applet.reloadConfig()
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js
new file mode 100644
index 0000000..2ef00cb
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js
@@ -0,0 +1,3 @@
+applet.currentConfigGroup = ["General"]
+applet.writeConfig("icon", "distributor-logo-steamdeck")
+applet.reloadConfig()
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.systemtray.js b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.systemtray.js
new file mode 100644
index 0000000..7eaae7a
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/plasmoidsetupscripts/org.kde.plasma.systemtray.js
@@ -0,0 +1,6 @@
+systemtrayId = applet.readConfig("SystrayContainmentId");
+if (systemtrayId) {
+ const systrayContainer = desktopById(systemtrayId);
+ systrayContainer.currentConfigGroup = ["General"];
+ systrayContainer.writeConfig("scaleIconsToFit", true);
+}
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/previews/preview.png b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/previews/preview.png
new file mode 100644
index 0000000..708bcf3
Binary files /dev/null and b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/previews/preview.png differ
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/Splash.qml b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/Splash.qml
new file mode 100644
index 0000000..8f75650
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/Splash.qml
@@ -0,0 +1,85 @@
+/*
+ SPDX-FileCopyrightText: 2014 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.kirigami 2 as Kirigami
+
+Rectangle {
+ id: root
+ color: "black"
+
+ property int stage
+
+ onStageChanged: {
+ if (stage == 2) {
+ introAnimation.running = true;
+ } else if (stage == 5) {
+ introAnimation.target = busyIndicator;
+ introAnimation.from = 1;
+ introAnimation.to = 0;
+ introAnimation.running = true;
+ }
+ }
+
+ width: 1280
+ height: 800
+
+ Component.onCompleted: stage = 2
+
+ Item {
+ id: content
+ anchors.fill: parent
+ opacity: 0
+
+ Image {
+ id: logo
+ //match SDDM/lockscreen avatar positioning
+ readonly property real size: Kirigami.Units.gridUnit * 8
+
+ anchors.centerIn: parent
+
+ asynchronous: true
+ source: "images/miasma-logo.svg"
+
+ sourceSize.width: size
+ sourceSize.height: size
+ }
+
+ // TODO: port to PlasmaComponents3.BusyIndicator
+ Image {
+ id: busyIndicator
+ //in the middle of the remaining space
+ y: parent.height - (parent.height - logo.y) / 2 - height/2
+ anchors.horizontalCenter: parent.horizontalCenter
+ asynchronous: true
+ source: "images/busywidget.svgz"
+ sourceSize.height: Kirigami.Units.gridUnit * 2
+ sourceSize.width: Kirigami.Units.gridUnit * 2
+ RotationAnimator on rotation {
+ id: rotationAnimator
+ from: 0
+ to: 360
+ // Not using a standard duration value because we don't want the
+ // animation to spin faster or slower based on the user's animation
+ // scaling preferences; it doesn't make sense in this context
+ duration: 2000
+ loops: Animation.Infinite
+ // Don't want it to animate at all if the user has disabled animations
+ running: Kirigami.Units.longDuration > 1
+ }
+ }
+ }
+
+ OpacityAnimator {
+ id: introAnimation
+ running: false
+ target: content
+ from: 0
+ to: 1
+ duration: Kirigami.Units.veryLongDuration * 2
+ easing.type: Easing.InOutQuad
+ }
+}
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/images/busywidget.svgz b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/images/busywidget.svgz
new file mode 100644
index 0000000..b7c7037
Binary files /dev/null and b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/images/busywidget.svgz differ
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/images/miasma-logo.svg b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/images/miasma-logo.svg
new file mode 100644
index 0000000..309d9f7
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/contents/splash/images/miasma-logo.svg
@@ -0,0 +1,1402 @@
+
+
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/metadata.desktop b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/metadata.desktop
new file mode 100644
index 0000000..f6d278e
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/metadata.desktop
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Comment=Vapor - SteamOS Theme based on KDE BreezeDark
+Name=Vapor
+Type=Service
+
+X-KDE-ServiceTypes=Plasma/LookAndFeel
+X-KDE-ParentApp=
+X-KDE-PluginInfo-Author=Valve
+X-KDE-PluginInfo-Category=
+X-KDE-PluginInfo-Email=
+X-KDE-PluginInfo-License=GPL-2.0+
+X-KDE-PluginInfo-Name=com.valve.vapor.desktop
+X-KDE-PluginInfo-Version=0.01
+X-KDE-PluginInfo-Website=
+X-Plasma-MainScript=defaults
+X-KDE-PluginInfo-License=GPLv2+
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/metadata.json b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/metadata.json
new file mode 100644
index 0000000..f31d521
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vapor.desktop/metadata.json
@@ -0,0 +1,23 @@
+{
+ "KPackageStructure": "Plasma/LookAndFeel",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "",
+ "Name": "Valve"
+ }
+ ],
+ "Category": "",
+ "Description": "The stock SteamOS theme",
+ "Id": "com.valve.vapor.desktop",
+ "License": "GPLv2+",
+ "Name": "Vapor",
+ "ServiceTypes": [
+ "Plasma/LookAndFeel"
+ ],
+ "Version": "0.01",
+ "Website": "https://steampowered.com/"
+ },
+ "X-KDE-ParentApp": "",
+ "X-Plasma-MainScript": "defaults"
+}
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/defaults b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/defaults
new file mode 100644
index 0000000..80a3b9b
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/defaults
@@ -0,0 +1,27 @@
+[kdeglobals][KDE]
+widgetStyle=Windows
+
+[kdeglobals][General]
+ColorScheme=VGUI
+
+[kdeglobals][Icons]
+Theme=breeze-dark
+
+[plasmarc][Theme]
+name=default
+
+[kcminputrc][Mouse]
+cursorTheme=KDE_Classic
+
+[kwinrc][WindowSwitcher]
+LayoutName=org.kde.breeze.desktop
+
+[kwinrc][DesktopSwitcher]
+LayoutName=org.kde.breeze.desktop
+
+[kwinrc][org.kde.kdecoration2]
+library=org.kde.kwin.aurorae
+theme=kwin4_decoration_qml_plastik
+
+[KSplash]
+Theme=com.valve.vapor
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/icons/deck_icon.png b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/icons/deck_icon.png
new file mode 100644
index 0000000..7e596c0
Binary files /dev/null and b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/icons/deck_icon.png differ
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.folder.js b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.folder.js
new file mode 100644
index 0000000..8cfef49
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.folder.js
@@ -0,0 +1,4 @@
+applet.wallpaperPlugin = 'org.kde.image'
+applet.currentConfigGroup = ["Wallpaper", "org.kde.image", "General"]
+applet.writeConfig("Image", "/usr/share/wallpapers/miasma-default.jxl")
+applet.reloadConfig()
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js
new file mode 100644
index 0000000..2ef00cb
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js
@@ -0,0 +1,3 @@
+applet.currentConfigGroup = ["General"]
+applet.writeConfig("icon", "distributor-logo-steamdeck")
+applet.reloadConfig()
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.systemtray.js b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.systemtray.js
new file mode 100644
index 0000000..7eaae7a
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/plasmoidsetupscripts/org.kde.plasma.systemtray.js
@@ -0,0 +1,6 @@
+systemtrayId = applet.readConfig("SystrayContainmentId");
+if (systemtrayId) {
+ const systrayContainer = desktopById(systemtrayId);
+ systrayContainer.currentConfigGroup = ["General"];
+ systrayContainer.writeConfig("scaleIconsToFit", true);
+}
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/previews/preview.png b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/previews/preview.png
new file mode 100644
index 0000000..24bc6e7
Binary files /dev/null and b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/previews/preview.png differ
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/Splash.qml b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/Splash.qml
new file mode 100644
index 0000000..8f75650
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/Splash.qml
@@ -0,0 +1,85 @@
+/*
+ SPDX-FileCopyrightText: 2014 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.kirigami 2 as Kirigami
+
+Rectangle {
+ id: root
+ color: "black"
+
+ property int stage
+
+ onStageChanged: {
+ if (stage == 2) {
+ introAnimation.running = true;
+ } else if (stage == 5) {
+ introAnimation.target = busyIndicator;
+ introAnimation.from = 1;
+ introAnimation.to = 0;
+ introAnimation.running = true;
+ }
+ }
+
+ width: 1280
+ height: 800
+
+ Component.onCompleted: stage = 2
+
+ Item {
+ id: content
+ anchors.fill: parent
+ opacity: 0
+
+ Image {
+ id: logo
+ //match SDDM/lockscreen avatar positioning
+ readonly property real size: Kirigami.Units.gridUnit * 8
+
+ anchors.centerIn: parent
+
+ asynchronous: true
+ source: "images/miasma-logo.svg"
+
+ sourceSize.width: size
+ sourceSize.height: size
+ }
+
+ // TODO: port to PlasmaComponents3.BusyIndicator
+ Image {
+ id: busyIndicator
+ //in the middle of the remaining space
+ y: parent.height - (parent.height - logo.y) / 2 - height/2
+ anchors.horizontalCenter: parent.horizontalCenter
+ asynchronous: true
+ source: "images/busywidget.svgz"
+ sourceSize.height: Kirigami.Units.gridUnit * 2
+ sourceSize.width: Kirigami.Units.gridUnit * 2
+ RotationAnimator on rotation {
+ id: rotationAnimator
+ from: 0
+ to: 360
+ // Not using a standard duration value because we don't want the
+ // animation to spin faster or slower based on the user's animation
+ // scaling preferences; it doesn't make sense in this context
+ duration: 2000
+ loops: Animation.Infinite
+ // Don't want it to animate at all if the user has disabled animations
+ running: Kirigami.Units.longDuration > 1
+ }
+ }
+ }
+
+ OpacityAnimator {
+ id: introAnimation
+ running: false
+ target: content
+ from: 0
+ to: 1
+ duration: Kirigami.Units.veryLongDuration * 2
+ easing.type: Easing.InOutQuad
+ }
+}
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/images/busywidget.svgz b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/images/busywidget.svgz
new file mode 100644
index 0000000..b7c7037
Binary files /dev/null and b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/images/busywidget.svgz differ
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/images/miasma-logo.svg b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/images/miasma-logo.svg
new file mode 100644
index 0000000..309d9f7
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/contents/splash/images/miasma-logo.svg
@@ -0,0 +1,1402 @@
+
+
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/metadata.desktop b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/metadata.desktop
new file mode 100644
index 0000000..f0f1dea
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/metadata.desktop
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Comment=VGUI2 Classic styled theme for KDE Plasma
+Name=VGUI2 Classic
+Type=Service
+
+X-KDE-ServiceTypes=Plasma/LookAndFeel
+X-KDE-ParentApp=
+X-KDE-PluginInfo-Author=Valve
+X-KDE-PluginInfo-Category=
+X-KDE-PluginInfo-Email=
+X-KDE-PluginInfo-License=GPL-2.0+
+X-KDE-PluginInfo-Name=com.valve.vgui.desktop
+X-KDE-PluginInfo-Version=0.01
+X-KDE-PluginInfo-Website=
+X-Plasma-MainScript=defaults
+X-KDE-PluginInfo-License=GPLv2+
diff --git a/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/metadata.json b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/metadata.json
new file mode 100644
index 0000000..76eec3a
--- /dev/null
+++ b/files/system/usr/share/plasma/look-and-feel/com.valve.vgui.desktop/metadata.json
@@ -0,0 +1,23 @@
+{
+ "KPackageStructure": "Plasma/LookAndFeel",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "",
+ "Name": "Valve"
+ }
+ ],
+ "Category": "",
+ "Description": "Any color you like, as long as it's green",
+ "Id": "com.valve.vgui.desktop",
+ "License": "GPLv2+",
+ "Name": "VGUI2",
+ "ServiceTypes": [
+ "Plasma/LookAndFeel"
+ ],
+ "Version": "0.01",
+ "Website": "https://steampowered.com/"
+ },
+ "X-KDE-ParentApp": "",
+ "X-Plasma-MainScript": "defaults"
+}
diff --git a/files/system/usr/share/plasma/packages/org.kde.paneltoolbox/contents/ui/main.qml b/files/system/usr/share/plasma/packages/org.kde.paneltoolbox/contents/ui/main.qml
new file mode 100644
index 0000000..486dbc2
--- /dev/null
+++ b/files/system/usr/share/plasma/packages/org.kde.paneltoolbox/contents/ui/main.qml
@@ -0,0 +1,125 @@
+/*
+ SPDX-FileCopyrightText: 2011 Sebastian Kügler
+ SPDX-FileCopyrightText: 2013 Marco Martin
+ SPDX-FileCopyrightText: 2022 Harald Sitter
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.plasmoid
+import org.kde.kirigami as Kirigami
+
+Item {
+ id: main
+
+ property bool isVertical: Plasmoid.formFactor === 3
+
+ width: Kirigami.Settings.hasTransientTouchInput
+ ? (isVertical ? Plasmoid.width : height)
+ : (isVertical
+ ? Kirigami.Units.iconSizes.medium
+ : Kirigami.Units.iconSizes.smallMedium + Kirigami.Units.smallSpacing * 2)
+ height: Kirigami.Settings.hasTransientTouchInput
+ ? (isVertical ? width : Plasmoid.height)
+ : (isVertical
+ ? Kirigami.Units.iconSizes.smallMedium + Kirigami.Units.smallSpacing * 2
+ : Kirigami.Units.iconSizes.medium)
+
+ z: 999
+
+ states: [
+ State {
+ when: Plasmoid.containment.corona.editMode
+ PropertyChanges {
+ target: main
+ visible: true
+ }
+ PropertyChanges {
+ target: main
+ opacity: mouseArea.containsMouse || Plasmoid.userConfiguring ? 1 : 0.5
+ }
+ },
+ State {
+ when: !Plasmoid.containment.corona.editMode
+ PropertyChanges {
+ target: main
+ visible: false
+ }
+ PropertyChanges {
+ target: main
+ opacity: 0
+ }
+ }
+ ]
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: Kirigami.Units.longDuration;
+ easing.type: Easing.InOutQuad;
+ }
+ }
+
+ anchors {
+ left: undefined
+ top: undefined
+ right: isVertical || !parent ? undefined : parent.right
+ bottom: isVertical && parent ? parent.bottom : undefined
+ verticalCenter: isVertical || !parent ? undefined : parent.verticalCenter
+ horizontalCenter: isVertical && parent ? parent.horizontalCenter : undefined
+ }
+
+ Kirigami.Icon {
+ source: "configure"
+
+ anchors.centerIn: mouseArea
+ width: Kirigami.Settings.hasTransientTouchInput
+ ? Kirigami.Units.iconSizes.medium
+ : Kirigami.Units.iconSizes.small
+ height: width
+ }
+
+ Connections {
+ target: Plasmoid
+ function onUserConfiguringChanged() {
+ if (Plasmoid.userConfiguring) {
+ Plasmoid.containment.corona.editMode = true;
+ toolTipArea.hideToolTip();
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: enabled
+ enabled: Plasmoid.containment.corona.editMode || Plasmoid.userConfiguring
+ onClicked: {
+ main.Plasmoid.internalAction("configure").trigger()
+ }
+ activeFocusOnTab: true
+ Keys.onPressed: event => {
+ switch (event.key) {
+ case Qt.Key_Space:
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ case Qt.Key_Select:
+ main.Plasmoid.internalAction("configure").trigger();
+ break;
+ }
+ }
+ objectName: "configurePanelButton" // used for stable accessible id
+ Accessible.name: i18ndc("plasma_toolbox_org.kde.paneltoolbox", "@info:whatsthis accessible name", "Configure Panel…")
+ Accessible.description: i18ndc("plasma_toolbox_org.kde.paneltoolbox", "@info:whatsthis accessible description", "Open Panel configuration ui")
+ Accessible.role: Accessible.Button
+ Accessible.onPressAction: main.Plasmoid.internalAction("configure").trigger();
+
+ PlasmaCore.ToolTipArea {
+ id: toolTipArea
+ anchors.fill: parent
+ mainText: main.Plasmoid.internalAction("configure").text
+ icon: "configure"
+ enabled: mouseArea.containsMouse
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/packages/org.kde.paneltoolbox/metadata.json b/files/system/usr/share/plasma/packages/org.kde.paneltoolbox/metadata.json
new file mode 100644
index 0000000..10f47f9
--- /dev/null
+++ b/files/system/usr/share/plasma/packages/org.kde.paneltoolbox/metadata.json
@@ -0,0 +1,178 @@
+{
+ "KPackageStructure": "Plasma/Generic",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "mart@kde.org",
+ "Name": "Marco Martin",
+ "Name[ar]": "ماركو مارتن",
+ "Name[ast]": "Marco Martin",
+ "Name[az]": "Marco Martin",
+ "Name[be]": "Marco Martin",
+ "Name[bg]": "Marco Martin",
+ "Name[ca@valencia]": "Marco Martin",
+ "Name[ca]": "Marco Martin",
+ "Name[cs]": "Marco Martin",
+ "Name[da]": "Marco Martin",
+ "Name[de]": "Marco Martin",
+ "Name[el]": "Marco Martin",
+ "Name[en_GB]": "Marco Martin",
+ "Name[eo]": "Marco Martin",
+ "Name[es]": "Marco Martin",
+ "Name[et]": "Marco Martin",
+ "Name[eu]": "Marco Martin",
+ "Name[fi]": "Marco Martin",
+ "Name[fr]": "Marco Martin",
+ "Name[ga]": "Marco Martin",
+ "Name[gl]": "Marco Martin",
+ "Name[he]": "מרקו מרטין",
+ "Name[hu]": "Marco Martin",
+ "Name[ia]": "Marco Martin",
+ "Name[id]": "Marco Martin",
+ "Name[ie]": "Marco Martin",
+ "Name[is]": "Marco Martin",
+ "Name[it]": "Marco Martin",
+ "Name[ja]": "Marco Martin",
+ "Name[ka]": "მაკრო მარტინი",
+ "Name[ko]": "Marco Martin",
+ "Name[lt]": "Marco Martin",
+ "Name[lv]": "Marco Martin",
+ "Name[nb]": "Marco Martin",
+ "Name[nl]": "Marco Martin",
+ "Name[nn]": "Marco Martin",
+ "Name[pl]": "Marco Martin",
+ "Name[pt]": "Marco Martin",
+ "Name[pt_BR]": "Marco Martin",
+ "Name[ro]": "Marco Martin",
+ "Name[ru]": "Marco Martin",
+ "Name[sa]": "मार्को मार्टिन्",
+ "Name[sk]": "Marco Martin",
+ "Name[sl]": "Marco Martin",
+ "Name[sv]": "Marco Martin",
+ "Name[ta]": "மார்க்கோ மார்ட்டின்",
+ "Name[tr]": "Marco Martin",
+ "Name[uk]": "Marco Martin",
+ "Name[vi]": "Marco Martin",
+ "Name[zh_CN]": "Marco Martin",
+ "Name[zh_TW]": "Marco Martin"
+ }
+ ],
+ "Category": "Toolbox",
+ "Description": "Manage Plasma panel",
+ "Description[ar]": "يدير لوحة بلازما",
+ "Description[az]": "Plasma paneli meneceri",
+ "Description[be]": "Кіраванне панэлямі Plasma",
+ "Description[bg]": "Управление на Plasma панел",
+ "Description[ca@valencia]": "Gestioneu el quadro de Plasma",
+ "Description[ca]": "Gestió del plafó del Plasma",
+ "Description[cs]": "Spravovat panel Plasma",
+ "Description[da]": "Håndtér Plasma-panel",
+ "Description[de]": "Plasma-Kontrollleiste verwalten",
+ "Description[el]": "Διαχείριση πίνακα Plasma",
+ "Description[en_GB]": "Manage Plasma panel",
+ "Description[eo]": "Administri Plasma-panelon",
+ "Description[es]": "Gestión del panel de Plasma",
+ "Description[et]": "Plasma paneeli haldamine",
+ "Description[eu]": "Kudeatu Plasma panela",
+ "Description[fi]": "Plasma-paneelin hallinta",
+ "Description[fr]": "Gérer le panneau de Plasma",
+ "Description[ga]": "Bainistigh painéal Plasma",
+ "Description[gl]": "Xestionar o panel de Plasma.",
+ "Description[he]": "ניהול לוח פלזמה",
+ "Description[hu]": "Plasma panel kezelése",
+ "Description[ia]": "Gere pannello de Plasma",
+ "Description[id]": "Kelola panel Plasma",
+ "Description[ie]": "Gerer li panel de Plasma",
+ "Description[is]": "Umsjón með Plasma-skjáborðsstiku",
+ "Description[it]": "Gestisci il pannello di Plasma",
+ "Description[ja]": "Plasma パネルを管理",
+ "Description[ka]": "Plasma-ის პანელის მორგება",
+ "Description[ko]": "Plasma 패널 관리",
+ "Description[lt]": "Tvarkyti Plasma skydelį",
+ "Description[lv]": "Pārvaldīt „Plasma“ paneli",
+ "Description[nb]": "Håndter Plasma-panel",
+ "Description[nl]": "Plasmapaneel beheren",
+ "Description[nn]": "Handsam Plasma-panel",
+ "Description[pa]": "ਪਲਾਜ਼ਮਾ ਪੈਨਲ ਦਾ ਇੰਤਜ਼ਾਮ",
+ "Description[pl]": "Zarządzanie panelem Plazmy",
+ "Description[pt]": "Gerir o painel do Plasma",
+ "Description[pt_BR]": "Gerencia o painel do Plasma",
+ "Description[ro]": "Gestionează panoul Plasma",
+ "Description[ru]": "Настройка панели Plasma",
+ "Description[sa]": "प्लाज्मा पटलस्य प्रबन्धनं कुर्वन्तु",
+ "Description[sk]": "Spravovať panel Plasma",
+ "Description[sl]": "Upravljanje plošče Plasme",
+ "Description[sv]": "Hantera Plasma-panel",
+ "Description[ta]": "பிளாஸ்மா பலகையை நிர்வகியுங்கள்",
+ "Description[tr]": "Plasma panelini yönetin",
+ "Description[uk]": "Керування панеллю Плазми",
+ "Description[vi]": "Quản lí bảng Plasma",
+ "Description[zh_CN]": "管理 Plasma 面板",
+ "Description[zh_TW]": "管理 Plasma 面板",
+ "EnabledByDefault": true,
+ "Icon": "plasma",
+ "Id": "org.kde.paneltoolbox",
+ "License": "LGPLv2+",
+ "Name": "Panel Toolbox",
+ "Name[ar]": "صندوق أدوات اللوحة",
+ "Name[az]": "Alətlər qutusu paneli",
+ "Name[be]": "Панэль інструментаў",
+ "Name[bg]": "Панелни инструменти",
+ "Name[bs]": "Panel kutija sa alatom",
+ "Name[ca@valencia]": "Quadro d'eines del quadro",
+ "Name[ca]": "Quadre d'eines del plafó",
+ "Name[cs]": "Nástroje panelu",
+ "Name[da]": "Panelværktøjskasse",
+ "Name[de]": "Werkzeugkasten für die Kontrollleiste",
+ "Name[el]": "Εργαλειοθήκη πίνακα",
+ "Name[en_GB]": "Panel Toolbox",
+ "Name[eo]": "Panela Ilaro",
+ "Name[es]": "Caja de herramientas del panel",
+ "Name[et]": "Paneeli tööriistakast",
+ "Name[eu]": "Paneleko tresna-kutxa",
+ "Name[fi]": "Paneelin työkalupakki",
+ "Name[fr]": "Boîte à outils de tableau de bord",
+ "Name[ga]": "Bosca Uirlisí Painéil",
+ "Name[gl]": "Caixa de ferramentas de panel",
+ "Name[he]": "ארגז הכלים של הלוח",
+ "Name[hu]": "Panel eszköztár",
+ "Name[ia]": "Instrumentario de pannello",
+ "Name[id]": "Perkakas Panel",
+ "Name[is]": "Verkfæri skjáborðsstiku",
+ "Name[it]": "Strumento per pannelli",
+ "Name[ja]": "パネルツールボックス",
+ "Name[ka]": "ხელსაწყოების ზოლი",
+ "Name[kk]": "Панель құралдары",
+ "Name[ko]": "패널 도구 상자",
+ "Name[lt]": "Skydelio priemonių komplektas",
+ "Name[lv]": "Paneļa rīkkaste",
+ "Name[mr]": "पटल साधने",
+ "Name[nb]": "Panelverktøykasse",
+ "Name[nds]": "Paneel-Warktüüchkist",
+ "Name[nl]": "Paneelhulpmiddelen",
+ "Name[nn]": "Panelverktøykasse",
+ "Name[pa]": "ਪੈਨਲ ਟੂਲਬਾਕਸ",
+ "Name[pl]": "Przybornik panelu",
+ "Name[pt]": "Barra do Painel",
+ "Name[pt_BR]": "Barra de ferramentas painel",
+ "Name[ro]": "Trusa de unelte a panoului",
+ "Name[ru]": "Инструменты панели",
+ "Name[sa]": "फलक उपकरणपेटी",
+ "Name[sk]": "Nástroje panelu",
+ "Name[sl]": "Orodjarna za pult",
+ "Name[sr@ijekavian]": "Панелска алатница",
+ "Name[sr@ijekavianlatin]": "Panelska alatnica",
+ "Name[sr@latin]": "Panelska alatnica",
+ "Name[sr]": "Панелска алатница",
+ "Name[sv]": "Panelverktygslåda",
+ "Name[ta]": "பலகை கருவிப்பெட்டி",
+ "Name[tg]": "Қуттии абзорҳои лавҳа",
+ "Name[tr]": "Panel Araç Kutusu",
+ "Name[uk]": "Набір інструментів панелі",
+ "Name[vi]": "Hộp công cụ bảng",
+ "Name[zh_CN]": "面板工具箱",
+ "Name[zh_TW]": "面板工具盒",
+ "Version": "0.1",
+ "Website": "https://www.kde.org/plasma-desktop"
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/config/config.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/config/config.qml
new file mode 100644
index 0000000..7fc41ee
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/config/config.qml
@@ -0,0 +1,36 @@
+/*
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.configuration
+
+ConfigModel {
+ id: configModel
+ property bool isFolder: (Plasmoid.pluginName === "org.kde.plasma.folder")
+
+ ConfigCategory {
+ name: i18nc("@title:group for configuration dialog page", "Location")
+ icon: "inode-directory"
+ source: "ConfigLocation.qml"
+ visible: configModel.isFolder
+ }
+
+ ConfigCategory {
+ name: i18nc("@title:group for configuration dialog page", "Icons")
+ icon: "preferences-desktop-icons"
+ source: "ConfigIcons.qml"
+ visible: configModel.isFolder
+ }
+
+ ConfigCategory {
+ name: i18nc("@title:group for configuration dialog page", "Filter")
+ icon: "preferences-desktop-filter"
+ source: "ConfigFilter.qml"
+ visible: configModel.isFolder
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/config/main.xml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/config/main.xml
new file mode 100644
index 0000000..85017a5
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/config/main.xml
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+ folder-symbolic
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ desktop:/
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 0
+
+
+
+ 0
+
+
+
+ false
+
+
+
+ 0
+
+
+
+ false
+
+
+
+ true
+
+
+
+ false
+
+
+
+ true
+
+
+
+ true
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+ 0
+
+
+
+ 3
+
+
+
+ 1
+
+
+
+ 2
+
+
+
+ white
+
+
+
+
+ *
+
+
+
+ 0
+
+
+
+ all/all
+
+
+
+ false
+
+
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ActionButton.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ActionButton.qml
new file mode 100644
index 0000000..2ea968d
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ActionButton.qml
@@ -0,0 +1,45 @@
+/*
+ SPDX-FileCopyrightText: 2011 Marco Martin
+ SPDX-FileCopyrightText: 2013 Sebastian Kügler
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.components as PC3
+
+PC3.ToolButton {
+ id: button
+
+ property PlasmaCore.Action qAction
+ readonly property int iconSize: Kirigami.Settings.hasTransientTouchInput
+ ? Kirigami.Units.iconSizes.medium
+ : Kirigami.Units.iconSizes.small
+
+ property alias toolTip: toolTip.text
+
+ onClicked: {
+ if (qAction) {
+ qAction.trigger()
+ }
+ if (!Plasmoid.containment.corona.editMode) {
+ appletContainer.editMode = false;
+ }
+ }
+
+ icon.width: iconSize
+ icon.height: iconSize
+
+ PC3.ToolTip {
+ id: toolTip
+ text: button.qAction ? button.qAction.text : ""
+ delay: 0
+ visible: button.hovered && text.length > 0
+ Kirigami.Theme.colorSet: Kirigami.Theme.Window
+ Kirigami.Theme.inherit: false
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/BackButtonItem.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/BackButtonItem.qml
new file mode 100644
index 0000000..b797ef3
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/BackButtonItem.qml
@@ -0,0 +1,126 @@
+/*
+ SPDX-FileCopyrightText: 2011-2013 Sebastian Kügler
+ SPDX-FileCopyrightText: 2011 Marco Martin
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.plasma.plasmoid
+
+import org.kde.ksvg as KSvg
+import org.kde.plasma.components as PlasmaComponents3
+import org.kde.kirigami as Kirigami
+
+KSvg.FrameSvgItem {
+ id: upButton
+
+ width: gridView.cellWidth
+ height: visible ? gridView.cellHeight : 0
+
+ visible: history.length !== 0
+
+ property bool ignoreClick: false
+ property bool containsDrag: false
+ property alias active: hoverActivateTimer.running
+
+ imagePath: "widgets/viewitem"
+
+ function handleDragMove() {
+ containsDrag = true;
+ hoverActivateTimer.restart();
+ }
+
+ function endDragMove() {
+ containsDrag = false;
+ hoverActivateTimer.stop();
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+
+ acceptedButtons: Qt.LeftButton | Qt.BackButton
+ hoverEnabled: true
+
+ onContainsMouseChanged: {
+ gridView.hoveredItem = null;
+ }
+
+ onPressed: mouse => {
+ if (mouse.buttons & Qt.BackButton) {
+ if (root.isPopup && dir.resolvedUrl !== dir.resolve(Plasmoid.configuration.url)) {
+ doBack();
+ upButton.ignoreClick = true;
+ }
+ }
+ }
+
+ onClicked: mouse => {
+ if (upButton.ignoreClick) {
+ upButton.ignoreClick = false;
+ return;
+ }
+
+ doBack();
+ }
+ }
+
+ Kirigami.Icon {
+ id: icon
+
+ anchors {
+ left: parent.left
+ leftMargin: Kirigami.Units.smallSpacing
+ verticalCenter: parent.verticalCenter
+ }
+
+ width: gridView.iconSize
+ height: gridView.iconSize
+
+ source: "arrow-left"
+ }
+
+ PlasmaComponents3.Label {
+ id: label
+
+ anchors {
+ left: icon.right
+ leftMargin: Kirigami.Units.smallSpacing * 2
+ verticalCenter: parent.verticalCenter
+ }
+
+ width: parent.width - icon.width - (Kirigami.Units.smallSpacing * 4);
+
+ height: undefined // Unset PlasmaComponents.Label's default.
+
+ textFormat: Text.PlainText
+
+ maximumLineCount: root.isPopup ? 1 : Plasmoid.configuration.textLines
+ wrapMode: Text.Wrap
+ elide: Text.ElideRight
+
+ text: i18nc("@action:button", "Back")
+ }
+
+ Timer {
+ id: hoverActivateTimer
+
+ interval: root.hoverActivateDelay
+
+ onTriggered: doBack()
+ }
+
+ states: [
+ State {
+ name: "hover"
+ when: mouseArea.containsMouse || upButton.containsDrag
+
+ PropertyChanges {
+ upButton.prefix: "hover"
+ }
+ }
+ ]
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/CompactRepresentation.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/CompactRepresentation.qml
new file mode 100644
index 0000000..76596cd
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/CompactRepresentation.qml
@@ -0,0 +1,74 @@
+/*
+ SPDX-FileCopyrightText: 2013-2014 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+import org.kde.draganddrop as DragDrop
+import org.kde.kirigami as Kirigami
+
+DragDrop.DropArea {
+ id: compactRoot
+ readonly property bool inPanel: [
+ PlasmaCore.Types.TopEdge,
+ PlasmaCore.Types.LeftEdge,
+ PlasmaCore.Types.RightEdge,
+ PlasmaCore.Types.BottomEdge,
+ ].includes(Plasmoid.location)
+
+ Layout.minimumWidth: Plasmoid.formFactor === PlasmaCore.Types.Horizontal ? height : Kirigami.Units.iconSizes.small
+ Layout.minimumHeight: Plasmoid.formFactor === PlasmaCore.Types.Vertical ? width : (Kirigami.Units.iconSizes.small + 2 * Kirigami.Units.iconSizes.sizeForLabels)
+
+ property FolderView folderView: null
+
+ onContainsDragChanged: contained => {
+ if (containsDrag) {
+ hoverActivateTimer.restart();
+ } else {
+ hoverActivateTimer.stop();
+ }
+ }
+
+ onDrop: event => {
+ folderView.model.dropCwd(event);
+ }
+
+ preventStealing: true
+
+ function toggle() {
+ root.expanded = !root.expanded;
+ }
+
+ Kirigami.Icon {
+ id: icon
+
+ anchors.fill: parent
+
+ active: mouseArea.containsMouse
+
+ source: Plasmoid.configuration.useCustomIcon ? Plasmoid.configuration.icon : compactRoot.folderView.model.iconName
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+
+ hoverEnabled: true
+
+ onClicked: mouse => compactRoot.toggle()
+ }
+
+ Timer {
+ id: hoverActivateTimer
+
+ interval: root.hoverActivateDelay
+
+ onTriggered: compactRoot.toggle()
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigFilter.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigFilter.qml
new file mode 100644
index 0000000..37dddc5
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigFilter.qml
@@ -0,0 +1,212 @@
+/*
+ SPDX-FileCopyrightText: 2014 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import org.kde.kirigami as Kirigami
+import org.kde.private.desktopcontainment.folder as Folder
+import org.kde.kitemmodels as KItemModels
+import org.kde.kcmutils as KCM
+
+KCM.ScrollViewKCM {
+ id: configIcons
+
+ property alias cfg_filterMode: filterMode.currentIndex
+ property alias cfg_filterPattern: filterPattern.text
+ property alias cfg_filterMimeTypes: mimeTypesModel.checkedTypes
+ property alias cfg_showHiddenFiles: showHiddenFiles.checked
+
+ KItemModels.KSortFilterProxyModel {
+ id: filteredMimeTypesModel
+
+ sourceModel: Folder.MimeTypesModel {
+ id: mimeTypesModel
+ }
+
+ filterRegularExpression: RegExp(mimeFilter.text, "i")
+ filterRoleName: "name"
+
+ sortRoleName: "name"
+ sortOrder: Qt.AscendingOrder
+
+ function checkFiltered() {
+ var types = [];
+
+ for (var i = 0; i < count; ++i) {
+ types.push(index(i, 0).data(Qt.UserRole));
+ }
+
+ mimeTypesModel.checkedTypes = types;
+ }
+
+ function uncheckFiltered() {
+ var types = [];
+
+ for (var i = 0; i < count; ++i) {
+ types.push(index(i, 0).data(Qt.UserRole));
+ }
+
+ mimeTypesModel.checkedTypes = mimeTypesModel.checkedTypes
+ .filter(x => types.indexOf(x) === -1);
+ }
+ }
+
+ header: Kirigami.FormLayout {
+ ComboBox {
+ id: filterMode
+ Kirigami.FormData.label: i18nc("@label:listbox filter mode", "Files:")
+ model: [i18nc("@item:inlistbox filter mode", "Show all"), i18nc("@item:inlistbox filter mode", "Show matching"), i18nc("@item:inlistbox filter mode", "Hide matching")]
+ }
+
+ TextField {
+ id: filterPattern
+ Kirigami.FormData.label: i18nc("@label:textbox", "File name pattern:")
+ enabled: (filterMode.currentIndex > 0)
+ inputMethodHints: Qt.ImhNoPredictiveText
+ }
+
+ Kirigami.SearchField {
+ id: mimeFilter
+ Kirigami.FormData.label: i18nc("@label:textbox filter list by", "File types:")
+ enabled: (filterMode.currentIndex > 0)
+ }
+
+ CheckBox {
+ id: showHiddenFiles
+ Kirigami.FormData.label: i18nc("@option:check prefix", "Show hidden files:")
+ }
+ }
+
+ view: ListView {
+ id: mimeTypesView
+ clip: true
+ enabled: (filterMode.currentIndex > 0)
+
+ // Signal the delegates listen to when user presses space to toggle current row.
+ signal toggleCurrent()
+
+
+ model: filteredMimeTypesModel
+ property real columnSize: Kirigami.Units.gridUnit * 15
+ headerPositioning: ListView.OverlayHeader
+
+ Keys.onSpacePressed: toggleCurrent()
+
+ header: HorizontalHeaderView {
+ id: headerView
+ z: 9
+ implicitWidth: mimeTypesView.width
+ rowHeightProvider: function () {
+ return Kirigami.Units.gridUnit * 2
+ }
+ clip: true // This removes event handling blocking by the header
+ model: ListModel {
+ Component.onCompleted: {
+ append({ display: i18nc("@title:column", "File Type") });
+ append({ display: i18nc("@title:column", "Description") });
+ }
+ }
+ interactive: false
+ columnWidthProvider: function(column) {
+ if (column === 0) {
+ return mimeTypesView.columnSize;
+ } else {
+ return mimeTypesView.width - mimeTypesView.columnSize;
+ }
+ }
+ }
+
+ delegate: ItemDelegate {
+ id: delegate
+ width: mimeTypesView.width
+ required property string name
+ required property string comment
+ required property var decoration
+
+ contentItem: RowLayout {
+ Layout.fillWidth: true
+ Layout.preferredHeight: Kirigami.Units.iconSizes.small
+ RowLayout {
+ Layout.preferredWidth: mimeTypesView.columnSize
+ Layout.maximumWidth: mimeTypesView.columnSize
+ Layout.fillHeight: true
+ CheckBox {
+ Layout.fillHeight: true
+ checked: mimeTypesModel.checkedTypes.indexOf(delegate.name) >= 0
+ onToggled: {
+ let idx = mimeTypesModel.checkedTypes.indexOf(delegate.name);
+ if (idx >= 0) {
+ mimeTypesModel.checkedTypes.splice(idx, 1);
+ } else {
+ mimeTypesModel.checkedTypes.push(delegate.name)
+ }
+ }
+ }
+ Kirigami.Icon {
+ Layout.fillHeight: true
+ implicitWidth: Kirigami.Units.iconSizes.small
+ implicitHeight: Kirigami.Units.iconSizes.small
+ animated: false // TableView reuses delegates, avoid animation when sorting/filtering.
+ source: delegate.decoration
+ }
+ Label {
+ text: delegate.name
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+ Label {
+ text: delegate.comment
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+ }
+ }
+ footer: RowLayout {
+ id: selectLayout
+ Button {
+ id: selectAllButton
+ enabled: (filterMode.currentIndex > 0)
+ icon.name: "edit-select-all"
+ ToolTip.delay: Kirigami.Units.toolTipDelay
+ ToolTip.visible: (Kirigami.Settings.isMobile ? pressed : hovered) && ToolTip.text.length > 0
+ ToolTip.text: i18nc("@action:button tooltip only Select all filetypes", "Select All")
+ onClicked: filteredMimeTypesModel.checkFiltered()
+ }
+
+ Button {
+ id: deselectAllButton
+ enabled: (filterMode.currentIndex > 0)
+ icon.name: "edit-select-none"
+ ToolTip.delay: Kirigami.Units.toolTipDelay
+ ToolTip.visible: (Kirigami.Settings.isMobile ? pressed : hovered) && ToolTip.text.length > 0
+ ToolTip.text: i18nc("@action:button tooltip only Deselect all filetypes", "Deselect All")
+ onClicked: filteredMimeTypesModel.uncheckFiltered()
+ }
+
+ Button {
+ enabled: (filterMode.currentIndex > 0)
+ icon.name: filteredMimeTypesModel.sortOrder === Qt.AscendingOrder ? "view-sort-ascending-symbolic" : "view-sort-descending-symbolic"
+ ToolTip.delay: Kirigami.Units.toolTipDelay
+ ToolTip.visible: (Kirigami.Settings.isMobile ? pressed : hovered) && ToolTip.text.length > 0
+ ToolTip.text: i18nc("@action:button tooltip only, ascending/descending", "Switch Sort Order")
+ onClicked: {
+ filteredMimeTypesModel.sortOrder = filteredMimeTypesModel.sortOrder === Qt.AscendingOrder ? Qt.DescendingOrder : Qt.AscendingOrder;
+ filteredMimeTypesModel.sort(0, filteredMimeTypesModel.sortOrder);
+ }
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigIcons.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigIcons.qml
new file mode 100644
index 0000000..29ac522
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigIcons.qml
@@ -0,0 +1,358 @@
+/*
+ SPDX-FileCopyrightText: 2014 Eike Hein
+ SPDX-FileCopyrightText: 2015 Kai Uwe Broulik
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.iconthemes as KIconThemes
+import org.kde.config // for KAuthorized
+import org.kde.kirigami as Kirigami
+import org.kde.kcmutils as KCM
+
+KCM.SimpleKCM {
+ id: configIcons
+
+ property bool isPopup: (Plasmoid.location !== PlasmaCore.Types.Floating)
+
+ property string cfg_icon: Plasmoid.configuration.icon
+ property alias cfg_useCustomIcon: useCustomIcon.checked
+ property alias cfg_arrangement: arrangement.currentIndex
+ property alias cfg_alignment: alignment.currentIndex
+ property bool cfg_locked
+ property alias cfg_sortMode: sortMode.mode
+ property alias cfg_sortDesc: sortDesc.checked
+ property alias cfg_sortDirsFirst: sortDirsFirst.checked
+ property alias cfg_toolTips: toolTips.checked
+ property alias cfg_selectionMarkers: selectionMarkers.checked
+ property alias cfg_renameInline: renameInline.checked
+ property alias cfg_popups: popups.checked
+ property alias cfg_previews: previews.checked
+ property var cfg_previewPlugins
+ property alias cfg_viewMode: viewMode.currentIndex
+ property alias cfg_iconSize: iconSize.value
+ property alias cfg_labelWidth: labelWidth.currentIndex
+ property alias cfg_textLines: textLines.value
+
+ readonly property bool lockedByKiosk: !KAuthorized.authorize("editable_desktop_icons")
+
+ KIconThemes.IconDialog {
+ id: iconDialog
+ onIconNameChanged: iconName => configIcons.cfg_icon = iconName || "folder-symbolic";
+ }
+
+ Kirigami.FormLayout {
+ // Panel button
+ RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+ visible: configIcons.isPopup
+
+ Kirigami.FormData.label: i18nc("@title:group prefix for checkbox + button", "Panel button:")
+
+ CheckBox {
+ id: useCustomIcon
+ visible: configIcons.isPopup
+ checked: configIcons.cfg_useCustomIcon
+ text: i18nc("@option:check", "Use a custom icon")
+ }
+
+ Button {
+ id: iconButton
+ Layout.minimumWidth: Kirigami.Units.iconSizes.large + Kirigami.Units.smallSpacing * 2
+ Layout.maximumWidth: Layout.minimumWidth
+ Layout.minimumHeight: Layout.minimumWidth
+ Layout.maximumHeight: Layout.minimumWidth
+
+ checkable: true
+ enabled: useCustomIcon.checked
+
+ onClicked: {
+ checked = Qt.binding(() =>
+ iconMenu.status === PlasmaExtras.Menu.Open);
+
+ iconMenu.open(0, height);
+ }
+
+ Kirigami.Icon {
+ anchors.centerIn: parent
+ width: Kirigami.Units.iconSizes.large
+ height: width
+ source: configIcons.cfg_icon
+ }
+ }
+
+ PlasmaExtras.Menu {
+ id: iconMenu
+ visualParent: iconButton
+
+ PlasmaExtras.MenuItem {
+ text: i18nc("@item:inmenu Open icon chooser dialog", "Choose…")
+ icon: "document-open-folder"
+ onClicked: iconDialog.open()
+ }
+
+ PlasmaExtras.MenuItem {
+ text: i18nc("@item:inmenu Reset icon to default", "Clear Icon")
+ icon: "edit-clear"
+ onClicked: configIcons.cfg_icon = "folder-symbolic";
+ }
+ }
+ }
+
+ Item {
+ visible: configIcons.isPopup
+ Kirigami.FormData.isSection: true
+ }
+
+
+
+ // Arrangement section
+ ComboBox {
+ id: arrangement
+ Layout.fillWidth: true
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+
+ Kirigami.FormData.label: i18nc("@label:listbox columns/rows", "Arrangement:")
+
+ model: [
+ i18nc("@item:inlistbox arrangement of icons", "In Columns"),
+ i18nc("@item:inlistbox arrangement of icons", "In Rows"),
+ ]
+ }
+
+ ComboBox {
+ id: alignment
+ Layout.fillWidth: true
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+
+ Kirigami.FormData.label: i18nc("@label:listbox, LtR/RtL", "Sort Alignment:")
+
+ model: {
+ const ltrText = i18nc("@item:inlistbox alignment of icons", "Left-to-Right");
+ const rtlText = i18nc("@item:inlistbox alignment of icons", "Right-to-Left");
+ if (Application.layoutDirection === Qt.LeftToRight) {
+ return [ltrText, rtlText];
+ }
+ else {
+ return [rtlText, ltrText];
+ }
+ }
+ }
+
+ CheckBox {
+ id: locked
+ visible: ("containmentType" in Plasmoid)
+ checked: configIcons.cfg_locked || configIcons.lockedByKiosk
+ enabled: !configIcons.lockedByKiosk
+
+ onCheckedChanged: {
+ if (!configIcons.lockedByKiosk) {
+ configIcons.cfg_locked = checked;
+ }
+ }
+
+ text: i18nc("@option:check lock icon positions", "Lock in place")
+ }
+
+ Item {
+ Kirigami.FormData.isSection: true
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+ }
+
+
+ // Sorting section
+ ComboBox {
+ id: sortMode
+ Layout.fillWidth: true
+
+ Kirigami.FormData.label: i18nc("@label:listbox sort items by field", "Sort by:")
+
+ property int mode
+ // FIXME TODO HACK: This maps the combo box list model to the KDirModel::ModelColumns
+ // enum, which should be done in C++.
+ property var indexToMode: [-1, 0, 1, 6, 2]
+ property var modeToIndex: {'-1': '0', '0': '1', '1': '2', '6': '3', '2': '4'}
+
+ model: [i18nc("@item:inlistbox sort icons manually", "Manual"),
+ i18nc("@item:inlistbox sort icons by name", "Name"),
+ i18nc("@item:inlistbox sort icons by size", "Size"),
+ i18nc("@item:inlistbox sort icons by file type", "Type"),
+ i18nc("@item:inlistbox sort icons by date", "Date")]
+
+ Component.onCompleted: currentIndex = modeToIndex[mode]
+ onActivated: index => mode = indexToMode[index]
+ }
+
+ CheckBox {
+ id: sortDesc
+
+ enabled: sortMode.currentIndex !== 0
+
+ text: i18nc("@option:check sort icons in descending order", "Descending")
+ }
+
+ CheckBox {
+ id: sortDirsFirst
+
+ enabled: sortMode.currentIndex !== 0
+
+ text: i18nc("@option:check sort icons with folders first", "Folders first")
+ }
+
+ Item {
+ Kirigami.FormData.isSection: true
+ }
+
+
+ // View Mode section (only if we're a pop-up)
+ ComboBox {
+ id: viewMode
+ visible: configIcons.isPopup
+ Layout.fillWidth: true
+
+ Kirigami.FormData.label: i18nc("whether to use icon or list view", "View mode:")
+
+ model: [i18nc("@item:inlistbox show icons in a list", "List"),
+ i18nc("@item:inlistbox show icons in a grid", "Grid")]
+ }
+
+
+ // Size section
+ Slider {
+ id: iconSize
+
+ Layout.fillWidth: true
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+
+ Kirigami.FormData.label: i18nc("@label:slider", "Icon size:")
+
+ from: 0
+ to: 6
+ stepSize: 1
+ snapMode: Slider.SnapAlways
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ Label {
+ Layout.alignment: Qt.AlignLeft
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+
+ text: i18nc("@item:inrange smallest icon size", "Small")
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ Label {
+ Layout.alignment: Qt.AlignRight
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+
+ text: i18nc("@item:inrange largest icon size", "Large")
+ }
+ }
+
+ ComboBox {
+ id: labelWidth
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+ Layout.fillWidth: true
+
+ Kirigami.FormData.label: i18nc("@label:listbox", "Label width:")
+
+ model: [
+ i18nc("@item:inlistbox how long a text label should be", "Narrow"),
+ i18nc("@item:inlistbox how long a text label should be", "Medium"),
+ i18nc("@item:inlistbox how long a text label should be", "Wide"),
+ ]
+ }
+
+ SpinBox {
+ id: textLines
+ visible: !configIcons.isPopup || viewMode.currentIndex === 1 /* Icons mode */
+
+ Kirigami.FormData.label: i18nc("@label:spinbox", "Text lines:")
+
+ from: 1
+ to: 10
+ stepSize: 1
+ }
+
+ Item {
+ Kirigami.FormData.isSection: true
+ }
+
+
+ // Features section
+ CheckBox {
+ id: toolTips
+
+ Kirigami.FormData.label: i18nc("@title:group prefix for checkbox group", "When hovering over icons:")
+
+ text: i18nc("@option:check When hovering over icons…", "Show tooltips")
+ }
+
+ CheckBox {
+ id: selectionMarkers
+ visible: Application.styleHints.singleClickActivation
+
+ text: i18nc("@option:check When hovering over icons…", "Show selection markers")
+ }
+
+ CheckBox {
+ id: popups
+ visible: !configIcons.isPopup
+
+ text: i18nc("@option:check When hovering over icons…", "Show folder preview popups")
+ }
+
+ Item {
+ Kirigami.FormData.isSection: true
+ }
+
+ CheckBox {
+ id: renameInline
+
+ Kirigami.FormData.label: i18nc("@label prefix for checkbox", "Rename:")
+
+ visible: !selectionMarkers.visible
+
+ text: i18nc("@option:check", "Rename inline by clicking selected item's text")
+ }
+
+ Item {
+ Kirigami.FormData.isSection: true
+ visible: renameInline.visible
+ }
+
+ CheckBox {
+ id: previews
+
+ Kirigami.FormData.label: i18nc("@title:group prefix for checkbox and button", "Previews:")
+
+ text: i18nc("@option:check", "Show preview thumbnails")
+ }
+
+ Button {
+ id: previewSettings
+ Layout.fillWidth: true
+
+ icon.name: "configure"
+ text: i18nc("@action:button opens dialog", "Configure Preview Plugins…")
+
+ onClicked: {
+ const component = Qt.createComponent(Qt.resolvedUrl("FolderItemPreviewPluginsDialog.qml"));
+ component.incubateObject(configIcons.Window.window.contentItem, {
+ "previewPlugins": configIcons.cfg_previewPlugins,
+ }, Qt.Asynchronous);
+ component.destroy();
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigLocation.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigLocation.qml
new file mode 100644
index 0000000..777b656
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigLocation.qml
@@ -0,0 +1,213 @@
+/*
+ SPDX-FileCopyrightText: 2014 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import org.kde.plasma.plasmoid
+import org.kde.kirigami as Kirigami
+import org.kde.kcmutils as KCM
+
+import org.kde.private.desktopcontainment.folder as Folder
+
+KCM.SimpleKCM {
+ id: configLocation
+
+ property string cfg_url
+ property alias cfg_labelMode: labelMode.currentIndex
+ property alias cfg_labelText: labelText.text
+ property bool titleVisible: Plasmoid.containment != Plasmoid
+
+ onCfg_urlChanged: applyConfig()
+
+ function applyConfig(force) {
+ if (!force && locationGroup.checkedButton !== null) {
+ return;
+ }
+
+ if (cfg_url === "desktop:/") {
+ locationDesktop.checked = true;
+ locationCustomValue.text = "";
+ } else if (cfg_url === "activities:/current/") {
+ locationCurrentActivity.checked = true;
+ locationCustomValue.text = "";
+ } else {
+ var placeForUrl = placesModel.indexForUrl(cfg_url);
+
+ if (placeForUrl !== -1) {
+ locationPlaceValue.currentIndex = placeForUrl; // needs to happen before checking the radiobutton
+ locationPlace.checked = true;
+ locationCustomValue.text = "";
+ } else {
+ locationCustom.checked = true;
+ locationCustomValue.text = cfg_url;
+ }
+ }
+
+ locationPlaceValue.enabled = locationPlace.checked;
+ }
+
+ Folder.PlacesModel {
+ id: placesModel
+ showDesktopEntry: false
+
+ onPlacesChanged: configLocation.applyConfig(true)
+ }
+
+ ButtonGroup {
+ id: locationGroup
+
+ buttons: [locationDesktop, locationCurrentActivity, locationPlace, locationCustom]
+
+ onCheckedButtonChanged: {
+ if (checkedButton === locationDesktop) {
+ configLocation.cfg_url = "desktop:/";
+ } else if (checkedButton === locationCurrentActivity) {
+ configLocation.cfg_url = "activities:/current/";
+ }
+ }
+ }
+
+ Kirigami.FormLayout {
+
+ RadioButton {
+ id: locationDesktop
+ implicitHeight: locationCustomValue.implicitHeight
+
+ Kirigami.FormData.label: i18nc("@title:group form label for radiobutton group", "Show:")
+
+ text: i18nc("@option:radio", "Desktop folder")
+ }
+
+ RadioButton {
+ id: locationCurrentActivity
+ visible: placesModel.activityLinkingEnabled
+ implicitHeight: locationCustomValue.implicitHeight
+
+ text: i18nc("@option:radio", "Files linked to the current activity")
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ spacing: Kirigami.Units.smallSpacing
+ RadioButton {
+ id: locationPlace
+
+ text: i18nc("@option:radio also label for combobox", "Places panel item:")
+ Layout.minimumWidth: Math.max(locationPlace.implicitWidth, locationCustom.implicitWidth, labelMode.implicitWidth)
+
+ onCheckedChanged: {
+ locationPlaceValue.enabled = checked;
+ }
+ }
+
+ ComboBox {
+ id: locationPlaceValue
+
+ Layout.fillWidth: true
+
+ model: placesModel
+ textRole: "display"
+
+ enabled: true
+
+ onEnabledChanged: {
+ if (enabled && currentIndex !== -1) {
+ configLocation.cfg_url = Folder.DesktopSchemeHelper.getDesktopUrl(placesModel.urlForIndex(currentIndex));
+ }
+ }
+
+ onActivated: index => {
+ configLocation.cfg_url = Folder.DesktopSchemeHelper.getDesktopUrl(placesModel.urlForIndex(index));
+ }
+ }
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ spacing: Kirigami.Units.smallSpacing
+ RadioButton {
+ id: locationCustom
+ Layout.minimumWidth: Math.max(locationPlace.implicitWidth, locationCustom.implicitWidth, labelMode.implicitWidth)
+
+ text: i18nc("@option:radio also label for text field", "Custom location:")
+ }
+
+ TextField {
+ id: locationCustomValue
+ enabled: locationCustom.checked
+ Layout.fillWidth: true
+
+ placeholderText: i18nc("@info:placeholder custom location", "Type path or URL…")
+
+ inputMethodHints: Qt.ImhNoPredictiveText
+
+ onEnabledChanged: {
+ if (enabled && text !== "") {
+ configLocation.cfg_url = Folder.DesktopSchemeHelper.getDesktopUrl(text);
+ }
+ }
+
+ onTextChanged: {
+ if (enabled) {
+ configLocation.cfg_url = Folder.DesktopSchemeHelper.getDesktopUrl(text);
+ }
+ }
+ }
+ Button {
+ icon.name: "document-open"
+
+ enabled: locationCustom.checked
+
+ onClicked: {
+ directoryPicker.open();
+ }
+ }
+ Folder.DirectoryPicker {
+ id: directoryPicker
+
+ onUrlChanged: {
+ locationCustomValue.text = Folder.DesktopSchemeHelper.getDesktopUrl(url);
+ }
+ }
+ }
+
+ Item {
+ visible: configLocation.titleVisible
+ Kirigami.FormData.isSection: true
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ spacing: Kirigami.Units.smallSpacing
+ visible: configLocation.titleVisible
+ Kirigami.FormData.label: i18nc("@label:textbox custom widget title", "Title:")
+
+ ComboBox {
+ id: labelMode
+ Layout.minimumWidth: Math.max(locationPlace.implicitWidth, locationCustom.implicitWidth, labelMode.implicitWidth)
+ visible: configLocation.titleVisible
+
+
+ model: [
+ i18nc("@item:inlistbox no title", "None"),
+ i18nc("@item:inlistbox default title", "Default"),
+ i18nc("@item:inlistbox full path as title", "Full path"),
+ i18nc("@item:inlistbox title from text input field", "Custom")
+ ]
+ }
+
+ TextField {
+ id: labelText
+ Layout.fillWidth: true
+ enabled: (labelMode.currentIndex === 3)
+
+ placeholderText: i18nc("@info:placeholder custom window title", "Enter title…")
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigOverlay.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigOverlay.qml
new file mode 100644
index 0000000..5e02867
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/ConfigOverlay.qml
@@ -0,0 +1,256 @@
+/*
+ SPDX-FileCopyrightText: 2019 Marco Martin
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.kirigami as Kirigami
+import org.kde.ksvg as KSvg
+
+
+import org.kde.plasma.private.containmentlayoutmanager as ContainmentLayoutManager
+
+ContainmentLayoutManager.ConfigOverlayWithHandles {
+ id: overlay
+
+ SequentialAnimation {
+ id: removeAnim
+
+ NumberAnimation {
+ target: overlay.itemContainer
+ property: "scale"
+ from: 1
+ to: 0
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ ScriptAction {
+ script: {
+ appletContainer.applet.plasmoid.internalAction("remove").trigger();
+ appletContainer.editMode = false;
+ }
+ }
+ }
+
+ KSvg.FrameSvgItem {
+ id: frame
+
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: {
+ let heightDifference = Math.round((frame.height - overlay.height) / 2)
+ if (heightDifference > 0) {
+ if (heightDifference > overlay.topAvailableSpace) {
+ return heightDifference - overlay.topAvailableSpace
+ }
+ if (heightDifference > overlay.bottomAvailableSpace) {
+ return overlay.bottomAvailableSpace - heightDifference
+ }
+ }
+ return 0
+ }
+ x: overlay.rightAvailableSpace > width + Kirigami.Units.gridUnit
+ ? parent.width + Kirigami.Units.gridUnit
+ : -width - Kirigami.Units.gridUnit
+
+ // This MouseArea is used to block input between the applet and the handle, to not make it steal by other applets
+ MouseArea {
+ anchors {
+ top: parent.top
+ bottom: parent.bottom
+ }
+ z: -1
+ x: overlay.rightAvailableSpace > parent.width + Kirigami.Units.gridUnit ? -Kirigami.Units.gridUnit : 0
+ width: Kirigami.Units.gridUnit + parent.width
+ hoverEnabled: true
+ }
+ transform: Translate {
+ x: overlay.open ? 0 : (overlay.rightAvailableSpace > frame.width + Kirigami.Units.gridUnit ? -frame.width : frame.width)
+
+ Behavior on x {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ width: layout.implicitWidth + margins.left + margins.right
+ height: Math.max(layout.implicitHeight + margins.top + margins.bottom, parent.height)
+ imagePath: "widgets/background"
+
+ ColumnLayout {
+ id: layout
+ anchors {
+ fill: parent
+ topMargin: parent.margins.top
+ leftMargin: parent.margins.left
+ bottomMargin: parent.margins.bottom
+ rightMargin: parent.margins.right
+ }
+
+ ActionButton {
+ id: rotateButton
+ icon.name: "object-rotate-left-symbolic"
+ toolTip: !rotateHandle.pressed ? i18nc("@action:button tooltip rotate widget", "Click and drag to rotate") : ""
+ action: applet ? applet.plasmoid.internalAction("rotate") : null
+ down: rotateHandle.pressed
+ Component.onCompleted: {
+ if (action !== null) {
+ action.enabled = true;
+ }
+ }
+ MouseArea {
+ id: rotateHandle
+ anchors.fill: parent
+
+ property int startRotation
+ property real startCenterRelativeAngle
+
+ function pointAngle(pos: point): real {
+ var r = Math.sqrt(pos.x * pos.x + pos.y * pos.y);
+ var cosine = pos.x / r;
+
+ if (pos.y >= 0) {
+ return Math.acos(cosine) * (180/Math.PI);
+ } else {
+ return -Math.acos(cosine) * (180/Math.PI);
+ }
+ }
+
+ function centerRelativePos(x: real, y: real): point {
+ var mousePos = overlay.itemContainer.parent.mapFromItem(rotateButton, x, y);
+ var centerPos = overlay.itemContainer.parent.mapFromItem(overlay.itemContainer, overlay.itemContainer.width/2, overlay.itemContainer.height/2);
+
+ mousePos.x -= centerPos.x;
+ mousePos.y -= centerPos.y;
+ return mousePos;
+ }
+
+ onPressed: mouse => {
+ mouse.accepted = true;
+ startRotation = overlay.itemContainer.rotation;
+ startCenterRelativeAngle = pointAngle(centerRelativePos(mouse.x, mouse.y));
+ }
+
+ onPositionChanged: mouse => {
+ var rot = startRotation % 360;
+ var snap = 4;
+ var newRotation = Math.round(pointAngle(centerRelativePos(mouse.x, mouse.y)) - startCenterRelativeAngle + startRotation);
+
+ if (newRotation < 0) {
+ newRotation = newRotation + 360;
+ } else if (newRotation >= 360) {
+ newRotation = newRotation % 360;
+ }
+
+ snapIt(0);
+ snapIt(90);
+ snapIt(180);
+ snapIt(270);
+
+ function snapIt(snapTo) {
+ if (newRotation > (snapTo - snap) && newRotation < (snapTo + snap)) {
+ newRotation = snapTo;
+ }
+ }
+
+ overlay.itemContainer.rotation = newRotation;
+ }
+
+ onReleased: mouse => {
+ // save rotation
+ overlay.itemContainer.layout.save();
+ }
+ }
+ }
+
+ ActionButton {
+ icon.name: "configure"
+ visible: qAction && qAction.enabled && (applet && applet.plasmoid.hasConfigurationInterface)
+ qAction: applet ? applet.plasmoid.internalAction("configure") : null
+ Component.onCompleted: {
+ if (qAction) {
+ qAction.enabled = true;
+ }
+ }
+ }
+
+ ActionButton {
+ icon.name: "show-background"
+ toolTip: checked ? i18nc("@action:button tooltip hide widget background", "Hide Background") : i18nc("@action:button tooltip", "Show Background")
+ visible: (applet.plasmoid.backgroundHints & PlasmaCore.Types.ConfigurableBackground)
+ checked: applet.plasmoid.effectiveBackgroundHints & PlasmaCore.Types.StandardBackground || applet.plasmoid.effectiveBackgroundHints & PlasmaCore.Types.TranslucentBackground
+ checkable: true
+ onClicked: {
+ if (checked) {
+ if (applet.plasmoid.backgroundHints & PlasmaCore.Types.StandardBackground || applet.plasmoid.backgroundHints & PlasmaCore.Types.TranslucentBackground) {
+ applet.plasmoid.userBackgroundHints = applet.plasmoid.backgroundHints;
+ } else {
+ applet.plasmoid.userBackgroundHints = PlasmaCore.Types.StandardBackground;
+ }
+ } else {
+ if (applet.plasmoid.backgroundHints & PlasmaCore.Types.ShadowBackground || applet.plasmoid.backgroundHints & PlasmaCore.Types.NoBackground) {
+ applet.plasmoid.userBackgroundHints = applet.plasmoid.backgroundHints;
+ } else {
+ applet.plasmoid.userBackgroundHints = PlasmaCore.Types.ShadowBackground;
+ }
+ }
+ }
+ }
+
+ MouseArea {
+ drag.target: overlay.itemContainer
+ Layout.minimumHeight: Kirigami.Units.gridUnit * 3
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ cursorShape: containsPress ? Qt.DragMoveCursor : Qt.OpenHandCursor
+ hoverEnabled: true
+ onPressed: mouse => {
+ overlay.itemContainer.layout.releaseSpace(overlay.itemContainer);
+ }
+ onPositionChanged: mouse => {
+ if (!pressed) {
+ return;
+ }
+ overlay.itemContainer.layout.showPlaceHolderForItem(overlay.itemContainer);
+ var dragPos = mapToItem(overlay.itemContainer, mouse.x, mouse.y);
+ overlay.itemContainer.userDrag(Qt.point(overlay.itemContainer.x, overlay.itemContainer.y), dragPos);
+ }
+ onReleased: mouse => {
+ overlay.itemContainer.layout.hidePlaceHolder();
+ overlay.itemContainer.layout.positionItem(overlay.itemContainer);
+ }
+ }
+
+ ActionButton {
+ id: closeButton
+ icon.name: "edit-delete-remove"
+ toolTip: i18nc("@action:button tooltip remove widget", "Remove")
+ visible: {
+ if (!applet) {
+ return false;
+ }
+ var a = applet.plasmoid.internalAction("remove");
+ return a && a.enabled || false;
+ }
+ // we don't set action, since we want to catch the button click,
+ // animate, and then trigger the "remove" action
+ // Triggering the action is handled in the overlay.itemContainer, we just
+ // Q_EMIT a signal here to avoid the applet-gets-removed-before-we-
+ // can-animate it race condition.
+ onClicked: {
+ removeAnim.restart();
+ }
+ Component.onCompleted: {
+ var a = applet.plasmoid.internalAction("remove");
+ if (a) {
+ a.enabled = true;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemActionButton.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemActionButton.qml
new file mode 100644
index 0000000..e71eee0
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemActionButton.qml
@@ -0,0 +1,77 @@
+/*
+ SPDX-FileCopyrightText: 2014 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.plasmoid
+import org.kde.kirigami as Kirigami
+import org.kde.ksvg as KSvg
+
+KSvg.SvgItem {
+ id: actionButton
+
+ width: {
+ if (!visible) {
+ return 0;
+ }
+ switch (Plasmoid.configuration.iconSize) {
+ case 0: return Kirigami.Units.iconSizes.small;
+ case 1: return Kirigami.Units.iconSizes.small;
+ case 2: return Kirigami.Units.iconSizes.smallMedium;
+ case 3: return Kirigami.Units.iconSizes.smallMedium;
+ case 4: return Kirigami.Units.iconSizes.smallMedium;
+ case 5: return Kirigami.Units.iconSizes.medium;
+ case 6: return Kirigami.Units.iconSizes.large;
+ default: return Kirigami.Units.iconSizes.small;
+ }
+ }
+ height: width
+
+ signal clicked()
+
+ property string element
+
+ svg: KSvg.Svg {
+ imagePath: "widgets/action-overlays"
+ multipleImages: true
+ size: Qt.size(16, 16)
+ }
+ elementId: element + "-normal"
+
+ Behavior on opacity {
+ NumberAnimation { duration: Kirigami.Units.shortDuration }
+ }
+
+ MouseArea {
+ id: actionButtonMouseArea
+
+ anchors.fill: actionButton
+
+ acceptedButtons: Qt.LeftButton
+ hoverEnabled: true
+
+ onClicked: mouse => actionButton.clicked()
+
+ states: [
+ State {
+ name: "hover"
+ when: actionButtonMouseArea.containsMouse && !actionButtonMouseArea.pressed
+
+ PropertyChanges {
+ actionButton.elementId: actionButton.element + "-hover"
+ }
+ },
+ State {
+ name: "pressed"
+ when: actionButtonMouseArea.pressed
+
+ PropertyChanges {
+ actionButton.elementId: actionButton.element + "-pressed"
+ }
+ }
+ ]
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemDelegate.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemDelegate.qml
new file mode 100644
index 0000000..54f4447
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemDelegate.qml
@@ -0,0 +1,489 @@
+/*
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Window
+import Qt5Compat.GraphicalEffects
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.extras as PlasmaExtras
+
+import org.kde.kirigami as Kirigami
+
+import org.kde.private.desktopcontainment.folder as Folder
+
+Item {
+ id: main
+
+ required property var model
+
+ property int index: model.index
+ property string name: model.blank ? "" : model.display
+ property string nameWrapped: model.blank ? "" : model.displayWrapped
+ property bool blank: model.blank
+ property bool selected: model.blank ? false : model.selected
+ property bool isDir: loader.item ? loader.item.isDir : false
+ property bool isOnRootView: false
+ property /*FolderViewDialog*/ Folder.SubDialog popupDialog: loader.item ? loader.item.popupDialog : null
+ property Item iconArea: loader.item ? loader.item.iconArea : null
+ property Item label: loader.item ? loader.item.label : null
+ property Item labelArea: loader.item ? loader.item.labelArea : null
+ property Item actionsOverlay: loader.item ? loader.item.actionsOverlay : null
+ property Item hoverArea: loader.item ? loader.item.hoverArea : null
+ property Item frame: loader.item ? loader.item.frame : null
+ property PlasmaCore.ToolTipArea toolTip: loader.item ? loader.item.toolTip : null
+ property real contentHeight: loader.item && !root.useListViewMode ? loader.item.contentHeight : null
+ Accessible.name: name
+ Accessible.role: Accessible.Canvas
+
+ // This MouseArea exists to intercept press and hold; preventing edit mode
+ // from being triggered when pressing and holding on an icon (if there is one).
+ MouseArea {
+ anchors.fill: parent
+ visible: !main.blank
+ }
+
+ function openPopup() {
+ if (isDir) {
+ loader.item.openPopup();
+ }
+ }
+
+ function closePopup() {
+ if (popupDialog && popupDialog.allowClosing) {
+ (popupDialog as FolderViewDialog).requestDestroy();
+ loader.item.popupDialog = null;
+ }
+ }
+
+ Loader {
+ id: loader
+
+ // On the desktop we pad our cellSize to avoid a gap at the right/bottom of the screen.
+ // The padding per item is quite small and causes the delegate to be positioned on fractional pixels
+ // leading to blurry rendering. The Loader is offset to account for this.
+ x: -main.x % 1
+ y: -main.y % 1
+ width: parent.width
+ height: parent.height
+
+ visible: status === Loader.Ready
+
+ active: !main.model.blank
+
+ sourceComponent: delegateImplementation
+
+ asynchronous: true
+ }
+
+ function updateDragImage() {
+ if (selected && !blank) {
+ loader.grabToImage(result => {
+ dir.addItemDragImage(positioner.map(index), main.x + loader.x, main.y + loader.y, loader.width, loader.height, result.image);
+ });
+ }
+ }
+
+ Component {
+ id: delegateImplementation
+
+ Item {
+ id: impl
+
+ anchors.fill: parent
+
+ property bool blank: main.model.blank
+ property bool isDir: main.model.blank ? false : main.model.isDir
+ property bool hovered: (main.GridView.view.hoveredItem === main)
+ property /*FolderViewDialog*/ Folder.SubDialog popupDialog: null
+ property Item iconArea: icon
+ property Item label: label
+ property Item labelArea: label
+ property Item actionsOverlay: actions
+ property Item hoverArea: toolTip
+ property Item frame: frameLoader
+ property alias toolTip: toolTip
+ property Item selectionButton: selectionButtonComponent.createObject(actions) as FolderItemActionButton
+ property Item popupButton: null
+ property int contentHeight: frameLoader.height + frameLoader.y * 2
+
+ readonly property bool iconAndLabelsShouldlookSelected: impl.hovered
+
+
+ Connections {
+ target: main.model
+
+ function onSelectedChanged() {
+ if (dir.usedByContainment && main.model.selected) {
+ gridView.currentIndex = main.model.index;
+ }
+ }
+ }
+
+ onHoveredChanged: {
+ if (hovered) {
+ if (Plasmoid.configuration.selectionMarkers && Application.styleHints.singleClickActivation) {
+ selectionButton.visible = true;
+ }
+
+ if (main.model.isDir) {
+ if (!main.GridView.view.isRootView || root.containsDrag) {
+ hoverActivateTimer.restart();
+ }
+
+ if (Plasmoid.configuration.popups && !root.useListViewMode) {
+ popupButton = popupButtonComponent.createObject(actions);
+ }
+ }
+ } else if (!hovered) {
+ if (popupDialog != null) {
+ main.closePopup();
+ }
+
+ selectionButton.visible = false;
+
+ if (popupButton) {
+ popupButton.destroy();
+ popupButton = null;
+ }
+ }
+ }
+
+ function openPopup() {
+ if (folderViewDialogComponent.status === Component.Ready) {
+ impl.popupDialog = folderViewDialogComponent.createObject(impl);
+ impl.popupDialog.visualParent = icon;
+ impl.popupDialog.url = Folder.DesktopSchemeHelper.getDesktopUrl(main.model.linkDestinationUrl);
+ impl.popupDialog.visible = true;
+ }
+ }
+
+ PlasmaCore.ToolTipArea {
+ id: toolTip
+ anchors.fill: impl
+
+ active: (Plasmoid.configuration.toolTips || label.truncated)
+ && impl.popupDialog === null
+ && !main.model.blank
+ interactive: false
+ location: root.useListViewMode ? (Plasmoid.location === PlasmaCore.Types.LeftEdge ? PlasmaCore.Types.LeftEdge : PlasmaCore.Types.RightEdge) : Plasmoid.location
+
+ onContainsMouseChanged: {
+ if (containsMouse && !main.model.blank) {
+ if (toolTip.active) {
+ toolTip.icon = main.model.decoration;
+ toolTip.mainText = main.model.display;
+
+ if (main.model.size !== undefined) {
+ toolTip.subText = main.model.type + "\n" + main.model.size;
+ } else {
+ toolTip.subText = main.model.type;
+ }
+ }
+
+ Qt.callLater(() => {
+ // Workaround for Qt Bug: https://bugreports.qt.io/browse/QTBUG-117444
+ // In some cases the signal order is reversed:
+ // - first it's delivered to the new object with "true" value
+ // - next it's delivered to the old object with "false" value
+ // In this case when the signal is emitted with "false" (to the old object),
+ // it's also delivered to the "FolderView" which sets the "hoveredItem" to
+ // "null" right after we set it here.
+ // The solution is to call later and check again to make sure if we still contains
+ // mouse and next set the "hoveredItem". In this approach the "FolderView" sets the
+ // old "hoveredItem" to "null" and next we set it to the new item here.
+ if (containsMouse && !main.model.blank) {
+ main.GridView.view.hoveredItem = main;
+ }
+ })
+ }
+ }
+
+ states: [
+ State { // icon view
+ when: !root.useListViewMode
+
+ AnchorChanges {
+ target: toolTip
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ PropertyChanges {
+ toolTip.y: frameLoader.y + icon.y
+ toolTip.width: Math.max(icon.paintedWidth, label.paintedWidth)
+ toolTip.height: (label.y + label.paintedHeight) - y
+ }
+ },
+ State { // list view
+ when: root.useListViewMode
+
+ AnchorChanges {
+ target: toolTip
+ anchors.horizontalCenter: undefined
+ }
+
+ PropertyChanges {
+ toolTip.x: frameLoader.x
+ toolTip.y: frameLoader.y
+ toolTip.width: frameLoader.width
+ toolTip.height: frameLoader.height
+ }
+ }
+ ]
+ }
+
+ Loader {
+ id: frameLoader
+
+ x: root.useListViewMode ? 0 : Kirigami.Units.smallSpacing
+ y: root.useListViewMode ? 0 : Kirigami.Units.smallSpacing
+
+ property Item iconShadow: null
+ property string prefix: ""
+
+ sourceComponent: frameComponent
+ active: impl.iconAndLabelsShouldlookSelected || (main.model?.selected ?? false)
+ asynchronous: true
+
+ width: {
+ if (root.useListViewMode) {
+ if (main.GridView.view.overflowing) {
+ return parent.width - Kirigami.Units.smallSpacing;
+ } else {
+ return parent.width;
+ }
+ }
+
+ return parent.width - (Kirigami.Units.smallSpacing * 2);
+ }
+
+ height: root.useListViewMode
+ ? parent.height
+ // the smallSpacings are for padding
+ : icon.height + label.implicitHeight + (Kirigami.Units.smallSpacing * 3)
+
+ Kirigami.Icon {
+ id: icon
+
+ z: 2
+
+ states: [
+ State { // icon view
+ when: !root.useListViewMode
+
+ AnchorChanges {
+ target: icon
+ anchors.top: parent.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ },
+ State { // list view
+ when: root.useListViewMode
+
+ AnchorChanges {
+ target: icon
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+ ]
+
+ anchors {
+ topMargin: Kirigami.Units.smallSpacing
+ leftMargin: Kirigami.Units.smallSpacing
+ }
+
+ width: root.useListViewMode ? main.GridView.view.iconSize : (parent.width - 2 * Kirigami.Units.smallSpacing)
+ height: main.GridView.view.iconSize
+
+ opacity: {
+ if (root.useListViewMode && impl.selectionButton.visible) {
+ return 0.3;
+ }
+
+ if (main.model.isHidden) {
+ return 0.6;
+ }
+
+ return 1.0;
+ }
+
+ animated: false
+
+ source: main.model.decoration
+ }
+
+ PlasmaExtras.ShadowedLabel {
+ id: label
+
+ readonly property bool renaming: (editor && editor.targetItem === main)
+
+ z: 2 // So it's always above the highlight effect
+
+ states: [
+ State { // icon view
+ when: !root.useListViewMode
+
+ AnchorChanges {
+ target: label
+ anchors.top: icon.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ PropertyChanges {
+ label.anchors.topMargin: Kirigami.Units.smallSpacing
+ label.width: label.parent.width - Kirigami.Units.smallSpacing
+ label.maximumLineCount: label.Plasmoid.configuration.textLines
+ label.horizontalAlignment: Text.AlignHCenter
+ }
+ },
+ State { // list view
+ when: root.useListViewMode
+
+ AnchorChanges {
+ target: label
+ anchors.left: icon.right
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ PropertyChanges {
+ label.anchors.leftMargin: Kirigami.Units.smallSpacing * 2
+ label.anchors.rightMargin: Kirigami.Units.smallSpacing * 2
+ label.width: label.parent.width - icon.width - (Kirigami.Units.smallSpacing * 4)
+ label.maximumLineCount: 1
+ label.horizontalAlignment: Text.AlignLeft
+ }
+ }
+ ]
+
+ color: {
+ if (main.isOnRootView) {
+ // In this situation there's a shadow or a background rect, both of which are always black
+ return "white";
+ }
+
+ if (main.model.selected) {
+ return Kirigami.Theme.highlightedTextColor;
+ }
+
+ return Kirigami.Theme.textColor;
+
+ }
+ visible: !renaming
+ renderShadow: main.isOnRootView && !renaming
+ opacity: main.model.isHidden ? 0.6 : 1
+
+ text: main.nameWrapped
+ font.italic: (main.model?.isLink ?? false)
+ wrapMode: (maximumLineCount === 1) ? Text.NoWrap : Text.Wrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Component {
+ id: frameComponent
+
+ PlasmaExtras.Highlight {
+ // Workaround for a bug where the frameComponent does not
+ // get unloaded when items are dragged to a different
+ // place on the desktop.
+ visible: this === frameLoader.item
+ hovered: impl.iconAndLabelsShouldlookSelected
+ pressed: main.model.selected
+ active: Window.active
+ }
+ }
+
+ Component {
+ id: selectionButtonComponent
+
+ FolderItemActionButton {
+ element: main.model.selected ? "remove" : "add"
+
+ onClicked: {
+ dir.toggleSelected(positioner.map(main.index));
+ main.GridView.view.currentIndex = main.index;
+ }
+ }
+ }
+
+ Component {
+ id: popupButtonComponent
+
+ FolderItemActionButton {
+ visible: main.GridView.view.isRootView && (impl.popupDialog == null)
+
+ element: "open"
+
+ onClicked: {
+ dir.setSelected(positioner.map(main.index));
+ main.GridView.view.currentIndex = main.index;
+ main.openPopup();
+ }
+ }
+ }
+
+ Component {
+ id: iconShadowComponent
+
+ DropShadow {
+ anchors.fill: icon
+
+ z: 1
+
+ verticalOffset: 1
+
+ radius: 5.0
+ samples: radius * 2 + 1
+ spread: 0.05
+
+ color: "black"
+
+ opacity: main.model.isHidden ? 0.3 : 0.6
+
+ source: icon
+ }
+ }
+ }
+
+ Column {
+ id: actions
+
+ visible: {
+ if (main.GridView.view.isRootView && root.containsDrag) {
+ return false;
+ }
+
+ if (!main.GridView.view.isRootView && main.GridView.view.dialog && main.GridView.view.dialog.containsDrag) {
+ return false;
+ }
+
+ if (main.popupDialog) {
+ return false;
+ }
+
+ return true;
+ }
+
+ anchors {
+ left: frameLoader.left
+ top: frameLoader.top
+ leftMargin: root.useListViewMode ? (icon.x + (icon.width / 2)) - (width / 2) : 0
+ topMargin: root.useListViewMode ? (icon.y + (icon.height / 2)) - (height / 2) : 0
+ }
+
+ width: implicitWidth
+ height: implicitHeight
+ }
+
+ Component.onCompleted: {
+ selectionButton.visible = false;
+ if (Plasmoid.isContainment && main.GridView.view.isRootView && root.GraphicsInfo.api === GraphicsInfo.OpenGL) {
+ frameLoader.iconShadow = iconShadowComponent.createObject(frameLoader);
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemPreviewPluginsDialog.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemPreviewPluginsDialog.qml
new file mode 100644
index 0000000..2c77711
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderItemPreviewPluginsDialog.qml
@@ -0,0 +1,53 @@
+/*
+ SPDX-FileCopyrightText: 2014 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls
+
+import org.kde.private.desktopcontainment.folder as Folder
+import org.kde.kirigami as Kirigami
+
+Kirigami.Dialog {
+ id: dialog
+
+ required property var previewPlugins
+
+ title: i18nc("@title:window", "Preview Plugins")
+
+ preferredWidth: Kirigami.Units.gridUnit * 15
+ implicitHeight: Math.round(parent.height * 0.8)
+ standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
+
+ onAccepted: {
+ configIcons.cfg_previewPlugins = previewPluginsModel.checkedPlugins;
+ dialog.close();
+ }
+ onRejected: {
+ dialog.close();
+ destroy();
+ }
+ onClosed: destroy()
+
+ ListView {
+ model: Folder.PreviewPluginsModel {
+ id: previewPluginsModel
+ }
+
+ delegate: CheckDelegate {
+ required property var model // for display, which shadows a delegate property
+ required checked
+ width: ListView.view.width
+ text: model.display
+
+ onToggled: model.checked = checked;
+ }
+ }
+
+ Component.onCompleted: {
+ previewPluginsModel.checkedPlugins = dialog.previewPlugins;
+ open();
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderView.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderView.qml
new file mode 100644
index 0000000..d09dfba
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderView.qml
@@ -0,0 +1,1418 @@
+/*
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+ SPDX-FileCopyrightText: 2023 Harald Sitter
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQml
+
+import org.kde.plasma.plasmoid
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.components as PlasmaComponents
+import org.kde.kquickcontrolsaddons
+
+import org.kde.private.desktopcontainment.folder as Folder
+import "code/FolderTools.js" as FolderTools
+
+FocusScope {
+ id: main
+
+ signal pressed()
+
+ property Folder.FolderModel model: dir
+ property Item rubberBand: null
+
+ property alias view: gridView
+ property alias isRootView: gridView.isRootView
+ property alias currentIndex: gridView.currentIndex
+ property alias url: dir.url
+ property alias status: dir.status
+ property alias perStripe: positioner.perStripe
+ property alias positionerApplet: positioner.applet
+ property alias errorString: dir.errorString
+ property alias dragging: dir.dragging
+ property alias dragInProgressAnywhere: dir.dragInProgressAnywhere
+ property alias locked: dir.locked
+ property alias sortMode: dir.sortMode
+ property alias filterMode: dir.filterMode
+ property alias filterPattern: dir.filterPattern
+ property alias filterMimeTypes: dir.filterMimeTypes
+ property alias showHiddenFiles: dir.showHiddenFiles
+ property alias creatingNewItems: dir.creatingNewItems
+ property alias flow: gridView.flow
+ property alias layoutDirection: gridView.layoutDirection
+ property alias cellWidth: gridView.cellWidth
+ property alias cellHeight: gridView.cellHeight
+ property alias overflowing: gridView.overflowing
+ property alias scrollLeft: gridView.scrollLeft
+ property alias scrollRight: gridView.scrollRight
+ property alias scrollUp: gridView.scrollUp
+ property alias scrollDown: gridView.scrollDown
+ property alias hoveredItem: gridView.hoveredItem
+ property var history: []
+ property var lastPosition: null
+ property bool goingBack: false
+ property BackButtonItem backButton: null
+ property var dialog: null
+ property Item editor: null
+
+ property int previouslySelectedItemIndex: -1
+
+ function positionViewAtBeginning() {
+ gridView.positionViewAtBeginning();
+ }
+
+ function rename() {
+ if (gridView.currentIndex !== -1) {
+ let renameAction = model.action("rename");
+ if (renameAction && !renameAction.enabled) {
+ return;
+ }
+
+ if (!main.editor) {
+ editor = editorComponent.createObject(listener);
+ }
+
+ main.editor.targetItem = gridView.currentItem;
+ }
+ }
+
+ function cancelRename() {
+ if (main.editor) {
+ main.editor.targetItem = null;
+ }
+ }
+
+ function linkHere(sourceUrl) {
+ dir.linkHere(sourceUrl);
+ }
+
+ function handleDragMove(x, y) {
+ let child = childAt(x, y);
+
+ if (child !== null && child === main.backButton) {
+ hoveredItem = null;
+ main.backButton.handleDragMove();
+ } else {
+ if (main.backButton && main.backButton.containsDrag) {
+ main.backButton.endDragMove();
+ }
+
+ let pos = mapToItem(gridView.contentItem, x, y);
+ let item = gridView.safeItemAt(pos.x, pos.y);
+
+ if (item && item.isDir) {
+ hoveredItem = item;
+ } else {
+ hoveredItem = null;
+ }
+ }
+ }
+
+ function endDragMove() {
+ if (main.backButton && main.backButton.active) {
+ main.backButton.endDragMove();
+ } else if (hoveredItem && !hoveredItem.popupDialog) {
+ hoveredItem = null;
+ }
+ }
+
+ function dropItemAt(pos) {
+ let item = gridView.safeItemAt(pos.x, pos.y);
+
+ if (item && !item.blank) {
+ gridView.currentIndex = item.index
+ return positioner.map(item.index);
+ }
+
+ return -1;
+ }
+
+ function drop(target, event, pos) {
+ let dropPos = mapToItem(gridView.contentItem, pos.x, pos.y);
+ let dropIndex = gridView.safeIndexAt(dropPos.x, dropPos.y);
+ let dragPos = mapToItem(gridView.contentItem, listener.dragX, listener.dragY);
+ let dragIndex = gridView.safeIndexAt(dragPos.x, dragPos.y);
+
+ if (listener.dragX === -1 || dragIndex !== dropIndex) {
+ dir.drop(target, event, dropItemAt(dropPos), Plasmoid.isContainment && !Plasmoid.immutable);
+ }
+ }
+
+ function generateDragImage() {
+ for (let i = 0; i < gridView.count; i++) {
+ let item = gridView.itemAtIndex(i) as FolderItemDelegate;
+ if (item) {
+ item.updateDragImage();
+ }
+ }
+ }
+
+ Connections {
+ target: dir
+ function onPopupMenuAboutToShow(dropJob, mimeData, x, y) {
+ if (Plasmoid.isContainment && !Plasmoid.immutable) {
+ root.processMimeData(mimeData, x, y, dropJob);
+ }
+ }
+
+ // Create drag images before dragging
+ // Due to async operations we can't call this before dragging starts,
+ // but we have to call it after a selection is done
+ function onSelectionDone() {
+ main.generateDragImage();
+ }
+ }
+
+ Connections {
+ target: root
+ function onExpandedChanged() {
+ if (root.expanded && dir.status === Folder.FolderModel.Ready && !gridView.model) {
+ gridView.model = positioner;
+ }
+ }
+ }
+
+ Binding {
+ target: Plasmoid
+ property: "busy"
+ value: !gridView.model && dir.status === Folder.FolderModel.Listing
+ restoreMode: Binding.RestoreBinding
+ }
+
+ function makeBackButton() {
+ return Qt.createQmlObject("BackButtonItem {}", main);
+ }
+
+ function doCd(row) {
+ history.push({ url: url, index: gridView.currentIndex, yPosition: gridView.visibleArea.yPosition});
+ historyChanged();
+ dir.cd(row);
+ gridView.currentIndex = -1;
+ }
+
+ function doBack() {
+ goingBack = true;
+ gridView.currentIndex = -1;
+ lastPosition = history.pop();
+ url = lastPosition.url;
+ historyChanged();
+ }
+
+ Connections {
+ target: root
+
+ function onIsPopupChanged() {
+ if (main.backButton === null && root.useListViewMode) {
+ main.backButton = main.makeBackButton();
+ } else if (main.backButton !== null) {
+ main.backButton.destroy();
+ }
+ }
+ }
+
+ Folder.EventGenerator {
+ id: eventGenerator
+ }
+
+ MouseEventListener {
+ id: listener
+
+ enabled: !Plasmoid.containment.corona.editMode
+
+ anchors {
+ topMargin: main.backButton !== null ? main.backButton.height : undefined
+ fill: parent
+ }
+
+ property alias hoveredItem: gridView.hoveredItem
+
+ property Item pressedItem: null
+ property int pressX: -1
+ property int pressY: -1
+ property int dragX: -1
+ property int dragY: -1
+ property var cPress: null
+ property bool doubleClickInProgress: false
+ property bool renameByLabelClickInitiated: false
+
+ acceptedButtons: {
+ if (hoveredItem === null && main.isRootView) {
+ return root.isPopup ? (Qt.LeftButton | Qt.MiddleButton | Qt.BackButton) : Qt.LeftButton;
+ }
+
+ return root.isPopup ? (Qt.LeftButton | Qt.MiddleButton | Qt.RightButton | Qt.BackButton)
+ : (Qt.LeftButton | Qt.RightButton);
+ }
+
+ hoverEnabled: true
+
+ onPressXChanged: {
+ cPress = mapToItem(gridView.contentItem, pressX, pressY);
+ }
+
+ onPressYChanged: {
+ cPress = mapToItem(gridView.contentItem, pressX, pressY);
+ }
+
+ onPressed: mouse => {
+
+ // Ignore press events outside the viewport (i.e. on scrollbars).
+ if (!scrollArea.viewport.contains(Qt.point(mouse.x, mouse.y))) {
+ return;
+ }
+
+ // Ignore clicks if main.editor is enabled and we click on that
+ // BUG:494558
+ if (main.editor && childAt(mouse.x, mouse.y) === main.editor) {
+ return;
+ }
+
+ scrollArea.focus = true;
+
+ if (mouse.buttons & Qt.BackButton) {
+ if (root.isPopup && dir.resolvedUrl !== dir.resolve(Plasmoid.configuration.url)) {
+ main.doBack();
+ mouse.accepted = true;
+ }
+
+ return;
+ }
+
+ if (main.editor && childAt(mouse.x, mouse.y) !== main.editor) {
+ main.editor.commit();
+ }
+
+ const mappedPos = mapToItem(gridView.contentItem, mouse.x, mouse.y)
+ const index = gridView.safeIndexAt(mappedPos.x, mappedPos.y);
+ const indexItem = gridView.itemAtIndex(index) as FolderItemDelegate;
+
+ if (indexItem && indexItem.iconArea) { // update position in case of touch or untriggered hover
+ gridView.currentIndex = index;
+ hoveredItem = indexItem;
+ } else {
+ gridView.currentIndex = -1
+ hoveredItem = null;
+ }
+
+ if (mouse.source === Qt.MouseEventSynthesizedByQt) {
+ if (gridView.hoveredItem && gridView.hoveredItem.toolTip.active) {
+ gridView.hoveredItem.toolTip.hideToolTip();
+ }
+ }
+
+ pressX = mouse.x;
+ pressY = mouse.y;
+
+ if (!hoveredItem || hoveredItem.blank) {
+ if (!gridView.ctrlPressed) {
+ gridView.currentIndex = -1;
+ main.previouslySelectedItemIndex = -1;
+ dir.clearSelection();
+ }
+
+ if (mouse.buttons & Qt.RightButton) {
+ clearPressState();
+
+ // If it's the desktop, fall through to the desktop context menu plugin
+ // Disallow opening contextmenu if we're already creating new items
+ if (!dir.usedByContainment && !dir.creatingNewItems) {
+ dir.openContextMenu(main, mouse.modifiers);
+ mouse.accepted = true;
+ }
+ }
+ } else {
+ pressedItem = hoveredItem;
+
+ let pos = mapToItem(hoveredItem.actionsOverlay, mouse.x, mouse.y);
+
+ if (!(pos.x <= hoveredItem.actionsOverlay.width && pos.y <= hoveredItem.actionsOverlay.height)) {
+ if (gridView.shiftPressed && gridView.currentIndex !== -1) {
+ positioner.setRangeSelected(gridView.anchorIndex, hoveredItem.index);
+ } else {
+ // Deselecting everything else when one item is clicked is handled in onReleased in order to distinguish between drag and click
+ if (!gridView.ctrlPressed && !dir.isSelected(positioner.map(hoveredItem.index))) {
+ main.previouslySelectedItemIndex = -1;
+ dir.clearSelection();
+ }
+
+ if (gridView.ctrlPressed) {
+ dir.toggleSelected(positioner.map(hoveredItem.index));
+ } else {
+ dir.setSelected(positioner.map(hoveredItem.index));
+ }
+ }
+
+ gridView.currentIndex = hoveredItem.index;
+
+ if (mouse.buttons & Qt.RightButton) {
+ if (pressedItem.toolTip && pressedItem.toolTip.active) {
+ pressedItem.toolTip.hideToolTip();
+ }
+
+ clearPressState();
+
+ dir.openContextMenu(hoveredItem, mouse.modifiers);
+ mouse.accepted = true;
+ }
+ }
+ }
+
+ main.pressed();
+ }
+
+ onCanceled: pressCanceled()
+
+ onReleased: mouse => {
+ // if we click on an item, cancel the current selection and select just the clicked icon
+ // the cachedRectangleSelection guards this release being associated with an existing drag
+ if (!gridView.cachedRectangleSelection && hoveredItem && !hoveredItem.blank && mouse.button !== Qt.RightButton) {
+ const pos = mapToItem(hoveredItem.actionsOverlay, mouse.x, mouse.y);
+ if (!(pos.x <= hoveredItem.actionsOverlay.width && pos.y <= hoveredItem.actionsOverlay.height)
+ && (!(gridView.shiftPressed && gridView.currentIndex !== -1) && !gridView.ctrlPressed)) {
+ dir.clearSelection();
+ dir.setSelected(positioner.map(hoveredItem.index));
+ }
+ }
+ pressCanceled();
+ }
+
+ onPressAndHold: mouse => {
+ if (mouse.source === Qt.MouseEventSynthesizedByQt) {
+ if (pressedItem) {
+ if (pressedItem.toolTip && pressedItem.toolTip.active) {
+ pressedItem.toolTip.hideToolTip();
+ }
+ }
+ clearPressState();
+ if (hoveredItem) {
+ dir.openContextMenu(hoveredItem, mouse.modifiers);
+ }
+ }
+ }
+
+ onClicked: mouse => {
+ clearPressState();
+
+ if (mouse.button === Qt.RightButton ||
+ (main.editor && childAt(mouse.x, mouse.y) === main.editor)) {
+ return;
+ }
+
+ if (!hoveredItem || hoveredItem.blank || gridView.currentIndex === -1 || gridView.ctrlPressed || gridView.shiftPressed) {
+ // Bug 357367: Replay mouse event, so containment actions assigned to left mouse button work.
+ eventGenerator.sendMouseEvent(root, Folder.EventGenerator.MouseButtonPress, mouse.x, mouse.y, mouse.button, mouse.buttons, mouse.modifiers);
+ return;
+ }
+
+ let pos = mapToItem(hoveredItem, mouse.x, mouse.y);
+
+ // Moving from an item to its preview popup dialog doesn't unset hoveredItem
+ // even though the cursor has left it, so we need to check whether the click
+ // actually occurred inside the item we expect it in before going ahead. If it
+ // didn't, clean up (e.g. dismissing the dialog as a side-effect of unsetting
+ // hoveredItem) and abort.
+ if (pos.x < 0 || pos.x > hoveredItem.width || pos.y < 0 || pos.y > hoveredItem.height) {
+ hoveredItem = null;
+ main.previouslySelectedItemIndex = -1;
+ dir.clearSelection();
+
+ return;
+ // If the hoveredItem is clicked while having a preview popup dialog open,
+ // only dismiss the dialog and abort.
+ } else if (hoveredItem.popupDialog) {
+ hoveredItem.closePopup();
+
+ return;
+ }
+
+ pos = mapToItem(hoveredItem.actionsOverlay, mouse.x, mouse.y);
+
+ if (!(pos.x <= hoveredItem.actionsOverlay.width && pos.y <= hoveredItem.actionsOverlay.height)) {
+
+ // Clicked on the label of an already-selected item: schedule it for renaming when doubleClickTimer expires
+ renameByLabelClickInitiated = (pos.x > hoveredItem.labelArea.x
+ && pos.x <= hoveredItem.labelArea.x + hoveredItem.labelArea.width
+ && pos.y > hoveredItem.labelArea.y
+ && pos.y <= hoveredItem.labelArea.y + hoveredItem.labelArea.height
+ && main.previouslySelectedItemIndex === gridView.currentIndex
+ && gridView.currentIndex !== -1
+ && !Qt.styleHints.singleClickActivation
+ && Plasmoid.configuration.renameInline
+ )
+
+ // Single-click mode and single-clicked on the item or
+ // double-click mode and double-clicked on the item: activate it
+ if (Qt.styleHints.singleClickActivation || doubleClickInProgress || mouse.source === Qt.MouseEventSynthesizedByQt) {
+ doubleClickInProgress = false
+ if (mouse.modifiers & Qt.AltModifier) {
+ dir.openPropertiesDialog();
+ } else if (root.useListViewMode && mouse.button === Qt.LeftButton && hoveredItem.isDir) {
+ main.doCd(positioner.map(gridView.currentIndex));
+ } else {
+ dir.run(positioner.map(gridView.currentIndex));
+ }
+ main.previouslySelectedItemIndex = gridView.currentIndex;
+ hoveredItem = null;
+ } else {
+ // None of the above: select it
+ doubleClickInProgress = true;
+ doubleClickTimer.interval = Qt.styleHints.mouseDoubleClickInterval;
+ doubleClickTimer.start();
+ main.previouslySelectedItemIndex = gridView.currentIndex;
+ }
+ }
+ }
+
+ onPositionChanged: mouse => {
+ gridView.ctrlPressed = (mouse.modifiers & Qt.ControlModifier);
+ gridView.shiftPressed = (mouse.modifiers & Qt.ShiftModifier);
+
+ const mappedPos = mapToItem(gridView.contentItem, mouse.x, mouse.y)
+ const item = gridView.safeItemAt(mappedPos.x, mappedPos.y);
+ const leftEdge = Math.min(gridView.contentX, gridView.originX);
+
+ if (!item || item.blank) {
+ if (gridView.hoveredItem && !root.containsDrag && (!main.dialog || !main.dialog.containsDrag) && !gridView.hoveredItem.popupDialog) {
+ gridView.hoveredItem = null;
+ }
+ }
+
+ // Trigger autoscroll.
+ if (pressX !== -1) {
+ gridView.scrollLeft = (mouse.x <= 0 && gridView.contentX > leftEdge);
+ gridView.scrollRight = (mouse.x >= gridView.width
+ && gridView.contentX < gridView.contentItem.width - gridView.width);
+ gridView.scrollUp = (mouse.y <= 0 && gridView.contentY > 0);
+ gridView.scrollDown = (mouse.y >= gridView.height
+ && gridView.contentY < gridView.contentItem.height - gridView.height);
+ }
+
+ // Update rubberband geometry.
+ if (main.rubberBand) {
+ let rB = main.rubberBand;
+ let cPos = mapToItem(gridView.contentItem, mouse.x, mouse.y);
+
+ if (cPos.x < cPress.x) {
+ rB.x = Math.max(leftEdge, cPos.x);
+ rB.width = Math.abs(rB.x - cPress.x);
+ } else {
+ rB.x = cPress.x;
+ let ceil = Math.max(gridView.width, gridView.contentItem.width) + leftEdge;
+ rB.width = Math.min(ceil - rB.x, Math.abs(rB.x - cPos.x));
+ }
+
+ if (cPos.y < cPress.y) {
+ rB.y = Math.max(0, cPos.y);
+ rB.height = Math.abs(rB.y - cPress.y);
+ } else {
+ rB.y = cPress.y;
+ let ceil = Math.max(gridView.height, gridView.contentItem.height);
+ rB.height = Math.min(ceil - rB.y, Math.abs(rB.y - cPos.y));
+ }
+
+ // Ensure rubberband is at least 1px in size or else it will become
+ // invisible and not match any items.
+ rB.width = Math.max(1, rB.width);
+ rB.height = Math.max(1, rB.height);
+
+ Qt.callLater(gridView.rectangleSelect, rB.x, rB.y, rB.width, rB.height, main.rubberBand);
+
+ return;
+ }
+
+ // Drag initiation.
+ if (pressX !== -1 && root.isDrag(pressX, pressY, mouse.x, mouse.y)) {
+ if (pressedItem !== null && dir.isSelected(positioner.map(pressedItem.index))) {
+ pressedItem.toolTip.hideToolTip();
+ dragX = mouse.x;
+ dragY = mouse.y;
+ gridView.verticalDropHitscanOffset = pressedItem.iconArea.y + (pressedItem.iconArea.height / 2);
+ dir.dragSelected(mouse.x, mouse.y);
+ dragX = -1;
+ dragY = -1;
+ clearPressState();
+ } else {
+ // Disable rubberband in popup list view mode or while renaming
+ if (root.useListViewMode || (main.editor && main.editor.targetItem) || (verticalScrollBar.active || horizontalScrollBar.active)) {
+ return;
+ }
+
+ dir.pinSelection();
+ main.rubberBand = rubberBandObject.createObject(gridView.contentItem, {x: cPress.x, y: cPress.y});
+ gridView.interactive = false;
+ }
+ }
+ }
+
+ Component {
+ id: rubberBandObject
+
+ Rectangle {
+ id: rubberBand
+
+ width: 0
+ height: 0
+ z: 99999
+
+ SystemPalette {
+ id: sysPalette
+ colorGroup: SystemPalette.Active
+ }
+
+ radius: Kirigami.Units.cornerRadius
+ border.color: sysPalette.highlight
+ color: Qt.alpha(border.color, 0.3)
+
+ function intersects(rect) {
+ return x + width >= rect.x && y + height >= rect.y && rect.x + rect.width >= x && rect.y + rect.height >= y;
+ }
+
+ function close() {
+ opacityAnimation.restart();
+ }
+
+ OpacityAnimator {
+ id: opacityAnimation
+ target: rubberBand
+ to: 0
+ from: 1
+ duration: Kirigami.Units.shortDuration
+
+ // This easing curve has an elognated start, which works
+ // better than a standard easing curve for the rubberband
+ // animation, which fades out fast and is generally of a
+ // small area.
+ easing {
+ bezierCurve: [0.4, 0.0, 1, 1]
+ type: Easing.Bezier
+ }
+
+ onFinished: {
+ rubberBand.visible = false;
+ rubberBand.enabled = false;
+ // We need to explicitly generate an image here
+ // to make sure we have one before we start dragging
+ main.generateDragImage();
+ rubberBand.destroy();
+ }
+ }
+ }
+ }
+
+ onContainsMouseChanged: {
+ if (!containsMouse && !main.rubberBand) {
+ clearPressState();
+ if (!(hoveredItem?.popupDialog?.visible ?? false)) {
+ hoveredItem = null;
+ }
+ }
+ }
+
+ onHoveredItemChanged: {
+ doubleClickInProgress = false;
+
+ if (!hoveredItem) {
+ hoverActivateTimer.stop();
+ }
+ }
+
+ function pressCanceled() {
+ if (main.rubberBand) {
+ main.rubberBand.close();
+ main.rubberBand = null;
+
+ gridView.interactive = true;
+ gridView.cachedRectangleSelection = null;
+ dir.unpinSelection();
+ }
+
+ clearPressState();
+ gridView.cancelAutoscroll();
+ }
+
+ function clearPressState() {
+ pressedItem = null;
+ pressX = -1;
+ pressY = -1;
+ }
+
+ Timer {
+ id: doubleClickTimer
+
+ onTriggered: {
+ if (listener.renameByLabelClickInitiated && listener.doubleClickInProgress) {
+ main.rename()
+ }
+ listener.renameByLabelClickInitiated = false
+ listener.doubleClickInProgress = false;
+ }
+ }
+
+ Timer {
+ id: hoverActivateTimer
+
+ interval: root.hoverActivateDelay
+
+ onTriggered: {
+ if (!main.hoveredItem) {
+ return;
+ }
+
+ if (root.useListViewMode && main.dragging) {
+ main.doCd((main.hoveredItem as FolderItemDelegate).index);
+ } else if (!root.useListViewMode && Plasmoid.configuration.popups) {
+ hoveredItem.openPopup();
+ }
+ }
+ }
+
+ FocusScope {
+ id: scrollArea
+
+ anchors.fill: parent
+
+ focus: true
+
+ property bool ready: false
+ readonly property int viewportWidth: scrollArea.ready && viewport ? Math.ceil(viewport.width) : 0
+ readonly property int viewportHeight: scrollArea.ready && viewport ? Math.ceil(viewport.height) : 0
+ readonly property Flickable viewport: gridView
+
+ Component.onCompleted: {
+ scrollArea.ready = true;
+ }
+
+ GridView {
+ id: gridView
+ clip: true
+ anchors.fill: parent
+
+ property bool isRootView: false
+
+ property int iconSize: makeIconSize()
+ property int verticalDropHitscanOffset: 0
+
+ property FolderItemDelegate hoveredItem: null
+
+ property int anchorIndex: 0
+ property bool ctrlPressed: false
+ property bool shiftPressed: false
+
+ property bool overflowing: {
+ // widthRatio or heightRatio may be 0 when it's not actually
+ // overflowing, so account for that.
+ let widthOverflow = visibleArea.widthRatio > 0.0 && visibleArea.widthRatio < 1.0
+ let heightOverflow = visibleArea.heightRatio > 0.0 && visibleArea.heightRatio < 1.0
+ return widthOverflow || heightOverflow
+ }
+
+ property bool scrollLeft: false
+ property bool scrollRight: false
+ property bool scrollUp: false
+ property bool scrollDown: false
+
+ property var cachedRectangleSelection: null
+
+ currentIndex: -1
+
+ keyNavigationWraps: false
+ boundsBehavior: Flickable.StopAtBounds
+ focus: true
+
+ // itemAt returns the item that's in the cell at
+ // coordinates x, y, even if it's smaller than it.
+ // safeItemAt checks if x, y is actually within the
+ // element within the cell.
+ function safeItemAt(x, y) {
+ let item = itemAt(x, y)
+ if (!item) return;
+ let coord = mapFromItem(gridView.contentItem, x, y)
+ coord = item.mapFromItem(gridView, coord.x, coord.y)
+ if (!item.contains(coord)) {
+ return
+ }
+ return item;
+ }
+
+ function safeIndexAt(x, y) {
+ if (safeItemAt(x, y)) {
+ return indexAt(x, y)
+ }
+ return -1
+ }
+
+ PlasmaComponents.ScrollBar.vertical: PlasmaComponents.ScrollBar {
+ id: verticalScrollBar
+ }
+ PlasmaComponents.ScrollBar.horizontal: PlasmaComponents.ScrollBar {
+ id: horizontalScrollBar
+ }
+
+ function calcExtraSpacing(cellSize, containerSize) {
+ const availableColumns = Math.floor(containerSize / cellSize);
+ let extraSpacing = 0;
+ if (availableColumns > 0) {
+ let allColumnSize = availableColumns * cellSize;
+ let extraSpace = Math.max(containerSize - allColumnSize, 0);
+ extraSpacing = extraSpace / availableColumns;
+ }
+ return Math.floor(extraSpacing);
+ }
+
+ cellWidth: {
+ if (root.useListViewMode) {
+ return gridView.width - (verticalScrollBar.visible ? verticalScrollBar.width : 0);
+ } else {
+ const iconWidth = iconSize + (2 * Kirigami.Units.gridUnit) + (2 * Kirigami.Units.smallSpacing);
+ if (root.isContainment && isRootView && scrollArea.viewportWidth > 0) {
+ const minIconWidth = Math.max(iconWidth, Kirigami.Units.iconSizes.small * ((Plasmoid.configuration.labelWidth * 2) + 4));
+ const extraWidth = calcExtraSpacing(minIconWidth, scrollArea.viewportWidth);
+ return minIconWidth + extraWidth;
+ } else {
+ return iconWidth;
+ }
+ }
+ }
+
+ cellHeight: {
+ if (root.useListViewMode) {
+ return Math.ceil((Math.max(Kirigami.Units.iconSizes.sizeForLabels, iconSize)
+ + Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom,
+ listItemSvg.margins.top + listItemSvg.margins.bottom)) / 2) * 2;
+ } else {
+ // the smallSpacings are for padding
+ const iconHeight = iconSize + (Kirigami.Units.gridUnit * Plasmoid.configuration.textLines) + (Kirigami.Units.smallSpacing * 3);
+ if (root.isContainment && isRootView && scrollArea.viewportHeight > 0) {
+ let extraHeight = calcExtraSpacing(iconHeight, scrollArea.viewportHeight);
+ return iconHeight + extraHeight;
+ } else {
+ return iconHeight;
+ }
+ }
+ }
+
+ delegate: FolderItemDelegate {
+ width: gridView.cellWidth
+ height: contentHeight ? Math.min(contentHeight, gridView.cellHeight) : gridView.cellHeight
+ isOnRootView: main.isRootView
+ }
+
+ onContentXChanged: {
+ if (hoveredItem) {
+ hoverActivateTimer.stop();
+ }
+
+ cancelRename();
+
+ dir.setDragHotSpotScrollOffset(contentX, contentY);
+
+ if (contentX === 0) {
+ scrollLeft = false;
+ }
+
+ if (contentX === contentItem.width - width) {
+ scrollRight = false;
+ }
+
+ // Update rubberband geometry.
+ if (main.rubberBand) {
+ const rB = main.rubberBand;
+
+ if (scrollLeft) {
+ rB.x = Math.min(gridView.contentX, gridView.originX);
+ rB.width = listener.cPress.x;
+ }
+
+ if (scrollRight) {
+ const lastCol = gridView.contentX + gridView.width;
+ rB.width = lastCol - rB.x;
+ }
+
+ Qt.callLater(gridView.rectangleSelect, rB.x, rB.y, rB.width, rB.height, main.rubberBand);
+ }
+ }
+
+ onContentYChanged: {
+ if (hoveredItem) {
+ hoverActivateTimer.stop();
+ }
+
+ main.cancelRename();
+
+ dir.setDragHotSpotScrollOffset(contentX, contentY);
+
+ if (contentY === 0) {
+ scrollUp = false;
+ }
+
+ if (contentY === contentItem.height - height) {
+ scrollDown = false;
+ }
+
+ // Update rubberband geometry.
+ if (main.rubberBand) {
+ const rB = main.rubberBand;
+
+ if (scrollUp) {
+ rB.y = 0;
+ rB.height = listener.cPress.y;
+ }
+
+ if (scrollDown) {
+ const lastRow = gridView.contentY + gridView.height;
+ rB.height = lastRow - rB.y;
+ }
+
+ Qt.callLater(gridView.rectangleSelect, rB.x, rB.y, rB.width, rB.height, main.rubberBand);
+ }
+ }
+
+ onScrollLeftChanged: {
+ if (scrollLeft && gridView.visibleArea.widthRatio < 1.0) {
+ smoothX.enabled = true;
+ contentX = (gridView.flow === GridView.FlowLeftToRight) ? gridView.contentX : gridView.originX;
+ } else {
+ contentX = contentX;
+ smoothX.enabled = false;
+ }
+ }
+
+ onScrollRightChanged: {
+ if (scrollRight && gridView.visibleArea.widthRatio < 1.0) {
+ smoothX.enabled = true;
+ contentX = ((gridView.flow === GridView.FlowLeftToRight) ? gridView.contentX : gridView.originX)
+ + (contentItem.width - width);
+ } else {
+ contentX = contentX;
+ smoothX.enabled = false;
+ }
+ }
+
+ onScrollUpChanged: {
+ if (scrollUp && gridView.visibleArea.heightRatio < 1.0) {
+ smoothY.enabled = true;
+ contentY = 0;
+ } else {
+ contentY = contentY;
+ smoothY.enabled = false;
+ }
+ }
+
+ onScrollDownChanged: {
+ if (scrollDown && gridView.visibleArea.heightRatio < 1.0) {
+ smoothY.enabled = true;
+ contentY = contentItem.height - height;
+ } else {
+ contentY = contentY;
+ smoothY.enabled = false;
+ }
+ }
+
+ onCurrentIndexChanged: {
+ positionViewAtIndex(currentIndex, GridView.Contain);
+ }
+
+ onCachedRectangleSelectionChanged: {
+ if (cachedRectangleSelection === null) {
+ return;
+ }
+
+ if (cachedRectangleSelection.length) {
+ // Set current index to start of selection.
+ // cachedRectangleSelection is pre-sorted.
+ currentIndex = cachedRectangleSelection[0];
+ }
+
+ dir.updateSelection(cachedRectangleSelection.map(row => positioner.map(row)),
+ gridView.ctrlPressed);
+ }
+
+ function makeIconSize() {
+ if (root.useListViewMode) {
+ return Kirigami.Units.iconSizes.small;
+ }
+
+ return FolderTools.iconSizeFromTheme(Plasmoid.configuration.iconSize);
+ }
+
+ function updateSelection(modifier) {
+ if (modifier & Qt.ShiftModifier) {
+ positioner.setRangeSelected(anchorIndex, currentIndex);
+ } else {
+ dir.clearSelection();
+ dir.setSelected(positioner.map(currentIndex));
+ if (currentIndex === -1) {
+ main.previouslySelectedItemIndex = -1;
+ }
+ main.previouslySelectedItemIndex = currentIndex;
+ }
+ }
+
+ function cancelAutoscroll() {
+ scrollLeft = false;
+ scrollRight = false;
+ scrollUp = false;
+ scrollDown = false;
+ }
+
+ function rectangleSelect(x, y, width, height, rubberBand) {
+ const rows = (gridView.flow === GridView.FlowLeftToRight);
+ const stripes = Math.ceil(gridView.count / positioner.perStripe);
+ const cWidth = gridView.cellWidth - (2 * Kirigami.Units.smallSpacing);
+ const cHeight = gridView.cellHeight - (2 * Kirigami.Units.smallSpacing);
+ const midWidth = gridView.cellWidth / 2;
+ const midHeight = gridView.cellHeight / 2;
+ let indices = [];
+
+ for (let s = 0; s < stripes; s++) {
+ for (let i = 0; i < positioner.perStripe; i++) {
+ let index = (s * positioner.perStripe) + i;
+
+ if (index >= gridView.count) {
+ break;
+ }
+
+ if (positioner.isBlank(index)) {
+ continue;
+ }
+
+ let itemX = ((rows ? i : s) * gridView.cellWidth);
+ let itemY = ((rows ? s : i) * gridView.cellHeight);
+
+ if (gridView.effectiveLayoutDirection === Qt.RightToLeft) {
+ itemX -= (rows ? gridView.contentX : gridView.originX);
+ itemX += cWidth;
+ itemX = (rows ? gridView.width : gridView.contentItem.width) - itemX;
+ }
+
+ const item = gridView.contentItem.childAt(itemX + midWidth, itemY + midHeight);
+ if (item && rubberBand.intersects(Qt.rect(item.x, item.y, item.width, item.height))) {
+ indices.push(index)
+ }
+
+ }
+ }
+
+ gridView.cachedRectangleSelection = indices;
+ }
+
+ function runOrCdSelected() {
+ if (currentIndex !== -1 && dir.hasSelection()) {
+ if (root.useListViewMode && currentItem.isDir) {
+ main.doCd(positioner.map(currentIndex));
+ } else {
+ dir.runSelected();
+ }
+ }
+ }
+
+ Behavior on contentX { id: smoothX; enabled: false; SmoothedAnimation { velocity: 700 } }
+ Behavior on contentY { id: smoothY; enabled: false; SmoothedAnimation { velocity: 700 } }
+
+ Keys.onReturnPressed: event => {
+ if (event.modifiers === Qt.AltModifier) {
+ dir.openPropertiesDialog();
+ } else {
+ runOrCdSelected();
+ }
+ }
+
+ Keys.onEnterPressed: event => Keys.returnPressed(event)
+
+ Keys.onMenuPressed: event => {
+ if (currentIndex !== -1 && dir.hasSelection() && currentItem) {
+ dir.setSelected(positioner.map(currentIndex));
+ dir.openContextMenu(currentItem.frame, event.modifiers);
+ } else {
+ // Otherwise let the containment handle it.
+ event.accepted = false;
+ }
+ }
+
+ Keys.onEscapePressed: event => {
+ if (!main.editor || !main.editor.targetItem) {
+ main.previouslySelectedItemIndex = -1;
+ dir.clearSelection();
+ event.accepted = false;
+ }
+ }
+
+ Folder.ShortCut {
+ Component.onCompleted: {
+ installAsEventFilterFor(gridView);
+ }
+
+ onDeleteFile: {
+ dir.deleteSelected();
+ }
+
+ onRenameFile: {
+ main.rename();
+ }
+
+ onMoveToTrash: {
+ const action = dir.action("trash");
+ if (action && action.enabled) {
+ action.trigger();
+ }
+ }
+
+ onCreateFolder: {
+ model.createFolder();
+ }
+ }
+
+ Keys.onPressed: event => {
+ event.accepted = true;
+
+ if (event.key === Qt.Key_Control) {
+ ctrlPressed = true;
+ } else if (event.key === Qt.Key_Shift) {
+ shiftPressed = true;
+
+ if (currentIndex !== -1) {
+ anchorIndex = currentIndex;
+ }
+ } else if (event.key === Qt.Key_Home) {
+ currentIndex = 0;
+ updateSelection(event.modifiers);
+ } else if (event.key === Qt.Key_End) {
+ currentIndex = count - 1;
+ updateSelection(event.modifiers);
+ } else if (event.matches(StandardKey.Copy)) {
+ dir.copy();
+ } else if (event.matches(StandardKey.Paste)) {
+ dir.paste();
+ } else if (event.matches(StandardKey.Cut)) {
+ dir.cut();
+ } else if (event.matches(StandardKey.Undo)) {
+ dir.undo();
+ } else if (event.matches(StandardKey.Refresh)) {
+ dir.refresh();
+ } else if (event.matches(StandardKey.SelectAll)) {
+ positioner.setRangeSelected(0, count - 1);
+ } else {
+ event.accepted = false;
+ }
+ }
+
+ Keys.onReleased: event => {
+ if (event.key === Qt.Key_Control) {
+ ctrlPressed = false;
+ } else if (event.key === Qt.Key_Shift) {
+ shiftPressed = false;
+ anchorIndex = 0;
+ }
+ }
+
+ Keys.onLeftPressed: event => {
+ if (root.isPopup && root.useListViewMode) {
+ if (dir.resolvedUrl !== dir.resolve(Plasmoid.configuration.url)) {
+ main.doBack();
+ }
+ } else if (positioner.enabled) {
+ const newIndex = positioner.nearestItem(currentIndex,
+ FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.LeftArrow));
+
+ if (newIndex !== -1) {
+ currentIndex = newIndex;
+ updateSelection(event.modifiers);
+ }
+ } else {
+ const oldIndex = currentIndex;
+
+ moveCurrentIndexLeft();
+
+ if (oldIndex === currentIndex) {
+ return;
+ }
+
+ updateSelection(event.modifiers);
+ }
+ }
+
+ Keys.onRightPressed: event => {
+ if (root.isPopup && root.useListViewMode) {
+ if (currentIndex !== -1 && dir.hasSelection() && currentItem.isDir) {
+ main.doCd(positioner.map(currentIndex));
+ }
+ } else if (positioner.enabled) {
+ const newIndex = positioner.nearestItem(currentIndex,
+ FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.RightArrow));
+
+ if (newIndex !== -1) {
+ currentIndex = newIndex;
+ updateSelection(event.modifiers);
+ }
+ } else {
+ const oldIndex = currentIndex;
+
+ moveCurrentIndexRight();
+
+ if (oldIndex === currentIndex) {
+ return;
+ }
+
+ updateSelection(event.modifiers);
+ }
+ }
+
+ Keys.onUpPressed: event => {
+ if (positioner.enabled) {
+ const newIndex = positioner.nearestItem(currentIndex,
+ FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.UpArrow));
+
+ if (newIndex !== -1) {
+ currentIndex = newIndex;
+ updateSelection(event.modifiers);
+ }
+ } else {
+ const oldIndex = currentIndex;
+
+ moveCurrentIndexUp();
+
+ if (oldIndex === currentIndex) {
+ return;
+ }
+
+ updateSelection(event.modifiers);
+ }
+ }
+
+ Keys.onDownPressed: event => {
+ if (positioner.enabled) {
+ const newIndex = positioner.nearestItem(currentIndex,
+ FolderTools.effectiveNavDirection(gridView.flow, gridView.effectiveLayoutDirection, Qt.DownArrow));
+
+ if (newIndex !== -1) {
+ currentIndex = newIndex;
+ updateSelection(event.modifiers);
+ }
+ } else {
+ const oldIndex = currentIndex;
+
+ moveCurrentIndexDown();
+
+ if (oldIndex === currentIndex) {
+ return;
+ }
+
+ updateSelection(event.modifiers);
+ }
+ }
+
+ Keys.onBackPressed: event => {
+ if (root.isPopup && dir.resolvedUrl !== dir.resolve(Plasmoid.configuration.url)) {
+ main.doBack();
+ }
+ }
+
+ Connections {
+ target: Plasmoid.configuration
+
+ function onIconSizeChanged() {
+ gridView.iconSize = gridView.makeIconSize();
+ }
+
+ function onViewModeChanged() {
+ gridView.iconSize = gridView.makeIconSize();
+ }
+
+ function onUrlChanged() {
+ main.history = [];
+ main.historyChanged();
+ }
+ }
+ }
+
+ Kirigami.InlineMessage {
+ width: parent.width / 2.0
+ anchors.horizontalCenter: parent.horizontalCenter
+ type: Kirigami.MessageType.Warning
+ text: i18nc("@info",
+ "There are a lot of files and folders on the desktop. This can cause bugs and performance issues. Please consider moving some of them elsewhere.")
+ // Note: the trigger amount is intentionally lower than the screen mapping cap. We want to warn ahead of hitting our caps.
+ visible: main.isRootView && gridView.count > 2048
+ }
+ }
+
+ Folder.WheelInterceptor {
+ anchors.fill: parent
+
+ enabled: root.isContainment && !gridView.overflowing
+ destination: root
+ }
+
+ Folder.FolderModel {
+ id: dir
+
+ usedByContainment: root.isContainment && main.isRootView
+ sortDesc: Plasmoid.configuration.sortDesc
+ sortDirsFirst: Plasmoid.configuration.sortDirsFirst
+ parseDesktopFiles: (Plasmoid.configuration.url === "desktop:/")
+ previews: Plasmoid.configuration.previews
+ previewPlugins: Plasmoid.configuration.previewPlugins
+ applet: Plasmoid
+
+ onListingCompleted: {
+ if (!gridView.model && root.expanded) {
+ gridView.model = positioner;
+ gridView.currentIndex = isPopup ? 0 : -1;
+ } else if (main.goingBack) {
+ main.goingBack = false;
+ gridView.currentIndex = Math.min(main.lastPosition.index, gridView.count - 1);
+ setSelected(positioner.map(gridView.currentIndex));
+ gridView.contentY = main.lastPosition.yPosition * gridView.contentHeight;
+ }
+ }
+
+ onMove: (x, y, urls) => {
+ if (!positioner.enabled) {
+ return;
+ }
+ const rows = (gridView.flow === GridView.FlowLeftToRight);
+ const dropPos = gridView.mapToItem(gridView.contentItem, x, y);
+ const leftEdge = Math.min(gridView.contentX, gridView.originX);
+
+ let moves = []
+ let itemX = -1;
+ let itemY = -1;
+ let col = -1;
+ let row = -1;
+ let from = -1;
+ let to = -1;
+
+ for (let i = 0; i < urls.length; i++) {
+ from = positioner.indexForUrl(urls[i]);
+ to = -1;
+
+ if (from === -1) {
+ continue;
+ }
+
+ let offset = dir.dragCursorOffset(positioner.map(from));
+
+ if (offset.x === -1) {
+ continue;
+ }
+
+ // The +(gridView.cellWidth / 2) is kept here to make it easier to drag items between cells.
+ itemX = dropPos.x + offset.x + (listener.dragX % gridView.cellWidth) + (gridView.cellWidth / 2);
+ itemY = dropPos.y + offset.y + (listener.dragY % gridView.cellHeight) + gridView.verticalDropHitscanOffset;
+
+
+ if (gridView.effectiveLayoutDirection === Qt.RightToLeft) {
+ itemX -= (rows ? gridView.contentX : gridView.originX);
+ itemX = (rows ? gridView.width : gridView.contentItem.width) - itemX;
+ }
+
+ col = rows ? Math.floor(itemX / gridView.cellWidth) : Math.floor(itemY / gridView.cellHeight);
+ row = rows ? Math.floor(itemY / gridView.cellHeight) : Math.floor(itemX / gridView.cellWidth);
+
+
+ if (col <= positioner.perStripe) {
+ // We have somehow moved the item outside of the available
+ // areas (usually during file creation), so make sure
+ // the col is within perStripe
+ if (col === positioner.perStripe) {
+ col -= 1;
+ }
+
+ to = (row * positioner.perStripe) + col;
+
+ if (to < 0) {
+ return;
+ }
+ }
+
+ if (from !== to) {
+ moves.push(from);
+ moves.push(to);
+ }
+ }
+
+ if (moves.length) {
+ // Update also the currentIndex, otherwise it
+ // is not set properly.
+ gridView.currentIndex = positioner.move(moves);
+ gridView.forceLayout();
+ }
+
+ main.previouslySelectedItemIndex = -1;
+ }
+ }
+
+ Folder.Positioner {
+ id: positioner
+
+ enabled: main.isRootView && main.sortMode === -1
+
+ folderModel: dir
+
+ optimalStripes: Math.floor((gridView.flow === GridView.FlowLeftToRight)
+ ? (gridView.height / gridView.cellHeight)
+ : (gridView.width / gridView.cellWidth))
+ perStripe: Math.floor((gridView.flow === GridView.FlowLeftToRight)
+ ? (gridView.width / gridView.cellWidth)
+ : (gridView.height / gridView.cellHeight))
+
+ onModelReset: {
+ // When reset, listener.pressedItem will be invalidated.
+ listener.clearPressState();
+ }
+ }
+
+ Folder.ItemViewAdapter {
+ id: viewAdapter
+
+ adapterView: gridView
+ adapterModel: positioner
+ adapterIconSize: gridView.iconSize * 2
+ adapterVisibleArea: Qt.rect(gridView.contentX, gridView.contentY, gridView.contentWidth, gridView.contentHeight)
+
+ Component.onCompleted: {
+ gridView.movementStarted.connect(viewAdapter.viewScrolled);
+ dir.viewAdapter = viewAdapter;
+ }
+ }
+
+ Component {
+ id: editorComponent
+
+ RenameEditor {
+ id: editor
+
+ visible: false
+
+ onCommit: {
+ if (targetItem) {
+ dir.rename(positioner.map(targetItem.index), text);
+ targetItem = null;
+ gridView.forceActiveFocus();
+ }
+ }
+
+ onVisibleChanged: {
+ if (root.visible) {
+ focus = true;
+ } else {
+ scrollArea.focus = true;
+ }
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ dir.requestRename.connect(main.rename);
+ }
+ }
+
+ Component.onCompleted: {
+ if (main.backButton === null && root.useListViewMode) {
+ main.backButton = makeBackButton();
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewDialog.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewDialog.qml
new file mode 100644
index 0000000..72fe782
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewDialog.qml
@@ -0,0 +1,129 @@
+/*
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+
+import org.kde.private.desktopcontainment.folder as Folder
+
+Folder.SubDialog {
+ id: dialog
+
+ visible: false
+
+ property bool containsDrag: {
+ if (folderViewDropArea.containsDrag) {
+ return true;
+ }
+
+ if (folderView.hoveredItem && folderView.hoveredItem.popupDialog) {
+ return folderView.hoveredItem.popupDialog.containsDrag;
+ }
+
+ return false;
+ }
+
+ property QtObject closeTimer: closeTimer
+ property QtObject childDialog: (folderView.hoveredItem !== null) ? folderView.hoveredItem.popupDialog : null
+ property bool containsMouse: folderView.containsMouse || (childDialog !== null && childDialog.containsMouse)
+
+ property alias url: folderView.url
+
+ location: PlasmaCore.Types.Floating
+ hideOnWindowDeactivate: (allowClosing && (childDialog === null))
+
+ onContainsMouseChanged: {
+ if (containsMouse) {
+ closeTimer.stop();
+ } else {
+ closeTimer.start();
+ }
+ }
+
+ mainItem: FolderViewDropArea {
+ id: folderViewDropArea
+
+ width: folderView.cellWidth * 3 + Kirigami.Units.gridUnit // FIXME HACK: Use actual scrollbar width.
+ height: folderView.cellHeight * 2
+
+ folderView: folderView
+
+ FolderView {
+ id: folderView
+
+ anchors.fill: parent
+
+ isRootView: false
+ dialog: dialog
+
+ locked: true
+
+ sortMode: ((Plasmoid.configuration.sortMode === 0) ? 1 : Plasmoid.configuration.sortMode)
+ filterMode: 0
+
+ // TODO: Bidi.
+ flow: GridView.FlowLeftToRight
+ layoutDirection: Qt.LeftToRight
+
+ onDragInProgressAnywhereChanged: {
+ if (!dragInProgressAnywhere && !dialog.visible) {
+ dialog.destroy();
+ }
+ }
+ onCreatingNewItemsChanged: {
+ dialog.allowClosing = !creatingNewItems;
+ }
+ }
+
+ Loader {
+ anchors.centerIn: parent
+ width: parent.width - (Kirigami.Units.gridUnit * 4)
+ active: folderView.view.count === 0
+ sourceComponent: PlasmaExtras.PlaceholderMessage {
+ text: i18nc("@info:placeholder", "Folder is empty")
+ }
+ }
+ }
+
+ data: [
+ Timer {
+ id: closeTimer
+
+ interval: Kirigami.Units.humanMoment
+
+ onTriggered: {
+ if (dialog.childDialog !== null) {
+ dialog.childDialog.closeTimer.stop();
+ dialog.childDialog.visible = false;
+ }
+
+ dialog.visible = false;
+ dialog.delayedDestroy();
+ }
+ }
+ ]
+
+ function requestDestroy() {
+ if (folderView.dragInProgressAnywhere) {
+ visible = false;
+ } else {
+ destroy();
+ }
+ }
+
+ function delayedDestroy() {
+ Qt.callLater(() => itemDialog.destroy());
+ }
+
+ Component.onDestruction: {
+ closeTimer.stop();
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewDropArea.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewDropArea.qml
new file mode 100644
index 0000000..d74b257
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewDropArea.qml
@@ -0,0 +1,60 @@
+/*
+ SPDX-FileCopyrightText: 2014-2017 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.draganddrop as DragDrop
+import org.kde.kirigami as Kirigami
+
+DragDrop.DropArea {
+ id: dropArea
+
+ property FolderView folderView: null
+
+ function handleDragMove(folderView, pos) {
+ // Trigger autoscroll.
+ folderView.scrollLeft = (pos.x < (Kirigami.Units.gridUnit * 3));
+ folderView.scrollRight = (pos.x > width - (Kirigami.Units.gridUnit * 3));
+ folderView.scrollUp = (pos.y < (Kirigami.Units.gridUnit * 3));
+ folderView.scrollDown = (pos.y > height - (Kirigami.Units.gridUnit * 3));
+
+ folderView.handleDragMove(pos.x, pos.y);
+ }
+
+ function handleDragEnd(folderView) {
+ // Cancel autoscroll.
+ folderView.scrollLeft = false;
+ folderView.scrollRight = false;
+ folderView.scrollUp = false;
+ folderView.scrollDown = false;
+
+ folderView.endDragMove();
+ }
+
+ onDragMove: event => {
+ // TODO: We should reject drag moves onto file items that don't accept drops
+ // (cf. QAbstractItemModel::flags() here, but DeclarativeDropArea currently
+ // is currently incapable of rejecting drag events.
+
+ if (folderView) {
+ handleDragMove(folderView, mapToItem(folderView, event.x, event.y));
+ }
+ }
+
+ onDragLeave: event => {
+ if (folderView) {
+ handleDragEnd(folderView);
+ }
+ }
+
+ onDrop: event => {
+ if (folderView) {
+ handleDragEnd(folderView);
+
+ folderView.drop(folderView, event, mapToItem(folderView, event.x, event.y));
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewLayer.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewLayer.qml
new file mode 100644
index 0000000..a235747
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/FolderViewLayer.qml
@@ -0,0 +1,385 @@
+/*
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQml
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.components as PlasmaComponents
+import org.kde.config // for KAuthorized
+import org.kde.kirigami as Kirigami
+
+import org.kde.private.desktopcontainment.folder as Folder
+
+FocusScope {
+ id: folderViewLayerComponent
+
+ // these need to be passed in from main, but required properties with Loaders are awkward
+ /*required*/ property bool isPopup
+ /*required*/ property bool useListViewMode
+
+ property var sharedActions: ["newMenu", "paste", "undo", "emptyTrash"]
+ property Component folderViewDialogComponent: Qt.createComponent("FolderViewDialog.qml", Qt.Asynchronous, root)
+
+ property FolderView view: folderView
+ property Item label: null
+ property int labelHeight: Kirigami.Units.iconSizes.sizeForLabels + (Kirigami.Units.smallSpacing * 2)
+
+ property alias model: folderView.model
+ property alias overflowing: folderView.overflowing
+ property alias flow: folderView.flow
+
+ readonly property bool lockedByKiosk: !KAuthorized.authorize("editable_desktop_icons")
+
+ focus: true
+
+ function updateContextualActions() {
+ folderView.model.updateActions();
+
+ for (let i = 0, len = sharedActions.length; i < len; i++) {
+ const actionName = sharedActions[i];
+ const appletAction = Plasmoid.internalAction(actionName);
+ if (appletAction) {
+ modelAction = folderView.model.action(actionName);
+ appletAction.text = modelAction.text;
+ appletAction.enabled = modelAction.enabled;
+ appletAction.visible = modelAction.visible;
+ }
+ }
+ }
+
+ function cancelRename() {
+ folderView.cancelRename();
+ }
+
+ function goHome() {
+ if (folderView.url !== Plasmoid.configuration.url) {
+ folderView.url = Qt.binding(() => Plasmoid.configuration.url);
+ folderView.history = [];
+ folderView.historyChanged();
+ }
+ }
+
+ Binding {
+ target: Plasmoid
+ property: "title"
+ value: labelGenerator.displayLabel
+ restoreMode: Binding.RestoreBinding
+ }
+
+ Folder.LabelGenerator {
+ id: labelGenerator
+
+ folderModel: folderView.model
+ rtl: (Application.layoutDirection === Qt.RightToLeft)
+ labelMode: Plasmoid.configuration.labelMode || (Plasmoid.isContainment ? 0 : 1)
+ labelText: Plasmoid.configuration.labelText
+ }
+
+ Folder.ViewPropertiesMenu {
+ id: viewPropertiesMenu
+
+ showLayoutActions: !folderViewLayerComponent.isPopup
+ showLockAction: Plasmoid.isContainment
+ showIconSizeActions: !folderViewLayerComponent.useListViewMode
+
+ lockedEnabled: !folderViewLayerComponent.lockedByKiosk
+
+ onArrangementChanged: {
+ Plasmoid.configuration.arrangement = arrangement;
+ }
+
+ onAlignmentChanged: {
+ Plasmoid.configuration.alignment = alignment;
+ }
+
+ onPreviewsChanged: {
+ Plasmoid.configuration.previews = previews;
+ }
+
+ onLockedChanged: {
+ if (!folderViewLayerComponent.lockedByKiosk) {
+ Plasmoid.configuration.locked = locked;
+ }
+ }
+
+ onSortModeChanged: {
+ Plasmoid.configuration.sortMode = sortMode;
+ }
+
+ onSortDescChanged: {
+ Plasmoid.configuration.sortDesc = sortDesc;
+ }
+
+ onSortDirsFirstChanged: {
+ Plasmoid.configuration.sortDirsFirst = sortDirsFirst;
+ }
+
+ onIconSizeChanged: {
+ Plasmoid.configuration.iconSize = iconSize;
+ }
+
+ Component.onCompleted: {
+ arrangement = Plasmoid.configuration.arrangement;
+ alignment = Plasmoid.configuration.alignment;
+ previews = Plasmoid.configuration.previews;
+ locked = Plasmoid.configuration.locked || folderViewLayerComponent.lockedByKiosk;
+ sortMode = Plasmoid.configuration.sortMode;
+ sortDesc = Plasmoid.configuration.sortDesc;
+ sortDirsFirst = Plasmoid.configuration.sortDirsFirst;
+ iconSize = Plasmoid.configuration.iconSize;
+ }
+ }
+
+ PlasmaComponents.Label {
+ anchors.fill: parent
+
+ text: folderView.errorString
+ textFormat: Text.PlainText
+
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.Wrap
+ }
+
+ Connections {
+ target: root
+
+ function onExpandedChanged() {
+ if (folderViewLayerComponent.isPopup) {
+ if (root.expanded) {
+ folderView.currentIndex = -1;
+ folderView.forceActiveFocus();
+ folderView.positionViewAtBeginning();
+ } else {
+ folderViewLayerComponent.goHome();
+
+ folderView.currentIndex = -1;
+ folderView.model.clearSelection();
+ folderView.cancelRename();
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: Plasmoid.configuration
+
+ function onArrangementChanged() {
+ viewPropertiesMenu.arrangement = Plasmoid.configuration.arrangement;
+ }
+
+ function onAlignmentChanged() {
+ viewPropertiesMenu.alignment = Plasmoid.configuration.alignment;
+ }
+
+ function onLockedChanged() {
+ viewPropertiesMenu.locked = Plasmoid.configuration.locked;
+ }
+
+ function onSortModeChanged() {
+ folderView.sortMode = Plasmoid.configuration.sortMode;
+ viewPropertiesMenu.sortMode = Plasmoid.configuration.sortMode;
+ }
+
+ function onSortDescChanged() {
+ viewPropertiesMenu.sortDesc = Plasmoid.configuration.sortDesc;
+ }
+
+ function onSortDirsFirstChanged() {
+ viewPropertiesMenu.sortDirsFirst = Plasmoid.configuration.sortDirsFirst;
+ }
+
+ function onIconSizeChanged() {
+ viewPropertiesMenu.iconSize = Plasmoid.configuration.iconSize;
+ }
+ }
+
+ FolderView {
+ id: folderView
+
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.topMargin: folderViewLayerComponent.label !== null ? folderViewLayerComponent.label.height : 0
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+
+ focus: true
+ isRootView: Plasmoid.isContainment
+ positionerApplet: Plasmoid
+
+ url: Plasmoid.configuration.url
+ locked: (Plasmoid.configuration.locked || !Plasmoid.isContainment || folderViewLayerComponent.lockedByKiosk)
+ filterMode: Plasmoid.configuration.filterMode
+ filterPattern: Plasmoid.configuration.filterPattern
+ filterMimeTypes: Plasmoid.configuration.filterMimeTypes
+ showHiddenFiles: Plasmoid.configuration.showHiddenFiles
+
+ flow: (Plasmoid.configuration.arrangement === 0) ? GridView.FlowLeftToRight : GridView.FlowTopToBottom
+ layoutDirection: (Plasmoid.configuration.alignment === 0) ? Qt.LeftToRight : Qt.RightToLeft
+
+ onSortModeChanged: {
+ Plasmoid.configuration.sortMode = sortMode;
+ }
+
+ Component.onCompleted: {
+ folderView.sortMode = Plasmoid.configuration.sortMode;
+ }
+ }
+
+ Component {
+ id: labelComponent
+
+ Item {
+ id: label
+
+ // If we bind height to visible, it will be invisible initially (since "visible"
+ // propagates recursively) and that confuses the Label, hence the temp property.
+ readonly property bool active: (Plasmoid.configuration.labelMode !== 0)
+
+ readonly property bool showPin: folderViewLayerComponent.isPopup && root.compactRepresentationItem && root.compactRepresentationItem.visible
+
+ width: parent.width
+ height: active ? folderViewLayerComponent.labelHeight : 0
+
+ visible: active
+
+ property Item windowPin: null
+ property Item homeButton: null
+
+ onVisibleChanged: {
+ if (folderViewLayerComponent.isPopup && !visible) {
+ root.hideOnWindowDeactivate = true;
+ }
+ }
+
+ onShowPinChanged: {
+ if (!windowPin && showPin) {
+ windowPin = windowPinComponent.createObject(label);
+ } else if (windowPin) {
+ windowPin.destroy();
+ windowPin = null;
+ }
+ }
+
+ Connections {
+ target: folderView
+
+ function onUrlChanged() {
+ if (!label.homeButton && folderView.url !== Plasmoid.configuration.url) {
+ label.homeButton = homeButtonComponent.createObject(label);
+ } else if (label.homeButton && folderView.url === Plasmoid.configuration.url) {
+ label.homeButton.destroy();
+ }
+ }
+ }
+
+ PlasmaComponents.Label {
+ id: text
+
+ anchors {
+ left: label.homeButton ? label.homeButton.right : parent.left
+ right: label.windowPin ? label.windowPin.left : parent.right
+ margins: Kirigami.Units.smallSpacing
+ }
+ height: parent.height
+
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignTop
+ elide: Text.ElideMiddle
+ text: labelGenerator.displayLabel
+ textFormat: Text.PlainText
+ font.underline: labelMouseArea.containsMouse
+ }
+
+ MouseArea {
+ id: labelMouseArea
+ anchors {
+ top: text.top
+ horizontalCenter: text.horizontalCenter
+ }
+ width: text.contentWidth
+ height: text.contentHeight
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+
+ onClicked: {
+ Folder.AppLauncher.openUrl(folderView.url)
+ }
+ }
+
+ Component {
+ id: windowPinComponent
+
+ PlasmaComponents.ToolButton {
+ id: windowPin
+
+ anchors.right: parent.right
+
+ visible: label.showPin
+
+ width: folderViewLayerComponent.isPopup ? Math.round(Kirigami.Units.gridUnit * 1.25) : 0
+ height: width
+ checkable: true
+ icon.name: "window-pin"
+ onCheckedChanged: root.hideOnWindowDeactivate = !checked
+ }
+ }
+
+ Component {
+ id: homeButtonComponent
+
+ PlasmaComponents.ToolButton {
+ id: homeButton
+
+ anchors.left: parent.left
+
+ visible: folderViewLayerComponent.isPopup && folderView.url !== Plasmoid.configuration.url
+
+ width: folderViewLayerComponent.isPopup ? Math.round(Kirigami.Units.gridUnit * 1.25) : 0
+ height: width
+ icon.name: "go-home"
+
+ onClicked: folderViewLayerComponent.goHome()
+ }
+ }
+ }
+ }
+
+
+ PlasmaCore.Action {
+ id: viewPropertiesAction
+ text: i18nc("@item:inmenu opens submenu with view options like sorting", "Icons")
+ icon.name: "view-list-icons"
+ menu: viewPropertiesMenu.menu
+ }
+ PlasmaCore.Action {
+ id: actionSeparator
+ isSeparator: true
+ }
+
+ Component.onCompleted: {
+ if (!Plasmoid.isContainment) {
+ label = labelComponent.createObject(folderViewLayerComponent);
+ }
+
+ for (let i = 0, len = sharedActions.length; i < len; i++) {
+ const actionName = sharedActions[i];
+ const modelAction = folderView.model.action(actionName);
+ Plasmoid.contextualActions.push(modelAction)
+ if (actionName === "emptyTrash") {
+ Plasmoid.contextualActions.push(viewPropertiesAction)
+ }
+ }
+
+ Plasmoid.contextualActions.push(actionSeparator);
+
+ Plasmoid.contextualActionsAboutToShow.connect(updateContextualActions);
+ Plasmoid.contextualActionsAboutToShow.connect(folderView.model.clearSelection);
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/RenameEditor.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/RenameEditor.qml
new file mode 100644
index 0000000..c291165
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/RenameEditor.qml
@@ -0,0 +1,206 @@
+/*
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQml
+import QtQuick.Controls as QQC2
+
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.components as PlasmaComponents
+import org.kde.kirigami as Kirigami
+
+
+PlasmaComponents.ScrollView {
+ id: root
+
+ property alias text: editor.text
+ property alias targetItem: editor.targetItem
+ signal commit
+
+ onFocusChanged: {
+ if (focus) {
+ editor.forceActiveFocus();
+ }
+ }
+
+ // We use QQC2.TextArea here to allow context menu to appear,
+ // since PlasmaComponents.TextArea does not have a context menu
+ // BUG:427292
+ QQC2.TextArea {
+ id: editor
+
+ wrapMode: root.useListViewMode ? TextEdit.NoWrap : TextEdit.Wrap
+
+ textMargin: 0
+
+ horizontalAlignment: root.useListViewMode ? TextEdit.AlignLeft : TextEdit.AlignHCenter
+
+ rightPadding: root.PlasmaComponents.ScrollBar.vertical.visible ? root.PlasmaComponents.ScrollBar.vertical.width : 0
+
+ Kirigami.SpellCheck.enabled: false
+
+ background: Rectangle {
+ color: Kirigami.Theme.backgroundColor
+ radius: Kirigami.Units.cornerRadius
+ border.color: Kirigami.Theme.highlightColor
+ border.width: 1
+ }
+
+ property FolderItemDelegate targetItem: null
+
+ Binding {
+ target: editor.background
+ property: "width"
+ value: root.width
+ }
+ Binding {
+ target: editor.background
+ property: "height"
+ value: root.height
+ }
+ Component.onCompleted: root.contentItem.clip = false
+
+ onTargetItemChanged: {
+ if (targetItem !== null) {
+ var xy = getXY();
+ root.x = xy[0];
+ root.y = xy[1];
+ root.width = getWidth();
+ root.height = getInitHeight();
+ text = targetItem.name;
+ adjustSize();
+ editor.select(0, dir.fileExtensionBoundary(positioner.map(targetItem.index)));
+ if (isPopup) {
+ root.contentItem.contentX = Math.max(root.contentItem.contentWidth - contentItem.width, 0);
+ } else {
+ root.contentItem.contentY = Math.max(root.contentItem.contentHeight - contentItem.height, 0);
+ }
+ root.visible = true;
+ } else {
+ root.x = 0;
+ root.y = 0;
+ root.visible = false;
+ }
+ }
+
+ Keys.onPressed: event => {
+ switch (event.key) {
+ case Qt.Key_Return:
+ case Qt.Key_Enter:
+ root.commit();
+ break;
+ case Qt.Key_Escape:
+ if (targetItem) {
+ targetItem = null;
+ event.accepted = true;
+ }
+ break;
+ case Qt.Key_Home:
+ if (event.modifiers & Qt.ShiftModifier) {
+ editor.select(0, cursorPosition);
+ } else {
+ editor.select(0, 0);
+ }
+ event.accepted = true;
+ break;
+ case Qt.Key_End:
+ if (event.modifiers & Qt.ShiftModifier) {
+ editor.select(cursorPosition, text.length);
+ } else {
+ editor.select(text.length, text.length);
+ }
+ event.accepted = true;
+ break;
+ default:
+ adjustSize();
+ break;
+ }
+ }
+
+ Keys.onReleased: event => {
+ adjustSize();
+ }
+
+ function getXY() {
+ if (!targetItem) {
+ return [0,0];
+ }
+ var pos = main.mapFromItem(targetItem, targetItem.labelArea.x, targetItem.labelArea.y);
+ var _x, _y;
+ if (root.useListViewMode) {
+ _x = targetItem.labelArea.x - editor.leftPadding;
+ _y = pos.y - editor.topPadding;
+ } else {
+ _x = targetItem.x + Math.abs(Math.min(gridView.contentX, gridView.originX));
+ _x += editor.leftPadding;
+ _x += scrollArea.viewport.x;
+ if (root.PlasmaComponents.ScrollBar.vertical.policy === Qt.ScrollBarAlwaysOn
+ && gridView.effectiveLayoutDirection === Qt.RightToLeft) {
+ _x -= root.PlasmaComponents.ScrollBar.vertical.width;
+ }
+ _y = pos.y + Kirigami.Units.smallSpacing - editor.topPadding;
+ }
+ return [ _x, _y ];
+ }
+
+ function getWidth(addWidthVerticalScroller) {
+ if (!targetItem) {
+ return 0;
+ }
+ return(targetItem.label.parent.width - Kirigami.Units.smallSpacing +
+ (root.useListViewMode ? -(editor.leftPadding + editor.rightPadding + Kirigami.Units.smallSpacing) : 0) +
+ (addWidthVerticalScroller ? root.PlasmaComponents.ScrollBar.vertical.width : 0));
+ }
+
+ function getHeight(addWidthHoriozontalScroller, init) {
+ if (!targetItem) {
+ return 0;
+ }
+ var _height;
+ if (isPopup || init) {
+ _height = targetItem.labelArea.height + editor.topPadding + editor.bottomPadding;
+ } else {
+ var realHeight = contentHeight + editor.topPadding + editor.bottomPadding;
+ var maxHeight = Kirigami.Units.iconSizes.sizeForLabels * (Plasmoid.configuration.textLines + 1) + editor.topPadding + editor.bottomPadding;
+ _height = Math.min(realHeight, maxHeight);
+ }
+ return _height + (addWidthHoriozontalScroller ? root.PlasmaComponents.ScrollBar.horizontal.height : 0);
+ }
+
+ function getInitHeight() {
+ return getHeight(false, true);
+ }
+
+ function adjustSize() {
+ if (isPopup) {
+ if(contentWidth + editor.leftPadding + editor.rightPadding > root.width) {
+ root.visible = targetItem !== null;
+ root.PlasmaComponents.ScrollBar.horizontal.policy = Qt.ScrollBarAlwaysOn;
+ root.height = getHeight(true);
+ } else {
+ root.PlasmaComponents.ScrollBar.horizontal.policy = Qt.ScrollBarAlwaysOff;
+ root.height = getHeight();
+ }
+ } else {
+ root.height = getHeight();
+ if(contentHeight + editor.topPadding + editor.bottomPadding > root.height) {
+ root.visible = targetItem !== null;
+ root.PlasmaComponents.ScrollBar.vertical.policy = Qt.ScrollBarAlwaysOn;
+ root.width = getWidth(true);
+ } else {
+ root.PlasmaComponents.ScrollBar.vertical.policy = Qt.ScrollBarAlwaysOff;
+ root.width = getWidth();
+ }
+ }
+
+ var xy = getXY();
+ root.x = xy[0];
+ root.y = xy[1];
+ }
+ }
+}
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/code/FolderTools.js b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/code/FolderTools.js
new file mode 100644
index 0000000..dc354ca
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/code/FolderTools.js
@@ -0,0 +1,69 @@
+/*
+ SPDX-FileCopyrightText: 2014 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+var iconSizes = [Kirigami.Units.iconSizes.smallMedium,
+ Kirigami.Units.iconSizes.medium,
+ Kirigami.Units.iconSizes.large,
+ Kirigami.Units.iconSizes.huge,
+ Kirigami.Units.iconSizes.large*2,
+ Kirigami.Units.iconSizes.enormous,
+ Kirigami.Units.iconSizes.enormous*2];
+
+function iconSizeFromTheme(size) {
+ return iconSizes[size];
+}
+
+function effectiveNavDirection(flow, layoutDirection, direction) {
+ if (direction == Qt.LeftArrow) {
+ if (flow == GridView.FlowLeftToRight) {
+ if (layoutDirection == Qt.LeftToRight) {
+ return Qt.LeftArrow;
+ } else {
+ return Qt.RightArrow;
+ }
+ } else {
+ if (layoutDirection == Qt.LeftToRight) {
+ return Qt.UpArrow;
+ } else {
+ return Qt.DownArrow;
+ }
+ }
+ } else if (direction == Qt.RightArrow) {
+ if (flow == GridView.FlowLeftToRight) {
+ if (layoutDirection == Qt.LeftToRight) {
+ return Qt.RightArrow;
+ } else {
+ return Qt.LeftArrow;
+ }
+ } else {
+ if (layoutDirection == Qt.LeftToRight) {
+ return Qt.DownArrow;
+ } else {
+ return Qt.UpArrow;
+ }
+ }
+ } else if (direction == Qt.UpArrow) {
+ if (flow == GridView.FlowLeftToRight) {
+ return Qt.UpArrow;
+ } else {
+ return Qt.LeftArrow;
+ }
+ } else if (direction == Qt.DownArrow) {
+ if (flow == GridView.FlowLeftToRight) {
+ return Qt.DownArrow;
+ } else {
+ return Qt.RightArrow
+ }
+ }
+}
+
+function isFileDrag(event) {
+ var taskUrl = event.mimeData.formats.indexOf("text/x-orgkdeplasmataskmanager_taskurl") != -1;
+ var arkService = event.mimeData.formats.indexOf("application/x-kde-ark-dndextract-service") != -1;
+ var arkPath = event.mimeData.formats.indexOf("application/x-kde-ark-dndextract-path") != -1;
+
+ return (event.mimeData.hasUrls || taskUrl || (arkService && arkPath));
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/main.qml b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/main.qml
new file mode 100644
index 0000000..d2bcbd8
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/contents/ui/main.qml
@@ -0,0 +1,473 @@
+/*
+ SPDX-FileCopyrightText: 2011-2013 Sebastian Kügler
+ SPDX-FileCopyrightText: 2011-2019 Marco Martin
+ SPDX-FileCopyrightText: 2014-2015 Eike Hein
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+import org.kde.ksvg as KSvg
+import org.kde.kirigami as Kirigami
+
+import org.kde.private.desktopcontainment.folder as Folder
+
+import org.kde.plasma.private.containmentlayoutmanager as ContainmentLayoutManager
+
+import "code/FolderTools.js" as FolderTools
+
+ContainmentItem {
+ id: root
+
+ switchWidth: { switchSize(); }
+ switchHeight: { switchSize(); }
+
+ // Only exists because the default CompactRepresentation doesn't:
+ // - open on drag
+ // - allow defining a custom drop handler
+ // TODO remove once it gains that feature (perhaps optionally?)
+ compactRepresentation: (isFolder && !isContainment) ? compactRepresentation : null
+
+ objectName: isFolder ? "folder" : "desktop"
+
+ width: isPopup ? undefined : preferredWidth(false) // Initial size when adding to e.g. desktop.
+ height: isPopup ? undefined : preferredHeight(false) // Initial size when adding to e.g. desktop.
+
+ function switchSize() {
+ // Support expanding into the full representation on very thick vertical panels.
+ if (isPopup && Plasmoid.formFactor === PlasmaCore.Types.Vertical) {
+ return Kirigami.Units.gridUnit * 8;
+ }
+
+ return 0;
+ }
+
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+
+ property bool isFolder: (Plasmoid.pluginName === "org.kde.plasma.folder")
+ property bool isContainment: Plasmoid.isContainment
+ property bool isPopup: (Plasmoid.location !== PlasmaCore.Types.Floating)
+ property bool useListViewMode: isPopup && Plasmoid.configuration.viewMode === 0
+
+ property Component appletAppearanceComponent
+
+ property int handleDelay: 800
+ property real haloOpacity: 0.5
+
+ readonly property bool isUiReady: Plasmoid.containment.corona.isScreenUiReady(root.screen)
+
+ readonly property int hoverActivateDelay: 750 // Magic number that matches Dolphin's auto-expand folders delay.
+
+ readonly property FolderViewLayerLoader folderViewLayer: fullRepresentationItem.folderViewLayer
+ readonly property ContainmentLayoutManager.AppletsLayout appletsLayout: fullRepresentationItem.appletsLayout
+
+ // Plasmoid.title is set by a Binding {} in FolderViewLayer
+ toolTipSubText: ""
+ Plasmoid.icon: (!Plasmoid.configuration.useCustomIcon && folderViewLayer.ready) ? symbolicizeIconName(folderViewLayer.view?.model.iconName) : Plasmoid.configuration.icon
+
+ // We want to do this here rather than in the model because we don't always want
+ // symbolic icons everywhere, but we do know that we always want them in this
+ // specific representation right here
+ function symbolicizeIconName(iconName) {
+ const symbolicSuffix = "-symbolic";
+ if (iconName?.endsWith(symbolicSuffix)) {
+ return iconName;
+ }
+
+ return iconName + symbolicSuffix;
+ }
+
+ function addLauncher(desktopUrl) {
+ if (!isFolder) {
+ return;
+ }
+
+ folderViewLayer.view.linkHere(desktopUrl);
+ }
+
+ function preferredWidth(forMinimumSize: bool): real {
+ if ((isContainment || !folderViewLayer.ready) || (isPopup && !compactRepresentationItem.visible)) {
+ return -1;
+ } else if (useListViewMode) {
+ return (forMinimumSize ? folderViewLayer.view.cellHeight * 4 : Kirigami.Units.gridUnit * 16);
+ }
+
+ return (folderViewLayer.view.cellWidth * (forMinimumSize ? 1 : 3)) + (Kirigami.Units.gridUnit * 2);
+ }
+
+ function preferredHeight(forMinimumSize: bool): real {
+ let height;
+ if ((isContainment || !folderViewLayer.ready) || (isPopup && !compactRepresentationItem.visible)) {
+ return -1;
+ } else if (useListViewMode) {
+ height = (folderViewLayer.view.cellHeight * (forMinimumSize ? 1 : 15)) + Kirigami.Units.smallSpacing;
+ } else {
+ height = (folderViewLayer.view.cellHeight * (forMinimumSize ? 1 : 2)) + Kirigami.Units.gridUnit;
+ }
+
+ if (Plasmoid.configuration.labelMode !== 0) {
+ height += (folderViewLayer.item as FolderViewLayer).labelHeight;
+ }
+
+ return height;
+ }
+
+ function isDrag(fromX, fromY, toX, toY) {
+ const length = Math.abs(fromX - toX) + Math.abs(fromY - toY);
+ return length >= Application.styleHints.startDragDistance;
+ }
+
+ onFocusChanged: {
+ if (focus && isFolder) {
+ (folderViewLayer.item as Item)?.forceActiveFocus();
+ }
+ }
+
+ onExternalData: (mimetype, data) => {
+ Plasmoid.configuration.url = data
+ }
+
+ component ShortDropBehavior : Behavior {
+ NumberAnimation {
+ duration: Kirigami.Units.shortDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ component LongDropBehavior : Behavior {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ KSvg.FrameSvgItem {
+ id: highlightItemSvg
+
+ visible: false
+
+ imagePath: root.isPopup ? "widgets/viewitem" : ""
+ prefix: "hover"
+ }
+
+ KSvg.FrameSvgItem {
+ id: listItemSvg
+
+ visible: false
+
+ imagePath: root.isPopup ? "widgets/viewitem" : ""
+ prefix: "normal"
+ }
+
+ KSvg.Svg {
+ id: toolBoxSvg
+ imagePath: "widgets/toolbox"
+ property int rightBorder: elementSize("right").width
+ property int topBorder: elementSize("top").height
+ property int bottomBorder: elementSize("bottom").height
+ property int leftBorder: elementSize("left").width
+ }
+
+ // FIXME: the use and existence of this property is a workaround
+ preloadFullRepresentation: true
+ fullRepresentation: FolderViewDropArea {
+ id: dropArea
+
+ anchors {
+ fill: parent
+ leftMargin: (root.isContainment && root.availableScreenRect) ? root.availableScreenRect.x : 0
+ topMargin: (root.isContainment && root.availableScreenRect) ? root.availableScreenRect.y : 0
+
+ rightMargin: (root.isContainment && root.availableScreenRect && parent)
+ ? (parent.width - root.availableScreenRect.x - root.availableScreenRect.width) : 0
+
+ bottomMargin: (root.isContainment && root.availableScreenRect && parent)
+ ? (parent.height - root.availableScreenRect.y - root.availableScreenRect.height) : 0
+ }
+
+ LongDropBehavior on anchors.topMargin { }
+ LongDropBehavior on anchors.leftMargin { }
+ LongDropBehavior on anchors.rightMargin { }
+ LongDropBehavior on anchors.bottomMargin { }
+
+ property alias folderViewLayer: folderViewLayer
+ property alias appletsLayout: appletsLayout
+
+ // Layout size bindings are set in Component.onCompleted
+
+ preventStealing: true
+
+ onDragEnter: event => {
+ if (root.isContainment && Plasmoid.immutable && !(root.isFolder && FolderTools.isFileDrag(event))) {
+ event.ignore();
+ }
+
+ // Don't allow any drops while listing.
+ if (root.isFolder && folderViewLayer.view.status === Folder.FolderModel.Listing) {
+ event.ignore();
+ }
+
+ // Firefox tabs are regular drags. Since all of our drop handling is asynchronous
+ // we would accept this drop and have Firefox not spawn a new window. (Bug 337711)
+ if (event.mimeData.formats.indexOf("application/x-moz-tabbrowser-tab") !== -1) {
+ event.ignore();
+ }
+ }
+
+ onDragMove: event => {
+ // TODO: We should reject drag moves onto file items that don't accept drops
+ // (cf. QAbstractItemModel::flags() here, but DeclarativeDropArea currently
+ // is currently incapable of rejecting drag events.
+
+ // Trigger autoscroll.
+ if (root.isFolder && FolderTools.isFileDrag(event)) {
+ handleDragMove(folderViewLayer.view, mapToItem(folderViewLayer.view, event.x, event.y));
+ } else if (root.isContainment) {
+ appletsLayout.showPlaceHolderAt(
+ Qt.rect(event.x - appletsLayout.minimumItemWidth / 2,
+ event.y - appletsLayout.minimumItemHeight / 2,
+ appletsLayout.minimumItemWidth,
+ appletsLayout.minimumItemHeight)
+ );
+ }
+ }
+
+ onDragLeave: event => {
+ // Cancel autoscroll.
+ if (root.isFolder) {
+ handleDragEnd(folderViewLayer.view);
+ }
+
+ if (root.isContainment) {
+ appletsLayout.hidePlaceHolder();
+ }
+ }
+
+ onDrop: event => {
+ if (root.isFolder && FolderTools.isFileDrag(event)) {
+ handleDragEnd(folderViewLayer.view);
+ folderViewLayer.view.drop(root, event, mapToItem(folderViewLayer.view, event.x, event.y));
+ } else if (root.isContainment) {
+ root.processMimeData(event.mimeData,
+ event.x - appletsLayout.placeHolder.width / 2,
+ event.y - appletsLayout.placeHolder.height / 2);
+ event.accept(event.proposedAction);
+ appletsLayout.hidePlaceHolder();
+ }
+ }
+
+ Component {
+ id: compactRepresentation
+ CompactRepresentation { folderView: folderViewLayer.view }
+ }
+
+ Connections {
+ target: Plasmoid.containment.corona
+ ignoreUnknownSignals: true
+
+ function onEditModeChanged() {
+ appletsLayout.editMode = Plasmoid.containment.corona.editMode;
+ }
+
+ // When adding panels, sizes change. We want to make sure all panels
+ // are loaded, and when they all are loaded, we tell the folderViewLayer loader to start.
+ function onScreenUiReadyChanged(screen: int, newLayoutReady: bool) {
+ if (root.isContainment && root.isFolder && !folderViewLayer.ready && root.screen === screen && newLayoutReady){
+ // We skip x and y since that is handled by the parent of folderViewLayer
+ folderViewLayer.active = true;
+ }
+ }
+ }
+
+ ContainmentLayoutManager.AppletsLayout {
+ id: appletsLayout
+ anchors.fill: parent
+ relayoutLock: width !== root.availableScreenRect.width || height !== root.availableScreenRect.height
+ // NOTE: use root.availableScreenRect and not own width and height as they are updated not atomically
+ configKey: "ItemGeometries-" + Math.round(root.screenGeometry.width) + "x" + Math.round(root.screenGeometry.height)
+ fallbackConfigKey: root.availableScreenRect.width > root.availableScreenRect.height ? "ItemGeometriesHorizontal" : "ItemGeometriesVertical"
+
+ Binding on containment {
+ value: Plasmoid
+ when: Plasmoid.isContainment
+ }
+ containmentItem: root
+ editModeCondition: Plasmoid.immutable
+ ? ContainmentLayoutManager.AppletsLayout.Locked
+ : ContainmentLayoutManager.AppletsLayout.AfterPressAndHold
+
+ // Sets the containment in edit mode when we go in edit mode as well
+ onEditModeChanged: Plasmoid.containment.corona.editMode = editMode;
+
+ minimumItemWidth: Kirigami.Units.gridUnit * 3
+ minimumItemHeight: minimumItemWidth
+
+ cellWidth: Kirigami.Units.iconSizes.small
+ cellHeight: cellWidth
+ defaultItemWidth: cellWidth * 6
+ defaultItemHeight: cellHeight * 6
+
+ eventManagerToFilter: (folderViewLayer.item as FolderViewLayer)?.view.view ?? null
+
+ appletContainerComponent: ContainmentLayoutManager.BasicAppletContainer {
+ id: appletContainer
+
+ editModeCondition: Plasmoid.immutable
+ ? ContainmentLayoutManager.ItemContainer.Locked
+ : ContainmentLayoutManager.ItemContainer.AfterPressAndHold
+
+ configOverlaySource: "ConfigOverlay.qml"
+
+ Connections {
+ target: appletsLayout
+ function onEditModeChanged(): void {
+ if (!Plasmoid.containment.corona.editMode) {
+ appletContainer.cancelEdit();
+ }
+ }
+ }
+
+ onAppletChanged: {
+ applet.visible = true
+ }
+
+ Drag.dragType: Drag.Automatic
+ Drag.active: false
+ Drag.supportedActions: Qt.MoveAction
+ Drag.mimeData: {
+ "text/x-plasmoidinstanceid": Plasmoid.containment.id+':'+appletContainer.applet.plasmoid.id
+ }
+ Drag.onDragFinished: dropEvent => {
+ if (dropEvent == Qt.MoveAction) {
+ appletContainer.visible = true
+ appletContainer.applet.visible = true
+ //currentApplet.applet.plasmoid.internalAction("remove").trigger()
+ } else {
+ appletContainer.visible = true
+ //appletsModel.insert(configurationArea.draggedItemIndex - 1, {applet: appletContainer.applet});
+ }
+ //appletContainer.destroy()
+ //root.dragAndDropping = false
+ //root.layoutManager.save()
+ }
+
+ onUserDrag: (newPosition, dragCenter) => {
+ const pos = mapToItem(root.parent, dragCenter.x, dragCenter.y);
+ const newCont = root.containmentItemAt(pos.x, pos.y);
+ // User likely touched screen edges, so ignore that.
+ if (!newCont) {
+ return;
+ }
+
+ if (newCont.plasmoid !== Plasmoid) {
+ // First go out of applet edit mode, get rid of the config overlay, release mouse grabs in preparation of applet reparenting
+ cancelEdit();
+ appletsLayout.hidePlaceHolder();
+ appletContainer.grabToImage(result => {
+ appletContainer.Drag.imageSource = result.url
+ appletContainer.visible = false
+ appletContainer.Drag.active = true
+ })
+ }
+ }
+
+ ShortDropBehavior on x { }
+ ShortDropBehavior on y { }
+ }
+
+ placeHolder: ContainmentLayoutManager.PlaceHolder {}
+
+ component FolderViewLayerLoader: Loader {
+ property bool ready: status === Loader.Ready
+ property FolderView view: (item as FolderViewLayer)?.view ?? null
+ property Folder.FolderModel model: (item as FolderViewLayer)?.model ?? null
+
+ source: "FolderViewLayer.qml"
+ }
+
+
+ FolderViewLayerLoader {
+ id: folderViewLayer
+
+ anchors.fill: parent
+
+ focus: true
+
+ // Do not set this active by default for desktop, and disable it when folderMode is not used
+ active: {
+ if (root.isFolder){
+ if (!root.isContainment) {
+ // We are a folder widget
+ return true;
+ } else {
+ // For desktop, test if the screen is ready
+ return root.isUiReady;
+ }
+ }
+ return false;
+ }
+ asynchronous: false
+
+ onFocusChanged: {
+ if (!focus && model) {
+ model.clearSelection();
+ }
+ }
+
+ Binding {
+ target: folderViewLayer.item
+ property: "isPopup"
+ value: root.isPopup
+ }
+
+ Binding {
+ target: folderViewLayer.item
+ property: "useListViewMode"
+ value: root.useListViewMode
+ }
+
+ Connections {
+ target: folderViewLayer.view
+
+ // `FolderViewDropArea` is not a FocusScope. We need to forward manually.
+ function onPressed() {
+ folderViewLayer.forceActiveFocus();
+ }
+ }
+ }
+ }
+
+ PlasmaCore.Action {
+ id: configAction
+ text: i18nc("@action:inmenu opens config dialog", "Desktop and Wallpaper")
+ icon.name: "preferences-desktop-wallpaper"
+ shortcut:"Ctrl+Shift+D"
+ onTriggered: Plasmoid.containment.configureRequested(Plasmoid)
+ }
+
+ Component.onCompleted: {
+ // Layout bindings need to be set delayed; the intermediate steps as the other bindings happen cause loops
+ Qt.callLater( () => {
+ dropArea.Layout.minimumWidth = Qt.binding(() => root.preferredWidth(root.isPopup))
+ dropArea.Layout.minimumHeight = Qt.binding(() => root.preferredHeight(root.isPopup))
+
+ dropArea.Layout.preferredWidth = Qt.binding(() => root.preferredWidth(false))
+ dropArea.Layout.preferredHeight = Qt.binding(() => root.preferredHeight(false))
+
+ // Maximum size is intentionally unbounded
+ })
+
+ if (!Plasmoid.isContainment) {
+ return;
+ }
+
+ Plasmoid.setInternalAction("configure", configAction)
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/metadata.json
new file mode 100644
index 0000000..489e95d
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.desktopcontainment/metadata.json
@@ -0,0 +1,266 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "sebas@kde.org",
+ "Name": "Sebastian Kügler",
+ "Name[ar]": "سيباستيان كوغلر",
+ "Name[az]": "Sebastian Kügler",
+ "Name[be]": "Sebastian Kügler",
+ "Name[bg]": "Sebastian Kügler",
+ "Name[ca@valencia]": "Sebastian Kügler",
+ "Name[ca]": "Sebastian Kügler",
+ "Name[cs]": "Sebastian Kügler",
+ "Name[da]": "Sebastian Kügler",
+ "Name[de]": "Sebastian Kügler",
+ "Name[el]": "Sebastian kügler",
+ "Name[en_GB]": "Sebastian Kügler",
+ "Name[eo]": "Sebastian Kügler",
+ "Name[es]": "Sebastian Kügler",
+ "Name[et]": "Sebastian Kügler",
+ "Name[eu]": "Sebastian Kügler",
+ "Name[fi]": "Sebastian Kügler",
+ "Name[fr]": "Sebastian Kügler",
+ "Name[ga]": "Sebastian Kügler",
+ "Name[gl]": "Sebastian Kügler",
+ "Name[he]": "סבסטיאן קיגלר",
+ "Name[hu]": "Sebastian Kügler",
+ "Name[ia]": "Sebastian Kügler",
+ "Name[id]": "Sebastian Kügler",
+ "Name[ie]": "Sebastian Kügler",
+ "Name[is]": "Sebastian Kügler",
+ "Name[it]": "Sebastian Kügler",
+ "Name[ja]": "Sebastian Kügler",
+ "Name[ka]": "სებასტიან კუგლერი",
+ "Name[ko]": "Sebastian Kügler",
+ "Name[lt]": "Sebastian Kügler",
+ "Name[lv]": "Sebastian Kügler",
+ "Name[nb]": "Sebastian Kügler",
+ "Name[nl]": "Sebastian Kügler",
+ "Name[nn]": "Sebastian Kügler",
+ "Name[pl]": "Sebastian Kügler",
+ "Name[pt]": "Sebastian Kügler",
+ "Name[pt_BR]": "Sebastian Kügler",
+ "Name[ro]": "Sebastian Kügler",
+ "Name[ru]": "Sebastian Kügler",
+ "Name[sa]": "सेबास्टियन कुग्लर",
+ "Name[sk]": "Sebastian Kügler",
+ "Name[sl]": "Sebastian Kügler",
+ "Name[sv]": "Sebastian Kügler",
+ "Name[ta]": "ஸெபாஸ்டியன் கூக்லர்",
+ "Name[tr]": "Sebastian Kügler",
+ "Name[uk]": "Sebastian Kügler",
+ "Name[vi]": "Sebastian Kügler",
+ "Name[zh_CN]": "Sebastian Kügler",
+ "Name[zh_TW]": "Sebastian Kügler"
+ },
+ {
+ "Email": "hein@kde.org",
+ "Name": "Eike Hein",
+ "Name[ar]": "إيكي هين",
+ "Name[az]": "Eike Hein",
+ "Name[be]": "Eike Hein",
+ "Name[bg]": "Eike Hein",
+ "Name[ca@valencia]": "Eike Hein",
+ "Name[ca]": "Eike Hein",
+ "Name[cs]": "Eike Hein",
+ "Name[da]": "Eike Hein",
+ "Name[de]": "Eike Hein",
+ "Name[el]": "Eike Hein",
+ "Name[en_GB]": "Eike Hein",
+ "Name[eo]": "Eike Hein",
+ "Name[es]": "Eike Hein",
+ "Name[et]": "Eike Hein",
+ "Name[eu]": "Eike Hein",
+ "Name[fi]": "Eike Hein",
+ "Name[fr]": "Eike Hein",
+ "Name[ga]": "Eike Hein",
+ "Name[gl]": "Eike Hein",
+ "Name[he]": "אייק היין",
+ "Name[hu]": "Eike Hein",
+ "Name[ia]": "Eike Hein",
+ "Name[id]": "Eike Hein",
+ "Name[ie]": "Eike Hein",
+ "Name[is]": "Eike Hein",
+ "Name[it]": "Eike Hein",
+ "Name[ja]": "Eike Hein",
+ "Name[ka]": "აიკე ჰაინი",
+ "Name[ko]": "Eike Hein",
+ "Name[lt]": "Eike Hein",
+ "Name[lv]": "Eike Hein",
+ "Name[nb]": "Eike Hein",
+ "Name[nl]": "Eike Hein",
+ "Name[nn]": "Eike Hein",
+ "Name[pa]": "ਇਕੀ ਹੀਇਨ",
+ "Name[pl]": "Eike Hein",
+ "Name[pt]": "Eike Hein",
+ "Name[pt_BR]": "Eike Hein",
+ "Name[ro]": "Eike Hein",
+ "Name[ru]": "Eike Hein",
+ "Name[sa]": "ऐके हेन",
+ "Name[sk]": "Eike Hein",
+ "Name[sl]": "Eike Hein",
+ "Name[sv]": "Eike Hein",
+ "Name[ta]": "எய்கே ஹைன்",
+ "Name[tr]": "Eike Hein",
+ "Name[uk]": "Eike Hein",
+ "Name[vi]": "Eike Hein",
+ "Name[zh_CN]": "Eike Hein",
+ "Name[zh_TW]": "Eike Hein"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=Desktop%20Containment",
+ "Category": "Containments",
+ "Description": "A clean and simple layout",
+ "Description[ar]": "تخطيط نظيف وبسيط",
+ "Description[az]": "Təmiz və Sadə şablon",
+ "Description[be]": "Просты макет",
+ "Description[bg]": "Едно изчистено и просто оформление",
+ "Description[ca@valencia]": "Una disposició neta i senzilla",
+ "Description[ca]": "Una disposició neta i senzilla",
+ "Description[cs]": "Čisté a jednoduché rozvržení",
+ "Description[da]": "Et rent og simpelt layout",
+ "Description[de]": "Ein klares und einfaches Layout",
+ "Description[el]": "Μια καθαρή και απλή διάταξη",
+ "Description[en_GB]": "A clean and simple layout",
+ "Description[eo]": "Pura kaj simpla aranĝo",
+ "Description[es]": "Un esquema sencillo y claro",
+ "Description[et]": "Puhas ja lihtne paigutus",
+ "Description[eu]": "Antolaera garbi eta xumea",
+ "Description[fi]": "Selkeä ja yksinkertainen asettelu",
+ "Description[fr]": "Une disposition simple et épurée",
+ "Description[ga]": "Leagan amach glan agus simplí",
+ "Description[gl]": "Unha disposición sinxela e limpa.",
+ "Description[he]": "פריסה פשוטה ונקיה",
+ "Description[hu]": "Egy tiszta és egyszerű elrendezés",
+ "Description[ia]": "Un disposition simple e munde",
+ "Description[id]": "Sebuah tata letak yang bersih dan sederhana",
+ "Description[ie]": "Un simplic e nett arangement",
+ "Description[is]": "Skýr og einföld framsetning",
+ "Description[it]": "Una disposizione semplice e pulita",
+ "Description[ja]": "クリーンでシンプルなレイアウト",
+ "Description[ka]": "სუფთა და მარტივი განლაგება",
+ "Description[ko]": "깨끗하고 정돈된 레이아웃",
+ "Description[lt]": "Tvarkingas ir paprastas išdėstymas",
+ "Description[lv]": "Skaidrs un vienkāršs izkārtojums",
+ "Description[nb]": "En ren og enkel utforming",
+ "Description[nl]": "Een schone en simpele opmaak",
+ "Description[nn]": "Ei enkel og stilrein utforming",
+ "Description[pa]": "ਸਾਫ਼ ਅਤੇ ਸਧਾਰਨ ਲੇਆਉਟ",
+ "Description[pl]": "Schludny i prosty układ",
+ "Description[pt]": "Uma disposição limpa e simples",
+ "Description[pt_BR]": "Um layout limpo e simples",
+ "Description[ro]": "Aranjament curat și simplu",
+ "Description[ru]": "Ясный и простой шаблон",
+ "Description[sa]": "स्वच्छं सरलं च विन्यासः",
+ "Description[sk]": "Čisté a jednoduché rozloženie",
+ "Description[sl]": "Čist in preprost razpored",
+ "Description[sv]": "En ren och enkel layout",
+ "Description[ta]": "தெளிவான மற்றும் எளிய தளவமைப்பு",
+ "Description[tr]": "Temiz ve basit bir yerleşim",
+ "Description[uk]": "Просте компонування",
+ "Description[vi]": "Một bố cục thoáng đãng và đơn giản",
+ "Description[zh_CN]": "一款简洁的布局",
+ "Description[zh_TW]": "乾淨、簡單的佈局",
+ "EnabledByDefault": true,
+ "Icon": "user-desktop",
+ "Id": "org.kde.desktopcontainment",
+ "License": "GPL-2.0+",
+ "Name": "Desktop",
+ "Name[af]": "Werkskerm",
+ "Name[ar]": "سطح المكتب",
+ "Name[ast]": "Escritoriu",
+ "Name[az]": "İş masası",
+ "Name[be@latin]": "Rabočy stoł",
+ "Name[be]": "Працоўны стол",
+ "Name[bg]": "Работен плот",
+ "Name[bn]": "ডেস্কটপ",
+ "Name[bn_IN]": "ডেস্কটপ",
+ "Name[br]": "Gorretaol",
+ "Name[bs]": "Radna površina",
+ "Name[ca@valencia]": "Escriptori",
+ "Name[ca]": "Escriptori",
+ "Name[cs]": "Pracovní plocha",
+ "Name[csb]": "Pùlt",
+ "Name[cy]": "Penbwrdd",
+ "Name[da]": "Skrivebord",
+ "Name[de]": "Arbeitsfläche",
+ "Name[el]": "Επιφάνεια εργασίας",
+ "Name[en_GB]": "Desktop",
+ "Name[eo]": "Labortablo",
+ "Name[es]": "Escritorio",
+ "Name[et]": "Töölaud",
+ "Name[eu]": "Mahaigaina",
+ "Name[fa]": "رومیزی",
+ "Name[fi]": "Työpöytä",
+ "Name[fr]": "Bureau",
+ "Name[fy]": "Buroblêd",
+ "Name[ga]": "Deasc",
+ "Name[gl]": "Escritorio",
+ "Name[gu]": "ડેસ્કટોપ",
+ "Name[he]": "שולחן עבודה",
+ "Name[hi]": "डेस्कटॉप",
+ "Name[hne]": "डेस्कटाप",
+ "Name[hr]": "Radna površina",
+ "Name[hsb]": "Dźěłowy powjerch",
+ "Name[hu]": "Munkaasztal",
+ "Name[ia]": "Scriptorio",
+ "Name[id]": "Desktop",
+ "Name[ie]": "Pupitre",
+ "Name[is]": "Skjáborð",
+ "Name[it]": "Desktop",
+ "Name[ja]": "デスクトップ",
+ "Name[ka]": "სამუშაო მაგიდა",
+ "Name[kk]": "Жұмыс үстелі",
+ "Name[kn]": "ಗಣಕತೆರೆ",
+ "Name[ko]": "바탕 화면",
+ "Name[ku]": "Sermasê",
+ "Name[lt]": "Darbalaukis",
+ "Name[lv]": "Darbvirsma",
+ "Name[mai]": "डेस्कटाप",
+ "Name[mk]": "Работна површина",
+ "Name[ml]": "പണിയിടം",
+ "Name[mr]": "डेस्कटॉप",
+ "Name[ms]": "Ruang Kerja",
+ "Name[nb]": "Skrivebord",
+ "Name[nds]": "Schriefdisch",
+ "Name[ne]": "डेस्कटप",
+ "Name[nl]": "Bureaublad",
+ "Name[nn]": "Skrivebord",
+ "Name[oc]": "Burèu",
+ "Name[or]": "ଡ଼େସ୍କଟପ",
+ "Name[pa]": "ਡੈਸਕਟਾਪ",
+ "Name[pl]": "Pulpit",
+ "Name[pt]": "Ambiente de Trabalho",
+ "Name[pt_BR]": "Área de trabalho",
+ "Name[ro]": "Birou",
+ "Name[ru]": "Рабочий стол",
+ "Name[sa]": "डेस्कटॉप",
+ "Name[se]": "Čállinbeavdi",
+ "Name[si]": "වැඩතලය",
+ "Name[sk]": "Plocha",
+ "Name[sl]": "Namizje",
+ "Name[sr@ijekavian]": "Површ",
+ "Name[sr@ijekavianlatin]": "Površ",
+ "Name[sr@latin]": "Površ",
+ "Name[sr]": "Површ",
+ "Name[sv]": "Skrivbord",
+ "Name[ta]": "பணிமேடை",
+ "Name[te]": "రంగస్ఠలం",
+ "Name[tg]": "Мизи корӣ",
+ "Name[th]": "พื้นที่ทำงาน",
+ "Name[tr]": "Masaüstü",
+ "Name[uk]": "Стільниця",
+ "Name[uz@cyrillic]": "Иш столи",
+ "Name[uz]": "Ish stoli",
+ "Name[vi]": "Bàn làm việc",
+ "Name[wa]": "Sicribanne",
+ "Name[xh]": "Desktop",
+ "Name[zh_CN]": "桌面",
+ "Name[zh_TW]": "桌面",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-ContainmentType": "Desktop"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Battery.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Battery.qml
new file mode 100644
index 0000000..e68ad60
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Battery.qml
@@ -0,0 +1,80 @@
+/**
+ * SPDX-FileCopyrightText: 2014 Samoilenko Yuri
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "battery"
+ device: root.device
+ }
+
+ readonly property bool charging: battery?.isCharging ?? false
+ readonly property int charge: battery?.charge ?? -1
+
+ readonly property string displayString: {
+ if (available && charge > -1) {
+ if (charging) {
+ return i18n("%1% charging", charge);
+ } else {
+ return i18n("%1%", charge);
+ }
+ } else {
+ return i18n("No info");
+ }
+ }
+
+ property KDEConnect.BatteryDbusInterface battery
+
+ /**
+ * Suggests an icon name to use for the current battery level
+ */
+ readonly property string iconName: {
+ if (charge < 0) {
+ return "battery-missing-symbolic";
+ } else if (charge < 10) {
+ return charging
+ ? "battery-empty-charging-symbolic"
+ : "battery-empty-symbolic";
+ } else if (charge < 25) {
+ return charging
+ ? "battery-caution-charging-symbolic"
+ : "battery-caution-symbolic";
+ } else if (charge < 50) {
+ return charging
+ ? "battery-low-charging-symbolic"
+ : "battery-low-symbolic";
+ } else if (charge < 75) {
+ return charging
+ ? "battery-good-charging-symbolic"
+ : "battery-good-symbolic";
+ } else {
+ return charging
+ ? "battery-full-charging-symbolic"
+ : "battery-full-symbolic";
+ }
+ }
+
+ onAvailableChanged: {
+ if (available) {
+ battery = KDEConnect.DeviceBatteryDbusInterfaceFactory.create(device.id());
+ } else {
+ battery = null;
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Clipboard.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Clipboard.qml
new file mode 100644
index 0000000..d7b1b0e
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Clipboard.qml
@@ -0,0 +1,42 @@
+/**
+ * SPDX-FileCopyrightText: 2021 Yaman Qalieh
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "clipboard"
+ device: root.device
+ }
+
+ property KDEConnect.ClipboardDbusInterface clipboard
+
+ function sendClipboard(): void {
+ if (clipboard) {
+ clipboard.sendClipboard();
+ }
+ }
+
+ onAvailableChanged: {
+ if (available) {
+ clipboard = KDEConnect.ClipboardDbusInterfaceFactory.create(device.id());
+ } else {
+ clipboard = null;
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/CompactRepresentation.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/CompactRepresentation.qml
new file mode 100644
index 0000000..4d9b497
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/CompactRepresentation.qml
@@ -0,0 +1,44 @@
+/**
+ * SPDX-FileCopyrightText: 2014-2015 Frederic St-Pierre
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.plasmoid
+
+DropArea {
+ id: root
+
+ required property PlasmoidItem plasmoidItem
+
+ onEntered: drag => {
+ if (drag.hasUrls) {
+ root.plasmoidItem.expanded = true;
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+
+ property bool wasExpanded: false
+
+ onPressed: mouse => {
+ wasExpanded = root.plasmoidItem.expanded;
+ }
+
+ onClicked: mouse => {
+ root.plasmoidItem.expanded = !root.plasmoidItem.expanded;
+ }
+ }
+
+ Kirigami.Icon {
+ anchors.fill: parent
+ source: Plasmoid.icon
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Connectivity.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Connectivity.qml
new file mode 100644
index 0000000..dfa58fd
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Connectivity.qml
@@ -0,0 +1,129 @@
+/**
+ * SPDX-FileCopyrightText: 2021 David Shlemayev
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "connectivity_report"
+ device: root.device
+ }
+
+ /**
+ * Reports a string indicating the network type. Possible values:
+ * 5G
+ * LTE
+ * HSPA
+ * UMTS
+ * CDMA2000
+ * EDGE
+ * GPRS
+ * GSM
+ * CDMA
+ * iDEN
+ *
+ * The parsing from Android values into these strings is handled in the
+ * [ConnectivityReportPlugin.networkTypeToString method](https://invent.kde.org/network/kdeconnect-android/-/blob/master/src/org/kde/kdeconnect/Plugins/ConnectivityReportPlugin/ConnectivityReportPlugin.java#L82)
+ */
+ readonly property string networkType: connectivity?.cellularNetworkType ?? i18n("Unknown")
+
+ /**
+ * Reports a value between 0 and 4 (inclusive) which represents the strength of the cellular connection
+ */
+ readonly property int signalStrength: connectivity?.cellularNetworkStrength ?? -1
+
+ readonly property string displayString: {
+ if (connectivity !== null) {
+ return `${networkType} ${signalStrength}/4`;
+ } else {
+ return i18n("No signal");
+ }
+ }
+
+ property KDEConnect.ConnectivityReportDbusInterface connectivity
+
+ /**
+ * Suggests an icon name to use for the current signal level
+ *
+ * Returns names which correspond to Plasma Framework's network.svg:
+ * https://invent.kde.org/frameworks/plasma-framework/-/blob/master/src/desktoptheme/breeze/icons/network.svg
+ */
+ readonly property string iconName: {
+ // Firstly, get the name prefix which represents the signal strength
+ const signalStrengthIconName =
+ (signalStrength < 0 || connectivity === null) ?
+ // As long as the signal strength is nonsense or the plugin reports as non-ready,
+ // show us as disconnected
+ "network-mobile-off" :
+ (signalStrength === 0) ?
+ "network-mobile-0" :
+ (signalStrength === 1) ?
+ "network-mobile-20" :
+ (signalStrength === 2) ?
+ "network-mobile-60" :
+ (signalStrength === 3) ?
+ "network-mobile-80" :
+ (signalStrength === 4) ?
+ "network-mobile-100" :
+ // Since all possible values are enumerated above, this default case should never be hit.
+ // However, I need it in order for my ternary syntax to be valid!
+ "network-mobile-available";
+
+ // If we understand the network type, append to the icon name to show the type
+ const networkTypeSuffix =
+ (networkType === "5G") ?
+ "-5g" :
+ (networkType === "LTE") ?
+ "-lte" :
+ (networkType === "HSPA") ?
+ "-hspa" :
+ (networkType === "UMTS") ?
+ "-umts" :
+ (networkType === "CDMA2000") ?
+ // GSconnect just uses the 3g icon
+ // No icon for this case!
+ "" :
+ (networkType === "EDGE") ?
+ "-edge" :
+ (networkType === "GPRS") ?
+ "-gprs" :
+ (networkType === "GSM") ?
+ // GSconnect just uses the 2g icon
+ // No icon for this case!
+ "" :
+ (networkType === "CDMA") ?
+ // GSconnect just uses the 2g icon
+ // No icon for this case!
+ "" :
+ (networkType === "iDEN") ?
+ // GSconnect just uses the 2g icon
+ // No icon for this case!
+ "" :
+ ""; // We didn't recognize the network type. Don't append anything.
+
+ return signalStrengthIconName + networkTypeSuffix;
+ }
+
+ onAvailableChanged: {
+ if (available) {
+ connectivity = KDEConnect.DeviceConnectivityReportDbusInterfaceFactory.create(device.id());
+ } else {
+ connectivity = null;
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/DeviceDelegate.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/DeviceDelegate.qml
new file mode 100644
index 0000000..4abdbb5
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/DeviceDelegate.qml
@@ -0,0 +1,490 @@
+/**
+ * SPDX-FileCopyrightText: 2013 Albert Vaca
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtCore
+import QtQuick
+import QtQuick.Dialogs as QtDialogs
+import QtQuick.Layouts
+
+import org.kde.kdeconnect as KDEConnect
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.components as PlasmaComponents
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.extras as PlasmaExtras
+
+PlasmaComponents.ItemDelegate {
+ id: root
+
+ required property int index
+ required property var model
+
+ readonly property KDEConnect.DeviceDbusInterface device: KDEConnect.DeviceDbusInterfaceFactory.create(model.deviceId)
+
+ hoverEnabled: false
+ down: false
+
+ Battery {
+ id: battery
+ device: root.device
+ }
+
+ Clipboard {
+ id: clipboard
+ device: root.device
+ }
+
+ Connectivity {
+ id: connectivity
+ device: root.device
+ }
+
+ FindMyPhone {
+ id: findmyphone
+ device: root.device
+ }
+
+ RemoteCommands {
+ id: remoteCommands
+ device: root.device
+ }
+
+ Sftp {
+ id: sftp
+ device: root.device
+ }
+
+ Share {
+ id: share
+ device: root.device
+ }
+
+ SMS {
+ id: sms
+ device: root.device
+ }
+
+ VirtualMonitor {
+ id: virtualmonitor
+ device: root.device
+ }
+
+ Kirigami.PromptDialog {
+ id: prompt
+ visible: false
+ showCloseButton: true
+ standardButtons: Kirigami.Dialog.NoButton
+ title: i18n("Virtual Monitor is not available")
+ }
+
+ QtDialogs.FileDialog {
+ id: fileDialog
+ title: i18n("Please choose a file")
+ currentFolder: StandardPaths.writableLocation(StandardPaths.HomeLocation)
+ modality: Qt.NonModal
+ fileMode: QtDialogs.FileDialog.OpenFiles
+ onAccepted: {
+ selectedFiles.forEach(url => share.plugin.shareUrl(url));
+ }
+ }
+
+ PlasmaExtras.Menu {
+ id: menu
+
+ visualParent: overflowMenu
+ placement: PlasmaExtras.Menu.BottomPosedLeftAlignedPopup
+
+ // Share
+ PlasmaExtras.MenuItem {
+ icon: "document-share"
+ visible: share.available
+ text: i18n("Share file")
+ onClicked: fileDialog.open()
+ }
+
+ // Clipboard
+ PlasmaExtras.MenuItem {
+ icon: "klipper"
+ visible: clipboard.clipboard?.isAutoShareDisabled ?? false
+ text: i18n("Send Clipboard")
+
+ onClicked: {
+ clipboard.sendClipboard()
+ }
+ }
+
+ // Find my phone
+ PlasmaExtras.MenuItem {
+ icon: "irc-voice"
+ visible: findmyphone.available
+ text: i18n("Ring my phone")
+
+ onClicked: {
+ findmyphone.ring()
+ }
+ }
+
+ // SFTP
+ PlasmaExtras.MenuItem {
+ icon: "document-open-folder"
+ visible: sftp.available
+ text: i18n("Browse this device")
+
+ onClicked: {
+ sftp.browse()
+ }
+ }
+
+ // SMS
+ PlasmaExtras.MenuItem {
+ icon: "message-new"
+ visible: sms.available
+ text: i18n("SMS Messages")
+
+ onClicked: {
+ sms.plugin.launchApp()
+ }
+ }
+ }
+
+ DropArea {
+ id: fileDropArea
+ anchors.fill: parent
+
+ onDropped: drop => {
+ if (drop.hasUrls) {
+ const urls = new Set(drop.urls.map(url => url.toString()));
+ urls.forEach(url => share.plugin.shareUrl(url));
+ }
+ drop.accepted = true;
+ }
+
+ PlasmaCore.ToolTipArea {
+ id: dropAreaToolTip
+ anchors.fill: parent
+ active: true
+ mainText: i18n("File Transfer")
+ subText: i18n("Drop a file to transfer it onto your phone.")
+ }
+ }
+
+ contentItem: ColumnLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ RowLayout {
+ width: parent.width
+ spacing: Kirigami.Units.smallSpacing
+
+ PlasmaComponents.Label {
+ id: deviceName
+ elide: Text.ElideRight
+ text: root.model.name
+ Layout.fillWidth: true
+ textFormat: Text.PlainText
+ }
+
+ PlasmaComponents.ToolButton {
+ icon.name: "krdc"
+ visible: virtualmonitor.available
+ text: i18n("Virtual Display")
+ checked: visible && virtualmonitor.plugin.active
+ checkable: true
+
+ onClicked: {
+ if (virtualmonitor.plugin.active) {
+ virtualmonitor.plugin.stop();
+ prompt.visible = false;
+ } else {
+ virtualmonitor.plugin.requestVirtualMonitor();
+ prompt.subtitle = virtualmonitor.plugin.lastError;
+ prompt.visible = prompt.subtitle.length > 0;
+ }
+ }
+ }
+
+ RowLayout {
+ id: connectionInformation
+
+ visible: connectivity.available
+ spacing: Kirigami.Units.smallSpacing
+
+ // TODO: In the future, when the Connectivity Report plugin supports more than one
+ // subscription, add more signal strength icons to represent all the available
+ // connections.
+
+ Kirigami.Icon {
+ id: celluarConnectionStrengthIcon
+ source: connectivity.iconName
+ Layout.preferredHeight: connectivityText.height
+ Layout.preferredWidth: Layout.preferredHeight
+ Layout.alignment: Qt.AlignCenter
+ visible: valid
+ }
+
+ PlasmaComponents.Label {
+ // Fallback plain-text label. Only show this if the icon doesn't work.
+ id: connectivityText
+ text: connectivity.displayString
+ textFormat: Text.PlainText
+ visible: !celluarConnectionStrengthIcon.visible
+ }
+ }
+
+ RowLayout {
+ id: batteryInformation
+
+ visible: battery.available && battery.charge > -1
+ spacing: Kirigami.Units.smallSpacing
+
+ Kirigami.Icon {
+ id: batteryIcon
+ source: battery.iconName
+ // Make the icon the same size as the text so that it doesn't dominate
+ Layout.preferredHeight: batteryPercent.height
+ Layout.preferredWidth: Layout.preferredHeight
+ Layout.alignment: Qt.AlignCenter
+ }
+
+ PlasmaComponents.Label {
+ id: batteryPercent
+ text: i18nc("Battery charge percentage", "%1%", battery.charge)
+ textFormat: Text.PlainText
+ }
+ }
+
+ PlasmaComponents.ToolButton {
+ id: overflowMenu
+
+ icon.name: "application-menu"
+ checked: menu.status === PlasmaExtras.Menu.Open
+
+ onPressed: menu.openRelative()
+ }
+ }
+
+ // RemoteKeyboard
+ PlasmaComponents.ItemDelegate {
+ visible: remoteKeyboard.remoteState
+ Layout.fillWidth: true
+
+ contentItem: RowLayout {
+ width: parent.width
+ spacing: 5
+
+ PlasmaComponents.Label {
+ id: remoteKeyboardLabel
+ text: i18n("Remote Keyboard")
+ }
+
+ KDEConnect.RemoteKeyboard {
+ id: remoteKeyboard
+ device: root.device
+ Layout.fillWidth: true
+ }
+ }
+ }
+
+ // Notifications
+ PlasmaComponents.ItemDelegate {
+ visible: notificationsModel.count > 0
+ enabled: true
+ Layout.fillWidth: true
+
+ contentItem: RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ PlasmaComponents.Label {
+ text: i18n("Notifications:")
+ }
+
+ PlasmaComponents.ToolButton {
+ enabled: true
+ visible: notificationsModel.isAnyDimissable;
+ Layout.alignment: Qt.AlignRight
+ icon.name: "edit-clear-history"
+ PlasmaComponents.ToolTip.text: i18n("Dismiss all notifications")
+ onClicked: notificationsModel.dismissAll();
+ }
+ }
+ }
+
+ Repeater {
+ id: notificationsView
+
+ model: KDEConnect.NotificationsModel {
+ id: notificationsModel
+ deviceId: root.model.deviceId
+ }
+
+ delegate: PlasmaComponents.ItemDelegate {
+ id: listitem
+
+ required property int index
+ required property var model
+
+ enabled: true
+ onClicked: checked = !checked
+ Layout.fillWidth: true
+
+ property bool replying: false
+
+ contentItem: ColumnLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ Kirigami.Icon {
+ id: notificationIcon
+ source: listitem.model.appIcon
+ width: (valid && listitem.model.appIcon !== "") ? dismissButton.width : 0
+ height: width
+ Layout.alignment: Qt.AlignLeft
+ }
+
+ PlasmaComponents.Label {
+ id: notificationLabel
+ text: {
+ const { appName, notitext, title } = listitem.model;
+ const description = title !== "" ? (appName === title ? notitext : `${title}: ${notitext}`) : notitext;
+ return `${appName}: ${description}`;
+ }
+ elide: listitem.checked ? Text.ElideNone : Text.ElideRight
+ maximumLineCount: listitem.checked ? 0 : 1
+ wrapMode: Text.Wrap
+ Layout.fillWidth: true
+ }
+
+ PlasmaComponents.ToolButton {
+ id: replyButton
+ visible: listitem.model.repliable
+ enabled: listitem.model.repliable && !listitem.replying
+ icon.name: "mail-reply-sender"
+ PlasmaComponents.ToolTip.text: i18n("Reply")
+ onClicked: {
+ listitem.replying = true;
+ replyTextField.forceActiveFocus();
+ }
+ }
+
+ PlasmaComponents.ToolButton {
+ id: dismissButton
+ visible: notificationsModel.isAnyDimissable;
+ enabled: listitem.model.dismissable
+ Layout.alignment: Qt.AlignRight
+ icon.name: "window-close"
+ PlasmaComponents.ToolTip.text: i18n("Dismiss")
+ onClicked: listitem.model.dbusInterface.dismiss();
+ }
+ }
+
+ RowLayout {
+ visible: listitem.replying
+ width: notificationLabel.width + replyButton.width + dismissButton.width + Kirigami.Units.smallSpacing * 2
+ spacing: Kirigami.Units.smallSpacing
+
+ PlasmaComponents.Button {
+ id: replyCancelButton
+ Layout.alignment: Qt.AlignBottom
+ text: i18n("Cancel")
+ display: PlasmaComponents.AbstractButton.IconOnly
+ PlasmaComponents.ToolTip {
+ text: replyCancelButton.text
+ }
+ icon.name: "dialog-cancel"
+ onClicked: {
+ replyTextField.text = "";
+ listitem.replying = false;
+ }
+ }
+
+ PlasmaComponents.TextArea {
+ id: replyTextField
+ placeholderText: i18nc("@info:placeholder", "Reply to %1…", listitem.model.appName)
+ wrapMode: TextEdit.Wrap
+ Layout.fillWidth: true
+ Keys.onPressed: event => {
+ if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && !(event.modifiers & Qt.ShiftModifier)) {
+ replySendButton.clicked();
+ event.accepted = true;
+ }
+ if (event.key === Qt.Key_Escape) {
+ replyCancelButton.clicked();
+ event.accepted = true;
+ }
+ }
+ }
+
+ PlasmaComponents.Button {
+ Layout.alignment: Qt.AlignBottom
+ id: replySendButton
+ text: i18n("Send")
+ icon.name: "document-send"
+ enabled: replyTextField.text !== ""
+ onClicked: {
+ listitem.model.dbusInterface.sendReply(replyTextField.text);
+ replyTextField.text = "";
+ listitem.replying = false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Commands
+ RowLayout {
+ visible: remoteCommands.available
+ width: parent.width
+ spacing: Kirigami.Units.smallSpacing
+
+ PlasmaComponents.Label {
+ text: i18n("Run command")
+ Layout.fillWidth: true
+ }
+
+ PlasmaComponents.Button {
+ id: addCommandButton
+ icon.name: "list-add"
+ PlasmaComponents.ToolTip.text: i18n("Add command")
+ onClicked: remoteCommands.plugin.editCommands()
+ visible: remoteCommands.plugin?.canAddCommand ?? false
+ }
+ }
+
+ Repeater {
+ id: commandsView
+
+ visible: remoteCommands.available
+
+ model: KDEConnect.RemoteCommandsModel {
+ id: commandsModel
+ deviceId: root.model.deviceId
+ }
+
+ delegate: PlasmaComponents.ItemDelegate {
+ id: commandDelegate
+
+ required property int index
+ required property var model
+
+ enabled: true
+
+ onClicked: {
+ remoteCommands.plugin?.triggerCommand(commandDelegate.model.key);
+ }
+
+ Layout.fillWidth: true
+
+ contentItem: PlasmaComponents.Label {
+ text: `${commandDelegate.model.name}\n${commandDelegate.model.command}`
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/FindMyPhone.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/FindMyPhone.qml
new file mode 100644
index 0000000..aaa11f4
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/FindMyPhone.qml
@@ -0,0 +1,42 @@
+/**
+ * SPDX-FileCopyrightText: 2014 Samoilenko Yuri
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "findmyphone"
+ device: root.device
+ }
+
+ property KDEConnect.FindMyPhoneDbusInterface findMyPhone
+
+ function ring(): void {
+ if (findMyPhone) {
+ findMyPhone.ring();
+ }
+ }
+
+ onAvailableChanged: {
+ if (available) {
+ findMyPhone = KDEConnect.FindMyPhoneDbusInterfaceFactory.create(device.id());
+ } else {
+ findMyPhone = null;
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/FullRepresentation.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/FullRepresentation.qml
new file mode 100644
index 0000000..d108332
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/FullRepresentation.qml
@@ -0,0 +1,98 @@
+/**
+ * SPDX-FileCopyrightText: 2013 Albert Vaca
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+
+import org.kde.config as KConfig
+import org.kde.kdeconnect as KDEConnect
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.components as PlasmaComponents3
+import org.kde.plasma.extras as PlasmaExtras
+
+PlasmaExtras.Representation {
+ id: kdeconnect
+
+ property alias devicesModel: devicesView.model
+
+ collapseMarginsHint: true
+
+ KDEConnect.DevicesModel {
+ id: allDevicesModel
+ }
+
+ KDEConnect.DevicesModel {
+ id: pairedDevicesModel
+ displayFilter: KDEConnect.DevicesModel.Paired
+ }
+
+ PlasmaComponents3.ScrollView {
+ anchors.fill: parent
+
+ contentItem: ListView {
+ id: devicesView
+
+ spacing: Kirigami.Units.smallSpacing
+
+ clip: true
+
+ delegate: DeviceDelegate {
+ width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin
+ }
+
+ PlasmaExtras.PlaceholderMessage {
+ width: parent.width - Kirigami.Units.gridUnit * 2
+ anchors.centerIn: parent
+ visible: devicesView.count === 0
+
+ iconName: {
+ if (pairedDevicesModel.count >= 0) {
+ return pairedDevicesModel.count === 0 ? "edit-none" : "network-disconnect";
+ }
+ return "kdeconnect";
+ }
+
+ text: {
+ if (pairedDevicesModel.count >= 0) {
+ return pairedDevicesModel.count === 0 ? i18n("No paired devices") : i18np("Paired device is unavailable", "All paired devices are unavailable", pairedDevicesModel.count)
+ } else if (allDevicesModel.count === 0) {
+ return i18n("Install KDE Connect on your Android device to integrate it with Plasma!")
+ }
+ }
+ helpfulAction: QQC2.Action {
+ text: i18n("Pair a Device…")
+ icon.name: "list-add"
+ onTriggered: KDEConnect.OpenConfig.openConfiguration()
+ enabled: pairedDevicesModel.count === 0
+ }
+
+ PlasmaComponents3.Button {
+ Layout.leftMargin: Kirigami.Units.gridUnit * 3
+ Layout.rightMargin: Kirigami.Units.gridUnit * 3
+ Layout.alignment: Qt.AlignHCenter
+ Layout.fillWidth: true
+ visible: allDevicesModel.count === 0
+ text: i18n("Install from Google Play")
+ onClicked: Qt.openUrlExternally("https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp")
+ }
+
+ PlasmaComponents3.Button {
+ Layout.leftMargin: Kirigami.Units.gridUnit * 3
+ Layout.rightMargin: Kirigami.Units.gridUnit * 3
+ Layout.alignment: Qt.AlignHCenter
+ Layout.fillWidth: true
+ visible: allDevicesModel.count === 0
+ text: i18n("Install from F-Droid")
+ onClicked: Qt.openUrlExternally("https://f-droid.org/en/packages/org.kde.kdeconnect_tp/")
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/RemoteCommands.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/RemoteCommands.qml
new file mode 100644
index 0000000..4eec583
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/RemoteCommands.qml
@@ -0,0 +1,29 @@
+/**
+ * SPDX-FileCopyrightText: 2018 Nicolas Fella
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "remotecommands"
+ device: root.device
+ }
+
+ property KDEConnect.RemoteCommandsDbusInterface plugin:
+ available ? KDEConnect.RemoteCommandsDbusInterfaceFactory.create(device.id()) : null
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/SMS.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/SMS.qml
new file mode 100644
index 0000000..39b951f
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/SMS.qml
@@ -0,0 +1,29 @@
+/**
+ * SPDX-FileCopyrightText: 2019 Aleix Pol Gonzalez
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "sms"
+ device: root.device
+ }
+
+ readonly property KDEConnect.SmsDbusInterface plugin:
+ available ? KDEConnect.SmsDbusInterfaceFactory.create(device.id()) : null
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Sftp.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Sftp.qml
new file mode 100644
index 0000000..a032969
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Sftp.qml
@@ -0,0 +1,42 @@
+/**
+ * SPDX-FileCopyrightText: 2014 Samoilenko Yuri
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "sftp"
+ device: root.device
+ }
+
+ property KDEConnect.SftpDbusInterface sftp
+
+ function browse(): void {
+ if (sftp) {
+ sftp.startBrowsing();
+ }
+ }
+
+ onAvailableChanged: {
+ if (available) {
+ sftp = KDEConnect.SftpDbusInterfaceFactory.create(device.id());
+ } else {
+ sftp = null;
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Share.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Share.qml
new file mode 100644
index 0000000..a55450f
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/Share.qml
@@ -0,0 +1,29 @@
+/**
+ * SPDX-FileCopyrightText: 2018 Nicolas Fella
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "share"
+ device: root.device
+ }
+
+ property KDEConnect.ShareDbusInterface plugin:
+ available ? KDEConnect.ShareDbusInterfaceFactory.create(device.id()) : null
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/VirtualMonitor.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/VirtualMonitor.qml
new file mode 100644
index 0000000..b7b6936
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/VirtualMonitor.qml
@@ -0,0 +1,29 @@
+/**
+ * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.kdeconnect as KDEConnect
+
+QtObject {
+ id: root
+
+ required property KDEConnect.DeviceDbusInterface device
+
+ readonly property alias available: checker.available
+
+ readonly property KDEConnect.PluginChecker pluginChecker: KDEConnect.PluginChecker {
+ id: checker
+ pluginName: "virtualmonitor"
+ device: root.device
+ }
+
+ readonly property KDEConnect.VirtualmonitorDbusInterface plugin:
+ available ? KDEConnect.VirtualmonitorDbusInterfaceFactory.create(device.id()) : null
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/main.qml b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/main.qml
new file mode 100644
index 0000000..a1e930c
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/contents/ui/main.qml
@@ -0,0 +1,62 @@
+/**
+ * SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez
+ * SPDX-FileCopyrightText: 2024 ivan tkachenko
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import org.kde.config as KConfig
+import org.kde.kdeconnect as KDEConnect
+import org.kde.kquickcontrolsaddons as KQuickControlsAddons
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.plasmoid
+
+PlasmoidItem {
+ id: root
+
+ readonly property bool inPanel: [
+ PlasmaCore.Types.TopEdge,
+ PlasmaCore.Types.RightEdge,
+ PlasmaCore.Types.BottomEdge,
+ PlasmaCore.Types.LeftEdge,
+ ].includes(Plasmoid.location)
+
+ KDEConnect.DevicesModel {
+ id: connectedDeviceModel
+ displayFilter: KDEConnect.DevicesModel.Paired | KDEConnect.DevicesModel.Reachable
+ }
+
+ KDEConnect.DevicesModel {
+ id: pairedDeviceModel
+ displayFilter: KDEConnect.DevicesModel.Paired
+ }
+
+ Plasmoid.icon: inPanel
+ ? "kdeconnect-tray-symbolic"
+ : "kdeconnect-tray"
+
+ Plasmoid.status: connectedDeviceModel.count > 0 ? PlasmaCore.Types.ActiveStatus : PlasmaCore.Types.PassiveStatus
+
+ fullRepresentation: FullRepresentation {
+ devicesModel: connectedDeviceModel
+ }
+
+ compactRepresentation: CompactRepresentation {
+ plasmoidItem: root
+ }
+
+ PlasmaCore.Action {
+ id: configureAction
+ text: i18n("KDE Connect Settings…")
+ icon.name: "configure"
+ onTriggered: KDEConnect.OpenConfig.openConfiguration()
+ }
+
+ Component.onCompleted: {
+ Plasmoid.setInternalAction("configure", configureAction);
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/metadata.json
new file mode 100644
index 0000000..3e472c4
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.kdeconnect/metadata.json
@@ -0,0 +1,150 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "albertvaka@gmail.com",
+ "Name": "Albert Vaca Cintora",
+ "Name[ar]": "ألبرت فاكا سينتورا",
+ "Name[az]": "Albert Vaca Cintora",
+ "Name[bg]": "Albert Vaca Cintora",
+ "Name[ca@valencia]": "Albert Vaca Cintora",
+ "Name[ca]": "Albert Vaca Cintora",
+ "Name[cs]": "Albert Vaca Cintora",
+ "Name[da]": "Albert Vaca Cintora",
+ "Name[de]": "Albert Vaca Cintora",
+ "Name[en_GB]": "Albert Vaca Cintora",
+ "Name[eo]": "Albert Vaca Cintora",
+ "Name[es]": "Albert Vaca Cintora",
+ "Name[eu]": "Albert Vaca Cintora",
+ "Name[fi]": "Albert Vaca Cintora",
+ "Name[fr]": "Albert Vaca Cintora",
+ "Name[ga]": "Albert Vaca Cintora",
+ "Name[gl]": "Albert Vaca Cintora",
+ "Name[he]": "אלברט ואקה סינטורה",
+ "Name[hi]": "अल्बर्ट वाका सिंटोरा",
+ "Name[hu]": "Albert Vaca Cintora",
+ "Name[ia]": "Albert Vaca Cintora",
+ "Name[is]": "Albert Vaca Cintora",
+ "Name[it]": "Albert Vaca Cintora",
+ "Name[ja]": "Albert Vaca Cintora",
+ "Name[ka]": "Albert Vaca Cintora",
+ "Name[ko]": "Albert Vaca Cintora",
+ "Name[lt]": "Albert Vaca Cintora",
+ "Name[lv]": "Albert Vaca Cintora",
+ "Name[nl]": "Albert Vaca Cintora",
+ "Name[nn]": "Albert Vaca Cintora",
+ "Name[pl]": "Albert Vaca Cintora",
+ "Name[pt]": "Albert Vaca Cintora",
+ "Name[pt_BR]": "Albert Vaca Cintora",
+ "Name[ro]": "Albert Vaca Cintora",
+ "Name[ru]": "Albert Vaca Cintora",
+ "Name[sa]": "अल्बर्ट वाका सिन्टोरा",
+ "Name[sk]": "Albert Vaca Cintora",
+ "Name[sl]": "Albert Vaca Cintora",
+ "Name[sv]": "Albert Vaca Cintora",
+ "Name[tr]": "Albert Vaca Cintora",
+ "Name[uk]": "Albert Vaca Cintora",
+ "Name[zh_CN]": "Albert Vaca Cintora",
+ "Name[zh_TW]": "Albert Vaca Cintora"
+ }
+ ],
+ "Category": "System Information",
+ "Description": "Manage connected devices",
+ "Description[ar]": "تدير الأجهزة المتصلة",
+ "Description[bg]": "Управление на свързани устройства",
+ "Description[ca@valencia]": "Gestiona els dispositius connectats",
+ "Description[ca]": "Gestiona els dispositius connectats",
+ "Description[cs]": "Spravovat připojená zařízení",
+ "Description[da]": "Håndtér forbundede enheder",
+ "Description[de]": "Verbundene Geräte verwalten",
+ "Description[en_GB]": "Manage connected devices",
+ "Description[eo]": "Mastrumi konektitajn aparatojn",
+ "Description[es]": "Administrar dispositivos conectados",
+ "Description[eu]": "Konektatutako gailuak kudeatu",
+ "Description[fi]": "Hallitse kytkettyjä laitteita",
+ "Description[fr]": "Gérer les appareils connectés",
+ "Description[ga]": "Bainistigh gléasanna ceangailte",
+ "Description[gl]": "Xestionar os dispositivos conectados.",
+ "Description[he]": "ניהול התקנים מחוברים",
+ "Description[hu]": "Csatlakoztatott eszközök kezelése",
+ "Description[ia]": "Gere dispositivos connectite",
+ "Description[is]": "Stjórna tengdum tækjum",
+ "Description[it]": "Gestisci i dispositivi connessi",
+ "Description[ka]": "მიერთებული მოწყობილობების მართვა",
+ "Description[ko]": "연결된 장치 관리",
+ "Description[lt]": "Tvarkyti prijungtus įrenginius",
+ "Description[lv]": "Pārvaldīt savienotās ierīces",
+ "Description[nl]": "Verbonden apparaten beheren",
+ "Description[nn]": "Handsam tilkopla einingar",
+ "Description[pa]": "ਕਨੈਕਟ ਹੋਏ ਡਿਵਾਈਸਾਂ ਦਾ ਇੰਤਜ਼ਾਮ",
+ "Description[pl]": "Zarządzaj podłączonymi urządzeniami",
+ "Description[pt_BR]": "Gerenciar dispositivos conectados",
+ "Description[ro]": "Gestionează dispozitivele conectate",
+ "Description[ru]": "Управление подключёнными устройствами",
+ "Description[sa]": "संयोजितयन्त्राणां प्रबन्धनं कुर्वन्तु",
+ "Description[sl]": "Upravljaj povezane naprave",
+ "Description[sv]": "Hantera anslutna apparater",
+ "Description[ta]": "இணைந்துள்ள சாதனங்களை நிர்வகிக்க விடும்",
+ "Description[tr]": "Bağlı aygıtları yönetin",
+ "Description[uk]": "Керування з'єднаними пристроями",
+ "Description[zh_CN]": "管理已连接的设备",
+ "Description[zh_TW]": "管理已連線裝置",
+ "EnabledByDefault": true,
+ "Icon": "kdeconnect",
+ "Id": "org.kde.kdeconnect",
+ "License": "GPL",
+ "Name": "KDE Connect",
+ "Name[ar]": "جسر كِيدِي",
+ "Name[az]": "KDE Connect",
+ "Name[bg]": "KDE Connect",
+ "Name[ca@valencia]": "KDE Connect",
+ "Name[ca]": "KDE Connect",
+ "Name[cs]": "KDE Connect",
+ "Name[da]": "KDE Connect",
+ "Name[de]": "KDE Connect",
+ "Name[en_GB]": "KDE Connect",
+ "Name[eo]": "KDE Konekti",
+ "Name[es]": "KDE Connect",
+ "Name[eu]": "KDE Connect",
+ "Name[fi]": "KDE Connect",
+ "Name[fr]": "KDEConnect",
+ "Name[ga]": "KDE Connect",
+ "Name[gl]": "KDE Connect",
+ "Name[he]": "KDE Connect",
+ "Name[hi]": "केडीई कनेक्ट",
+ "Name[hu]": "KDE Connect",
+ "Name[ia]": "KDE Connect",
+ "Name[is]": "KDE Connect",
+ "Name[it]": "KDE Connect",
+ "Name[ja]": "KDE Connect",
+ "Name[ka]": "KDE Connect",
+ "Name[ko]": "KDE Connect",
+ "Name[lt]": "KDE Connect",
+ "Name[lv]": "KDE Connect",
+ "Name[nl]": "KDE Connect",
+ "Name[nn]": "KDE Connect",
+ "Name[pa]": "KDE ਕਨੈਕਟ",
+ "Name[pl]": "KDE Connect",
+ "Name[pt]": "KDE Connect",
+ "Name[pt_BR]": "KDE Connect",
+ "Name[ro]": "KDE Connect",
+ "Name[ru]": "KDE Connect",
+ "Name[sa]": "KDE Connect इति",
+ "Name[sk]": "KDE Connect",
+ "Name[sl]": "KDE Connect",
+ "Name[sv]": "KDE-anslut",
+ "Name[ta]": "கே.டீ.யீ. கனெக்ட்",
+ "Name[tr]": "KDE Bağlan",
+ "Name[uk]": "KDE Connect",
+ "Name[zh_CN]": "KDE Connect",
+ "Name[zh_TW]": "KDE Connect",
+ "Version": "0.1",
+ "Website": "https://albertvaka.wordpress.com"
+ },
+ "X-Plasma-API": "declarativeappletscript",
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-MainScript": "ui/main.qml",
+ "X-Plasma-NotificationArea": "true",
+ "X-Plasma-NotificationAreaCategory": "Hardware"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.activitypager/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.activitypager/metadata.json
new file mode 100644
index 0000000..5a64a50
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.activitypager/metadata.json
@@ -0,0 +1,177 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "plasma-devel@kde.org",
+ "Name": "The Plasma Team",
+ "Name[ar]": "فريق بلازما",
+ "Name[ast]": "L'equipu de Plasma",
+ "Name[az]": "Plasma komandası",
+ "Name[be]": "Каманда Plasma",
+ "Name[bg]": "Екипът на Plasma",
+ "Name[ca@valencia]": "L'equip de Plasma",
+ "Name[ca]": "L'equip del Plasma",
+ "Name[cs]": "Team Plasma",
+ "Name[da]": "Plasma-udviklingsholdet",
+ "Name[de]": "Das Plasma-Team",
+ "Name[el]": "Η ομάδα Plasma",
+ "Name[en_GB]": "The Plasma Team",
+ "Name[eo]": "La Teamo de Plasma",
+ "Name[es]": "El equipo de Plasma",
+ "Name[et]": "Plasma meeskond",
+ "Name[eu]": "Plasmaren taldea",
+ "Name[fi]": "Plasma-työryhmä",
+ "Name[fr]": "L'équipe de Plasma",
+ "Name[ga]": "An Fhoireann Plasma",
+ "Name[gl]": "O equipo de Plasma",
+ "Name[he]": "צוות פלזמה",
+ "Name[hu]": "A Plasma fejlesztői",
+ "Name[ia]": "Le equipa de Plasma",
+ "Name[id]": "Tim Plasma",
+ "Name[ie]": "Li equipe de Plasma",
+ "Name[is]": "Plasma-þróunarhópurinn",
+ "Name[it]": "La squadra di Plasma",
+ "Name[ja]": "Plasma チーム",
+ "Name[ka]": "Plasma-ის გუნდი",
+ "Name[ko]": "Plasma 팀",
+ "Name[lt]": "Plasma komanda",
+ "Name[lv]": "„Plasma“ komanda",
+ "Name[nb]": "Utviklingslaget for Plasma",
+ "Name[nl]": "Het team van Plasma",
+ "Name[nn]": "Utviklingslaget for Plasma",
+ "Name[pa]": "ਪਲਾਜ਼ਮਾ ਟੀਮ",
+ "Name[pl]": "Zespół Plazmy",
+ "Name[pt]": "A Equipa do Plasma",
+ "Name[pt_BR]": "A equipe do Plasma",
+ "Name[ro]": "Echipa Plasma",
+ "Name[ru]": "Команда разработчиков Plasma",
+ "Name[sa]": "प्लाज्मादलम्",
+ "Name[sk]": "Tím Plasma",
+ "Name[sl]": "Ekipa Plasme",
+ "Name[sv]": "Plasma-gruppen",
+ "Name[ta]": "பிளாஸ்மா குழு",
+ "Name[tr]": "Plasma Takımı",
+ "Name[uk]": "Команда розробників Плазми",
+ "Name[vi]": "Đội Plasma",
+ "Name[zh_CN]": "Plasma 开发团队",
+ "Name[zh_TW]": "Plasma 團隊"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=Pager%20widget",
+ "Category": "Windows and Tasks",
+ "Description": "Switch between activities",
+ "Description[ar]": "بدل بين الأنشطة",
+ "Description[az]": "Otaqlar arası keçid",
+ "Description[be]": "Пераключэнне паміж пакоямі",
+ "Description[bg]": "Превключване между дейностите",
+ "Description[ca@valencia]": "Canvia entre activitats",
+ "Description[ca]": "Commuta entre activitats",
+ "Description[cs]": "Přepnout mezi aktivitami",
+ "Description[da]": "Skift mellem aktiviteter",
+ "Description[de]": "Zwischen Aktivitäten umschalten",
+ "Description[el]": "Εναλλαγή μεταξύ δραστηριοτήτων",
+ "Description[en_GB]": "Switch between activities",
+ "Description[eo]": "Komuti inter aktivecoj",
+ "Description[es]": "Cambiar entre actividades",
+ "Description[et]": "Lülitumine tegevuste vahel",
+ "Description[eu]": "Jarduera artean trukatzea",
+ "Description[fi]": "Vaihda aktiviteetista toiseen",
+ "Description[fr]": "Basculer entre les activités",
+ "Description[ga]": "Athraigh idir gníomhaíochtaí",
+ "Description[gl]": "Cambia de actividade.",
+ "Description[he]": "מעבר בין פעילויות",
+ "Description[hu]": "Váltás az aktivitások között",
+ "Description[ia]": "Commuta inter activitates",
+ "Description[id]": "Beralih antar aktivitas",
+ "Description[ie]": "Alterar li activitás",
+ "Description[is]": "Skipt á milli athafna",
+ "Description[it]": "Passa da un'attività all'altra",
+ "Description[ja]": "アクティビティの切り替え",
+ "Description[ka]": "აქტივობებს შორის გადართვა",
+ "Description[ko]": "활동간 전환",
+ "Description[lt]": "Perjungti tarp veiklų",
+ "Description[lv]": "Pārslēgties starp aktivitātēm",
+ "Description[nb]": "Bytt mellom aktiviteter",
+ "Description[nl]": "Tussen activiteiten schakelen",
+ "Description[nn]": "Byt mellom aktivitetar",
+ "Description[pa]": "ਸਰਗਰਮੀਆਂ ਵਿਚਾਲੇ ਬਦਲੋ",
+ "Description[pl]": "Przełącza między aktywnościami",
+ "Description[pt]": "Mudar de actividades",
+ "Description[pt_BR]": "Alternar entre as atividades",
+ "Description[ro]": "Schimbă între activități",
+ "Description[ru]": "Переключение между комнатами",
+ "Description[sa]": "क्रियाकलापानाम् मध्ये परिवर्तनं कुर्वन्तु",
+ "Description[sk]": "Prepínanie medzi aktivitami",
+ "Description[sl]": "Preklopi med opravili",
+ "Description[sv]": "Byt mellan aktiviteter",
+ "Description[ta]": "செயல்பாடுகளுக்கிடையே தாவ உதவும்",
+ "Description[tr]": "Etkinlikler arasında gezin",
+ "Description[uk]": "Перемикання між просторами дій",
+ "Description[vi]": "Chuyển giữa các Hoạt động",
+ "Description[zh_CN]": "在不同活动之间切换",
+ "Description[zh_TW]": "在活動間切換",
+ "EnabledByDefault": true,
+ "Icon": "org.kde.plasma.pager",
+ "Id": "org.kde.plasma.activitypager",
+ "License": "GPL-2.0+",
+ "Name": "Activity Pager",
+ "Name[ar]": "مبوب الأنشطة",
+ "Name[az]": "İş otağı dəyişdiricisi",
+ "Name[be]": "Пэйджар пакояў",
+ "Name[bg]": "Пейджър на дейностите",
+ "Name[ca@valencia]": "Paginador d'activitats",
+ "Name[ca]": "Paginador d'activitats",
+ "Name[cs]": "Prohlížeč aktivit",
+ "Name[da]": "Aktivitetssøger",
+ "Name[de]": "Aktivitätenübersicht",
+ "Name[el]": "Σελιδοποίηση δραστηριότητας",
+ "Name[en_GB]": "Activity Pager",
+ "Name[eo]": "Aktiveca Tabulpaĝilo",
+ "Name[es]": "Paginador de actividades",
+ "Name[et]": "Tegevuste lülitaja",
+ "Name[eu]": "Jardueren orrialdekatzailea",
+ "Name[fi]": "Aktiviteettisivutin",
+ "Name[fr]": "Gestionnaire d'activités",
+ "Name[ga]": "Leathanach Gníomhaíochta",
+ "Name[gl]": "Paxinador de actividades",
+ "Name[he]": "דפדפן פעילויות",
+ "Name[hu]": "Aktivitásváltó",
+ "Name[ia]": "Pager de activitate",
+ "Name[id]": "Pager Aktivitas",
+ "Name[ie]": "Paginator de activitás",
+ "Name[is]": "Athafnaflettir",
+ "Name[it]": "Paginatore attività",
+ "Name[ja]": "アクティビティページャ",
+ "Name[ka]": "აქტივობის პეიჯერი",
+ "Name[ko]": "활동 호출기",
+ "Name[lt]": "Veiklų perjungiklis",
+ "Name[lv]": "Aktivitāšu lapotājs",
+ "Name[nb]": "Aktivitetsbytter",
+ "Name[nl]": "Pager van activiteiten",
+ "Name[nn]": "Aktivitetsbytar",
+ "Name[pa]": "ਸਰਗਰਮੀ ਪੇਜ਼ਰ",
+ "Name[pl]": "Przełącznik aktywności",
+ "Name[pt]": "Paginador de Actividades",
+ "Name[pt_BR]": "Paginador de atividades",
+ "Name[ro]": "Paginator de activități",
+ "Name[ru]": "Переключение комнат",
+ "Name[sa]": "गतिविधि पेजर",
+ "Name[sk]": "Stránkovač aktivít",
+ "Name[sl]": "Pager dejavnosti",
+ "Name[sv]": "Aktivitetsbytare",
+ "Name[ta]": "செயல்பாடு மாற்றி",
+ "Name[tr]": "Etkinlik Sayfalayıcısı",
+ "Name[uk]": "Пейджер просторів дій",
+ "Name[vi]": "Tổng quan Hoạt động",
+ "Name[zh_CN]": "活动切换器",
+ "Name[zh_TW]": "活動管理器",
+ "Website": "https://userbase.kde.org"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.virtualdesktops",
+ "org.kde.plasma.activities"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.pager"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.folder/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.folder/metadata.json
new file mode 100644
index 0000000..e066e84
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.folder/metadata.json
@@ -0,0 +1,185 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "hein@kde.org",
+ "Name": "Eike Hein",
+ "Name[ar]": "إيكي هين",
+ "Name[az]": "Eike Hein",
+ "Name[be]": "Eike Hein",
+ "Name[bg]": "Eike Hein",
+ "Name[ca@valencia]": "Eike Hein",
+ "Name[ca]": "Eike Hein",
+ "Name[cs]": "Eike Hein",
+ "Name[da]": "Eike Hein",
+ "Name[de]": "Eike Hein",
+ "Name[el]": "Eike Hein",
+ "Name[en_GB]": "Eike Hein",
+ "Name[eo]": "Eike Hein",
+ "Name[es]": "Eike Hein",
+ "Name[et]": "Eike Hein",
+ "Name[eu]": "Eike Hein",
+ "Name[fi]": "Eike Hein",
+ "Name[fr]": "Eike Hein",
+ "Name[ga]": "Eike Hein",
+ "Name[gl]": "Eike Hein",
+ "Name[he]": "אייק היין",
+ "Name[hu]": "Eike Hein",
+ "Name[ia]": "Eike Hein",
+ "Name[id]": "Eike Hein",
+ "Name[ie]": "Eike Hein",
+ "Name[is]": "Eike Hein",
+ "Name[it]": "Eike Hein",
+ "Name[ja]": "Eike Hein",
+ "Name[ka]": "აიკე ჰაინი",
+ "Name[ko]": "Eike Hein",
+ "Name[lt]": "Eike Hein",
+ "Name[lv]": "Eike Hein",
+ "Name[nb]": "Eike Hein",
+ "Name[nl]": "Eike Hein",
+ "Name[nn]": "Eike Hein",
+ "Name[pa]": "ਇਕੀ ਹੀਇਨ",
+ "Name[pl]": "Eike Hein",
+ "Name[pt]": "Eike Hein",
+ "Name[pt_BR]": "Eike Hein",
+ "Name[ro]": "Eike Hein",
+ "Name[ru]": "Eike Hein",
+ "Name[sa]": "ऐके हेन",
+ "Name[sk]": "Eike Hein",
+ "Name[sl]": "Eike Hein",
+ "Name[sv]": "Eike Hein",
+ "Name[ta]": "எய்கே ஹைன்",
+ "Name[tr]": "Eike Hein",
+ "Name[uk]": "Eike Hein",
+ "Name[vi]": "Eike Hein",
+ "Name[zh_CN]": "Eike Hein",
+ "Name[zh_TW]": "Eike Hein"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=Folder",
+ "Category": "File System",
+ "Description": "Display the contents of folders",
+ "Description[ar]": "اعرض محتويات المجلّدات",
+ "Description[az]": "Qovluqların tərkibinə baxış",
+ "Description[be]": "Паказваць змесціва каталогаў",
+ "Description[bg]": "Показване на съдържанието на папки",
+ "Description[ca@valencia]": "Mostra el contingut de les carpetes",
+ "Description[ca]": "Mostra el contingut de les carpetes",
+ "Description[cs]": "Zobrazit obsah složek",
+ "Description[da]": "Vis indholdet af mapper",
+ "Description[de]": "Ordnerinhalte anzeigen",
+ "Description[el]": "Εμφάνιση των περιεχομένων των φακέλων",
+ "Description[en_GB]": "Display the contents of folders",
+ "Description[eo]": "Montri la enhavon de dosierujoj",
+ "Description[es]": "Mostrar el contenido de carpetas",
+ "Description[et]": "Kataloogide sisu näitamine",
+ "Description[eu]": "Karpeten edukia erakustea",
+ "Description[fi]": "Näyttää kansion sisällön",
+ "Description[fr]": "Afficher le contenu des dossiers",
+ "Description[ga]": "Taispeáin ábhar na bhfillteán",
+ "Description[gl]": "Amosa o contido de cartafoles.",
+ "Description[he]": "מציג תוכן של תיקייה",
+ "Description[hu]": "Megjeleníti a mappák tartalmát",
+ "Description[ia]": "Monstra le contentos de dossieres",
+ "Description[id]": "Tampilkan konten folder",
+ "Description[ie]": "Monstrar li contenete de fólderes",
+ "Description[is]": "Sýna innihald í möppum",
+ "Description[it]": "Visualizza il contenuto delle cartelle",
+ "Description[ja]": "フォルダの内容を表示します",
+ "Description[ka]": "საქაღალდეების შიგთავსის ჩვენება",
+ "Description[ko]": "폴더의 내용 보기",
+ "Description[lt]": "Rodyti aplankų turinį",
+ "Description[lv]": "Parādīt mapju saturu",
+ "Description[nb]": "Vis innholdet i mapper",
+ "Description[nl]": "Toon de inhoud van mappen",
+ "Description[nn]": "Vis innhaldet i mapper",
+ "Description[pa]": "ਫੋਲਡਰਾਂ ਦੀ ਸਮੱਗਰੀ ਵੇਖਾਓ",
+ "Description[pl]": "Wyświetla zawartość katalogów",
+ "Description[pt]": "Mostrar o conteúdo das pastas",
+ "Description[pt_BR]": "Mostra o conteúdo das pastas",
+ "Description[ro]": "Afișează conținutul dosarelor",
+ "Description[ru]": "Вывод содержимого папки",
+ "Description[sa]": "पुटस्य सामग्रीं प्रदर्शयन्तु",
+ "Description[sk]": "Zobraziť obsah priečinkov",
+ "Description[sl]": "Pokaži vsebino map",
+ "Description[sv]": "Visa innehåll i kataloger",
+ "Description[ta]": "அடைவுகளின் உள்ளடக்கத்தை காட்டும்",
+ "Description[tr]": "Klasörlerin içeriğini görüntüle",
+ "Description[uk]": "Показ вмісту тек",
+ "Description[vi]": "Hiển thị nội dung các thư mục",
+ "Description[zh_CN]": "显示文件夹的内容",
+ "Description[zh_TW]": "顯示資料夾內容",
+ "EnabledByDefault": true,
+ "Icon": "org.kde.plasma.folder",
+ "Id": "org.kde.plasma.folder",
+ "License": "GPL-2.0+",
+ "Name": "Folder View",
+ "Name[ar]": "عرض المجلّد",
+ "Name[az]": "Qovluqlara baxış",
+ "Name[be]": "Каталогі",
+ "Name[bg]": "Преглед на папка",
+ "Name[ca@valencia]": "Vista de carpetes",
+ "Name[ca]": "Vista de carpeta",
+ "Name[cs]": "Pohled na složku",
+ "Name[da]": "Mappevisning",
+ "Name[de]": "Ordner-Ansicht",
+ "Name[el]": "Προβολή φακέλου",
+ "Name[en_GB]": "Folder View",
+ "Name[eo]": "Dosieruja Vidigo",
+ "Name[es]": "Vista de carpetas",
+ "Name[et]": "Kataloogivaade",
+ "Name[eu]": "Karpeta ikuspegia",
+ "Name[fi]": "Kansionäkymä",
+ "Name[fr]": "Vue de dossier",
+ "Name[ga]": "Amharc Fillteán",
+ "Name[gl]": "Vista de cartafoles",
+ "Name[he]": "הצגת תיקיות",
+ "Name[hu]": "Mappanézet",
+ "Name[ia]": "Vista del Dossier",
+ "Name[id]": "Tampilan Folder",
+ "Name[ie]": "Vise de fólder",
+ "Name[is]": "Möppuyfirlit",
+ "Name[it]": "Vista delle cartelle",
+ "Name[ja]": "フォルダビュー",
+ "Name[ka]": "საქაღალდის ხედი",
+ "Name[ko]": "폴더 보기",
+ "Name[lt]": "Aplankų rodinys",
+ "Name[lv]": "Mapes skats",
+ "Name[nb]": "Mappevisning",
+ "Name[nl]": "Mapweergave",
+ "Name[nn]": "Mappevising",
+ "Name[pa]": "ਫੋਲਡਰ ਝਲਕ",
+ "Name[pl]": "Widok katalogu",
+ "Name[pt]": "Vista da Pasta",
+ "Name[pt_BR]": "Visualização de pastas",
+ "Name[ro]": "Vizualizare dosare",
+ "Name[ru]": "Просмотр папки",
+ "Name[sa]": "समुच्चय दृश्यम्",
+ "Name[se]": "Máhppačájeheapmi",
+ "Name[sk]": "Pohľad priečinka",
+ "Name[sl]": "Prikaz mape",
+ "Name[sr@ijekavian]": "Приказ фасцикле",
+ "Name[sr@ijekavianlatin]": "Prikaz fascikle",
+ "Name[sr@latin]": "Prikaz fascikle",
+ "Name[sr]": "Приказ фасцикле",
+ "Name[sv]": "Katalogvy",
+ "Name[ta]": "அடைவு பார்வை",
+ "Name[tg]": "Намуди ҷузвадонҳо",
+ "Name[tr]": "Klasör Görünümü",
+ "Name[uk]": "Перегляд теки",
+ "Name[vi]": "Xem thư mục",
+ "Name[zh_CN]": "文件夹视图",
+ "Name[zh_TW]": "資料夾檢視",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-ContainmentType": "Desktop",
+ "X-Plasma-DropMimeTypes": [
+ "inode/directory"
+ ],
+ "X-Plasma-Provides": [
+ "org.kde.plasma.filemanagement"
+ ],
+ "X-Plasma-RootPath": "org.kde.desktopcontainment"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.icontasks/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.icontasks/metadata.json
new file mode 100644
index 0000000..1ce07f7
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.icontasks/metadata.json
@@ -0,0 +1,165 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "hein@kde.org",
+ "Name": "Eike Hein",
+ "Name[ar]": "إيكي هين",
+ "Name[az]": "Eike Hein",
+ "Name[be]": "Eike Hein",
+ "Name[bg]": "Eike Hein",
+ "Name[ca@valencia]": "Eike Hein",
+ "Name[ca]": "Eike Hein",
+ "Name[cs]": "Eike Hein",
+ "Name[da]": "Eike Hein",
+ "Name[de]": "Eike Hein",
+ "Name[el]": "Eike Hein",
+ "Name[en_GB]": "Eike Hein",
+ "Name[eo]": "Eike Hein",
+ "Name[es]": "Eike Hein",
+ "Name[et]": "Eike Hein",
+ "Name[eu]": "Eike Hein",
+ "Name[fi]": "Eike Hein",
+ "Name[fr]": "Eike Hein",
+ "Name[ga]": "Eike Hein",
+ "Name[gl]": "Eike Hein",
+ "Name[he]": "אייק היין",
+ "Name[hu]": "Eike Hein",
+ "Name[ia]": "Eike Hein",
+ "Name[id]": "Eike Hein",
+ "Name[ie]": "Eike Hein",
+ "Name[is]": "Eike Hein",
+ "Name[it]": "Eike Hein",
+ "Name[ja]": "Eike Hein",
+ "Name[ka]": "აიკე ჰაინი",
+ "Name[ko]": "Eike Hein",
+ "Name[lt]": "Eike Hein",
+ "Name[lv]": "Eike Hein",
+ "Name[nb]": "Eike Hein",
+ "Name[nl]": "Eike Hein",
+ "Name[nn]": "Eike Hein",
+ "Name[pa]": "ਇਕੀ ਹੀਇਨ",
+ "Name[pl]": "Eike Hein",
+ "Name[pt]": "Eike Hein",
+ "Name[pt_BR]": "Eike Hein",
+ "Name[ro]": "Eike Hein",
+ "Name[ru]": "Eike Hein",
+ "Name[sa]": "ऐके हेन",
+ "Name[sk]": "Eike Hein",
+ "Name[sl]": "Eike Hein",
+ "Name[sv]": "Eike Hein",
+ "Name[ta]": "எய்கே ஹைன்",
+ "Name[tr]": "Eike Hein",
+ "Name[uk]": "Eike Hein",
+ "Name[vi]": "Eike Hein",
+ "Name[zh_CN]": "Eike Hein",
+ "Name[zh_TW]": "Eike Hein"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=Task%20Manager%20and%20Icons-Only%20Task%20Manager%20widgets",
+ "Category": "Windows and Tasks",
+ "Description": "App bar displaying only icons",
+ "Description[ar]": "شريط التطبيقات يعرض أيقونات فقط",
+ "Description[az]": "Yalnız nişanları göstərən tətbiq paneli",
+ "Description[be]": "На панэлі праграм паказваюцца толькі значкі",
+ "Description[bg]": "Лента с приложения, показваща само икони",
+ "Description[ca@valencia]": "Barra d'aplicacions que mostra només les icones",
+ "Description[ca]": "Barra d'aplicacions que mostra només les icones",
+ "Description[da]": "App-linjen viser kun ikoner",
+ "Description[de]": "Nur Symbole werden auf der Anwendungsleiste angezeigt",
+ "Description[el]": "Γραμμή εφαρμογών που εμφανίζει μόνο εικονίδια",
+ "Description[en_GB]": "App bar displaying only icons",
+ "Description[eo]": "Apobreto montranta nur piktogramojn",
+ "Description[es]": "Barra de aplicaciones que solo muestra iconos",
+ "Description[eu]": "Ikonoak bakarrik azaltzen dituen aplikazio-barra",
+ "Description[fi]": "Vain kuvakkeet näyttävä sovelluspalkki",
+ "Description[fr]": "Barre d'applications n'affichant que des icônes",
+ "Description[ga]": "Barra aipeanna ag taispeáint deilbhíní amháin",
+ "Description[gl]": "Barra de aplicacións que amosa só iconas.",
+ "Description[he]": "סרגל היישומים מציג סמלים בלבד",
+ "Description[hu]": "Csak ikonokat megjelenítő alkalmazássáv",
+ "Description[ia]": "Barra de app monstrante solmente icones",
+ "Description[id]": "Bilah app menampilkan ikon saja",
+ "Description[is]": "Forritastika sem birtir eingöngu tákn",
+ "Description[it]": "Barra dell'applicazione che mostra solo le icone",
+ "Description[ja]": "アイコンのみを表示するアプリケーションバー",
+ "Description[ka]": "აპის პანელი, მხოლოდ, ხატულებს აჩვენებს",
+ "Description[ko]": "아이콘만 표시하는 앱 표시줄",
+ "Description[lt]": "Programų juosta atvaizduojanti tik piktogramas",
+ "Description[lv]": "Programmu josla, kurā ir tikai ikonas",
+ "Description[nb]": "Oppgavelinje med bare ikoner",
+ "Description[nl]": "Toepassingenbalk met alleen pictogrammen",
+ "Description[nn]": "Oppgåvelinje med berre ikon",
+ "Description[pl]": "Pasek aplikacji wyświetlający tylko ikony",
+ "Description[pt_BR]": "Barra de aplicativos apenas com ícones",
+ "Description[ro]": "Bară de aplicații ce afișează doar pictograme",
+ "Description[ru]": "Панель задач, использующая только значки",
+ "Description[sa]": "केवलं चिह्नानि प्रदर्शयति एप् बार",
+ "Description[sk]": "Panel aplikácií zobrazujúci iba ikony",
+ "Description[sl]": "Vrstica aplikacij, ki prikazuje samo ikone",
+ "Description[sv]": "Programrad som bara visar ikoner",
+ "Description[ta]": "சின்னங்களை மட்டும் காட்டும் பணிப்பட்டை",
+ "Description[tr]": "Yalnızca simgeler görüntüleyen uygulama çubuğu",
+ "Description[uk]": "Панель програм, де показано лише піктограми",
+ "Description[zh_CN]": "应用栏仅显示图标",
+ "Description[zh_TW]": "只顯示圖示的應用程式列",
+ "EnabledByDefault": true,
+ "Icon": "preferences-system-windows",
+ "Id": "org.kde.plasma.icontasks",
+ "License": "GPL-2.0+",
+ "Name": "Icons-Only Task Manager",
+ "Name[ar]": "مدير مهامّ بأيقونات فقط",
+ "Name[az]": "Yalnız nişanlı tapşırıq meneceri",
+ "Name[be]": "Кіраўнік задач у выглядзе значкоў",
+ "Name[bg]": "Мениджър на задачи (само икони)",
+ "Name[ca@valencia]": "Gestor de tasques només amb icones",
+ "Name[ca]": "Gestor de tasques només amb icones",
+ "Name[cs]": "Správce úloh pouze s ikonami",
+ "Name[da]": "Opgavelinje kun med ikoner",
+ "Name[de]": "Fensterleiste nur mit Symbolen",
+ "Name[el]": "Διαχείριση εργασιών μόνο με εικονίδια",
+ "Name[en_GB]": "Icons-Only Task Manager",
+ "Name[eo]": "Nur-Piktograma Taskadministrilo",
+ "Name[es]": "Gestor de tareas con solo iconos",
+ "Name[eu]": "Ikono-soileko ataza-kudeatzailea",
+ "Name[fi]": "Kuvaketehtävienhallinta",
+ "Name[fr]": "Gestionnaire de tâches uniquement par icônes",
+ "Name[ga]": "Bainisteoir Tascanna Deilbhíní Amháin",
+ "Name[gl]": "Xestor de tarefas de só iconas",
+ "Name[he]": "מנהל משימות של סמלים בלבד",
+ "Name[hu]": "Ikonos feladatkezelő",
+ "Name[ia]": "Gerente de carga a sol icone",
+ "Name[id]": "Pengelola Tugas Ikon Saja",
+ "Name[is]": "Verkefnastjóri með táknum eingöngu",
+ "Name[it]": "Gestore dei processi solo icone",
+ "Name[ja]": "アイコンだけのタスクマネージャ",
+ "Name[ka]": "მხოლოდ ხატულებიანი ამოცანების მმართველი",
+ "Name[ko]": "아이콘 전용 작업 관리자",
+ "Name[lt]": "Tik piktogramų užduočių tvarkytuvė",
+ "Name[lv]": "Tikai ikonu uzdevumu pārvaldnieks",
+ "Name[nb]": "Oppgavebehandler med bare ikoner",
+ "Name[nl]": "Takenbeheer met alleen pictogrammen",
+ "Name[nn]": "Oppgåvehandsamar med berre ikon",
+ "Name[pa]": "ਸਿਰਫ਼-ਆਈਕਾਨ ਟਾਸਕ ਮੈਨੇਜਰ",
+ "Name[pl]": "Ikonowy przełącznik zadań",
+ "Name[pt_BR]": "Gerenciador de tarefas apenas com ícones",
+ "Name[ro]": "Gestionar de sarcini numai cu pictograme",
+ "Name[ru]": "Панель задач (только значки)",
+ "Name[sa]": "चिह्न-केवलं कार्यप्रबन्धकम्",
+ "Name[sk]": "Správca úloh iba s ikonami",
+ "Name[sl]": "Upravljalnik opravil samo z ikonami",
+ "Name[sv]": "Aktivitetshanterare med bara ikoner",
+ "Name[ta]": "சின்னங்களை மட்டும் கொண்ட பணி மேலாளி",
+ "Name[tr]": "Simgesel Görev Yöneticisi",
+ "Name[uk]": "Керування задачами лише за допомогою піктограм",
+ "Name[zh_CN]": "图标任务管理器",
+ "Name[zh_TW]": "只有圖示的工作管理員",
+ "Website": "https://userbase.kde.org/Plasma/Tasks"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.multitasking"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.taskmanager"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.kickerdash/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.kickerdash/metadata.json
new file mode 100644
index 0000000..8914fe1
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.kickerdash/metadata.json
@@ -0,0 +1,155 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "hein@kde.org",
+ "Name": "Eike Hein",
+ "Name[ar]": "إيكي هين",
+ "Name[az]": "Eike Hein",
+ "Name[bg]": "Eike Hein",
+ "Name[ca@valencia]": "Eike Hein",
+ "Name[ca]": "Eike Hein",
+ "Name[cs]": "Eike Hein",
+ "Name[da]": "Eike Hein",
+ "Name[de]": "Eike Hein",
+ "Name[en_GB]": "Eike Hein",
+ "Name[eo]": "Eike Hein",
+ "Name[es]": "Eike Hein",
+ "Name[eu]": "Eike Hein",
+ "Name[fi]": "Eike Hein",
+ "Name[fr]": "Eike Hein",
+ "Name[gl]": "Eike Hein",
+ "Name[he]": "אייק היין",
+ "Name[hu]": "Eike Hein",
+ "Name[ia]": "Eike Hein",
+ "Name[id]": "Eike Hein",
+ "Name[is]": "Eike Hein",
+ "Name[it]": "Eike Hein",
+ "Name[ja]": "Eike Hein",
+ "Name[ka]": "აიკე ჰაინი",
+ "Name[ko]": "Eike Hein",
+ "Name[lt]": "Eike Hein",
+ "Name[lv]": "Eike Hein",
+ "Name[nl]": "Eike Hein",
+ "Name[nn]": "Eike Hein",
+ "Name[pl]": "Eike Hein",
+ "Name[pt]": "Eike Hein",
+ "Name[pt_BR]": "Eike Hein",
+ "Name[ro]": "Eike Hein",
+ "Name[ru]": "Eike Hein",
+ "Name[sa]": "ऐके हेन",
+ "Name[sk]": "Eike Hein",
+ "Name[sl]": "Eike Hein",
+ "Name[sv]": "Eike Hein",
+ "Name[ta]": "எய்கே ஹைன்",
+ "Name[tr]": "Eike Hein",
+ "Name[uk]": "Eike Hein",
+ "Name[vi]": "Eike Hein",
+ "Name[zh_CN]": "Eike Hein",
+ "Name[zh_TW]": "Eike Hein"
+ }
+ ],
+ "Category": "Application Launchers",
+ "Description": "A fullscreen application launcher",
+ "Description[ar]": "مطلق تطبيقات ملء الشاشة ",
+ "Description[az]": "Tam ekran tətbiq başladıcısı",
+ "Description[bg]": "Стартер на приложения на цял екран",
+ "Description[ca@valencia]": "Un iniciador d'aplicacions a pantalla completa",
+ "Description[ca]": "Un llançador d'aplicacions a pantalla completa",
+ "Description[cs]": "Spouštěč aplikací na celou obrazovku",
+ "Description[da]": "En fuldskærms programstarter",
+ "Description[de]": "Anwendungsstarter im Vollbildmodus",
+ "Description[en_GB]": "A fullscreen application launcher",
+ "Description[eo]": "Plenekrana aplikaĵlanĉilo",
+ "Description[es]": "Lanzador de aplicaciones a pantalla completa",
+ "Description[eu]": "Pantaila-osoko aplikazio abiarazle bat",
+ "Description[fi]": "Koko näytön sovelluskäynnistin",
+ "Description[fr]": "Un lanceur d'applications en plein écran",
+ "Description[gl]": "Un iniciador de aplicacións a pantalla completa",
+ "Description[he]": "משגר יישומים במסך מלא",
+ "Description[hu]": "Teljes képernyős alkalmazásindító",
+ "Description[ia]": "Un lanceator de application a schermo plen",
+ "Description[id]": "Sebuah peluncur aplikasi layar penuh",
+ "Description[is]": "Forritaræsir sem fyllir skjáinn",
+ "Description[it]": "Un lanciatore di applicazioni a schermo intero",
+ "Description[ja]": "フルスクリーンのアプリケーションランチャー",
+ "Description[ka]": "აპლიკაციების მთელ ეკრანზე გამშვები",
+ "Description[ko]": "전체 화면 앱 실행기",
+ "Description[lt]": "Viso ekrano programų paleidyklė",
+ "Description[lv]": "Pilnekrāna programmu palaidējs",
+ "Description[nl]": "Een programmastarter met volledig scherm",
+ "Description[nn]": "Fullskjerms programstartar",
+ "Description[pl]": "Pełnoekranowe menu programów",
+ "Description[pt]": "Um lançador de aplicações em ecrã completo",
+ "Description[pt_BR]": "Lançador de aplicativos em tela cheia",
+ "Description[ro]": "Lansator de aplicații pe tot ecranul",
+ "Description[ru]": "Полноэкранное меню запуска приложений",
+ "Description[sa]": "एकः पूर्णपर्दे अनुप्रयोगप्रक्षेपकः",
+ "Description[sk]": "Spúšťač aplikácií na celú obrazovku",
+ "Description[sl]": "Celozaslonski zaganjalnik aplikacij",
+ "Description[sv]": "Ett fullskärmsverktyg för programstart",
+ "Description[ta]": "முழுத்திரை செயலி ஏவி",
+ "Description[tr]": "Tam ekran uygulama başlatıcısı",
+ "Description[uk]": "Повноекранний засіб запуску програм",
+ "Description[vi]": "Trình khởi chạy ứng dụng, với kích cỡ toàn màn hình",
+ "Description[zh_CN]": "全屏应用程序启动器",
+ "Description[zh_TW]": "一個全螢幕應用程式啟動器",
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "start-here-kde",
+ "Id": "org.kde.plasma.kickerdash",
+ "License": "GPL-2.0+",
+ "Name": "Application Dashboard",
+ "Name[ar]": "لوحة معلومات التطبيق",
+ "Name[az]": "Tətbiq tablosu",
+ "Name[bg]": "Панел на приложения",
+ "Name[ca@valencia]": "Tauler d'aplicacions",
+ "Name[ca]": "Tauler d'aplicacions",
+ "Name[cs]": "Pracovní plocha aplikace",
+ "Name[da]": "Programoverblik",
+ "Name[de]": "Anwendungsübersicht",
+ "Name[en_GB]": "Application Dashboard",
+ "Name[eo]": "Aplika Instrumentpanelo",
+ "Name[es]": "Tablero de aplicaciones",
+ "Name[eu]": "Aplikazioen Aginte-mahaia",
+ "Name[fi]": "Sovelluskojelauta",
+ "Name[fr]": "Tableau de bord des applications",
+ "Name[gl]": "Cadro de control de aplicacións",
+ "Name[he]": "לוח מחווני יישומים",
+ "Name[hu]": "Alkalmazás irányítópult",
+ "Name[ia]": "Pannello de instrumentos de Application",
+ "Name[id]": "Dasbor Aplikasi",
+ "Name[is]": "Hugbúnaðarborð",
+ "Name[it]": "Cruscotto applicazioni",
+ "Name[ja]": "アプリケーションダッシュボード",
+ "Name[ka]": "აპლიკაციის სამუშაო დაფა",
+ "Name[ko]": "앱 대시보드",
+ "Name[lt]": "Programų skydelis",
+ "Name[lv]": "Programmu panelis",
+ "Name[nl]": "Toepassingendashboard",
+ "Name[nn]": "Programkontrollpult",
+ "Name[pl]": "Tablica programów",
+ "Name[pt]": "Quadro da Aplicação",
+ "Name[pt_BR]": "Painel de aplicativos",
+ "Name[ro]": "Panou de bord pentru aplicații",
+ "Name[ru]": "Доска приложений",
+ "Name[sa]": "अनुप्रयोग डैशबोर्ड",
+ "Name[sk]": "Hlavný panel aplikácií",
+ "Name[sl]": "Application Dashboard",
+ "Name[sv]": "Instrumentpanel för program",
+ "Name[ta]": "செயலி கருவிப்பலகை",
+ "Name[tr]": "Uygulama Gösterge Tablosu",
+ "Name[uk]": "Панель приладів програм",
+ "Name[vi]": "Bảng điều khiển ứng dụng",
+ "Name[zh_CN]": "应用程序面板",
+ "Name[zh_TW]": "應用程式儀表板",
+ "Website": "https://kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.launchermenu"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.kicker"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.minimizeall/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.minimizeall/metadata.json
new file mode 100644
index 0000000..e25667f
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.minimizeall/metadata.json
@@ -0,0 +1,170 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "sebas@kde.org",
+ "Name": "Sebastian Kügler",
+ "Name[ar]": "سيباستيان كوغلر",
+ "Name[az]": "Sebastian Kügler",
+ "Name[be]": "Sebastian Kügler",
+ "Name[bg]": "Sebastian Kügler",
+ "Name[ca@valencia]": "Sebastian Kügler",
+ "Name[ca]": "Sebastian Kügler",
+ "Name[cs]": "Sebastian Kügler",
+ "Name[da]": "Sebastian Kügler",
+ "Name[de]": "Sebastian Kügler",
+ "Name[el]": "Sebastian kügler",
+ "Name[en_GB]": "Sebastian Kügler",
+ "Name[eo]": "Sebastian Kügler",
+ "Name[es]": "Sebastian Kügler",
+ "Name[et]": "Sebastian Kügler",
+ "Name[eu]": "Sebastian Kügler",
+ "Name[fi]": "Sebastian Kügler",
+ "Name[fr]": "Sebastian Kügler",
+ "Name[ga]": "Sebastian Kügler",
+ "Name[gl]": "Sebastian Kügler",
+ "Name[he]": "סבסטיאן קיגלר",
+ "Name[hu]": "Sebastian Kügler",
+ "Name[ia]": "Sebastian Kügler",
+ "Name[id]": "Sebastian Kügler",
+ "Name[ie]": "Sebastian Kügler",
+ "Name[is]": "Sebastian Kügler",
+ "Name[it]": "Sebastian Kügler",
+ "Name[ja]": "Sebastian Kügler",
+ "Name[ka]": "სებასტიან კუგლერი",
+ "Name[ko]": "Sebastian Kügler",
+ "Name[lt]": "Sebastian Kügler",
+ "Name[lv]": "Sebastian Kügler",
+ "Name[nb]": "Sebastian Kügler",
+ "Name[nl]": "Sebastian Kügler",
+ "Name[nn]": "Sebastian Kügler",
+ "Name[pl]": "Sebastian Kügler",
+ "Name[pt]": "Sebastian Kügler",
+ "Name[pt_BR]": "Sebastian Kügler",
+ "Name[ro]": "Sebastian Kügler",
+ "Name[ru]": "Sebastian Kügler",
+ "Name[sa]": "सेबास्टियन कुग्लर",
+ "Name[sk]": "Sebastian Kügler",
+ "Name[sl]": "Sebastian Kügler",
+ "Name[sv]": "Sebastian Kügler",
+ "Name[ta]": "ஸெபாஸ்டியன் கூக்லர்",
+ "Name[tr]": "Sebastian Kügler",
+ "Name[uk]": "Sebastian Kügler",
+ "Name[vi]": "Sebastian Kügler",
+ "Name[zh_CN]": "Sebastian Kügler",
+ "Name[zh_TW]": "Sebastian Kügler"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=Show%20Desktop/Minimize%20All%20widget",
+ "Category": "Windows and Tasks",
+ "Description": "Shows the desktop by minimizing all windows",
+ "Description[ar]": "تظهر سطح المكتب بتصغير كل النوافذ",
+ "Description[az]": "Bütün pəncərələri kiçiltməklə İş Masasını göstərir",
+ "Description[be]": "Згортвае ўсе вокны і паказвае пусты працоўны стол",
+ "Description[bg]": "Показва работния плот, като минимизира всички прозорци",
+ "Description[ca@valencia]": "Mostra l'escriptori minimitzant totes les finestres",
+ "Description[ca]": "Mostra l'escriptori minimitzant totes les finestres",
+ "Description[cs]": "Zobrazit plochu minimalizací všech oken",
+ "Description[da]": "Viser skrivebordet ved at minimere alle vinduer",
+ "Description[de]": "Zeigt die Arbeitsfläche an, indem alle Fenster minimiert werden",
+ "Description[el]": "Εμφανίζει την επιφάνεια εργασίας ελαχιστοποιώντας όλα τα παράθυρα",
+ "Description[en_GB]": "Shows the desktop by minimising all windows",
+ "Description[eo]": "Montras la labortablon minimumigante ĉiujn fenestrojn",
+ "Description[es]": "Muestra el escritorio minimizando todas las ventanas",
+ "Description[et]": "Töölaua näitamine kõigi akende minimeerimise järel",
+ "Description[eu]": "Mahaigaina erakusten du leiho guztiak ikonotuz",
+ "Description[fi]": "Näyttää työpöydän pienentämällä kaikki ikkunat",
+ "Description[fr]": "Afficher le bureau en minimisant toutes les fenêtres",
+ "Description[ga]": "Taispeáin an deasc trí na fuinneoga go léir a íoslaghdú",
+ "Description[gl]": "Minimiza todas as xanelas para amosar o escritorio.",
+ "Description[he]": "מציג את שולחן העבודה על ידי מזעור כל החלונות",
+ "Description[hu]": "Megjeleníti az asztalt az összes ablak minimalizálásával",
+ "Description[ia]": "Monstra le scriptorio per minimisar omne fenestras",
+ "Description[id]": "Menampilkan desktop dengan meminimalkan semua jendela",
+ "Description[ie]": "Minimisar omni fenestres e monstrar li Pupitre",
+ "Description[is]": "Sýnir skjáborðið með því að fela alla glugga",
+ "Description[it]": "Mostra il desktop minimizzando tutte le finestre",
+ "Description[ja]": "すべてのウィンドウを最小化してデスクトップを表示します",
+ "Description[ka]": "ფანჯრების ჩაკეცვა და სამუშაო მაგიდის ჩვენება",
+ "Description[ko]": "모든 창을 최소화하여 바탕 화면 표시",
+ "Description[lt]": "Suskleisdamas visus langus, rodo darbalaukį",
+ "Description[lv]": "Parāda darbvirsmu, minimizējot visus logus",
+ "Description[nb]": "Vis skrivebordet ved å minimere alle vinduene",
+ "Description[nl]": "Toont het bureaublad door alle vensters te minimaliseren",
+ "Description[nn]": "Viser skrivebordet ved å minimera alle vindauga",
+ "Description[pa]": "ਸਾਰੀਆਂ ਵਿੰਡੋਆਂ ਨੂੰ ਘੱਟੋ-ਘੱਟ ਕਰਕੇ ਡੈਸਕਟਾਪ ਵੇਖਾਓ",
+ "Description[pl]": "Ukazuje pulpit minimalizując wszystkie okna",
+ "Description[pt]": "Mostra o ecrã, minimizando todas as janelas",
+ "Description[pt_BR]": "Mostra a área de trabalho ao minimizar todas as janelas",
+ "Description[ro]": "Arată biroul prin minimizarea tuturor ferestrelor",
+ "Description[ru]": "Показывает рабочий стол, свернув все окна",
+ "Description[sa]": "सर्वाणि विण्डोस् न्यूनीकृत्य डेस्कटॉप् दर्शयति",
+ "Description[sk]": "Zobrazí plochu minimalizovaním všetkých okien",
+ "Description[sl]": "Prikaže namizje s strnjevanjem vseh oken",
+ "Description[sv]": "Visar skrivbordet genom att minimera alla fönster",
+ "Description[ta]": "அனைத்து சாளரங்களையும் ஒதுக்கி பணிமேடையை காட்டும்",
+ "Description[tr]": "Bütün pencereleri küçülterek masaüstünü gösterir",
+ "Description[uk]": "Показати стільницю, мінімізувавши усі вікна",
+ "Description[vi]": "Hiện bàn làm việc bằng cách thu nhỏ tất cả các cửa sổ",
+ "Description[zh_CN]": "最小化所有窗口以显示桌面",
+ "Description[zh_TW]": "藉由將所有視窗最小化來顯示桌面",
+ "EnabledByDefault": true,
+ "Icon": "user-desktop",
+ "Id": "org.kde.plasma.minimizeall",
+ "License": "GPL-2.0+",
+ "Name": "Minimize All Windows",
+ "Name[ar]": "صغّر كلّ النّوافذ",
+ "Name[az]": "Bütün pəncərələri yığmaq",
+ "Name[be]": "Згарнуць усе вокны",
+ "Name[bg]": "Минимизиране на всички прозорци",
+ "Name[ca@valencia]": "Minimitza totes les finestres",
+ "Name[ca]": "Minimitza totes les finestres",
+ "Name[cs]": "Minimalizovat všechna okna",
+ "Name[da]": "Minimér alle vinduer",
+ "Name[de]": "Alle Fenster minimieren",
+ "Name[el]": "Ελαχιστοποίηση όλων των παραθύρων",
+ "Name[en_GB]": "Minimise All Windows",
+ "Name[eo]": "Minimumigi Ĉiujn Fenestrojn",
+ "Name[es]": "Minimizar todas las ventanas",
+ "Name[eu]": "Ikonotu leiho guztiak",
+ "Name[fi]": "Pienennä kaikki ikkunat",
+ "Name[fr]": "Minimiser toutes les fenêtres",
+ "Name[ga]": "Íoslaghdaigh Gach Fuinneog",
+ "Name[gl]": "Minimizar todas as xanelas",
+ "Name[he]": "מזעור כל החלונות",
+ "Name[hu]": "Összes ablak minimalizálása",
+ "Name[ia]": "Minimisa omne fenestras",
+ "Name[id]": "Minimalkan Semua Jendela",
+ "Name[is]": "Fela alla glugga",
+ "Name[it]": "Minimizza tutte le finestre",
+ "Name[ja]": "ウィンドウ最小化",
+ "Name[ka]": "ყველა ფანჯრის ჩაკეცვა",
+ "Name[ko]": "모든 창 최소화",
+ "Name[lt]": "Suskleisti visus langus",
+ "Name[lv]": "Minimizēt visus logus",
+ "Name[nb]": "Minimer alle vinduene",
+ "Name[nl]": "Alle vensters minimaliseren",
+ "Name[nn]": "Minimer alle vindauga",
+ "Name[pa]": "ਸਭ ਵਿੰਡੋਆਂ ਨੂੰ ਘੱਟੋ-ਘੱਟ ਕਰੋ",
+ "Name[pl]": "Zminimalizuj wszystkie okna",
+ "Name[pt_BR]": "Minimizar todas as janelas",
+ "Name[ro]": "Minimizează toate ferestrele",
+ "Name[ru]": "Свернуть все окна",
+ "Name[sa]": "सर्वाणि विण्डोजानि न्यूनीकरोतु",
+ "Name[sk]": "Minimalizovať všetky okná",
+ "Name[sl]": "Strni vsa okna",
+ "Name[sv]": "Minimera alla fönster",
+ "Name[ta]": "அனைத்து சாளரங்களையும் ஒதுக்கு",
+ "Name[tr]": "Tüm Pencereleri Küçült",
+ "Name[uk]": "Мінімізувати усі вікна",
+ "Name[zh_CN]": "最小化所有窗口",
+ "Name[zh_TW]": "最小化所有視窗",
+ "Website": "https://kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.windowmanagement"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.showdesktop"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpu/contents/config/faceproperties b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpu/contents/config/faceproperties
new file mode 100644
index 0000000..47581ef
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpu/contents/config/faceproperties
@@ -0,0 +1,11 @@
+[Config]
+chartFace=org.kde.ksysguard.piechart
+highPrioritySensorIds=["cpu/all/usage"]
+totalSensors=["cpu/all/usage"]
+lowPrioritySensorIds=["cpu/all/cpuCount","cpu/all/coreCount"]
+
+[FaceConfig]
+rangeAuto=false
+rangeFrom=0
+rangeTo=100
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpu/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpu/metadata.json
new file mode 100644
index 0000000..7973fe4
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpu/metadata.json
@@ -0,0 +1,175 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "kde@privat.broulik.de",
+ "Name": "Kai Uwe Broulik",
+ "Name[ar]": "كاي أووي بروتيك",
+ "Name[ast]": "Kai Uwe Broulik",
+ "Name[az]": "Kai Uwe Broulik",
+ "Name[be]": "Kai Uwe Broulik",
+ "Name[bg]": "Kai Uwe Broulik",
+ "Name[ca@valencia]": "Kai Uwe Broulik",
+ "Name[ca]": "Kai Uwe Broulik",
+ "Name[cs]": "Kai Uwe Broulik",
+ "Name[da]": "Kai Uwe Broulik",
+ "Name[de]": "Kai Uwe Broulik",
+ "Name[el]": "Kai Uwe Broulik",
+ "Name[en_GB]": "Kai Uwe Broulik",
+ "Name[eo]": "Kai Uwe Broulik",
+ "Name[es]": "Kai Uwe Broulik",
+ "Name[et]": "Kai Uwe Broulik",
+ "Name[eu]": "Kai Uwe Broulik",
+ "Name[fi]": "Kai Uwe Broulik",
+ "Name[fr]": "Kai Uwe Broulik",
+ "Name[ga]": "Kai Uwe Broulik",
+ "Name[gl]": "Kai Uwe Broulik",
+ "Name[he]": "קאי אווה ברוליק",
+ "Name[hi]": "काई उवे ब्रोलिक",
+ "Name[hu]": "Kai Uwe Broulik",
+ "Name[ia]": "Kai Uwe Broulik",
+ "Name[id]": "Kai Uwe Broulik",
+ "Name[is]": "Kai Uwe Broulik",
+ "Name[it]": "Kai Uwe Broulik",
+ "Name[ja]": "Kai Uwe Broulik",
+ "Name[ka]": "კაი უვე ბროულიკი",
+ "Name[ko]": "Kai Uwe Broulik",
+ "Name[lt]": "Kai Uwe Broulik",
+ "Name[lv]": "Kai Uwe Broulik",
+ "Name[nb]": "Kai Uwe Broulik",
+ "Name[nl]": "Kai Uwe Broulik",
+ "Name[nn]": "Kai Uwe Broulik",
+ "Name[pa]": "ਕੋਈ ਉਵੇ ਬਰੋਉਲਿਕ",
+ "Name[pl]": "Kai Uwe Broulik",
+ "Name[pt]": "Kai Uwe Broulik",
+ "Name[pt_BR]": "Kai Uwe Broulik",
+ "Name[ro]": "Kai Uwe Broulik",
+ "Name[ru]": "Kai Uwe Broulik",
+ "Name[sa]": "कै उवे ब्रौलिक्",
+ "Name[sk]": "Kai Uwe Broulik",
+ "Name[sl]": "Kai Uwe Broulik",
+ "Name[sv]": "Kai Uwe Broulik",
+ "Name[ta]": "காய் ஊவே புரோலிக்",
+ "Name[tr]": "Kai Uwe Broulik",
+ "Name[uk]": "Kai Uwe Broulik",
+ "Name[vi]": "Kai Uwe Broulik",
+ "Name[zh_CN]": "Kai Uwe Broulik",
+ "Name[zh_TW]": "Kai Uwe Broulik"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Monitor%20widgets",
+ "Category": "System Information",
+ "Description": "System monitor widget that shows the total CPU usage",
+ "Description[ar]": "أداة مراقبة النظام التي تعرض مجموع استخدام المعالج",
+ "Description[az]": "Prosessorun ümumi istifadəsini göstərən sistem izləyici vidjeti",
+ "Description[be]": "Віджэт сістэмнага назіральніка, які паказвае агульнае выкарыстанне працэсара",
+ "Description[bg]": "Уиджет за системен монитор, което показва общото използване на процесора",
+ "Description[ca@valencia]": "Giny del monitor del sistema que mostra l'ús total de la CPU",
+ "Description[ca]": "Giny del monitor del sistema que mostra l'ús total de la CPU",
+ "Description[cs]": "Widget monitoru systému, zobrazující celkové využití CPU",
+ "Description[da]": "Systemovervågning-widget som viser den samlede CPU-brug",
+ "Description[de]": "Systemmonitor-Miniprogramm, das die Auslastung des gesamten Prozessors anzeigt",
+ "Description[el]": "Συστατικό παρακολούθησης συστήματος που εμφανίζει τη συνολική χρήση της ΚΜΕ",
+ "Description[en_GB]": "System monitor widget that shows the total CPU usage",
+ "Description[eo]": "Sistemmonitora fenestraĵo kiu montras la suman CPU-uzadon",
+ "Description[es]": "Elemento gráfico del monitor del sistema que muestra el uso total de CPU",
+ "Description[eu]": "PUZ erabileraren guztizkoa erakusten duen sistema gainbegiratzeko trepeta",
+ "Description[fi]": "Suorittimen kokonaiskäytön näyttävä järjestelmänvalvontasovelma",
+ "Description[fr]": "Composant graphique de surveillance du système, affichant l'utilisation globale du processeur.",
+ "Description[gl]": "Trebello de vixilancia do sistema que mostra o uso total do procesador.",
+ "Description[he]": "יישומון צג מערכת שמציג את ניצולת המעבד הכללית",
+ "Description[hu]": "Rendszermonitor elem, amely a teljes processzorhasználatot mutatja",
+ "Description[ia]": "Widget de supervision de systema que monstra le uso total de CPU",
+ "Description[id]": "Widget pemantau sistem yang menampilkan penggunaan total CPU",
+ "Description[is]": "Kerfisvöktunargræja sem sýnir heildarnotkun örgjörva",
+ "Description[it]": "Oggetto di monitoraggio del sistema che mostra l'utilizzo totale del processore",
+ "Description[ja]": "CPU 全体の使用率を表示するウィジェット",
+ "Description[ka]": "სისტემური მონიტორის ვიჯეტი, რომელიც CPU-ის ჯამურ დატვირთვას აჩვენებს",
+ "Description[ko]": "총 CPU 사용량을 표시하는 시스템 모니터 위젯",
+ "Description[lt]": "Sistemos prižiūryklės valdiklis, kuris rodo bendrą procesoriaus naudojimą",
+ "Description[lv]": "Sistēmas pārraudzības logdaļa, kas parāda CPU kopējo noslodzi",
+ "Description[nb]": "Systemovervåking-element som viser bruk av alle prosessorkjernene",
+ "Description[nl]": "Systeemmonitorwidget die het totale gebruik toont de CPU toont",
+ "Description[nn]": "Systemovervaking som viser total prosessorlast",
+ "Description[pa]": "ਕੁੱਲ CPU ਵਰਤੋਂ ਵਿਖਾਉਣ ਵਾਲਾ ਸਿਸਟਮ ਮਾਨੀਟਰ ਵਿਜੈੱਟ",
+ "Description[pl]": "Element interfejsu, który pokazuje całkowite wykorzystanie procesora",
+ "Description[pt_BR]": "Widget monitor do sistema que mostra o uso total da CPU",
+ "Description[ro]": "Control grafic de monitorizare a sistemului ce arată utilizarea totală a procesorului",
+ "Description[ru]": "Мониторинг общей загрузки процессора",
+ "Description[sa]": "सङ्गणकतन्त्रस्य निरीक्षकस्य विजेट् यत् कुल CPU उपयोगं दर्शयति",
+ "Description[sk]": "Miniaplikácia monitorovania systému, ktorá zobrazuje celkové využitie CPU",
+ "Description[sl]": "Gradnik sistemskega monitorja, ki prikazuje celotno rabo CPE",
+ "Description[sv]": "Grafisk systemövervakningskomponent som visar total processoranvändning",
+ "Description[ta]": "மொத்த CPU பயன்பாட்டைக் காட்டும் பிளாஸ்மாய்ட்",
+ "Description[tr]": "Toplam CPU kullanımını gösteren sistem monitörü araç takımı",
+ "Description[uk]": "Віджет нагляду за системою, який показує загальне використання процесора",
+ "Description[zh_CN]": "显示总 CPU 占用率的系统监视小部件",
+ "Description[zh_TW]": "顯示總 CPU 用量的系統監控元件",
+ "EnabledByDefault": true,
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "cpu",
+ "Id": "org.kde.plasma.systemmonitor.cpu",
+ "License": "GPL-2.0+",
+ "Name": "Total CPU Use",
+ "Name[ar]": "مجموع استخدام المعالج",
+ "Name[az]": "Ümumi MP istifadəsi",
+ "Name[be]": "Агульнае выкарыстанне працэсара",
+ "Name[bg]": "Общо използване на процесора",
+ "Name[ca@valencia]": "Ús total de CPU",
+ "Name[ca]": "Ús total de CPU",
+ "Name[cs]": "Celkové použití CPU",
+ "Name[da]": "Samlet CPU-brug",
+ "Name[de]": "Gesamt-CPU-Auslastung",
+ "Name[el]": "Συνολική χρήση ΚΜΕ",
+ "Name[en_GB]": "Total CPU Use",
+ "Name[eo]": "Suma Uzo de CPU",
+ "Name[es]": "Uso total de CPU",
+ "Name[et]": "Protsessori kogukasutus",
+ "Name[eu]": "PUZ erabileraren guztizkoa",
+ "Name[fi]": "Suorittimen kokonaiskäyttö",
+ "Name[fr]": "Utilisation globale du processeur",
+ "Name[gl]": "Uso de procesador total",
+ "Name[he]": "ניצולת מעבד כוללת",
+ "Name[hi]": "कुल सीपीयू उपयोग",
+ "Name[hu]": "Teljes processzorhasználat",
+ "Name[ia]": "Uso total de CPU",
+ "Name[id]": "Total Penggunaan CPU",
+ "Name[is]": "Heildarnotkun örgjörva",
+ "Name[it]": "Utilizzo totale CPU",
+ "Name[ja]": "全体の CPU 使用率",
+ "Name[ka]": "CPU-ის ჯამური დატვირთვა",
+ "Name[ko]": "총 CPU 사용량",
+ "Name[lt]": "Bendras procesoriaus naudojimas",
+ "Name[lv]": "Kopējā CPU noslodze",
+ "Name[ml]": "ആകെ സിപിയു ഉപയോഗം",
+ "Name[nb]": "Total prosessorbruk",
+ "Name[nl]": "Totaal CPU-gebruik",
+ "Name[nn]": "Total prosessorlast",
+ "Name[pa]": "ਕੁੱਲ CPU ਵਰਤੋ",
+ "Name[pl]": "Całkowite użycie procesora",
+ "Name[pt]": "Carga Total do CPU",
+ "Name[pt_BR]": "Uso total da CPU",
+ "Name[ro]": "Utilizare totală procesor",
+ "Name[ru]": "Общая загрузка ЦП",
+ "Name[sa]": "कुल CPU उपयोगः",
+ "Name[sk]": "Celkové využitie CPU",
+ "Name[sl]": "Celotna raba CPE",
+ "Name[sv]": "Total processoranvändning",
+ "Name[ta]": "மொத்த CPU பயன்பாட்டு",
+ "Name[tok]": "kepeken pi ilo nanpa ale",
+ "Name[tr]": "Toplam CPU Kullanımı",
+ "Name[uk]": "Загальне використання процесора",
+ "Name[vi]": "Tổng lượng dùng CPU",
+ "Name[zh_CN]": "总 CPU 使用率",
+ "Name[zh_TW]": "總 CPU 用量",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.systemmonitor"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.systemmonitor"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpucore/contents/config/faceproperties b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpucore/contents/config/faceproperties
new file mode 100644
index 0000000..7961e52
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpucore/contents/config/faceproperties
@@ -0,0 +1,10 @@
+[Config]
+chartFace=org.kde.ksysguard.barchart
+highPrioritySensorIds=["cpu/cpu.*/usage"]
+totalSensors=["cpu/all/usage"]
+
+[FaceConfig]
+rangeAuto=false
+rangeFrom=0
+rangeTo=100
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpucore/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpucore/metadata.json
new file mode 100644
index 0000000..970f4de
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.cpucore/metadata.json
@@ -0,0 +1,174 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "kde@privat.broulik.de",
+ "Name": "Kai Uwe Broulik",
+ "Name[ar]": "كاي أووي بروتيك",
+ "Name[ast]": "Kai Uwe Broulik",
+ "Name[az]": "Kai Uwe Broulik",
+ "Name[be]": "Kai Uwe Broulik",
+ "Name[bg]": "Kai Uwe Broulik",
+ "Name[ca@valencia]": "Kai Uwe Broulik",
+ "Name[ca]": "Kai Uwe Broulik",
+ "Name[cs]": "Kai Uwe Broulik",
+ "Name[da]": "Kai Uwe Broulik",
+ "Name[de]": "Kai Uwe Broulik",
+ "Name[el]": "Kai Uwe Broulik",
+ "Name[en_GB]": "Kai Uwe Broulik",
+ "Name[eo]": "Kai Uwe Broulik",
+ "Name[es]": "Kai Uwe Broulik",
+ "Name[et]": "Kai Uwe Broulik",
+ "Name[eu]": "Kai Uwe Broulik",
+ "Name[fi]": "Kai Uwe Broulik",
+ "Name[fr]": "Kai Uwe Broulik",
+ "Name[ga]": "Kai Uwe Broulik",
+ "Name[gl]": "Kai Uwe Broulik",
+ "Name[he]": "קאי אווה ברוליק",
+ "Name[hi]": "काई उवे ब्रोलिक",
+ "Name[hu]": "Kai Uwe Broulik",
+ "Name[ia]": "Kai Uwe Broulik",
+ "Name[id]": "Kai Uwe Broulik",
+ "Name[is]": "Kai Uwe Broulik",
+ "Name[it]": "Kai Uwe Broulik",
+ "Name[ja]": "Kai Uwe Broulik",
+ "Name[ka]": "კაი უვე ბროულიკი",
+ "Name[ko]": "Kai Uwe Broulik",
+ "Name[lt]": "Kai Uwe Broulik",
+ "Name[lv]": "Kai Uwe Broulik",
+ "Name[nb]": "Kai Uwe Broulik",
+ "Name[nl]": "Kai Uwe Broulik",
+ "Name[nn]": "Kai Uwe Broulik",
+ "Name[pa]": "ਕੋਈ ਉਵੇ ਬਰੋਉਲਿਕ",
+ "Name[pl]": "Kai Uwe Broulik",
+ "Name[pt]": "Kai Uwe Broulik",
+ "Name[pt_BR]": "Kai Uwe Broulik",
+ "Name[ro]": "Kai Uwe Broulik",
+ "Name[ru]": "Kai Uwe Broulik",
+ "Name[sa]": "कै उवे ब्रौलिक्",
+ "Name[sk]": "Kai Uwe Broulik",
+ "Name[sl]": "Kai Uwe Broulik",
+ "Name[sv]": "Kai Uwe Broulik",
+ "Name[ta]": "காய் ஊவே புரோலிக்",
+ "Name[tr]": "Kai Uwe Broulik",
+ "Name[uk]": "Kai Uwe Broulik",
+ "Name[vi]": "Kai Uwe Broulik",
+ "Name[zh_CN]": "Kai Uwe Broulik",
+ "Name[zh_TW]": "Kai Uwe Broulik"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Monitor%20widgets",
+ "Category": "System Information",
+ "Description": "System monitor widget that shows usage of individual CPU cores",
+ "Description[ar]": "أداة مراقبة النظام التي تعرض استخدام كل نواة من المعالج",
+ "Description[az]": "Hər prosessorun istifadəsini göstərən sistem izləyici vidjeti",
+ "Description[be]": "Віджэт сістэмнага назіральніка, які паказвае выкарыстанне ядзер працэсара паасобку",
+ "Description[bg]": "Уиджет за системен монитор, който показва използването на отделни ядра на процесора",
+ "Description[ca@valencia]": "Giny del monitor del sistema que mostra l'ús individual dels nuclis de la CPU",
+ "Description[ca]": "Giny del monitor del sistema que mostra l'ús individual dels nuclis de la CPU",
+ "Description[cs]": "Widget monitoru systému, zobrazující využití jednotlivých jader CPU",
+ "Description[da]": "Systemovervågning-widget som viser brug af hver CPU-kerne",
+ "Description[de]": "Systemmonitor-Miniprogramm, das die Auslastung einzelner CPU-Kerne anzeigt",
+ "Description[el]": "Συστατικό παρακολούθησης συστήματος που δείχνει τη χρήση των πυρήνων ΚΜΕ ξεχωριστά",
+ "Description[en_GB]": "System monitor widget that shows usage of individual CPU cores",
+ "Description[eo]": "Sistemmonitora fenestraĵo kiu montras uzadon de individuaj CPU-kernoj",
+ "Description[es]": "Elemento gráfico del monitor del sistema que muestra el uso de los núcleos individuales de la CPU",
+ "Description[eu]": "PUZeko nukleoen banakako erabilera erakusten duen sistema gainbegiratzeko trepeta",
+ "Description[fi]": "Yksittäisten järjestelmäydinten käytön näyttävä järjestelmänvalvontasovelma",
+ "Description[fr]": "Composant graphique de surveillance du système, affichant l'utilisation de chaque cœur du processeur.",
+ "Description[gl]": "Trebello de vixilancia do sistema que mostra o uso de núcleos de procesador individuais.",
+ "Description[he]": "יישומון צג מערכת שמציג ניצולת של ליבות מעבד בנפרד",
+ "Description[hu]": "Rendszermonitor elem, amely az egyes logikai processzorok használatát mutatja",
+ "Description[ia]": "Widget de supervision de systema que monstra le uso del nucleos individual",
+ "Description[id]": "Widget pemantau sistem yang menampilkan penggunaan core CPU individual",
+ "Description[is]": "Kerfisvöktunargræja sem sýnir notkun á einstökum örgjörvakjörnum",
+ "Description[it]": "Oggetto di monitoraggio del sistema che mostra l'utilizzo dei singoli core del processore",
+ "Description[ja]": "CPU の各コアの使用率を表示するウィジェット",
+ "Description[ka]": "სისტემური მონიტორის ვიჯეტი, რომელიც CPU-ის ბირთვების დატვირთვას სათითაოდ აჩვენებს",
+ "Description[ko]": "개별 CPU 코어 사용량을 표시하는 시스템 모니터 위젯",
+ "Description[lt]": "Sistemos prižiūryklės valdiklis, kuris rodo atskirų procesoriaus branduolių naudojimą",
+ "Description[lv]": "Sistēmas pārraudzības logdaļa, kas parāda atsevišķu CPU kodolu noslodzi",
+ "Description[nb]": "Systemovervåking-element som viser bruk av individuelle prosessorkjerner",
+ "Description[nl]": "Systeemmonitorwidget die gebruik toont van individuele CPU-kernen",
+ "Description[nn]": "Systemovervaking som viser bruk av einskilde prosessorkjernar",
+ "Description[pa]": "ਵੱਖ-ਵੱਖ CPU ਕੋਰਾਂ ਦੀ ਵਰਤੋਂ ਵਿਖਾਉਣ ਵਾਲਾ ਸਿਸਟਮ ਮਾਨੀਟਰ ਵਿਜੈੱਟ",
+ "Description[pl]": "Element interfejsu, który pokazuje wykorzystanie poszczególnych rdzeni procesora",
+ "Description[pt_BR]": "Widget monitor do sistema que mostra o uso individual dos núcleos da CPU",
+ "Description[ro]": "Control grafic de monitorizare a sistemului ce arată utilizarea nucleelor individuale ale procesorului",
+ "Description[ru]": "Мониторинг загрузки процессора, предоставляющий сведения об индивидуальном использовании ядер",
+ "Description[sa]": "सङ्गणकतन्त्रस्य निरीक्षकस्य विजेट् यत् व्यक्तिगत CPU कोर्स् इत्यस्य उपयोगं दर्शयति",
+ "Description[sk]": "Miniaplikácia monitorovania systému, ktorá zobrazuje využitie jednotlivých jadier",
+ "Description[sl]": "Gradnik sistemskega monitorja, ki prikazuje rabo posameznih jeder CPE",
+ "Description[sv]": "Grafisk systemövervakningskomponent som visar användning av individuella processorkärnor",
+ "Description[ta]": "தனிப்பட்ட CPU core-களின் பயன்பாட்டைக் காட்டும் பிளாஸ்மாய்ட்",
+ "Description[tr]": "Tekil CPU çekirdeklerini gösteren sistem monitörü araç takımı",
+ "Description[uk]": "Віджет нагляду за системою, який показує використання окремих ядер процесора",
+ "Description[zh_CN]": "显示单个 CPU 核心占用率的系统监视小部件",
+ "Description[zh_TW]": "顯示個別 CPU 核心用量的系統監控元件",
+ "EnabledByDefault": true,
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "ksysguardd",
+ "Id": "org.kde.plasma.systemmonitor.cpucore",
+ "License": "GPL-2.0+",
+ "Name": "Individual Core Usage",
+ "Name[ar]": "استخدام النوى الفردية",
+ "Name[az]": "MP nüvəsinin yükü",
+ "Name[be]": "Выкарыстанне ядзер працэсара",
+ "Name[bg]": "Използване на ядрата на процесора",
+ "Name[ca@valencia]": "Ús individual del nucli",
+ "Name[ca]": "Ús individual del nucli",
+ "Name[da]": "Brug af hver kerne",
+ "Name[de]": "Auslastung einzelner Prozessorkerne",
+ "Name[el]": "Ατομική χρήση πυρήνα",
+ "Name[en_GB]": "Individual Core Usage",
+ "Name[eo]": "Uzado de Individuaj Kernoj",
+ "Name[es]": "Uso de núcleos individuales",
+ "Name[et]": "Iga tuuma kasutus",
+ "Name[eu]": "Nukleoen banakako erabilera",
+ "Name[fi]": "Yksittäisten ydinten käyttö",
+ "Name[fr]": "Utilisation de chaque cœur ",
+ "Name[gl]": "Uso de núcleos individuais",
+ "Name[he]": "ניצולת לליבה בודדת",
+ "Name[hi]": "व्यक्तिगत कोर उपयोग ",
+ "Name[hu]": "Logikai processzorok használata",
+ "Name[ia]": "Uso de nucleo (core) individual",
+ "Name[id]": "Penggunaan Core Individual",
+ "Name[is]": "Notkun einstakra kjarna",
+ "Name[it]": "Utilizzo del singolo core",
+ "Name[ja]": "各コアの使用率",
+ "Name[ka]": "თითოეული ბირთვის დატვირთვა",
+ "Name[ko]": "개별 코어 사용량",
+ "Name[lt]": "Atskirų branduolių naudojimas",
+ "Name[lv]": "Atsevišķa kodola noslodze",
+ "Name[ml]": "വ്യക്തിഗത കോർ ഉപയോഗം",
+ "Name[nb]": "Individuell kjernebruk",
+ "Name[nl]": "Individueel gebruik van kernen",
+ "Name[nn]": "Einskildkjerne-bruk",
+ "Name[pa]": "ਵੱਖੋ-ਵੱਖ ਕੋਰ ਵਰਤੋਂ",
+ "Name[pl]": "Wykorzystanie na rdzeń",
+ "Name[pt]": "Carga dos Núcleos Individuais",
+ "Name[pt_BR]": "Uso individual do núcleo",
+ "Name[ro]": "Utilizare individuală nuclee",
+ "Name[ru]": "Загрузка ядер ЦП",
+ "Name[sa]": "व्यक्तिगत मूलप्रयोग",
+ "Name[sk]": "Využitie jednotlivých jadier",
+ "Name[sl]": "Poraba posameznega jedra",
+ "Name[sv]": "Användning av individuella kärnor",
+ "Name[ta]": "தனிப்பட்ட கணிப்பி பயன்பாட்டு",
+ "Name[tok]": "kepeken pi ilo nanpa wan",
+ "Name[tr]": "Tekil Çekirdek Kullanımı",
+ "Name[uk]": "Використання окремих ядер",
+ "Name[vi]": "Lượng dùng mỗi lõi riêng lẻ",
+ "Name[zh_CN]": "单个核心使用率",
+ "Name[zh_TW]": "獨立核心用量",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.systemmonitor"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.systemmonitor"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskactivity/contents/config/faceproperties b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskactivity/contents/config/faceproperties
new file mode 100644
index 0000000..694dc4f
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskactivity/contents/config/faceproperties
@@ -0,0 +1,8 @@
+[Config]
+chartFace=org.kde.ksysguard.linechart
+highPrioritySensorIds=["disk/all/write","disk/all/read"]
+
+[FaceConfig]
+rangeAuto=true
+lineChartStacked=true
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskactivity/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskactivity/metadata.json
new file mode 100644
index 0000000..baabab8
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskactivity/metadata.json
@@ -0,0 +1,181 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "mart@kde.org",
+ "Name": "Marco Martin",
+ "Name[ar]": "ماركو مارتن",
+ "Name[ast]": "Marco Martin",
+ "Name[az]": "Marco Martin",
+ "Name[be]": "Marco Martin",
+ "Name[bg]": "Марко Мартин",
+ "Name[ca@valencia]": "Marco Martin",
+ "Name[ca]": "Marco Martin",
+ "Name[cs]": "Marco Martin",
+ "Name[da]": "Marco Martin",
+ "Name[de]": "Marco Martin",
+ "Name[el]": "Marco Martin",
+ "Name[en_GB]": "Marco Martin",
+ "Name[eo]": "Marco Martin",
+ "Name[es]": "Marco Martin",
+ "Name[et]": "Marco Martin",
+ "Name[eu]": "Marco Martin",
+ "Name[fi]": "Marco Martin",
+ "Name[fr]": "Marco Martin",
+ "Name[ga]": "Marco Martin",
+ "Name[gl]": "Marco Martin",
+ "Name[he]": "מרקו מרטין",
+ "Name[hi]": "मार्को मार्टिन",
+ "Name[hu]": "Marco Martin",
+ "Name[ia]": "Marco Martin",
+ "Name[id]": "Marco Martin",
+ "Name[is]": "Marco Martin",
+ "Name[it]": "Marco Martin",
+ "Name[ja]": "Marco Martin",
+ "Name[ka]": "მაკრო მარტინი",
+ "Name[ko]": "Marco Martin",
+ "Name[lt]": "Marco Martin",
+ "Name[lv]": "Marco Martin",
+ "Name[nb]": "Marco Martin",
+ "Name[nl]": "Marco Martin",
+ "Name[nn]": "Marco Martin",
+ "Name[pa]": "ਮਾਰਕੋ ਮਾਰਟਿਨ",
+ "Name[pl]": "Marco Martin",
+ "Name[pt]": "Marco Martin",
+ "Name[pt_BR]": "Marco Martin",
+ "Name[ro]": "Marco Martin",
+ "Name[ru]": "Marco Martin",
+ "Name[sa]": "मार्को मार्टिन्",
+ "Name[sk]": "Marco Martin",
+ "Name[sl]": "Marco Martin",
+ "Name[sv]": "Marco Martin",
+ "Name[ta]": "மார்க்கோ மார்ட்டின்",
+ "Name[tr]": "Marco Martin",
+ "Name[uk]": "Marco Martin",
+ "Name[vi]": "Marco Martin",
+ "Name[zh_CN]": "Marco Martin",
+ "Name[zh_TW]": "Marco Martin"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Monitor%20widgets",
+ "Category": "System Information",
+ "Description": "An applet that monitors hard disk throughput and input/output",
+ "Description[ar]": "بُريْمج يراقب استخدام إنتاجيّة القرص الصلب ودَخْله/خَرْجه",
+ "Description[az]": "Sərt Diskdə verilənlərin ötürmələsini və giriş/çıxışını izləyən tətbiq",
+ "Description[be]": "Аплет, які назірае за прапускной здольнасцю цвёрдага дыска і аперацыямі з ім",
+ "Description[bg]": "Аплет, който следи пропускателната способност и вход/изход на твърдия диск",
+ "Description[ca@valencia]": "Una miniaplicació que controla la velocitat de transferència, així com l'entrada/eixida de les dades en el disc dur",
+ "Description[ca]": "Una miniaplicació que controla la velocitat de transferència, així com l'entrada/sortida de les dades al disc dur",
+ "Description[cs]": "Aplet, jenž monitoruje propustnost disku a vstup/výstup",
+ "Description[da]": "En applet som overvåger gennemgang og input/output for harddisken",
+ "Description[de]": "Ein Miniprogramm, das den Festplattendurchsatz und die Festplattenein- und -ausgabe überwacht",
+ "Description[el]": "Μικροεφαρμογή που εποπτεύει την ρυθμοαπόδοση του σκληρού δίσκου και την είσοδο/έξοδο",
+ "Description[en_GB]": "An applet that monitors hard disk throughput and input/output",
+ "Description[eo]": "Apleto kiu monitoras durdiskan trairon kaj enigon/eligon",
+ "Description[es]": "Una miniaplicación que monitoriza el rendimiento y la entrada/salida del disco duro",
+ "Description[et]": "Kõvaketta läbilaset ja sisendit/väljundit jälgiv aplett",
+ "Description[eu]": "Disko zurrunaren transferentzia tasa eraginkorra («throughput») eta sarrera/irteera gainbegiratzen dituen aplikaziotxo bat",
+ "Description[fi]": "Tarkkailee levyjen suoritustehoa ja siirtomäärää",
+ "Description[fr]": "Une applet surveillant le débit des disques durs et leurs entrées / sorties.",
+ "Description[gl]": "Un trebello que vixía o rendemento e a entrada e saída do disco duro.",
+ "Description[he]": "יישומונית למעקב אחר תעבורת הכונן וקלט/פלט",
+ "Description[hi]": "एक एप्लेट जो हार्ड डिस्क प्रवाह क्षमता और इनपुट/आउटपुट की निगरानी करता है",
+ "Description[hu]": "Egy kisalkalmazás, amely figyeli a merevlemez átvitelét és a bemenetet/kimenetet",
+ "Description[ia]": "Un applet que que monitora le prestation (throughput) e ingresso/egresso de disco dur",
+ "Description[id]": "Sebuah applet yang memantau lalu-lalang dan input/output hard disk",
+ "Description[is]": "Smáforrit sem fylgist með afköstum harðra diska og inntaki/úttaki",
+ "Description[it]": "Un'applet che controlla le prestazioni e l'uso del disco fisso",
+ "Description[ja]": "ハードディスクのスループットと入力/出力を監視するウィジェット",
+ "Description[ka]": "აპლეტი, რომელიც მყარი დისკის გამტარობასა და შეტანა/გამოტანას უყურებს",
+ "Description[ko]": "하드 디스크 대역폭 및 I/O 상태를 보여 주는 애플릿",
+ "Description[lt]": "Programėlė, kuri stebi disko apkrovą ir įvedimą/išvedimą",
+ "Description[lv]": "Sīklietotne, kas pārrauga cietā diska caurlaidspēju un ievadi/izvadi",
+ "Description[nb]": "Skjermelement som overvåker dataflyt til og fra harddisk",
+ "Description[nl]": "Een applet die de activiteit van de harde schijf volgt",
+ "Description[nn]": "Skjermelement som overvaker dataflyt til og frå harddisk",
+ "Description[pa]": "ਹਾਰਡ ਡਿਸਕ ਥਰੂਪੁੱਟ ਅਤੇ ਇੰਪੁੱਟ/ਆਉਟਪੁੱਟ ਦੀ ਨਿਗਰਾਨੀ ਲਈ ਐਪਲਿਟ",
+ "Description[pl]": "Monitoruje przepustowość WE/WY dysku twardego",
+ "Description[pt]": "Uma 'applet' que vigia o rendimento e o fluxo de entrada-saída do disco",
+ "Description[pt_BR]": "Monitora a taxa de transferência e entrada/saída do disco rígido",
+ "Description[ro]": "Miniaplicație ce monitorizează traficul de intrare și cel de ieșire pentru discul dur",
+ "Description[ru]": "Мониторинг пропускной способности и процессов ввода/вывода жёстких дисков",
+ "Description[sa]": "एकं एप्लेट् यत् हार्डडिस्क सम्पादनक्षमता तथा निवेशः/निर्गमः निरीक्षते",
+ "Description[sk]": "Applet, ktorý monitoruje priepustnosť pevného disku a vstup/výstup",
+ "Description[sl]": "Programček, ki nadzoruje prepustnost in vhod/izhod trdega diska",
+ "Description[sv]": "Ett miniprogram som övervakar hårddiskprestanda samt in- och utmatning",
+ "Description[ta]": "வட்டின் உள்ளீடு/வெளியீடு மற்றும் செயல் வீதம் ஆகியவற்றை கண்காணிக்கும் பிளாஸ்மாய்ட்",
+ "Description[tr]": "Sabit disk girişini/çıkışını izleyen bir uygulamacık",
+ "Description[uk]": "Аплет, який стежить за даними, які записуються на жорсткий диск та читаються з жорсткого диска",
+ "Description[vi]": "Một tiểu ứng dụng giám sát vào/ra và thông lượng của đĩa cứng",
+ "Description[zh_CN]": "监视硬盘吞吐量和输入输出情况的小程序",
+ "Description[zh_TW]": "監視硬碟效能與 I/O 的小程式",
+ "EnabledByDefault": true,
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "drive-harddisk",
+ "Id": "org.kde.plasma.systemmonitor.diskactivity",
+ "License": "GPL-2.0+",
+ "Name": "Hard Disk Activity",
+ "Name[ar]": "نشاط القرص الصلب",
+ "Name[az]": "Sərt Disk istifadəsi",
+ "Name[be]": "Актыўнасць цвёрдага дыска",
+ "Name[bg]": "Активност на твърдия диск",
+ "Name[ca@valencia]": "Activitat del disc dur",
+ "Name[ca]": "Activitat del disc dur",
+ "Name[cs]": "Aktivita pevného disku",
+ "Name[da]": "Harddisk-aktivitet",
+ "Name[de]": "Festplattenaktivität",
+ "Name[el]": "Δραστηριότητα σκληρού δίσκου",
+ "Name[en_GB]": "Hard Disk Activity",
+ "Name[eo]": "Malmoldiska Aktiveco",
+ "Name[es]": "Actividad del disco duro",
+ "Name[et]": "Kõvaketta tegevus",
+ "Name[eu]": "Disko zurruneko jarduera",
+ "Name[fi]": "Kiintolevyn toiminta",
+ "Name[fr]": "Activité des disques durs",
+ "Name[gl]": "Actividade do disco duro",
+ "Name[he]": "פעילות כונן קשיח",
+ "Name[hi]": "हार्ड डिस्क गतिविधि",
+ "Name[hsb]": "Monitor, kiž pokazuje aktiwitu kruteje tačele",
+ "Name[hu]": "Merevlemez-aktivitás",
+ "Name[ia]": "Activitate del disco dur",
+ "Name[id]": "Aktivitas Hard Disk",
+ "Name[is]": "Virkni harðdiska",
+ "Name[it]": "Attività disco fisso",
+ "Name[ja]": "ディスクの状態",
+ "Name[ka]": "მყარი დისკის აქტივობა",
+ "Name[ko]": "하드 디스크 활동",
+ "Name[lt]": "Standžiojo disko veikla",
+ "Name[lv]": "Cietā diska noslodze",
+ "Name[ml]": "ഹാർഡ് ഡിസ്ക് പ്രവർത്തനം",
+ "Name[nb]": "Harddiskaktivitet",
+ "Name[nl]": "Activiteit van de vaste schijf",
+ "Name[nn]": "Harddiskaktivitet",
+ "Name[pa]": "ਹਾਰਡ ਡਿਸਕ ਸਰਗਰਮੀ",
+ "Name[pl]": "Ruch na dysku twardym",
+ "Name[pt]": "Actividade do Disco Rígido",
+ "Name[pt_BR]": "Atividade do disco rígido",
+ "Name[ro]": "Activitate disc dur",
+ "Name[ru]": "Загрузка дисковой подсистемы",
+ "Name[sa]": "हार्ड् डिस्क् गतिविधि",
+ "Name[sk]": "Aktivita pevného disku",
+ "Name[sl]": "Nadzornik aktivnosti trdega diska",
+ "Name[sv]": "Hårddiskaktivitet",
+ "Name[ta]": "வட்டு செயல்பாட்டு",
+ "Name[tg]": "Фаъолияти диски компютерӣ",
+ "Name[tok]": "pali poki",
+ "Name[tr]": "Sabit Disk Etkinliği",
+ "Name[uk]": "Робота із жорстким диском",
+ "Name[vi]": "Hoạt động của đĩa cứng",
+ "Name[zh_CN]": "磁盘活动",
+ "Name[zh_TW]": "硬碟活動",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.systemmonitor"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.systemmonitor"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskusage/contents/config/faceproperties b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskusage/contents/config/faceproperties
new file mode 100644
index 0000000..2c60a80
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskusage/contents/config/faceproperties
@@ -0,0 +1,11 @@
+[Config]
+chartFace=org.kde.ksysguard.horizontalbars
+highPrioritySensorIds=["disk/.*/usedPercent"]
+totalSensors=["disk/all/usedPercent"]
+lowPrioritySensorIds=["disk/all/total"]
+
+[FaceConfig]
+rangeAuto=true
+rangeFrom=0
+rangeTo=100
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskusage/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskusage/metadata.json
new file mode 100644
index 0000000..9df28b1
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.diskusage/metadata.json
@@ -0,0 +1,178 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "mart@kde.org",
+ "Name": "Marco Martin",
+ "Name[ar]": "ماركو مارتن",
+ "Name[ast]": "Marco Martin",
+ "Name[az]": "Marco Martin",
+ "Name[be]": "Marco Martin",
+ "Name[bg]": "Марко Мартин",
+ "Name[ca@valencia]": "Marco Martin",
+ "Name[ca]": "Marco Martin",
+ "Name[cs]": "Marco Martin",
+ "Name[da]": "Marco Martin",
+ "Name[de]": "Marco Martin",
+ "Name[el]": "Marco Martin",
+ "Name[en_GB]": "Marco Martin",
+ "Name[eo]": "Marco Martin",
+ "Name[es]": "Marco Martin",
+ "Name[et]": "Marco Martin",
+ "Name[eu]": "Marco Martin",
+ "Name[fi]": "Marco Martin",
+ "Name[fr]": "Marco Martin",
+ "Name[ga]": "Marco Martin",
+ "Name[gl]": "Marco Martin",
+ "Name[he]": "מרקו מרטין",
+ "Name[hi]": "मार्को मार्टिन",
+ "Name[hu]": "Marco Martin",
+ "Name[ia]": "Marco Martin",
+ "Name[id]": "Marco Martin",
+ "Name[is]": "Marco Martin",
+ "Name[it]": "Marco Martin",
+ "Name[ja]": "Marco Martin",
+ "Name[ka]": "მაკრო მარტინი",
+ "Name[ko]": "Marco Martin",
+ "Name[lt]": "Marco Martin",
+ "Name[lv]": "Marco Martin",
+ "Name[nb]": "Marco Martin",
+ "Name[nl]": "Marco Martin",
+ "Name[nn]": "Marco Martin",
+ "Name[pa]": "ਮਾਰਕੋ ਮਾਰਟਿਨ",
+ "Name[pl]": "Marco Martin",
+ "Name[pt]": "Marco Martin",
+ "Name[pt_BR]": "Marco Martin",
+ "Name[ro]": "Marco Martin",
+ "Name[ru]": "Marco Martin",
+ "Name[sa]": "मार्को मार्टिन्",
+ "Name[sk]": "Marco Martin",
+ "Name[sl]": "Marco Martin",
+ "Name[sv]": "Marco Martin",
+ "Name[ta]": "மார்க்கோ மார்ட்டின்",
+ "Name[tr]": "Marco Martin",
+ "Name[uk]": "Marco Martin",
+ "Name[vi]": "Marco Martin",
+ "Name[zh_CN]": "Marco Martin",
+ "Name[zh_TW]": "Marco Martin"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Monitor%20widgets",
+ "Category": "System Information",
+ "Description": "System monitor widget that shows the usage of the root partition",
+ "Description[ar]": "أداة مراقبة النظام التي تعرض استخدام قسم الجذر",
+ "Description[az]": "Kök bölməsinin istifadəsini göstərən sistem izləyici vidjeti",
+ "Description[be]": "Віджэт сістэмнага назіральніка, які паказвае выкарыстанне каранёвага раздзела",
+ "Description[bg]": "Уиджет за системен монитор, който показва използването на основния дял",
+ "Description[ca@valencia]": "Giny del monitor del sistema que mostra l'ús de la partició arrel",
+ "Description[ca]": "Giny del monitor del sistema que mostra l'ús de la partició arrel",
+ "Description[cs]": "Widget monitoru systému, zobrazující celkové využití kořenového oddílu",
+ "Description[da]": "Systemovervågning-widget som viser brug af rod-partitionen",
+ "Description[de]": "Systemmonitor-Miniprogramm, das die Belegung der Systempartition anzeigt",
+ "Description[el]": "Συστατικό παρακολούθησης συστήματος που δείχνει τη χρήση της ριζικής κατάτμησης",
+ "Description[en_GB]": "System monitor widget that shows the usage of the root partition",
+ "Description[eo]": "Sistemmonitora fenestraĵo kiu montras la uzadon de la radika sekcio",
+ "Description[es]": "Elemento gráfico del monitor del sistema que muestra el uso de la partición raíz",
+ "Description[eu]": "Erro partizioaren erabilera erakusten duen sistema gainbegiratzeko trepeta",
+ "Description[fi]": "Juuriosion käyttöasteen näyttävä järjestelmänvalvontasovelma",
+ "Description[fr]": "Composant graphique de surveillance du système, affichant l'utilisation de la partition « Système ».",
+ "Description[gl]": "Trebello de vixilancia do sistema que mostra o uso da partición raíz.",
+ "Description[he]": "יישומון צג מערכת שמציג את ניצולת מחיצת העל",
+ "Description[hu]": "Rendszermonitor elem, amely a root partíció használatát mutatja",
+ "Description[ia]": "Widget de supervision de systema que monstra le uso del partition de root (radice)",
+ "Description[id]": "Widget pemantau sistem yang menampilkan penggunaan partisi root",
+ "Description[is]": "Kerfisvöktunargræja sem sýnir notkunina á rótarsneiðinni",
+ "Description[it]": "Oggetto di monitoraggio del sistema che mostra l'utilizzo della partizione radice",
+ "Description[ja]": "root パーティションの使用率を表示するウィジェット",
+ "Description[ka]": "სისტემური მონიტორის ვიჯეტი, რომელიც საწყისი დანაყოფის გამოყენებას გაჩვენებთ",
+ "Description[ko]": "루트 파티션 사용량을 표시하는 시스템 모니터 위젯",
+ "Description[lt]": "Sistemos prižiūryklės valdiklis, kuris rodo šaknies skaidinio naudojimą",
+ "Description[lv]": "Sistēmas pārraudzības logdaļa, kas parāda saknes nodalījuma lietojumu",
+ "Description[nb]": "Systemovervåking-element som viser bruk av rotpartisjonen",
+ "Description[nl]": "Systeemmonitorwidget die het totale gebruik toont van de root-partitie",
+ "Description[nn]": "Systemovervaking som viser bruk av rotpartisjonen",
+ "Description[pa]": "ਰੂਟ ਪਾਰਟੀਸ਼ਨ ਦੀ ਵਰਤੋਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦਿਖਾਉਣ ਵਾਲਾ ਸਿਸਟਮ ਮਾਨੀਟਰ ਵਿਜੈਟ ",
+ "Description[pl]": "Element interfejsu, który pokazuje wykorzystanie głównej partycji",
+ "Description[pt_BR]": "Widget monitor do sistema que mostra o uso da partição raiz",
+ "Description[ro]": "Control grafic de monitorizare a sistemului ce arată utilizarea partiției root",
+ "Description[ru]": "Мониторинг использования дискового пространства корневым разделом",
+ "Description[sa]": "सङ्गणकतन्त्रस्य निरीक्षकस्य विजेट् यत् मूलविभाजनस्य उपयोगं दर्शयति",
+ "Description[sk]": "Miniaplikácia monitorovania systému, ktorá zobrazuje využitie koreňovej partície",
+ "Description[sl]": "Gradnik sistemskega monitorja, ki prikazuje rabo korenske particije",
+ "Description[sv]": "Grafisk systemövervakningskomponent som visar användning av rotpartitionen",
+ "Description[ta]": "ரூட் வகிர்வின் பயன்பாட்டைக் காட்டும் பிளாஸ்மாய்ட்",
+ "Description[tr]": "Kök bölüntünün kullanımını gösteren sistem monitörü araç takımı",
+ "Description[uk]": "Віджет нагляду за системою, який показує використання кореневого розділу",
+ "Description[zh_CN]": "显示根分区占用率的系统监视小部件",
+ "Description[zh_TW]": "顯示 root 分割區用量的系統監控元件",
+ "EnabledByDefault": true,
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "cpu",
+ "Id": "org.kde.plasma.systemmonitor.diskusage",
+ "License": "GPL-2.0+",
+ "Name": "Disk Usage",
+ "Name[ar]": "استخدام القرص",
+ "Name[az]": "Disk sahəsnin İstifadəsi",
+ "Name[be]": "Выкарыстанне дыска",
+ "Name[bg]": "Използване на диска",
+ "Name[ca@valencia]": "Ús del disc",
+ "Name[ca]": "Ús del disc",
+ "Name[cs]": "Zaplnění Disku",
+ "Name[da]": "Diskforbrug",
+ "Name[de]": "Datenträgerbelegung",
+ "Name[el]": "Χρήση δίσκου",
+ "Name[en_GB]": "Disk Usage",
+ "Name[eo]": "Disk-Uzado",
+ "Name[es]": "Uso del disco duro",
+ "Name[et]": "Kettakasutus",
+ "Name[eu]": "Diskoaren erabilera",
+ "Name[fi]": "Levyn käyttö",
+ "Name[fr]": "Utilisation des disques",
+ "Name[ga]": "Úsáid Diosca",
+ "Name[gl]": "Uso de disco",
+ "Name[he]": "ניצולת כונן",
+ "Name[hi]": "डिस्क उपयोग",
+ "Name[hsb]": "Wužiwanje tačele",
+ "Name[hu]": "Lemezhasználat",
+ "Name[ia]": "Uso de disco",
+ "Name[id]": "Penggunaan Disk",
+ "Name[is]": "Notkun diska",
+ "Name[it]": "Utilizzo disco",
+ "Name[ja]": "ディスク使用率",
+ "Name[ka]": "დისკის გამოყენება",
+ "Name[ko]": "디스크 사용량",
+ "Name[lt]": "Disko naudojimas",
+ "Name[lv]": "Diska noslodze",
+ "Name[ml]": "ഡിസ്ക് ഉപയോഗം",
+ "Name[nb]": "Diskbruk",
+ "Name[nl]": "Schijfgebruik",
+ "Name[nn]": "Diskbruk",
+ "Name[pa]": "ਡਿਸਕ ਥਾਂ ਦੀ ਵਰਤੋਂ",
+ "Name[pl]": "Wykorzystanie dysku",
+ "Name[pt]": "Utilização do Disco",
+ "Name[pt_BR]": "Uso do disco",
+ "Name[ro]": "Utilizare disc",
+ "Name[ru]": "Использование дискового пространства",
+ "Name[sa]": "डिस्कस्य उपयोगः",
+ "Name[sk]": "Využitie disku",
+ "Name[sl]": "Uporaba diska",
+ "Name[sv]": "Diskanvändning",
+ "Name[ta]": "வட்டு பயன்பாட்டு",
+ "Name[tg]": "Истифодабарии диск",
+ "Name[tok]": "kepeken poki",
+ "Name[tr]": "Disk Kullanımı",
+ "Name[uk]": "Використання диска",
+ "Name[vi]": "Lượng dùng đĩa",
+ "Name[zh_CN]": "磁盘使用率",
+ "Name[zh_TW]": "磁碟用量",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.systemmonitor"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.systemmonitor"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.memory/contents/config/faceproperties b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.memory/contents/config/faceproperties
new file mode 100644
index 0000000..3bf41bb
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.memory/contents/config/faceproperties
@@ -0,0 +1,11 @@
+[Config]
+chartFace=org.kde.ksysguard.piechart
+highPrioritySensorIds=["memory/physical/used"]
+totalSensors=["memory/physical/usedPercent"]
+lowPrioritySensorIds=["memory/physical/total"]
+
+[FaceConfig]
+rangeAuto=true
+rangeFrom=0
+rangeTo=100
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.memory/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.memory/metadata.json
new file mode 100644
index 0000000..555ab28
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.memory/metadata.json
@@ -0,0 +1,178 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "kde@privat.broulik.de",
+ "Name": "Kai Uwe Broulik",
+ "Name[ar]": "كاي أووي بروتيك",
+ "Name[ast]": "Kai Uwe Broulik",
+ "Name[az]": "Kai Uwe Broulik",
+ "Name[be]": "Kai Uwe Broulik",
+ "Name[bg]": "Kai Uwe Broulik",
+ "Name[ca@valencia]": "Kai Uwe Broulik",
+ "Name[ca]": "Kai Uwe Broulik",
+ "Name[cs]": "Kai Uwe Broulik",
+ "Name[da]": "Kai Uwe Broulik",
+ "Name[de]": "Kai Uwe Broulik",
+ "Name[el]": "Kai Uwe Broulik",
+ "Name[en_GB]": "Kai Uwe Broulik",
+ "Name[eo]": "Kai Uwe Broulik",
+ "Name[es]": "Kai Uwe Broulik",
+ "Name[et]": "Kai Uwe Broulik",
+ "Name[eu]": "Kai Uwe Broulik",
+ "Name[fi]": "Kai Uwe Broulik",
+ "Name[fr]": "Kai Uwe Broulik",
+ "Name[ga]": "Kai Uwe Broulik",
+ "Name[gl]": "Kai Uwe Broulik",
+ "Name[he]": "קאי אווה ברוליק",
+ "Name[hi]": "काई उवे ब्रोलिक",
+ "Name[hu]": "Kai Uwe Broulik",
+ "Name[ia]": "Kai Uwe Broulik",
+ "Name[id]": "Kai Uwe Broulik",
+ "Name[is]": "Kai Uwe Broulik",
+ "Name[it]": "Kai Uwe Broulik",
+ "Name[ja]": "Kai Uwe Broulik",
+ "Name[ka]": "კაი უვე ბროულიკი",
+ "Name[ko]": "Kai Uwe Broulik",
+ "Name[lt]": "Kai Uwe Broulik",
+ "Name[lv]": "Kai Uwe Broulik",
+ "Name[nb]": "Kai Uwe Broulik",
+ "Name[nl]": "Kai Uwe Broulik",
+ "Name[nn]": "Kai Uwe Broulik",
+ "Name[pa]": "ਕੋਈ ਉਵੇ ਬਰੋਉਲਿਕ",
+ "Name[pl]": "Kai Uwe Broulik",
+ "Name[pt]": "Kai Uwe Broulik",
+ "Name[pt_BR]": "Kai Uwe Broulik",
+ "Name[ro]": "Kai Uwe Broulik",
+ "Name[ru]": "Kai Uwe Broulik",
+ "Name[sa]": "कै उवे ब्रौलिक्",
+ "Name[sk]": "Kai Uwe Broulik",
+ "Name[sl]": "Kai Uwe Broulik",
+ "Name[sv]": "Kai Uwe Broulik",
+ "Name[ta]": "காய் ஊவே புரோலிக்",
+ "Name[tr]": "Kai Uwe Broulik",
+ "Name[uk]": "Kai Uwe Broulik",
+ "Name[vi]": "Kai Uwe Broulik",
+ "Name[zh_CN]": "Kai Uwe Broulik",
+ "Name[zh_TW]": "Kai Uwe Broulik"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Monitor%20widgets",
+ "Category": "System Information",
+ "Description": "System monitor widget that shows physical memory usage",
+ "Description[ar]": "أداة مراقبة النظام التي تعرض استخدام الذاكرة الفعلية",
+ "Description[az]": "Fiziki yaddaşın istifadəsini gösərən sistem izləyici vidjeti",
+ "Description[be]": "Віджэт сістэмнага назіральніка, які паказвае выкарыстанне фізічнай памяці",
+ "Description[bg]": "Уиджет за системен монитор, което показва използването на физическа памет",
+ "Description[ca@valencia]": "Giny del monitor del sistema que mostra l'ús de la memòria física",
+ "Description[ca]": "Giny del monitor del sistema que mostra l'ús de la memòria física",
+ "Description[cs]": "Widget monitoru systému, zobrazující celkové využití paměti",
+ "Description[da]": "Systemovervågning-widget som viser brug af den fysiske hukommelse",
+ "Description[de]": "Systemmonitor-Miniprogramm, das die Auslastung des Arbeitsspeichers anzeigt",
+ "Description[el]": "Συστατικό παρακολούθησης συστήματος που δείχνει τη χρήση φυσικής μνήμης",
+ "Description[en_GB]": "System monitor widget that shows physical memory usage",
+ "Description[eo]": "Sistemmonitora fenestraĵo kiu montras fizikan memoruzon",
+ "Description[es]": "Elemento gráfico del monitor del sistema que muestra el uso de la memoria física",
+ "Description[eu]": "Memoria fisikoaren erabilera erakusten duen sistema gainbegiratzeko trepeta",
+ "Description[fi]": "Fyysisen muistin käytön näyttävä järjestelmänvalvontasovelma",
+ "Description[fr]": "Composant graphique de surveillance du système, affichant l'utilisation de la mémoire physique.",
+ "Description[gl]": "Trebello de vixilancia do sistema que mostra o uso da memoria física.",
+ "Description[he]": "יישומון צג מערכת שמציג את ניצולת הזיכרון הפיזי",
+ "Description[hu]": "A fizikai memória használati statisztikáit megjelenítő elem",
+ "Description[ia]": "Widget de supervision de systema que monstra le uso de memoria physic",
+ "Description[id]": "Widget pemantau sistem yang menampilkan penggunaan memori fisik",
+ "Description[is]": "Kerfisvöktunargræja sem sýnir notkun á innra minninu",
+ "Description[it]": "Oggetto di monitoraggio del sistema che mostra l'utilizzo della memoria fisica",
+ "Description[ja]": "物理メモリの使用率を表示するウィジェット",
+ "Description[ka]": "სისტემური მონიტორის ვიჯეტი, რომელიც ფიზიკური მეხსიერების გამოყენებას აჩვენებს",
+ "Description[ko]": "물리적 메모리 사용량을 표시하는 시스템 모니터 위젯",
+ "Description[lt]": "Sistemos prižiūryklės valdiklis, kuris rodo fizinės atminties naudojimą",
+ "Description[lv]": "Sistēmas pārraudzības logdaļa, kas parāda fiziskās atmiņas lietojumu",
+ "Description[nb]": "Systemovervåking-element som viser bruk av fysisk minne",
+ "Description[nl]": "Systeemmonitorwidget die het gebruik van fysiek geheugen toont",
+ "Description[nn]": "Systemovervaking som viser bruk av fysisk minne",
+ "Description[pa]": "ਕੁੱਲ ਫਿਜ਼ੀਕਲ ਮੈਮੋਰੀ ਵਰਤੋਂ ਦਿਖਾਉਣ ਵਾਲਾ ਸਿਸਟਮ ਮਾਨੀਟਰ ਵਿਜੈੱਟ",
+ "Description[pl]": "Element interfejsu, który pokazuje wykorzystanie pamięci fizycznej",
+ "Description[pt_BR]": "Widget monitor do sistema que mostra o uso da memória física",
+ "Description[ro]": "Control grafic de monitorizare a sistemului ce arată utilizarea memoriei fizice",
+ "Description[ru]": "Мониторинг использования физической памяти",
+ "Description[sa]": "सङ्गणकतन्त्रस्य निरीक्षकस्य विजेट् यत् भौतिकस्मृतिप्रयोगं दर्शयति",
+ "Description[sk]": "Miniaplikácia monitorovania systému, ktorá zobrazuje využitie fyzickej pamäte",
+ "Description[sl]": "Gradnik sistemskega monitorja, ki prikazuje rabo fizičnega pomnilnika",
+ "Description[sv]": "Grafisk systemövervakningskomponent som fysisk minnesanvändning",
+ "Description[ta]": "நினைவகத்தின் பயன்பாட்டைக் காட்டும் பிளாஸ்மாய்ட்",
+ "Description[tr]": "Fiziksel bellek kullanımını gösteren sistem monitörü araç takımı",
+ "Description[uk]": "Віджет нагляду за системою, який показує використання фізичної пам'яті",
+ "Description[zh_CN]": "显示物理内存占用率的系统监视小部件",
+ "Description[zh_TW]": "顯示實體記憶體用量的系統監控元件",
+ "EnabledByDefault": true,
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "ksysguardd",
+ "Id": "org.kde.plasma.systemmonitor.memory",
+ "License": "GPL-2.0+",
+ "Name": "Memory Usage",
+ "Name[ar]": "استخدام الذاكرة",
+ "Name[ast]": "Usu de la memoria",
+ "Name[az]": "Yaddaş İstifadəsi",
+ "Name[be]": "Выкарыстанне памяці",
+ "Name[bg]": "Използване на паметта",
+ "Name[ca@valencia]": "Ús de memòria",
+ "Name[ca]": "Ús de memòria",
+ "Name[cs]": "Spotřeba paměti",
+ "Name[da]": "Hukommelsesforbrug",
+ "Name[de]": "Speicherbelegung",
+ "Name[el]": "Χρήση μνήμης",
+ "Name[en_GB]": "Memory Usage",
+ "Name[eo]": "Memor-Uzado",
+ "Name[es]": "Uso de memoria",
+ "Name[et]": "Mälukasutus",
+ "Name[eu]": "Memoria erabilera",
+ "Name[fi]": "Muistin käyttö",
+ "Name[fr]": "Utilisation de la mémoire",
+ "Name[gl]": "Uso de memoria",
+ "Name[he]": "ניצולת זיכרון",
+ "Name[hi]": "मेमोरी उपयोग",
+ "Name[hsb]": "Wužiwanje pomjatka",
+ "Name[hu]": "Memóriahasználat",
+ "Name[ia]": "Uso de Memoria",
+ "Name[id]": "Penggunaan Memori",
+ "Name[is]": "Minnisnotkun",
+ "Name[it]": "Utilizzo memoria",
+ "Name[ja]": "メモリ使用率",
+ "Name[ka]": "მეხსიერების გამოყენება",
+ "Name[ko]": "메모리 사용량",
+ "Name[lt]": "Atminties naudojimas",
+ "Name[lv]": "Atmiņas lietojums",
+ "Name[ml]": "മെമ്മറി ഉപയോഗം",
+ "Name[nb]": "Minnebruk",
+ "Name[nl]": "Geheugengebruik",
+ "Name[nn]": "Minnebruk",
+ "Name[pa]": "ਮੈਮੋਰੀ ਦੀ ਵਰਤੋਂ",
+ "Name[pl]": "Wykorzystanie pamięci",
+ "Name[pt]": "Utilização da Memória",
+ "Name[pt_BR]": "Uso da memória",
+ "Name[ro]": "Utilizare memorie",
+ "Name[ru]": "Использование памяти",
+ "Name[sa]": "स्मृतिप्रयोगः",
+ "Name[sk]": "Využitie pamäte",
+ "Name[sl]": "Raba pomnilnika",
+ "Name[sv]": "Minnesanvändning",
+ "Name[ta]": "நினைவு பயன்பாட்டு",
+ "Name[tg]": "Истифодабарии ҳофиза",
+ "Name[tok]": "kepeken sona",
+ "Name[tr]": "Bellek Kullanımı",
+ "Name[uk]": "Використання пам'яті",
+ "Name[vi]": "Lượng dùng bộ nhớ",
+ "Name[zh_CN]": "内存使用率",
+ "Name[zh_TW]": "記憶體用量",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.systemmonitor"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.systemmonitor"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.net/contents/config/faceproperties b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.net/contents/config/faceproperties
new file mode 100644
index 0000000..363130e
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.net/contents/config/faceproperties
@@ -0,0 +1,7 @@
+[Config]
+chartFace=org.kde.ksysguard.linechart
+highPrioritySensorIds=["network/all/download","network/all/upload"]
+
+[FaceConfig]
+lineChartSmooth=true
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.net/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.net/metadata.json
new file mode 100644
index 0000000..696eb06
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor.net/metadata.json
@@ -0,0 +1,169 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "mart@kde.org",
+ "Name": "Marco Martin",
+ "Name[ar]": "ماركو مارتن",
+ "Name[ast]": "Marco Martin",
+ "Name[az]": "Marco Martin",
+ "Name[be]": "Marco Martin",
+ "Name[bg]": "Марко Мартин",
+ "Name[ca@valencia]": "Marco Martin",
+ "Name[ca]": "Marco Martin",
+ "Name[cs]": "Marco Martin",
+ "Name[da]": "Marco Martin",
+ "Name[de]": "Marco Martin",
+ "Name[el]": "Marco Martin",
+ "Name[en_GB]": "Marco Martin",
+ "Name[eo]": "Marco Martin",
+ "Name[es]": "Marco Martin",
+ "Name[et]": "Marco Martin",
+ "Name[eu]": "Marco Martin",
+ "Name[fi]": "Marco Martin",
+ "Name[fr]": "Marco Martin",
+ "Name[ga]": "Marco Martin",
+ "Name[gl]": "Marco Martin",
+ "Name[he]": "מרקו מרטין",
+ "Name[hi]": "मार्को मार्टिन",
+ "Name[hu]": "Marco Martin",
+ "Name[ia]": "Marco Martin",
+ "Name[id]": "Marco Martin",
+ "Name[is]": "Marco Martin",
+ "Name[it]": "Marco Martin",
+ "Name[ja]": "Marco Martin",
+ "Name[ka]": "მაკრო მარტინი",
+ "Name[ko]": "Marco Martin",
+ "Name[lt]": "Marco Martin",
+ "Name[lv]": "Marco Martin",
+ "Name[nb]": "Marco Martin",
+ "Name[nl]": "Marco Martin",
+ "Name[nn]": "Marco Martin",
+ "Name[pa]": "ਮਾਰਕੋ ਮਾਰਟਿਨ",
+ "Name[pl]": "Marco Martin",
+ "Name[pt]": "Marco Martin",
+ "Name[pt_BR]": "Marco Martin",
+ "Name[ro]": "Marco Martin",
+ "Name[ru]": "Marco Martin",
+ "Name[sa]": "मार्को मार्टिन्",
+ "Name[sk]": "Marco Martin",
+ "Name[sl]": "Marco Martin",
+ "Name[sv]": "Marco Martin",
+ "Name[ta]": "மார்க்கோ மார்ட்டின்",
+ "Name[tr]": "Marco Martin",
+ "Name[uk]": "Marco Martin",
+ "Name[vi]": "Marco Martin",
+ "Name[zh_CN]": "Marco Martin",
+ "Name[zh_TW]": "Marco Martin"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Monitor%20widgets",
+ "Category": "System Information",
+ "Description": "System monitor widget that shows the download and upload data rate",
+ "Description[ar]": "أداة مراقبة النظام التي تعرض سرعة تنزيل ورفع البيانات",
+ "Description[az]": "Verilənlərin endirmə və yükləmə sürətini göstərən sistem izləyici vidjeti",
+ "Description[be]": "Віджэт сістэмнага назіральніка, які паказвае хуткасць спампоўвання і запампоўвання даных",
+ "Description[bg]": "Уиджет за системен монитор, който показва скоростта на изтегляне и качване на данни",
+ "Description[ca@valencia]": "Giny del monitor del sistema que mostra la velocitat de baixada i pujada de les dades",
+ "Description[ca]": "Giny del monitor del sistema que mostra la velocitat de baixada i pujada de les dades",
+ "Description[cs]": "Widget monitoru systému, zobrazující přenosovou rychlost stahování a odesílání",
+ "Description[da]": "Systemovervågning-widget som viser download- og uploadhastighed",
+ "Description[de]": "Systemmonitor-Miniprogramm, das die Download- und Upload-Datenrate anzeigt",
+ "Description[el]": "Συστατικό παρακολούθησης συστήματος που δείχνει το ρυθμό λήψης και μεταφόρτωσης δεδομένων",
+ "Description[en_GB]": "System monitor widget that shows the download and upload data rate",
+ "Description[eo]": "Sistemmonitora fenestraĵo kiu montras la elŝutan kaj alŝutan datumrapidecon",
+ "Description[es]": "Elemento gráfico del monitor del sistema que muestra las velocidades de subida y bajada de datos",
+ "Description[eu]": "Zama-jaiste eta -igotze datuen emaria erakusten duen sistema gainbegiratzeko trepeta",
+ "Description[fi]": "Lataus- ja lähetysnopeuden näyttävä järjestelmänvalvontasovelma",
+ "Description[fr]": "Composant graphique de surveillance du système, affichant le débit pour les envois et les téléchargements de données.",
+ "Description[gl]": "Trebello de vixilancia do sistema que amosa a velocidade de descarga e envío de datos.",
+ "Description[he]": "יישומון צג מערכת שמציג את קצב ההורדה וההעלאה",
+ "Description[hu]": "A le- és feltöltési sebességet megjelenítő elem",
+ "Description[ia]": "Widget de supervision de systema que monstra le velocitate de discargar e incargar datos",
+ "Description[id]": "Widget pemantau sistem yang menampilkan laju data unggah dan unduh",
+ "Description[is]": "Kerfisvöktunargræja sem sýnir gagnahraða fyrir sóttar skrár og upphleðslur",
+ "Description[it]": "Oggetto di monitoraggio del sistema che mostra la velocità di ricezione e invio dei dati",
+ "Description[ja]": "ダウンロード/アップロード速度を表示するウィジェット",
+ "Description[ka]": "სისტემური მონიტორის ვიჯეტი, რომელიც გადმოწერისა და ატვირთვის სიჩქარეს გაჩვენებთ",
+ "Description[ko]": "데이터 다운로드 및 업로드 전송률을 표시하는 시스템 모니터 위젯",
+ "Description[lt]": "Sistemos prižiūryklės valdiklis, kuris rodo duomenų atsiuntimo ir išsiuntimo spartą",
+ "Description[lv]": "Sistēmas pārraudzības logdaļa, kas parāda datu lejupielādes un augšupielādes ātrumu",
+ "Description[nb]": "Systemovervåking-element som viser ned- og opplastingshastighet",
+ "Description[nl]": "Systeemmonitorwidget die gegevenssnelheid van down- en uploaden toont",
+ "Description[nn]": "Systemovervaking som viser ned- og opplastingsratar",
+ "Description[pa]": "ਡਾਊਨਲੋਡ ਅਤੇ ਅੱਪਲੋਡ ਡਾਟਾ ਦਰ ਵਿਖਾਉਣ ਵਾਲਾ ਸਿਸਟਮ ਮਾਨੀਟਰ ਵਿਜੈੱਟ",
+ "Description[pl]": "Element interfejsu, który pokazuje szybkość wysyłania i pobierania danych",
+ "Description[pt_BR]": "Widget monitor do sistema que mostra a taxa de download e upload",
+ "Description[ro]": "Control grafic de monitorizare a sistemului ce arată rata de încărcare și descărcare a datelor",
+ "Description[ru]": "Мониторинг скорости получения и передачи данных по сети",
+ "Description[sa]": "सङ्गणकतन्त्रस्य निरीक्षकस्य विजेट् यत् अवारोपण उपारोपण च दत्तांशदरः दर्शयति",
+ "Description[sk]": "Miniaplikácia monitorovania systému, ktorá zobrazuje množstvo sťahovaných a odosielaných dát",
+ "Description[sl]": "Gradnik sistemskega monitorja, ki prikazuje podatke prenosa podatkov noter in ven",
+ "Description[sv]": "Grafisk systemövervakningskomponent som visar nerladdnings- och uppladdningshastighet för data",
+ "Description[ta]": "பதிவிறக்க மற்றும் பதிவேற்ற விகிதத்தைக் காட்டும் பிளாஸ்மாய்ட்",
+ "Description[tr]": "Veri indirme ve karşıya yükleme hızını gösteren sistem monitörü araç takımı",
+ "Description[uk]": "Віджет нагляду за системою, який показує швидкість отримання та вивантаження даних",
+ "Description[zh_CN]": "显示下载和上传速率的系统监视小部件",
+ "Description[zh_TW]": "顯示下載與上傳之資料速率的系統監控元件",
+ "EnabledByDefault": true,
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "network-workgroup",
+ "Id": "org.kde.plasma.systemmonitor.net",
+ "License": "GPL-2.0+",
+ "Name": "Network Speed",
+ "Name[ar]": "سرعة الشبكة",
+ "Name[az]": "Şəbəkə sürəti",
+ "Name[be]": "Хуткасць сеткі",
+ "Name[bg]": "Скорост на мрежата",
+ "Name[ca@valencia]": "Velocitat de xarxa",
+ "Name[ca]": "Velocitat de xarxa",
+ "Name[cs]": "Rychlost sítě",
+ "Name[da]": "Netværkshastighed",
+ "Name[de]": "Netzwerkgeschwindigkeit",
+ "Name[el]": "Ταχύτητα δικτύου",
+ "Name[en_GB]": "Network Speed",
+ "Name[eo]": "Reta Rapideco",
+ "Name[es]": "Velocidad de la red",
+ "Name[eu]": "Sareko abiadura",
+ "Name[fi]": "Verkon nopeus",
+ "Name[fr]": "Débit du réseau",
+ "Name[gl]": "Velocidade de rede",
+ "Name[he]": "מהירות רשת",
+ "Name[hu]": "Hálózati sebesség",
+ "Name[ia]": "Velocitate de Rete",
+ "Name[id]": "Kecepatan Jaringan",
+ "Name[is]": "Nethraði",
+ "Name[it]": "Velocità di rete",
+ "Name[ja]": "ネットワーク速度",
+ "Name[ka]": "ქსელის სიჩქარე",
+ "Name[ko]": "네트워크 속도",
+ "Name[lt]": "Tinklo greitis",
+ "Name[lv]": "Tīkla ātrums",
+ "Name[nb]": "Nettverkshastighet",
+ "Name[nl]": "Netwerksnelheid",
+ "Name[nn]": "Nettverksfart",
+ "Name[pa]": "ਨੈੱਟਵਰਕ ਸਪੀਡ",
+ "Name[pl]": "Szybkość sieci",
+ "Name[pt_BR]": "Velocidade de rede",
+ "Name[ro]": "Viteza rețelei",
+ "Name[ru]": "Скорость передачи данных по сети",
+ "Name[sa]": "संजालस्य गतिः",
+ "Name[sk]": "Rýchlosť siete",
+ "Name[sl]": "Hitrost omrežja",
+ "Name[sv]": "Nätverkshastighet",
+ "Name[ta]": "பிணைய வேகம்",
+ "Name[tr]": "Ağ Hızı",
+ "Name[uk]": "Швидкість мережі",
+ "Name[zh_CN]": "网络速度",
+ "Name[zh_TW]": "網路速度",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.systemmonitor"
+ ],
+ "X-Plasma-RootPath": "org.kde.plasma.systemmonitor"
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/config/config.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/config/config.qml
new file mode 100644
index 0000000..23136b7
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/config/config.qml
@@ -0,0 +1,25 @@
+import QtQuick
+import org.kde.ksysguard.sensors as Sensors
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.configuration
+
+ConfigModel {
+ ConfigCategory {
+ name: i18n("Appearance")
+ icon: "preferences-desktop-color"
+ source: "config/ConfigAppearance.qml"
+ }
+ ConfigCategory {
+ name: i18n("%1 Details", Plasmoid.faceController.name)
+ icon: Plasmoid.faceController.icon
+ visible: Plasmoid.faceController.faceConfigUi !== null
+ source: "config/FaceDetails.qml"
+ }
+ ConfigCategory {
+ name: i18n("Sensors Details")
+ icon: "ksysguardd"
+ source: "config/ConfigSensors.qml"
+ }
+}
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/config/main.xml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/config/main.xml
new file mode 100644
index 0000000..a7d3191
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/config/main.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ org.kde.ksysguard.piechart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/CompactRepresentation.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/CompactRepresentation.qml
new file mode 100644
index 0000000..6e9ef5b
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/CompactRepresentation.qml
@@ -0,0 +1,62 @@
+/*
+ SPDX-FileCopyrightText: 2019 Marco Martin
+ SPDX-FileCopyrightText: 2019 David Edmundson
+ SPDX-FileCopyrightText: 2019 Arjen Hiemstra
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtQml
+
+import org.kde.plasma.plasmoid
+import org.kde.plasma.core as PlasmaCore
+
+import org.kde.ksysguard.faces as Faces
+
+Control {
+ id: chartFace
+ Layout.fillWidth: contentItem ? contentItem.Layout.fillWidth : false
+ Layout.fillHeight: contentItem ? contentItem.Layout.fillHeight : false
+
+ Layout.minimumWidth: (contentItem ? contentItem.Layout.minimumWidth : 0) + leftPadding + rightPadding
+ Layout.minimumHeight: (contentItem ? contentItem.Layout.minimumHeight : 0) + leftPadding + rightPadding
+
+ Layout.preferredWidth: (contentItem ? contentItem.Layout.preferredWidth : 0) + leftPadding + rightPadding
+ Layout.preferredHeight: (contentItem ? contentItem.Layout.preferredHeight : 0) + leftPadding + rightPadding
+
+ Layout.maximumWidth: (contentItem ? contentItem.Layout.maximumWidth : 0) + leftPadding + rightPadding
+ Layout.maximumHeight: (contentItem ? contentItem.Layout.maximumHeight : 0) + leftPadding + rightPadding
+
+ leftPadding: 0
+ topPadding: 0
+ rightPadding: 0
+ bottomPadding: 0
+
+ anchors.fill: parent
+ contentItem: Plasmoid.faceController.compactRepresentation
+
+ Binding {
+ target: Plasmoid.faceController.compactRepresentation
+ property: "formFactor"
+ value: {
+ switch (Plasmoid.formFactor) {
+ case PlasmaCore.Types.Horizontal:
+ return Faces.SensorFace.Horizontal;
+ case PlasmaCore.Types.Vertical:
+ return Faces.SensorFace.Vertical;
+ default:
+ return Faces.SensorFace.Planar;
+ }
+ }
+ restoreMode: Binding.RestoreBinding
+ }
+
+ MouseArea {
+ parent: chartFace
+ anchors.fill: parent
+ onClicked: root.expanded = !root.expanded
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/FullRepresentation.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/FullRepresentation.qml
new file mode 100644
index 0000000..382818a
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/FullRepresentation.qml
@@ -0,0 +1,62 @@
+/*
+ SPDX-FileCopyrightText: 2019 Marco Martin
+ SPDX-FileCopyrightText: 2019 David Edmundson
+ SPDX-FileCopyrightText: 2019 Arjen Hiemstra
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtQuick.Window
+import Qt5Compat.GraphicalEffects
+import QtQml
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.plasmoid
+
+import org.kde.ksysguard.faces as Faces
+
+
+Control {
+ id: chartFace
+
+ Layout.minimumWidth: (contentItem ? contentItem.Layout.minimumWidth : 0) + leftPadding + rightPadding
+ Layout.minimumHeight: (contentItem ? contentItem.Layout.minimumHeight : 0) + leftPadding + rightPadding
+ Layout.preferredWidth: (contentItem
+ ? (contentItem.Layout.preferredWidth > 0 ? contentItem.Layout.preferredWidth : contentItem.implicitWidth)
+ : 0) + leftPadding + rightPadding
+ Layout.preferredHeight: (contentItem
+ ? (contentItem.Layout.preferredHeight > 0 ? contentItem.Layout.preferredHeight: contentItem.implicitHeight)
+ : 0) + leftPadding + rightPadding
+ Layout.maximumWidth: (contentItem ? contentItem.Layout.maximumWidth : 0) + leftPadding + rightPadding
+ Layout.maximumHeight: (contentItem ? contentItem.Layout.maximumHeight : 0) + leftPadding + rightPadding
+
+ contentItem: Plasmoid.faceController.fullRepresentation
+
+ // This empty mousearea serves for the sole purpose of refusing touch events
+ // which otherwise are eaten by Control stealing the event from any of its parents
+ // TODO KF6: Check if this is still needed as Qt6 doesn't accept touch by default on Control
+ MouseArea {
+ parent: chartFace
+ anchors.fill:parent
+ }
+
+ Binding {
+ target: Plasmoid.faceController.fullRepresentation
+ property: "formFactor"
+ value: {
+ switch (Plasmoid.formFactor) {
+ case PlasmaCore.Types.Horizontal:
+ return Faces.SensorFace.Horizontal;
+ case PlasmaCore.Types.Vertical:
+ return Faces.SensorFace.Vertical;
+ default:
+ return Faces.SensorFace.Planar;
+ }
+ }
+ restoreMode: Binding.RestoreBinding
+ }
+}
+
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/ConfigAppearance.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/ConfigAppearance.qml
new file mode 100644
index 0000000..8b5c15e
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/ConfigAppearance.qml
@@ -0,0 +1,52 @@
+/*
+ SPDX-FileCopyrightText: 2019 Marco Martin
+ SPDX-FileCopyrightText: 2019 David Edmundson
+ SPDX-FileCopyrightText: 2019 Arjen Hiemstra
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.plasmoid
+import org.kde.kcmutils as KCM
+
+KCM.SimpleKCM {
+ id: root
+
+ signal configurationChanged
+
+ function saveConfig() {
+ configUi.saveConfig()
+ Plasmoid.faceController.reloadConfig()
+ }
+
+ // Workaround for Bug 424458, when reusing the controller/item things break
+ readonly property Item configUi: Plasmoid.workaroundController(root).appearanceConfigUi
+
+ // We cannot directly override the contentItem since SimpleKCM is a
+ // Kirigami.ScrollablePage which breaks if we override the contentItem. So
+ // instead use a placeholder item and reparent the config UI into that item,
+ // making sure to bind the required properties so sizing is correct.
+ Item {
+ id: contents
+
+ implicitWidth: root.configUi.implicitWidth
+ implicitHeight: root.configUi.implicitHeight
+
+ children: root.configUi
+
+ Binding {
+ target: root.configUi
+ property: "width"
+ value: contents.width
+ }
+ }
+
+ Connections {
+ target: root.configUi
+ function onConfigurationChanged() {
+ root.configurationChanged()
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/ConfigSensors.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/ConfigSensors.qml
new file mode 100644
index 0000000..b63e194
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/ConfigSensors.qml
@@ -0,0 +1,50 @@
+/*
+ SPDX-FileCopyrightText: 2019 Marco Martin
+ SPDX-FileCopyrightText: 2019 David Edmundson
+ SPDX-FileCopyrightText: 2019 Arjen Hiemstra
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.plasmoid
+import org.kde.kcmutils as KCM
+
+KCM.SimpleKCM {
+ id: root
+
+ signal configurationChanged
+
+ function saveConfig() {
+ configUi.saveConfig();
+ }
+
+ readonly property Item configUi: Plasmoid.faceController.sensorsConfigUi
+
+ // We cannot directly override the contentItem since SimpleKCM is a
+ // Kirigami.ScrollablePage which breaks if we override the contentItem. So
+ // instead use a placeholder item and reparent the config UI into that item,
+ // making sure to bind the required properties so sizing is correct.
+ Item {
+ id: contents
+
+ implicitWidth: root.configUi.implicitWidth
+ implicitHeight: root.configUi.implicitHeight
+
+ children: root.configUi
+
+ Binding {
+ target: root.configUi
+ property: "width"
+ value: contents.width
+ }
+ }
+
+ Connections {
+ target: root.configUi
+ function onConfigurationChanged() {
+ root.configurationChanged()
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/FaceDetails.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/FaceDetails.qml
new file mode 100644
index 0000000..041a700
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/config/FaceDetails.qml
@@ -0,0 +1,50 @@
+/*
+ SPDX-FileCopyrightText: 2019 Marco Martin
+ SPDX-FileCopyrightText: 2019 David Edmundson
+ SPDX-FileCopyrightText: 2019 Arjen Hiemstra
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.plasmoid
+import org.kde.kcmutils as KCM
+
+KCM.SimpleKCM {
+ id: root
+
+ signal configurationChanged
+
+ function saveConfig() {
+ configUi.saveConfig();
+ }
+
+ readonly property Item configUi: Plasmoid.faceController.faceConfigUi
+
+ // We cannot directly override the contentItem since SimpleKCM is a
+ // Kirigami.ScrollablePage which breaks if we override the contentItem. So
+ // instead use a placeholder item and reparent the config UI into that item,
+ // making sure to bind the required properties so sizing is correct.
+ Item {
+ id: contents
+
+ implicitWidth: root.configUi.implicitWidth
+ implicitHeight: root.configUi.implicitHeight
+
+ children: root.configUi
+
+ Binding {
+ target: root.configUi
+ property: "width"
+ value: contents.width
+ }
+ }
+
+ Connections {
+ target: root.configUi
+ function onConfigurationChanged() {
+ root.configurationChanged()
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/main.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/main.qml
new file mode 100644
index 0000000..357c9b1
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/contents/ui/main.qml
@@ -0,0 +1,96 @@
+/*
+ SPDX-FileCopyrightText: 2019 Marco Martin
+ SPDX-FileCopyrightText: 2019 David Edmundson
+ SPDX-FileCopyrightText: 2019 Arjen Hiemstra
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Window
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.plasmoid
+import org.kde.kirigami as Kirigami
+
+import org.kde.ksysguard.sensors as Sensors
+
+
+PlasmoidItem {
+ id: root
+ Plasmoid.backgroundHints: PlasmaCore.Types.DefaultBackground | PlasmaCore.Types.ConfigurableBackground
+
+ // Determine the right value to use for representation switching
+ function switchSizeFromSize(formFactor, compactMax, fullMin) {
+ // If we are planar (aka on the desktop), do not do any switching
+ if (Plasmoid.formFactor === PlasmaCore.Types.Planar) {
+ return -1
+ }
+
+ // If we are in a form factor where we can extend freely one way, don't
+ // use that for determining switching.
+ if (Plasmoid.formFactor === formFactor) {
+ // 0 or less is considered as "no switching" so return the smallest
+ // possible still valid value.
+ return 1
+ }
+
+ // Layout.maximumWidth will return Infinity if it isn't set, so handle that.
+ if (!Number.isFinite(compactMax)) {
+ // This is the default maximum size for compact reps, with 1 subtracted
+ // to ensure we switch if the maximum is reached.
+ compactMax = Kirigami.Units.iconSizes.enormous - 1
+ }
+
+ // Layout.minimumWidth will return -1 if it is not set, handle that.
+ if (fullMin <= 0) {
+ fullMin = Kirigami.Units.iconSizes.enormous - 1
+ }
+
+ // Use the larger of the two sizes to ensure we switch when the compact
+ // rep reaches its maximum but we don't try to cram in a full rep that
+ // won't actually fit.
+ return Math.max(compactMax, fullMin)
+ }
+
+ switchWidth: switchSizeFromSize(PlasmaCore.Types.Horizontal, compactRepresentationItem?.Layout.maximumWidth ?? Infinity, fullRepresentationItem?.Layout.minimumWidth ?? -1)
+ switchHeight: switchSizeFromSize(PlasmaCore.Types.Vertical, compactRepresentationItem?.Layout.maximumHeight ?? Infinity, fullRepresentationItem?.Layout.minimumHeight ?? -1)
+
+ preferredRepresentation: Plasmoid.formFactor === PlasmaCore.Types.Planar ? fullRepresentation : null
+
+ Plasmoid.title: Plasmoid.faceController?.title || i18n("System Monitor")
+ toolTipSubText: totalSensor.sensorId ? i18nc("Sensor name: value", "%1: %2", totalSensor.name, totalSensor.formattedValue) : ""
+
+ compactRepresentation: CompactRepresentation {
+ }
+ fullRepresentation: FullRepresentation {
+ }
+
+ Plasmoid.configurationRequired: (Plasmoid.faceController ?? false) &&
+ Plasmoid.faceController.highPrioritySensorIds.length == 0 &&
+ Plasmoid.faceController.lowPrioritySensorIds.length == 0 &&
+ Plasmoid.faceController.totalSensors.length == 0 &&
+ ! (["org.kde.ksysguard.applicationstable",
+ "org.kde.ksysguard.processtable"].includes(Plasmoid.faceController.faceId))
+
+ Sensors.Sensor {
+ id: totalSensor
+ sensorId: Plasmoid.faceController?.totalSensors[0] || ""
+ updateRateLimit: Plasmoid.faceController?.updateRateLimit
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.MiddleButton
+ onClicked: Plasmoid.openSystemMonitor()
+ }
+
+ Plasmoid.contextualActions: [
+ PlasmaCore.Action {
+ text: i18nc("@action", "Open System Monitor…")
+ icon.name: "utilities-system-monitor"
+ onTriggered: Plasmoid.openSystemMonitor()
+ }
+ ]
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/metadata.json
new file mode 100644
index 0000000..b46f243
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.systemmonitor/metadata.json
@@ -0,0 +1,169 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Name": "Marco Martin",
+ "Name[ar]": "ماركو مارتن",
+ "Name[ast]": "Marco Martin",
+ "Name[az]": "Marco Martin",
+ "Name[be]": "Marco Martin",
+ "Name[bg]": "Марко Мартин",
+ "Name[ca@valencia]": "Marco Martin",
+ "Name[ca]": "Marco Martin",
+ "Name[cs]": "Marco Martin",
+ "Name[da]": "Marco Martin",
+ "Name[de]": "Marco Martin",
+ "Name[el]": "Marco Martin",
+ "Name[en_GB]": "Marco Martin",
+ "Name[eo]": "Marco Martin",
+ "Name[es]": "Marco Martin",
+ "Name[et]": "Marco Martin",
+ "Name[eu]": "Marco Martin",
+ "Name[fi]": "Marco Martin",
+ "Name[fr]": "Marco Martin",
+ "Name[ga]": "Marco Martin",
+ "Name[gl]": "Marco Martin",
+ "Name[he]": "מרקו מרטין",
+ "Name[hi]": "मार्को मार्टिन",
+ "Name[hu]": "Marco Martin",
+ "Name[ia]": "Marco Martin",
+ "Name[id]": "Marco Martin",
+ "Name[is]": "Marco Martin",
+ "Name[it]": "Marco Martin",
+ "Name[ja]": "Marco Martin",
+ "Name[ka]": "მაკრო მარტინი",
+ "Name[ko]": "Marco Martin",
+ "Name[lt]": "Marco Martin",
+ "Name[lv]": "Marco Martin",
+ "Name[nb]": "Marco Martin",
+ "Name[nl]": "Marco Martin",
+ "Name[nn]": "Marco Martin",
+ "Name[pa]": "ਮਾਰਕੋ ਮਾਰਟਿਨ",
+ "Name[pl]": "Marco Martin",
+ "Name[pt]": "Marco Martin",
+ "Name[pt_BR]": "Marco Martin",
+ "Name[ro]": "Marco Martin",
+ "Name[ru]": "Marco Martin",
+ "Name[sa]": "मार्को मार्टिन्",
+ "Name[sk]": "Marco Martin",
+ "Name[sl]": "Marco Martin",
+ "Name[sv]": "Marco Martin",
+ "Name[ta]": "மார்க்கோ மார்ட்டின்",
+ "Name[tr]": "Marco Martin",
+ "Name[uk]": "Marco Martin",
+ "Name[vi]": "Marco Martin",
+ "Name[zh_CN]": "Marco Martin",
+ "Name[zh_TW]": "Marco Martin"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=plasmashell&component=System%20Monitor%20widgets",
+ "Category": "System Information",
+ "Description": "Displays a configurable chart of a system monitor sensor",
+ "Description[ar]": "يعرض مخططًا قابلًا للضبط لمتحسسات مراقبة النظام",
+ "Description[az]": "Sistem monitoru sensorunun ayarlana bilən zolaqlarını göstərir",
+ "Description[be]": "Паказвае наладжвальную дыяграму сэнсара сістэмнага назіральніка",
+ "Description[bg]": "Показва конфигурируема диаграма на сензор за системен монитор",
+ "Description[ca@valencia]": "Mostra un diagrama configurable d'un sensor del monitor del sistema",
+ "Description[ca]": "Mostra un diagrama configurable d'un sensor del monitor del sistema",
+ "Description[da]": "Viser et konfigurerbart diagram over en systemovervågning-sensor",
+ "Description[de]": "Zeigt ein anpassbares Diagramm eines Systemmonitor-Sensors an",
+ "Description[el]": "Εμφανίζει ένα διαμορφώσιμο διάγραμμα ενός αισθητήρα παρακολούθησης συστήματος",
+ "Description[en_GB]": "Displays a configurable chart of a system monitor sensor",
+ "Description[eo]": "Montras agordeblan diagramon de sistemmonitora sensilo",
+ "Description[es]": "Muestra un gráfico configurable de un sensor del monitor del sistema",
+ "Description[et]": "Süsteemi jälgija sensori seadistatava diagrammi näitamine",
+ "Description[eu]": "Sistema gainbegiratzeko sentsore baten diagrama konfiguragarri bat azaltzen du",
+ "Description[fi]": "Näyttää mukautettavissa olevan kaavion järjestelmänvalvonnan anturista",
+ "Description[fr]": "Affiche un graphique configurable du senseur de surveillance du système.",
+ "Description[gl]": "Amosa un gráfico configurábel dun sensor de vixilancia do sistema",
+ "Description[he]": "יישומון צג מערכת שמציג את חיישן צג המערכת",
+ "Description[hi]": "तंत्र परिवीक्षक सेंसर का विन्यास करने योग्य लेखा-चित्र प्रदर्शित करता है ",
+ "Description[hu]": "Testre szabható szenzorokat megjelenítő elem",
+ "Description[ia]": "Monstra un graphico configurabile de un sensor de supervision de systema",
+ "Description[id]": "Menampilkan sebuah bagan yang bisa dikonfigurasi pada sebuah sensor pemantau sistem",
+ "Description[is]": "Sýnir stillanlegt myndrit yfir kerfisvöktunarskynjara",
+ "Description[it]": "Visualizza un grafico configurabile di un sensore di monitoraggio del sistema",
+ "Description[ja]": "カスタム可能なチャートを表示します",
+ "Description[ka]": "სისტემური მონიტორის სენსორის მორგებადი ცხვრილის ჩვენება",
+ "Description[ko]": "설정 가능한 시스템 모니터 센서 차트 표시",
+ "Description[lt]": "Rodo konfigūruojamą sistemos prižiūryklės jutiklio diagramą",
+ "Description[lv]": "Parāda sistēmas pārraudzības sensoru konfigurējamu diagrammu",
+ "Description[nb]": "Viser et tilpassbart diagram for en systemovervåkingssensor",
+ "Description[nl]": "Toont een te configureren grafiek van een systeemmonitorsensor",
+ "Description[nn]": "Viser eit tilpassbart diagram for ein systemovervakingssensor",
+ "Description[pa]": "ਸਿਸਟਮ ਮਾਨੀਟਰ ਸੈਂਸਰ ਦੀ ਸੰਰਚਨਾ-ਯੋਗ ਚਾਰਟ ਦਿਖਾਉਂਦਾ ਹੈ",
+ "Description[pl]": "Wyświetla wykres miernika monitora systemowego",
+ "Description[pt]": "Mostra um gráfico configurável de um sensor de monitorização do sistema",
+ "Description[pt_BR]": "Mostra um gráfico configurável do sensor do monitor do sistema",
+ "Description[ro]": "Afișează un grafic configurabil al unui senzor de monitorizare a sistemului",
+ "Description[ru]": "Настраиваемый график датчика системного монитора",
+ "Description[sa]": "प्रणालीनिरीक्षकसंवेदकस्य विन्यासयोग्यं चित्रपट प्रदर्शयति",
+ "Description[sk]": "Zobrazuje konfigurovateľný graf senzoru monitorovania systému",
+ "Description[sl]": "Prikaže nastavljiv grafikon sistemskega monitorja senzorja",
+ "Description[sv]": "Visar ett anpassningsbart diagram av en systemövervakningssensor",
+ "Description[ta]": "ஏதாவதொரு கணினி கண்காணிப்பு உணரியைக் காட்டும்",
+ "Description[tr]": "Sistem monitörü algılayıcısının yapılandırılabilir bir grafiğini görüntüler",
+ "Description[uk]": "Показує придатну до налаштовування діаграму на основі даних датчика нагляду за системою",
+ "Description[vi]": "Hiển thị một biểu đồ cấu hình được của một cảm biến giám sát hệ thống",
+ "Description[zh_CN]": "显示系统监视器的可配置图表",
+ "Description[zh_TW]": "顯示一個可自訂的系統監控偵測器圖表",
+ "FormFactors": [
+ "desktop"
+ ],
+ "Icon": "ksysguardd",
+ "Id": "org.kde.plasma.systemmonitor",
+ "License": "GPL",
+ "Name": "System Monitor Sensor",
+ "Name[ar]": "مستشعر مراقبة النظام",
+ "Name[az]": "Sistem İzləməsi Sensoru",
+ "Name[be]": "Сэнсар сістэмнага назіральніка",
+ "Name[bg]": "Сензор на системния монитор",
+ "Name[ca@valencia]": "Sensor del monitor del sistema",
+ "Name[ca]": "Sensor del monitor del sistema",
+ "Name[cs]": "Senzor monitoru systému",
+ "Name[da]": "Systemovervågning-sensor",
+ "Name[de]": "Systemmonitor-Sensor",
+ "Name[el]": "Αισθητήρας παρακολούθησης συστήματος",
+ "Name[en_GB]": "System Monitor Sensor",
+ "Name[eo]": "Sistemmonitora Sentilo",
+ "Name[es]": "Sensor del monitor del sistema",
+ "Name[eu]": "Sistema gainbegiratzeko sentsorea",
+ "Name[fi]": "Järjestelmävalvonnan anturi",
+ "Name[fr]": "Senseur de surveillance du système",
+ "Name[gl]": "Sensores de vixilancia do sistema",
+ "Name[he]": "חיישן צג המערכת",
+ "Name[hu]": "Rendszermonitor-szenzor",
+ "Name[ia]": "Sensor de Monitor (supervisor) de systema",
+ "Name[id]": "Sensor Pemantau Sistem",
+ "Name[is]": "Skynjari kerfiseftirlits",
+ "Name[it]": "Sensori di monitoraggio del sistema",
+ "Name[ja]": "システムモニタセンサー",
+ "Name[ka]": "სისტემური მონიტორის სენსორი",
+ "Name[ko]": "시스템 모니터 센서",
+ "Name[lt]": "Sistemos prižiūryklės jutiklis",
+ "Name[lv]": "Sistēmās pārraudzības sensors",
+ "Name[nb]": "Systemovervåkingssensor",
+ "Name[nl]": "Systeemmonitorsensor",
+ "Name[nn]": "Systemovervakingssensor",
+ "Name[pa]": "ਸਿਸਟਮ ਮਾਨੀਟਰ ਸੈਂਸਰ",
+ "Name[pl]": "Miernik monitora systemowego",
+ "Name[pt_BR]": "Sensor do monitor do sistema ",
+ "Name[ro]": "Senzor de monitorizare a sistemului",
+ "Name[ru]": "Датчик системного монитора",
+ "Name[sa]": "प्रणालीनिरीक्षकस्य संवेदक",
+ "Name[sk]": "Senzor monitorovania systému",
+ "Name[sl]": "Sistemski nadzornik senzorja",
+ "Name[sv]": "Systemövervakningssensor",
+ "Name[ta]": "கணினி கண்காணிப்பு உணரி",
+ "Name[tr]": "Sistem Monitörü Algılayıcısı",
+ "Name[uk]": "Датчик нагляду за системою",
+ "Name[zh_CN]": "系统监视传感器",
+ "Name[zh_TW]": "系統監控感測器",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-Provides": [
+ "org.kde.plasma.systemmonitor"
+ ]
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/contents/ui/VaultItem.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/contents/ui/VaultItem.qml
new file mode 100644
index 0000000..ea2fe06
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/contents/ui/VaultItem.qml
@@ -0,0 +1,79 @@
+/*
+ * SPDX-FileCopyrightText: 2017, 2018, 2019 Ivan Cukic
+ * SPDX-FileCopyrightText: 2020 Nate Graham
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls as QQC2
+
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.plasma.plasmoid
+
+PlasmaExtras.ExpandableListItem {
+ id: root
+
+ required index
+ required property var model
+
+ readonly property var vaultsModelActions: Plasmoid.vaultsModel.actionsModel()
+
+ icon: model.icon
+ iconEmblem: {
+ if (model.message.length !== 0) {
+ return "emblem-error";
+ } else if (model.isOpened) {
+ return "emblem-mounted";
+ } else if (model.isOfflineOnly) {
+ return "network-disconnect-symbolic";
+ } else {
+ return "";
+ }
+ }
+
+ title: model.name
+ subtitle: model.message
+ subtitleCanWrap: true
+ defaultActionButtonAction: QQC2.Action {
+ icon.name: root.model.isOpened ? "lock-symbolic" : "unlock-symbolic"
+ text: root.model.isOpened ? i18nd("plasmavault-kde", "Lock Vault") : i18nd("plasmavault-kde", "Unlock and Open")
+ onTriggered: source => {
+ if (root.model.isOpened) {
+ root.vaultsModelActions.toggle(root.model.device);
+ } else {
+ root.vaultsModelActions.openInFileManager(root.model.device);
+ }
+ }
+ }
+ isBusy: Plasmoid.busy
+ enabled: model.isEnabled
+ contextualActions: [
+ QQC2.Action {
+ enabled: root.model.isOpened
+ icon.name: "document-open-folder-symbolic"
+ text: i18nd("plasmavault-kde", "Show in File Manager")
+ onTriggered: source => {
+ root.vaultsModelActions.openInFileManager(root.model.device);
+ }
+ },
+ QQC2.Action {
+ icon.name: root.model.isOpened ? "window-close-symbolic" : "unlock-symbolic"
+ text: root.model.isOpened ? i18nd("plasmavault-kde", "Forcefully Lock Vault") : i18nd("plasmavault-kde", "Unlock Vault")
+ onTriggered: source => {
+ if (root.model.isOpened) {
+ root.vaultsModelActions.forceClose(root.model.device);
+ } else {
+ root.vaultsModelActions.toggle(root.model.device);
+ }
+ }
+ },
+ QQC2.Action {
+ icon.name: "configure-symbolic"
+ text: i18nd("plasmavault-kde", "Configure Vault…")
+ onTriggered: source => root.vaultsModelActions.configure(root.model.device);
+ }
+ ]
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/contents/ui/main.qml b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/contents/ui/main.qml
new file mode 100644
index 0000000..e505271
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/contents/ui/main.qml
@@ -0,0 +1,133 @@
+/*
+ * SPDX-FileCopyrightText: 2017, 2018, 2019 Ivan Cukic
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+
+import org.kde.kirigami as Kirigami
+import org.kde.kitemmodels as KItemModels
+import org.kde.plasma.components as PlasmaComponents3
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.plasma.plasmoid
+
+PlasmoidItem {
+ id: root
+
+ readonly property var vaultsModelActions: Plasmoid.vaultsModel.actionsModel()
+
+ readonly property bool inPanel: [
+ PlasmaCore.Types.TopEdge,
+ PlasmaCore.Types.RightEdge,
+ PlasmaCore.Types.BottomEdge,
+ PlasmaCore.Types.LeftEdge,
+ ].includes(Plasmoid.location)
+
+ Plasmoid.busy: vaultsModelActions.isBusy
+
+ Plasmoid.icon: {
+ let iconName = (vaultsModelActions.hasError ? "plasmavault_error" : "plasmavault");
+
+ if (inPanel) {
+ return iconName += "-symbolic"
+ }
+
+ return iconName;
+ }
+
+ Plasmoid.status: vaultsModelActions.hasOpenVaults ? PlasmaCore.Types.ActiveStatus : PlasmaCore.Types.PassiveStatus
+
+ onExpandedChanged: {
+ Plasmoid.vaultsModel.reloadDevices();
+ }
+
+ Plasmoid.contextualActions: [
+ PlasmaCore.Action {
+ id: createAction
+ text: i18nd("plasmavault-kde", "Create a New Vault…")
+ icon.name: "list-add-symbolic"
+ onTriggered: checked => root.vaultsModelActions.requestNewVault()
+ }
+ ]
+
+ fullRepresentation: PlasmaExtras.Representation {
+
+ Layout.minimumWidth: Kirigami.Units.gridUnit * 18
+ Layout.minimumHeight: Kirigami.Units.gridUnit * 12
+
+ collapseMarginsHint: true
+
+ PlasmaComponents3.ScrollView {
+ anchors.fill: parent
+
+ // HACK: workaround for https://bugreports.qt.io/browse/QTBUG-83890
+ PlasmaComponents3.ScrollBar.horizontal.policy: PlasmaComponents3.ScrollBar.AlwaysOff
+
+ contentWidth: availableWidth - vaultsList.leftMargin - vaultsList.rightMargin
+
+ contentItem: ListView {
+ id: vaultsList
+
+ model: KItemModels.KSortFilterProxyModel {
+ sortRoleName: "name"
+ sourceModel: Plasmoid.vaultsModel
+ }
+
+ clip: true
+ currentIndex: -1
+ spacing: Kirigami.Units.smallSpacing
+ topMargin: Kirigami.Units.largeSpacing
+ leftMargin: Kirigami.Units.largeSpacing
+ rightMargin: Kirigami.Units.largeSpacing
+ bottomMargin: Kirigami.Units.largeSpacing
+
+ highlight: PlasmaExtras.Highlight {}
+ highlightMoveDuration: Kirigami.Units.shortDuration
+ highlightResizeDuration: Kirigami.Units.shortDuration
+ delegate: VaultItem {}
+
+ PlasmaExtras.PlaceholderMessage {
+ id: noVaultsMessage
+
+ anchors.centerIn: parent
+ width: parent.width - (Kirigami.Units.gridUnit * 4)
+
+ visible: vaultsList.count === 0
+
+ iconName: "plasmavault"
+ text: i18nd("plasmavault-kde", "No Vaults have been set up")
+
+ helpfulAction: QQC2.Action {
+ text: createAction.text
+ icon.name: createAction.icon.name
+
+ onTriggered: source => createAction.trigger()
+ }
+ }
+ }
+ }
+
+ footer: PlasmaExtras.PlasmoidHeading {
+ visible: vaultsList.count > 0 && !(Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentDrawsPlasmoidHeading)
+
+ contentItem: RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ PlasmaComponents3.ToolButton {
+
+ text: createAction.text
+ icon.name: createAction.icon.name
+
+ onClicked: createAction.trigger()
+ Layout.alignment: Qt.AlignLeft
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/metadata.json b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/metadata.json
new file mode 100644
index 0000000..4d3e981
--- /dev/null
+++ b/files/system/usr/share/plasma/plasmoids/org.kde.plasma.vault/metadata.json
@@ -0,0 +1,148 @@
+{
+ "KPackageStructure": "Plasma/Applet",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "ivan.cukic at kde.org",
+ "Name": "Ivan Čukić",
+ "Name[ar]": "إيفان أووكيتش",
+ "Name[ast]": "Ivan Čukić",
+ "Name[az]": "Ivan Čukić",
+ "Name[be]": "Ivan Čukić",
+ "Name[bg]": "Ivan Čukić",
+ "Name[ca@valencia]": "Ivan Čukić",
+ "Name[ca]": "Ivan Čukić",
+ "Name[cs]": "Ivan Čukić",
+ "Name[da]": "Ivan Čukić",
+ "Name[de]": "Ivan Čukić",
+ "Name[en_GB]": "Ivan Čukić",
+ "Name[eo]": "Ivan Čukić",
+ "Name[es]": "Ivan Čukić",
+ "Name[eu]": "Ivan Čukić",
+ "Name[fi]": "Ivan Čukić",
+ "Name[fr]": "Ivan Čukić",
+ "Name[gl]": "Ivan Čukić",
+ "Name[he]": "איוון צ׳וקיץ׳",
+ "Name[hu]": "Ivan Čukić",
+ "Name[ia]": "Ivan Čukić",
+ "Name[is]": "Ivan Čukić",
+ "Name[it]": "Ivan Čukić",
+ "Name[ka]": "Ivan Čukić",
+ "Name[ko]": "Ivan Čukić",
+ "Name[lt]": "Ivan Čukić",
+ "Name[lv]": "Ivan Čukić",
+ "Name[nl]": "Ivan Čukić",
+ "Name[nn]": "Ivan Čukić",
+ "Name[pl]": "Ivan Čukić",
+ "Name[pt_BR]": "Ivan Čukić",
+ "Name[ro]": "Ivan Čukić",
+ "Name[ru]": "Ivan Čukić",
+ "Name[sa]": "इवान चुकिच्",
+ "Name[sk]": "Ivan Čukić",
+ "Name[sl]": "Ivan Čukić",
+ "Name[sv]": "Ivan Čukić",
+ "Name[tr]": "Ivan Čukić",
+ "Name[uk]": "Ivan Čukić",
+ "Name[zh_CN]": "Ivan Čukić",
+ "Name[zh_TW]": "Ivan Čukić"
+ }
+ ],
+ "BugReportUrl": "https://bugs.kde.org/enter_bug.cgi?product=Plasma%20Vault",
+ "Category": "Utilities",
+ "Description": "Create encrypted vaults",
+ "Description[ar]": "أنشئ خزنات معمّاة",
+ "Description[ast]": "Crea arques cifraes",
+ "Description[az]": "Şifrələnmiş seyflər yaratmaq",
+ "Description[be]": "Стварыць зашыфраваныя сховішчы",
+ "Description[bg]": "Създаване на криптирани трезори",
+ "Description[ca@valencia]": "Crea caixes fortes encriptades",
+ "Description[ca]": "Crea caixes fortes encriptades",
+ "Description[cs]": "Vytvářejte šifrované sejfy",
+ "Description[da]": "Opretter krypterede sikkerhedsbokse",
+ "Description[de]": "Verschlüsselte Tresore erstellen",
+ "Description[en_GB]": "Create encrypted vaults",
+ "Description[eo]": "Krei ĉifritajn trezorejojn",
+ "Description[es]": "Crear cajas fuertes cifradas",
+ "Description[eu]": "Sortu zifratutako kutxa-gotorrak",
+ "Description[fi]": "Luo salattuja holveja",
+ "Description[fr]": "Créer des coffres-forts chiffrés",
+ "Description[gl]": "Crear caixas fortes cifradas.",
+ "Description[he]": "יצירת כספות מוצפנות",
+ "Description[hu]": "Titkos tárolók létrehozása",
+ "Description[ia]": "Crea cellarios cryptate",
+ "Description[is]": "Setja upp dulritaðar öryggisgeymslur",
+ "Description[it]": "Crea caveau criptati",
+ "Description[ka]": "დაშიფრული სარდაფების შექმნა",
+ "Description[ko]": "암호화된 비밀 공간 생성",
+ "Description[lt]": "Sukurti šifruotas slėptuves",
+ "Description[lv]": "Izveidojiet šifrētus seifus",
+ "Description[nl]": "Versleutelde kluizen aanmaken",
+ "Description[nn]": "Lag krypterte datakvelv",
+ "Description[pa]": "ਇੰਕ੍ਰਿਪਟ ਕੀਤੇ ਵਾਲਟ ਬਣਾਓ",
+ "Description[pl]": "Tworzy zaszyfrowane sejfy",
+ "Description[pt_BR]": "Criar cofres criptografados",
+ "Description[ro]": "Creează bolți criptate",
+ "Description[ru]": "Создание зашифрованных папок",
+ "Description[sa]": "एन्क्रिप्टेड् वॉल्ट्स् रचयन्तु",
+ "Description[sk]": "Vytvoriť šifrované trezory",
+ "Description[sl]": "Ustvari šifrirane trezorje",
+ "Description[sv]": "Skapa krypterade valv",
+ "Description[tr]": "Şifrelenmiş kasalar oluşturun",
+ "Description[uk]": "Створення зашифрованих сховищ",
+ "Description[zh_CN]": "创建加密的保险库",
+ "Description[zh_TW]": "建立加密儲存庫",
+ "EnabledByDefault": true,
+ "Icon": "plasmavault",
+ "Id": "org.kde.plasma.vault",
+ "License": "GPL",
+ "Name": "Vaults",
+ "Name[ar]": "الخزنات",
+ "Name[ast]": "Arques",
+ "Name[az]": "Seyflər",
+ "Name[be]": "Сховішчы",
+ "Name[bg]": "Трезори",
+ "Name[ca@valencia]": "Caixes fortes",
+ "Name[ca]": "Caixes fortes",
+ "Name[cs]": "Sejfy",
+ "Name[da]": "Sikkerhedsbokse",
+ "Name[de]": "Tresore",
+ "Name[en_GB]": "Vaults",
+ "Name[eo]": "Trezorejoj",
+ "Name[es]": "Cajas fuertes",
+ "Name[eu]": "Kutxa-gotorrak",
+ "Name[fi]": "Holvi",
+ "Name[fr]": "Coffre-forts",
+ "Name[gl]": "Caixas fortes",
+ "Name[he]": "כספות",
+ "Name[hu]": "Titkos tárolók",
+ "Name[ia]": "Cellarios (Vaults)",
+ "Name[is]": "Öryggisgeymslur",
+ "Name[it]": "Caveau",
+ "Name[ka]": "საცავები",
+ "Name[ko]": "비밀 공간",
+ "Name[lt]": "Slėptuvės",
+ "Name[lv]": "Seifi",
+ "Name[nl]": "Kluizen",
+ "Name[nn]": "Datakvelv",
+ "Name[pa]": "ਵਾਲਟ",
+ "Name[pl]": "Sejfy",
+ "Name[pt_BR]": "Cofres",
+ "Name[ro]": "Bolți",
+ "Name[ru]": "Зашифрованные папки",
+ "Name[sa]": "तिजोरियाः",
+ "Name[sk]": "Trezory",
+ "Name[sl]": "Trezorji",
+ "Name[sv]": "Valv",
+ "Name[tr]": "Kasalar",
+ "Name[uk]": "Сховища",
+ "Name[zh_CN]": "保险库",
+ "Name[zh_TW]": "儲存庫",
+ "Version": "1.0",
+ "Website": "https://kde.org/plasma-desktop/"
+ },
+ "X-Plasma-API": "declarativeappletscript",
+ "X-Plasma-API-Minimum-Version": "6.0",
+ "X-Plasma-MainScript": "ui/main.qml",
+ "X-Plasma-NotificationArea": "true",
+ "X-Plasma-NotificationAreaCategory": "SystemServices"
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/InteractiveConsole.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/InteractiveConsole.qml
new file mode 100644
index 0000000..428071d
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/InteractiveConsole.qml
@@ -0,0 +1,35 @@
+/*
+ SPDX-FileCopyrightText: 2014 Aaron Seigo
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.private.shell
+
+Item {
+ id: main
+
+ property string scriptPath
+ property alias mode: interactiveConsole.mode
+ signal visibleChanged(bool visible)
+
+ onScriptPathChanged: {
+ interactiveConsole.loadScript(scriptPath);
+ }
+
+ InteractiveConsoleWindow {
+ id: interactiveConsole
+
+ onVisibleChanged: {
+ main.visibleChanged(visible);
+ }
+ }
+
+ Component.onCompleted: {
+ interactiveConsole.scriptEngine = scriptEngine;
+ interactiveConsole.visible = true;
+ }
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityItem.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityItem.qml
new file mode 100644
index 0000000..0c37be6
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityItem.qml
@@ -0,0 +1,376 @@
+/*
+ SPDX-FileCopyrightText: 2014-2020 Ivan Cukic
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick 2.0
+
+import org.kde.plasma.components 3.0 as PlasmaComponents
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.plasma.activityswitcher as ActivitySwitcher
+import org.kde.kirigami 2.20 as Kirigami
+
+import org.kde.kcmutils // KCMLauncher
+
+import "static.js" as S
+
+Item {
+ id: root
+
+ property int innerPadding : Kirigami.Units.gridUnit
+
+ property bool current : false
+ property bool selected : false
+
+ property alias title : title.text
+ property alias icon : icon.source
+ property alias hasWindows : hasWindowsIndicator.visible
+
+ z : current ? 10 :
+ selected ? 5 : 0
+
+ property string activityId : ""
+
+ property string background : ""
+
+ onBackgroundChanged: if (background[0] !== '#') {
+ // We have a proper wallpaper, hurroo!
+ backgroundColor.visible = false;
+
+ } else {
+ // We have only a color
+ backgroundColor.color = background;
+ backgroundColor.visible = true;
+ }
+
+ signal clicked
+
+ width : 200
+ height : width * 9.0 / 16.0
+
+ Item {
+ anchors {
+ fill: parent
+ }
+
+ // Background until we get something real
+ Rectangle {
+ id: backgroundColor
+
+ anchors.fill: parent
+ // This is intentional - while waiting for the wallpaper,
+ // we are showing a semi-transparent black background
+ color: "black"
+
+ opacity: root.selected ? .8 : .5
+ }
+
+ Image {
+ id: backgroundWallpaper
+
+ anchors.fill: parent
+
+ visible: !backgroundColor.visible
+ source: "image://wallpaperthumbnail/" + root.background
+ sourceSize: Qt.size(width, height)
+ }
+
+ // Title and the icon
+
+ Rectangle {
+ id: shade
+
+ width: parent.height
+ height: parent.width
+
+ anchors.centerIn: parent
+ rotation: 90
+
+ gradient: Gradient {
+ GradientStop { position: 1.0; color: "black" }
+ GradientStop { position: 0.0; color: "transparent" }
+ }
+
+ opacity : root.selected ? 0.5 : 1.0
+ }
+
+ Rectangle {
+ id: currentActivityHighlight
+
+ visible: root.current
+
+ border.width: root.current ? Kirigami.Units.smallSpacing : 0
+ border.color: Kirigami.Theme.highlightColor
+
+ z: 10
+
+ anchors {
+ fill: parent
+ // Hide the rounding error on the bottom of the rectangle
+ bottomMargin: -1
+ }
+
+ color: "transparent"
+ }
+
+ Item {
+ id: titleBar
+
+ anchors {
+ top : parent.top
+ left : parent.left
+ right : parent.right
+
+ leftMargin : 2 * Kirigami.Units.smallSpacing + 2
+ topMargin : 2 * Kirigami.Units.smallSpacing
+ }
+
+ PlasmaExtras.ShadowedLabel {
+ id: title
+
+ color : "white"
+ elide : Text.ElideRight
+ visible : shade.visible
+
+ font.bold : true
+
+ anchors {
+ top : parent.top
+ left : parent.left
+ right : icon.left
+ }
+ }
+
+ PlasmaExtras.ShadowedLabel {
+ id: description
+
+ color : "white"
+ elide : Text.ElideRight
+ text : model.description
+
+ anchors {
+ top : title.bottom
+ left : parent.left
+ right : icon.left
+ }
+ }
+
+ Kirigami.Icon {
+ id: icon
+
+ width : Kirigami.Units.iconSizes.medium
+ height : width
+
+ anchors {
+ right : parent.right
+ rightMargin : 2 * Kirigami.Units.smallSpacing
+ }
+ }
+ }
+
+ Column {
+ id: statsBar
+
+ height: childrenRect.height + Kirigami.Units.smallSpacing
+
+ anchors {
+ bottom : controlBar.top
+ left : parent.left
+ right : parent.right
+
+ leftMargin : 2 * Kirigami.Units.smallSpacing + 2
+ rightMargin : 2 * Kirigami.Units.smallSpacing
+ bottomMargin : Kirigami.Units.smallSpacing
+ }
+
+ Kirigami.Icon {
+ id : hasWindowsIndicator
+ source : "window-duplicate"
+ width : 16
+ height : width
+ opacity : .6
+ visible : false
+ }
+
+ PlasmaExtras.ShadowedLabel {
+ id: lastUsedDate
+
+ color : "white"
+ elide : Text.ElideRight
+
+ text: root.current ?
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:status currently active activity", "Currently being used") :
+ model.lastTimeUsedString
+ }
+ }
+
+ Rectangle {
+ id: dropHighlight
+ visible: moveDropAction.isHovered || copyDropAction.isHovered
+
+ onVisibleChanged: {
+ ActivitySwitcher.Backend.setDropMode(visible);
+ if (visible) {
+ root.state = "dropAreasShown";
+ } else {
+ root.state = "plain";
+ }
+ }
+
+ anchors {
+ fill: parent
+ topMargin: icon.height + 3 * Kirigami.Units.smallSpacing
+ }
+
+ opacity: .75
+ color: Kirigami.Theme.backgroundColor
+ }
+
+ TaskDropArea {
+ id: moveDropAction
+
+ anchors {
+ right: parent.horizontalCenter
+ left: parent.left
+ top: parent.top
+ bottom: parent.bottom
+ }
+
+ topPadding: icon.height + 3 * Kirigami.Units.smallSpacing
+ actionVisible: dropHighlight.visible
+
+ actionTitle: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action shows when dragging file over item", "Move to\nthis activity")
+
+ onTaskDropped: mimeData => {
+ ActivitySwitcher.Backend.dropMove(mimeData, root.activityId);
+ }
+
+ onClicked: {
+ root.clicked();
+ }
+
+ onEntered: {
+ S.showActivityItemActionsBar(root);
+ }
+
+ visible: ActivitySwitcher.Backend.dropEnabled
+ }
+
+ TaskDropArea {
+ id: copyDropAction
+
+ topPadding: icon.height + 3 * Kirigami.Units.smallSpacing
+ actionVisible: dropHighlight.visible
+
+ anchors {
+ right: parent.right
+ left: parent.horizontalCenter
+ top: parent.top
+ bottom: parent.bottom
+ }
+
+ actionTitle: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action shows when dragging file over item", "Show also\nin this activity")
+
+ onTaskDropped: mimeData => {
+ ActivitySwitcher.Backend.dropCopy(mimeData, root.activityId);
+ }
+
+ onClicked: {
+ root.clicked();
+ }
+
+ onEntered: {
+ S.showActivityItemActionsBar(root);
+ }
+
+ visible: ActivitySwitcher.Backend.dropEnabled
+
+ }
+
+ // Controls
+ Item {
+ id: controlBar
+
+ height: root.state == "showingControls" ?
+ (configButton.height + 4 * Kirigami.Units.smallSpacing) :
+ 0
+
+ Behavior on height {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ }
+ }
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+
+ clip: true
+
+ anchors {
+ bottom : parent.bottom
+ left : parent.left
+ right : parent.right
+ }
+
+ Rectangle {
+ anchors {
+ fill: parent
+ margins: - 2 * Kirigami.Units.smallSpacing
+ }
+
+ opacity: .75
+ color: Kirigami.Theme.backgroundColor
+ }
+
+ PlasmaComponents.Button {
+ id: configButton
+
+ icon.name: "configure"
+ PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay
+ PlasmaComponents.ToolTip.visible: hovered
+ PlasmaComponents.ToolTip.text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button tooltip only, opens kcm", "Configure")
+
+ onClicked: KCMLauncher.openSystemSettings("kcm_activities", root.activityId);
+
+ anchors {
+ left : parent.left
+ top : parent.top
+ leftMargin : 2 * Kirigami.Units.smallSpacing + 2
+ topMargin : 2 * Kirigami.Units.smallSpacing
+ }
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "plain"
+ PropertyChanges { shade.visible: true }
+ PropertyChanges { controlBar.opacity: 0 }
+ },
+ State {
+ name: "showingControls"
+ PropertyChanges { shade.visible: true }
+ PropertyChanges { controlBar.opacity: 1 }
+ },
+ State {
+ name: "dropAreasShown"
+ // PropertyChanges { shade.visible: false }
+ PropertyChanges { statsBar.visible: false }
+ PropertyChanges { controlBar.opacity: 0 }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ NumberAnimation {
+ properties : "opacity"
+ duration : Kirigami.Units.shortDuration
+ }
+ }
+ ]
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityList.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityList.qml
new file mode 100644
index 0000000..491ee0b
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityList.qml
@@ -0,0 +1,150 @@
+/* vim:set foldmethod=marker:
+
+ SPDX-FileCopyrightText: 2014 Ivan Cukic
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.kirigami as Kirigami
+
+import org.kde.plasma.activityswitcher as ActivitySwitcher
+
+Flickable {
+ id: root
+
+ // contentWidth: content.width
+ contentHeight: content.height
+
+ property var model: ActivitySwitcher.Backend.runningActivitiesModel()
+ property string filterString: ""
+ property bool showSwitcherOnly: false
+
+ property int itemsWidth: 0
+
+ property int selectedIndex: -1
+
+ function _selectRelativeToCurrent(distance)
+ {
+ var startingWithSelected = selectedIndex;
+ var visited = 0;
+
+ do {
+ selectedIndex += distance;
+ visited++;
+
+ if (selectedIndex >= activitiesList.count) {
+ selectedIndex = 0;
+ }
+
+ if (selectedIndex < 0) {
+ selectedIndex = activitiesList.count - 1;
+ }
+
+ if (visited >= activitiesList.count) {
+ // we've visited all activities but could not find a visible
+ // one, so stop searching and select the one we started with
+ selectedIndex = startingWithSelected;
+ break;
+ }
+
+ // Searching for the first item that is visible
+ } while (!activitiesList.itemAt(selectedIndex).visible);
+ _updateSelectedItem();
+
+ }
+
+ function selectNext()
+ {
+ _selectRelativeToCurrent(1);
+ }
+
+ function selectPrevious()
+ {
+ _selectRelativeToCurrent(-1);
+ }
+
+ function _updateSelectedItem()
+ {
+ for (var i = 0; i < activitiesList.count; i++) {
+ activitiesList.itemAt(i).selected = (i === selectedIndex);
+ }
+ }
+
+ function openSelected()
+ {
+ var selectedItem = null;
+
+ if (selectedIndex >= 0 && selectedIndex < activitiesList.count) {
+ selectedItem = activitiesList.itemAt(selectedIndex) as ActivityItem;
+
+ } else if (root.filterString != "") {
+ // If we have only one item shown, activate it. It doesn't matter
+ // that it is not really selected
+
+ for (var i = 0; i < activitiesList.count; i++) {
+ var item = activitiesList.itemAt(i) as ActivityItem;
+
+ if (item.visible) {
+ selectedItem = item;
+ break;
+ }
+ }
+ }
+
+ if (selectedItem !== null) {
+ ActivitySwitcher.Backend.setCurrentActivity(selectedItem.activityId);
+ }
+ }
+
+ Column {
+ id: content
+
+ // width: root.width - (root.width % 10)
+ width: root.itemsWidth
+ spacing: Kirigami.Units.smallSpacing * 2
+
+ Repeater {
+ id: activitiesList
+
+ model: ActivitySwitcher.Backend.runningActivitiesModel()
+
+ ActivityItem {
+
+ width: content.width
+
+ visible : (root.filterString == "") ||
+ (title.toLowerCase().indexOf(root.filterString) != -1)
+
+ activityId : model.id
+ title : model.name
+ icon : model.iconSource
+ background : model.background
+ current : model.isCurrent
+ hasWindows : model.hasWindows
+ innerPadding : 2 * Kirigami.Units.smallSpacing
+
+ onClicked : {
+ ActivitySwitcher.Backend.setCurrentActivity(model.id);
+ }
+ }
+ }
+
+ add: Transition {
+ NumberAnimation {
+ properties: "x"
+ from: -100
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+
+ move: Transition {
+ NumberAnimation {
+ id: animation
+ properties: "y"
+ duration: Kirigami.Units.longDuration
+ }
+ }
+ }
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityManager.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityManager.qml
new file mode 100644
index 0000000..9459464
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/ActivityManager.qml
@@ -0,0 +1,135 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+ SPDX-FileCopyrightText: 2014 Ivan Cukic
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick 2.0
+
+import org.kde.plasma.components 3.0 as PlasmaComponents
+import org.kde.kirigami 2.20 as Kirigami
+import org.kde.config as KConfig // KAuthorized
+import org.kde.kcmutils // KCMLauncher
+
+
+FocusScope {
+ id: root
+ signal closed()
+
+ //this is used to perfectly align the filter field and delegates
+ property int cellWidth: Kirigami.Units.iconSizes.sizeForLabels * 30
+ property int spacing: 2 * Kirigami.Units.smallSpacing
+
+ property bool showSwitcherOnly: false
+
+ width: Kirigami.Units.gridUnit * 16
+
+ Item {
+ id: activityBrowser
+
+ property int spacing: 2 * Kirigami.Units.smallSpacing
+
+ signal closeRequested()
+
+ Keys.onPressed: event => {
+ if (event.key === Qt.Key_Escape) {
+ if (heading.searchString.length > 0) {
+ heading.searchString = "";
+ } else {
+ activityBrowser.closeRequested();
+ }
+
+ } else if (event.key === Qt.Key_Up) {
+ activityList.selectPrevious();
+
+ } else if (event.key === Qt.Key_Down) {
+ activityList.selectNext();
+
+ } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
+ activityList.openSelected();
+
+ } else if (event.key === Qt.Key_Tab) {
+ // console.log("TAB KEY");
+
+ } else {
+ // console.log("OTHER KEY");
+ // event.accepted = false;
+ // heading.forceActiveFocus();
+ }
+ }
+
+ // Rectangle {
+ // anchors.fill : parent
+ // opacity : .4
+ // color : "white"
+ // }
+
+ Heading {
+ id: heading
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+
+ leftMargin: Kirigami.Units.smallSpacing
+ rightMargin: Kirigami.Units.smallSpacing
+ }
+
+ visible: !root.showSwitcherOnly
+
+ onCloseRequested: activityBrowser.closeRequested()
+ }
+
+ PlasmaComponents.ScrollView {
+ anchors {
+ top: heading.visible ? heading.bottom : parent.top
+ bottom: bottomPanel.visible ? bottomPanel.top : parent.bottom
+ left: parent.left
+ right: parent.right
+ topMargin: activityBrowser.spacing
+ }
+
+ ActivityList {
+ id: activityList
+ showSwitcherOnly: root.showSwitcherOnly
+ filterString: heading.searchString.toLowerCase()
+ itemsWidth: root.width - Kirigami.Units.smallSpacing
+ }
+ }
+
+ Item {
+ id: bottomPanel
+
+ height: newActivityButton.height + Kirigami.Units.gridUnit
+
+ visible: !root.showSwitcherOnly
+
+ anchors {
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ }
+
+ PlasmaComponents.ToolButton {
+ id: newActivityButton
+
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button opens Activity kcm", "Create activity…")
+ icon.name: "list-add"
+
+ width: parent.width
+
+ onClicked: KCMLauncher.openSystemSettings("kcm_activities", "newActivity")
+
+ visible: KConfig.KAuthorized.authorize("plasma-desktop/add_activities")
+ }
+ }
+
+ onCloseRequested: root.closed()
+
+ anchors.fill: parent
+ }
+
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/Heading.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/Heading.qml
new file mode 100644
index 0000000..b3e6408
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/Heading.qml
@@ -0,0 +1,108 @@
+/* vim:set foldmethod=marker:
+
+ SPDX-FileCopyrightText: 2014 Ivan Cukic
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.components as PlasmaComponents
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+
+import org.kde.kcmutils as KCM
+import org.kde.config as KConfig
+
+Item {
+ id: root
+
+ property alias searchString: searchText.text
+ property bool showingSearch: false
+
+ signal closeRequested
+
+ function focusSearch() {
+ searchText.forceActiveFocus()
+ }
+
+ onShowingSearchChanged: if (!showingSearch) searchText.text = ""
+
+ Keys.onPressed: event => {
+ if (event.key === Qt.Key_Escape) {
+ if (root.showingSearch) {
+ event.accepted = true;
+ root.showingSearch = false;
+ }
+ }
+ }
+
+ height: childrenRect.height
+
+ RowLayout {
+ id: buttonRow
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+
+ Item {
+ Kirigami.Heading {
+ id: heading
+
+ anchors.fill: parent
+
+ level: 1
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:window", "Activities")
+ textFormat: Text.PlainText
+ elide: Text.ElideRight
+
+ visible: !root.showingSearch
+ }
+
+ PlasmaExtras.SearchField {
+ id: searchText
+
+ anchors.fill: parent
+
+ focus: true
+ visible: root.showingSearch
+
+ onTextChanged: if (text != "") root.showingSearch = true
+ }
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ PlasmaComponents.ToolButton {
+ id: searchButton
+ icon.name: "edit-find"
+
+ // checkable: true
+ // onClicked: root.closeRequested()
+ onClicked: root.showingSearch = !root.showingSearch
+ checked: root.showingSearch
+ }
+
+ PlasmaComponents.ToolButton {
+ id: configureButton
+ icon.name: "configure"
+ visible: KConfig.KAuthorized.authorizeControlModule("kcm_activities")
+ onClicked: {
+ KCM.KCMLauncher.openSystemSettings("kcm_activities");
+ root.closeRequested();
+ }
+ }
+
+ PlasmaComponents.ToolButton {
+ id: closeButton
+ icon.name: "window-close"
+ onClicked: root.closeRequested()
+ }
+
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/TaskDropArea.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/TaskDropArea.qml
new file mode 100644
index 0000000..35579e3
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/TaskDropArea.qml
@@ -0,0 +1,88 @@
+/*
+ SPDX-FileCopyrightText: 2020 Ivan Cukic
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.kirigami as Kirigami
+import org.kde.draganddrop as DND
+import org.kde.plasma.extras as PlasmaExtras
+
+DND.DropArea {
+ id: root
+
+ signal taskDropped(var mimeData, var modifiers)
+ signal clicked()
+ signal entered()
+
+ property int topPadding: 0
+ property string activityName: ""
+ property bool selected: false
+ property string actionTitle: ""
+ property bool isHovered: false
+ property bool actionVisible: false
+
+ PlasmaExtras.Highlight {
+ id: dropHighlight
+ anchors {
+ fill: parent
+ // topMargin: icon.height + 3 * Kirigami.Units.smallSpacing
+ topMargin: root.topPadding
+ }
+ visible: root.isHovered
+ z: -1
+ }
+
+ Text {
+ id: dropAreaLeftText
+ anchors {
+ fill: dropHighlight
+ leftMargin: Kirigami.Units.gridUnit
+ rightMargin: Kirigami.Units.gridUnit
+ }
+
+ color: Kirigami.Theme.textColor
+ visible: root.actionVisible
+
+ text: root.actionTitle
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ maximumLineCount: 3
+ }
+
+ anchors {
+ left: parent.left
+ right: parent.horizontalCenter
+ top: parent.top
+ bottom: parent.bottom
+ }
+
+ preventStealing: true
+ enabled: true
+
+ onDrop: event => {
+ root.taskDropped(event.mimeData, event.modifiers);
+ }
+
+ onDragEnter: {
+ root.isHovered = true;
+ }
+
+ onDragLeave: {
+ root.isHovered = false;
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.clicked()
+ hoverEnabled: true
+ onEntered: root.entered()
+
+ Accessible.name: root.activityName
+ Accessible.role: Accessible.Button
+ Accessible.selected: root.selected
+ Accessible.onPressAction: root.clicked()
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/WindowPreview.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/WindowPreview.qml
new file mode 100644
index 0000000..1ef2ff4
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/WindowPreview.qml
@@ -0,0 +1,54 @@
+/*
+ SPDX-FileCopyrightText: 2014 Ivan Cukic
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.kirigami as Kirigami
+
+Image {
+ id: main
+
+ width: 480
+ height: 425
+
+ source: "images/window2.png"
+ anchors.centerIn: parent
+
+ Item {
+ id: title
+
+ width: titleText.width + 32
+ height: titleText.height + 32
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+ radius: Kirigami.Units.cornerRadius
+ opacity: .7
+ }
+
+ Text {
+ id: titleText
+ color: "white"
+ text: "Firefox"
+ font.pointSize: 24
+
+ anchors.centerIn: parent
+ }
+ }
+
+ Drag.active: mouseArea.drag.active
+ Drag.hotSpot.x: 32
+ Drag.hotSpot.y: 32
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+
+ drag {
+ target: title
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/static.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/static.js
new file mode 100644
index 0000000..a04a474
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/activitymanager/static.js
@@ -0,0 +1,23 @@
+/* vim:set foldmethod=marker:
+
+ SPDX-FileCopyrightText: 2015 Ivan Cukic
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+.pragma library
+
+var currentlyHoveredActivityItem = null;
+
+function showActivityItemActionsBar(activityItem) {
+ if (activityItem === currentlyHoveredActivityItem) {
+ return;
+ }
+
+ if (currentlyHoveredActivityItem !== null) {
+ currentlyHoveredActivityItem.state = "plain";
+ }
+
+ currentlyHoveredActivityItem = activityItem;
+ currentlyHoveredActivityItem.state = "showingControls";
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/AppletError.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/AppletError.qml
new file mode 100644
index 0000000..891153f
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/AppletError.qml
@@ -0,0 +1,262 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Window
+import QtQuick.Controls as QQC2
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.components as PC3
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.plasmoid
+
+PlasmoidItem {
+ id: root
+
+ enum LayoutType {
+ HorizontalPanel,
+ VerticalPanel,
+ Desktop,
+ DesktopCompact
+ }
+
+ property var errorInformation
+
+ readonly property real minimumPreferredWidth: Kirigami.Units.gridUnit * 12
+ readonly property real minimumPreferredHeight: Kirigami.Units.gridUnit * 12
+
+ // To properly show the error message in panel
+ readonly property int layoutForm: {
+ if (fullRepresentationItem.width >= root.minimumPreferredWidth) {
+ if (fullRepresentationItem.height >= root.minimumPreferredHeight) {
+ return AppletError.Desktop;
+ } else if (fullRepresentationItem.height >= Kirigami.Units.iconSizes.huge + root.fullRepresentationItem.buttonLayout.implicitHeight) {
+ return AppletError.DesktopCompact;
+ }
+ }
+
+ return Plasmoid.formFactor === PlasmaCore.Types.Vertical ? AppletError.VerticalPanel : AppletError.HorizontalPanel;
+ }
+ preloadFullRepresentation: true
+ fullRepresentation: GridLayout {
+ id: fullRep
+ property alias buttonLayout: buttonLayout
+ Layout.minimumWidth: {
+ switch (root.layoutForm) {
+ case AppletError.Desktop:
+ case AppletError.DesktopCompact:
+ // [Icon] [Text]
+ // [Button]
+ // [Information]
+ return Math.max(root.minimumPreferredWidth, buttonLayout.implicitWidth);
+ case AppletError.VerticalPanel:
+ // [Icon]
+ // [Copy]
+ // [Open]
+ return Math.max(headerIcon.implicitWidth, buttonLayout.implicitWidth);
+ case AppletError.HorizontalPanel:
+ // [Icon] [Copy] [Open]
+ return headingLayout.implicitWidth + rowSpacing + buttonLayout.implicitWidth;
+ }
+ }
+ Layout.minimumHeight: {
+ switch (root.layoutForm) {
+ case AppletError.Desktop:
+ return headingLayout.implicitHeight + fullRep.columnSpacing + buttonLayout.implicitHeight + fullRep.columnSpacing + fullContentView.implicitHeight;
+ case AppletError.DesktopCompact:
+ return Math.max(headingLayout.implicitHeight, buttonLayout.implicitHeight);
+ case AppletError.VerticalPanel:
+ return headingLayout.implicitHeight + fullRep.columnSpacing + buttonLayout.implicitHeight;
+ case AppletError.HorizontalPanel:
+ return Math.max(headingLayout.implicitHeight, buttonLayout.implicitHeight);
+ }
+ }
+ // Same as systray popups
+ Layout.preferredWidth: Kirigami.Units.gridUnit * 24
+ Layout.preferredHeight: Kirigami.Units.gridUnit * 24
+ Layout.maximumWidth: Kirigami.Units.gridUnit * 34
+ Layout.maximumHeight: Kirigami.Units.gridUnit * 34
+
+ rowSpacing: textArea.topPadding
+ columnSpacing: rowSpacing
+ flow: {
+ switch (root.layoutForm) {
+ case AppletError.HorizontalPanel:
+ return GridLayout.LeftToRight;
+ default:
+ return GridLayout.TopToBottom;
+ }
+ }
+
+ RowLayout {
+ id: headingLayout
+
+ Layout.margins: root.layoutForm !== AppletError.Desktop ? 0 : Kirigami.Units.gridUnit
+ Layout.maximumWidth: fullRep.width
+ spacing: 0
+ Layout.fillWidth: true
+
+ Kirigami.Icon {
+ id: headerIcon
+ implicitWidth: Math.min(Kirigami.Units.iconSizes.huge, fullRep.width, fullRep.height)
+ implicitHeight: implicitWidth
+
+ activeFocusOnTab: true
+ source: "dialog-error"
+
+ Accessible.description: heading.text
+
+ PlasmaCore.ToolTipArea {
+ anchors.fill: parent
+ enabled: !heading.visible || heading.truncated
+ mainText: heading.text
+ textFormat: Text.PlainText
+ }
+ }
+
+ Kirigami.Heading {
+ id: heading
+ visible: root.layoutForm !== AppletError.VerticalPanel
+ // Descent is equal to the amount of space above and below capital letters.
+ // Add descent to the sides to make the spacing around Latin text look more even.
+ leftPadding: headingFontMetrics.descent
+ rightPadding: headingFontMetrics.descent
+ text: root.errorInformation ? root.errorInformation.compactError : "No error information."
+ textFormat: Text.PlainText
+ level: 2
+ wrapMode: Text.Wrap
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ Layout.maximumHeight: headerIcon.implicitHeight
+
+ FontMetrics {
+ id: headingFontMetrics
+ font: heading.font
+ }
+ }
+ }
+
+ GridLayout {
+ id: buttonLayout
+
+ Layout.alignment: Qt.AlignCenter
+
+ rowSpacing: fullRep.rowSpacing
+ columnSpacing: parent.columnSpacing
+ flow: {
+ switch (root.layoutForm) {
+ case AppletError.HorizontalPanel:
+ case AppletError.VerticalPanel:
+ return fullRep.flow;
+ default:
+ return GridLayout.LeftToRight;
+ }
+ }
+
+ PC3.Button {
+ id: copyButton
+ display: root.layoutForm === AppletError.HorizontalPanel || root.layoutForm === AppletError.VerticalPanel ? PC3.AbstractButton.IconOnly : PC3.AbstractButton.TextBesideIcon
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Copy to Clipboard")
+ icon.name: "edit-copy"
+ onClicked: {
+ textArea.selectAll()
+ textArea.copy()
+ textArea.deselect()
+ }
+
+ PlasmaCore.ToolTipArea {
+ anchors.fill: parent
+ enabled: parent.display === PC3.AbstractButton.IconOnly
+ mainText: parent.text
+ textFormat: Text.PlainText
+ }
+ }
+
+ Loader {
+ id: compactContentLoader
+ active: root.layoutForm !== AppletError.Desktop
+ visible: active
+ sourceComponent: PC3.Button {
+ display: copyButton.display
+ icon.name: "window-new"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button opens dialog", "View Error Details…")
+ checked: dialog.visible
+ onClicked: dialog.visible = !dialog.visible
+
+ PlasmaCore.ToolTipArea {
+ anchors.fill: parent
+ enabled: parent.display === PC3.AbstractButton.IconOnly
+ mainText: parent.text
+ textFormat: Text.PlainText
+ }
+
+ QQC2.ApplicationWindow {
+ id: dialog
+ flags: Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint
+ minimumWidth: dialogFontMetrics.height * 12
+ + dialogTextArea.leftPadding + dialogTextArea.rightPadding
+ minimumHeight: dialogFontMetrics.height * 12
+ + dialogTextArea.topPadding + dialogTextArea.bottomPadding
+ width: Kirigami.Units.gridUnit * 24
+ height: Kirigami.Units.gridUnit * 24
+ color: palette.base
+ QQC2.ScrollView {
+ id: dialogScrollView
+ anchors.fill: parent
+ QQC2.TextArea {
+ id: dialogTextArea
+ // HACK: silence binding loop warnings.
+ // contentWidth seems to be causing the binding loop,
+ // but contentWidth is read-only and we have no control
+ // over how it is calculated.
+ implicitWidth: 0
+ wrapMode: TextEdit.Wrap
+ text: textArea.text
+ font.family: "monospace"
+ readOnly: true
+ selectByMouse: true
+ background: null
+ FontMetrics {
+ id: dialogFontMetrics
+ font: dialogTextArea.font
+ }
+ }
+ background: null
+ }
+ }
+ }
+ }
+ }
+
+ PC3.ScrollView {
+ id: fullContentView
+ // Not handled by a Loader because we need
+ // TextEdit::copy() to copy to clipboard.
+ visible: !compactContentLoader.active
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ PC3.TextArea {
+ id: textArea
+ // HACK: silence binding loop warnings.
+ // contentWidth seems to be causing the binding loop,
+ // but contentWidth is read-only and we have no control
+ // over how it is calculated.
+ implicitWidth: 0
+ wrapMode: TextEdit.Wrap
+ text: root.errorInformation && root.errorInformation.errors ?
+ root.errorInformation.errors.join("\n\n")
+ // This is just to suppress warnings. Users should never see this.
+ : "No error information."
+ font.family: "monospace"
+ readOnly: true
+ selectByMouse: true
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/CompactApplet.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/CompactApplet.qml
new file mode 100644
index 0000000..ae7701c
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/CompactApplet.qml
@@ -0,0 +1,369 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Window
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.ksvg as KSvg
+import org.kde.plasma.plasmoid
+import org.kde.kquickcontrolsaddons
+import org.kde.kirigami as Kirigami
+
+PlasmaCore.ToolTipArea {
+ id: root
+ objectName: "org.kde.desktop-CompactApplet"
+ anchors.fill: parent
+
+ mainText: plasmoidItem.toolTipMainText
+ subText: plasmoidItem.toolTipSubText
+ location: Plasmoid.location
+ active: !plasmoidItem.expanded
+ textFormat: plasmoidItem.toolTipTextFormat
+ mainItem: plasmoidItem.toolTipItem ? plasmoidItem.toolTipItem : null
+
+ readonly property bool vertical: location === PlasmaCore.Types.RightEdge || location === PlasmaCore.Types.LeftEdge
+
+ property Item fullRepresentation
+ property Item compactRepresentation
+ property Item expandedFeedback: expandedItem
+ property PlasmoidItem plasmoidItem
+
+ onCompactRepresentationChanged: {
+ if (compactRepresentation) {
+ compactRepresentation.anchors.fill = null;
+ compactRepresentation.parent = compactRepresentationParent;
+ compactRepresentation.anchors.fill = compactRepresentationParent;
+ compactRepresentation.visible = true;
+ }
+ root.visible = true;
+ }
+
+ onFullRepresentationChanged: {
+ if (fullRepresentation) {
+ fullRepresentation.anchors.fill = null;
+ fullRepresentation.parent = appletParent;
+ fullRepresentation.anchors.fill = appletParent;
+
+ // This avoids the content being drawn underneath the
+ // separator between the panel and the applet.
+ if (!separator.visible) {
+ return;
+ }
+ if (Plasmoid.location === PlasmaCore.Types.TopEdge) {
+ fullRepresentation.anchors.topMargin = separator.height
+ } else if (Plasmoid.location === PlasmaCore.Types.BottomEdge) {
+ fullRepresentation.anchors.bottomMargin = separator.height
+ } else if (Plasmoid.location === PlasmaCore.Types.LeftEdge) {
+ fullRepresentation.anchors.leftMargin = separator.width
+ } else if (Plasmoid.location === PlasmaCore.Types.RightEdge) {
+ fullRepresentation.anchors.rightMargin = separator.width
+ }
+ }
+ }
+
+ FocusScope {
+ id: compactRepresentationParent
+ anchors.fill: parent
+ activeFocusOnTab: true
+ onActiveFocusChanged: {
+ // When the scope gets the active focus, try to focus its first descendant,
+ // if there is on which has activeFocusOnTab
+ if (!activeFocus) {
+ return;
+ }
+ let nextItem = nextItemInFocusChain();
+ let candidate = nextItem;
+ while (candidate.parent) {
+ if (candidate === compactRepresentationParent) {
+ nextItem.forceActiveFocus();
+ return;
+ }
+ candidate = candidate.parent;
+ }
+ }
+
+ objectName: "expandApplet"
+ Accessible.name: root.mainText
+ Accessible.description: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:whatsthis Accessible description for panel widget %1", "Open %1", root.subText)
+ Accessible.role: Accessible.Button
+ Accessible.onPressAction: Plasmoid.activated()
+
+ Keys.onPressed: event => {
+ switch (event.key) {
+ case Qt.Key_Space:
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ case Qt.Key_Select:
+ Plasmoid.activated();
+ break;
+ }
+ }
+ }
+
+ KSvg.FrameSvgItem {
+ id: expandedItem
+ z: -100
+
+ property var containerMargins: {
+ let item = root;
+ while (item.parent) {
+ item = item.parent;
+ if (item.isAppletContainer) {
+ return item.getMargins;
+ }
+ }
+ return undefined;
+ }
+
+ anchors {
+ fill: parent
+ property bool returnAllMargins: true
+ // The above makes sure margin is returned even for side margins, that
+ // would be otherwise turned off.
+ bottomMargin: !vertical && containerMargins ? -containerMargins('bottom', returnAllMargins) : 0
+ topMargin: !vertical && containerMargins ? -containerMargins('top', returnAllMargins) : 0
+ leftMargin: vertical && containerMargins ? -containerMargins('left', returnAllMargins) : 0
+ rightMargin: vertical && containerMargins ? -containerMargins('right', returnAllMargins) : 0
+ }
+ imagePath: "widgets/tabbar"
+ visible: opacity > 0
+ prefix: {
+ let prefix;
+ switch (Plasmoid.location) {
+ case PlasmaCore.Types.LeftEdge:
+ prefix = "west-active-tab";
+ break;
+ case PlasmaCore.Types.TopEdge:
+ prefix = "north-active-tab";
+ break;
+ case PlasmaCore.Types.RightEdge:
+ prefix = "east-active-tab";
+ break;
+ default:
+ prefix = "south-active-tab";
+ }
+ if (!hasElementPrefix(prefix)) {
+ prefix = "active-tab";
+ }
+ return prefix;
+ }
+ opacity: root.plasmoidItem.expanded ? 1 : 0
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Kirigami.Units.shortDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+
+ Timer {
+ id: expandedSync
+ interval: 100
+ onTriggered: root.plasmoidItem.expanded = dialog.visible;
+ }
+
+ Connections {
+ target: Plasmoid.internalAction("configure")
+ function onTriggered() {
+ if (root.plasmoidItem.hideOnWindowDeactivate) {
+ root.plasmoidItem.expanded = false
+ }
+ }
+ }
+
+ Connections {
+ target: root.Plasmoid
+ function onContextualActionsAboutToShow() { root.hideImmediately() }
+ }
+
+ PlasmaCore.AppletPopup {
+ id: dialog
+ objectName: "popupWindow"
+
+ popupDirection: {
+ switch (Plasmoid.location) {
+ case PlasmaCore.Types.TopEdge:
+ return Qt.BottomEdge
+ case PlasmaCore.Types.LeftEdge:
+ return Qt.RightEdge
+ case PlasmaCore.Types.RightEdge:
+ return Qt.LeftEdge
+ default:
+ return Qt.TopEdge
+ }
+ }
+ margin: (Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentPrefersFloatingApplets) ? Kirigami.Units.largeSpacing : 0
+
+ Behavior on margin {
+ NumberAnimation {
+ // Since the panel animation won't be perfectly in sync,
+ // using a duration larger than the panel animation results
+ // in a better-looking animation.
+ duration: Kirigami.Units.veryLongDuration
+ easing.type: Easing.OutCubic
+ }
+ }
+
+ floating: Plasmoid.location === PlasmaCore.Types.Floating
+ removeBorderStrategy: Plasmoid.location === PlasmaCore.Types.Floating
+ ? PlasmaCore.AppletPopup.AtScreenEdges
+ : PlasmaCore.AppletPopup.AtScreenEdges | PlasmaCore.AppletPopup.AtPanelEdges
+
+ hideOnWindowDeactivate: root.plasmoidItem.hideOnWindowDeactivate
+ visible: root.plasmoidItem.expanded && root.fullRepresentation
+ visualParent: root.compactRepresentation
+ backgroundHints: (Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentPrefersOpaqueBackground) ? PlasmaCore.AppletPopup.SolidBackground : PlasmaCore.AppletPopup.StandardBackground
+ appletInterface: root.plasmoidItem
+
+ property var oldStatus: PlasmaCore.Types.UnknownStatus
+
+ onVisibleChanged: {
+ if (!visible) {
+ expandedSync.restart();
+ Plasmoid.status = oldStatus;
+ } else {
+ oldStatus = Plasmoid.status;
+ Plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus;
+ // This call currently fails and complains at runtime:
+ // QWindow::setWindowState: QWindow::setWindowState does not accept Qt::WindowActive
+ dialog.requestActivate();
+ }
+ }
+ //It's a MouseEventListener to get all the events, so the eventfilter will be able to catch them
+ mainItem: MouseEventListener {
+ id: appletParent
+
+ focus: true
+
+ Keys.onEscapePressed: {
+ root.plasmoidItem.expanded = false;
+ }
+
+ property real extraWidth: 0
+ property real extraHeight: 0
+
+ Layout.minimumWidth: root.fullRepresentation ? root.fullRepresentation.Layout.minimumWidth + extraWidth : 0
+ Layout.minimumHeight: root.fullRepresentation ? root.fullRepresentation.Layout.minimumHeight + extraHeight : 0
+
+ Layout.maximumWidth: root.fullRepresentation ? root.fullRepresentation.Layout.maximumWidth + extraWidth : Infinity
+ Layout.maximumHeight: root.fullRepresentation ? root.fullRepresentation.Layout.maximumHeight + extraHeight : Infinity
+
+ implicitWidth: {
+ if (root.fullRepresentation !== null) {
+ /****/ if (root.fullRepresentation.Layout.preferredWidth > 0) {
+ return root.fullRepresentation.Layout.preferredWidth + extraWidth;
+ } else if (root.fullRepresentation.implicitWidth > 0) {
+ return root.fullRepresentation.implicitWidth + extraWidth;
+ }
+ }
+ return Kirigami.Units.iconSizes.sizeForLabels * 35;
+ }
+ implicitHeight: {
+ if (root.fullRepresentation !== null) {
+ /****/ if (root.fullRepresentation.Layout.preferredHeight > 0) {
+ return root.fullRepresentation.Layout.preferredHeight + extraHeight;
+ } else if (root.fullRepresentation.implicitHeight > 0) {
+ return root.fullRepresentation.implicitHeight + extraHeight;
+ }
+ }
+ return Kirigami.Units.iconSizes.sizeForLabels * 25;
+ }
+
+ onActiveFocusChanged: {
+ if (activeFocus && root.fullRepresentation) {
+ root.fullRepresentation.forceActiveFocus()
+ }
+ }
+
+ // Draws a line between the applet dialog and the panel
+ KSvg.SvgItem {
+ id: separator
+ // Only draw for popups of panel applets, not desktop applets
+ visible: [PlasmaCore.Types.TopEdge, PlasmaCore.Types.LeftEdge, PlasmaCore.Types.RightEdge, PlasmaCore.Types.BottomEdge]
+ .includes(Plasmoid.location) && !dialog.margin
+ anchors {
+ topMargin: -dialog.topPadding
+ leftMargin: -dialog.leftPadding
+ rightMargin: -dialog.rightPadding
+ bottomMargin: -dialog.bottomPadding
+ }
+ z: 999 /* Draw the line on top of the applet */
+ elementId: (Plasmoid.location === PlasmaCore.Types.TopEdge || Plasmoid.location === PlasmaCore.Types.BottomEdge) ? "horizontal-line" : "vertical-line"
+ imagePath: "widgets/line"
+ states: [
+ State {
+ when: Plasmoid.location === PlasmaCore.Types.TopEdge
+ AnchorChanges {
+ target: separator
+ anchors {
+ top: separator.parent.top
+ left: separator.parent.left
+ right: separator.parent.right
+ }
+ }
+ PropertyChanges {
+ separator.height: 1
+ appletParent.extraHeight: 1
+ appletParent.extraWidth: 0
+ }
+ },
+ State {
+ when: Plasmoid.location === PlasmaCore.Types.LeftEdge
+ AnchorChanges {
+ target: separator
+ anchors {
+ left: separator.parent.left
+ top: separator.parent.top
+ bottom: separator.parent.bottom
+ }
+ }
+ PropertyChanges {
+ separator.width: 1
+ appletParent.extraHeight: 0
+ appletParent.extraWidth: 1
+ }
+ },
+ State {
+ when: Plasmoid.location === PlasmaCore.Types.RightEdge
+ AnchorChanges {
+ target: separator
+ anchors {
+ top: separator.parent.top
+ right: separator.parent.right
+ bottom: separator.parent.bottom
+ }
+ }
+ PropertyChanges {
+ separator.width: 1
+ appletParent.extraHeight: 0
+ appletParent.extraWidth: 1
+ }
+ },
+ State {
+ when: Plasmoid.location === PlasmaCore.Types.BottomEdge
+ AnchorChanges {
+ target: separator
+ anchors {
+ left: separator.parent.left
+ right: separator.parent.right
+ bottom: separator.parent.bottom
+ }
+ }
+ PropertyChanges {
+ separator.height: 1
+ appletParent.extraHeight: 1
+ appletParent.extraWidth: 0
+ }
+ }
+ ]
+ }
+
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/DefaultCompactRepresentation.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/DefaultCompactRepresentation.qml
new file mode 100644
index 0000000..356e495
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/applet/DefaultCompactRepresentation.qml
@@ -0,0 +1,130 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.plasmoid
+import org.kde.plasma.workspace.components as WorkspaceComponents
+import org.kde.kirigami as Kirigami
+
+Kirigami.Icon {
+ id: defaultCompactRepresentation
+ property PlasmoidItem plasmoidItem
+ readonly property bool inPanel: [PlasmaCore.Types.TopEdge, PlasmaCore.Types.RightEdge, PlasmaCore.Types.BottomEdge, PlasmaCore.Types.LeftEdge]
+ .includes(Plasmoid.location)
+
+ Layout.minimumWidth: {
+ switch (Plasmoid.formFactor) {
+ case PlasmaCore.Types.Vertical:
+ return 0;
+ case PlasmaCore.Types.Horizontal:
+ return height;
+ default:
+ return Kirigami.Units.gridUnit * 3;
+ }
+ }
+
+ Layout.minimumHeight: {
+ switch (Plasmoid.formFactor) {
+ case PlasmaCore.Types.Vertical:
+ return width;
+ case PlasmaCore.Types.Horizontal:
+ return 0;
+ default:
+ return Kirigami.Units.gridUnit * 3;
+ }
+ }
+
+ source: Plasmoid.icon || "plasma"
+ active: mouseArea.containsMouse
+
+ activeFocusOnTab: true
+
+ Keys.onPressed: event => {
+ switch (event.key) {
+ case Qt.Key_Space:
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ case Qt.Key_Select:
+ Plasmoid.activated();
+ event.accepted = true; // BUG 481393: Prevent system tray from receiving the event
+ break;
+ }
+ }
+
+ Accessible.name: Plasmoid.title
+ Accessible.description: plasmoidItem.toolTipSubText ?? ""
+ Accessible.role: Accessible.Button
+
+ MouseArea {
+ id: mouseArea
+
+ property bool wasExpanded: false
+
+ anchors.fill: parent
+ hoverEnabled: true
+ onPressed: wasExpanded = defaultCompactRepresentation.plasmoidItem.expanded
+ onClicked: mouse => {
+ if (mouse.button === Qt.MiddleButton) {
+ Plasmoid.secondaryActivated();
+ } else {
+ defaultCompactRepresentation.plasmoidItem.expanded = !wasExpanded;
+ }
+ }
+ }
+
+ // Open the FullRepresentation on drag-hover if the applet wants it
+ Loader {
+ anchors.fill: parent
+
+ active: defaultCompactRepresentation.plasmoidItem.expandedOnDragHover
+
+ sourceComponent: DropArea {
+ anchors.fill: parent
+
+ onEntered: dropTimer.restart()
+ onExited: dropTimer.stop()
+
+ Timer {
+ id: dropTimer
+ interval: 250 // matches taskmanager delay
+ onTriggered: {
+ defaultCompactRepresentation.plasmoidItem.expanded = true;
+ mouseArea.wasExpanded = true;
+ }
+ }
+ }
+ }
+
+ Loader {
+ id: badgeLoader
+
+ anchors.bottom: defaultCompactRepresentation.bottom
+ anchors.right: defaultCompactRepresentation.right
+
+ active: defaultCompactRepresentation.plasmoidItem.badgeText.length != 0
+
+ sourceComponent: WorkspaceComponents.BadgeOverlay {
+ text: defaultCompactRepresentation.plasmoidItem.badgeText
+ icon: defaultCompactRepresentation
+ }
+
+ // Non-default state to center if the badge is wider than the icon
+ states: [
+ State {
+ when: badgeLoader.width >= defaultCompactRepresentation.width
+ AnchorChanges {
+ target: badgeLoader
+ anchors.right: undefined
+ anchors.horizontalCenter: defaultCompactRepresentation.horizontalCenter
+ }
+ }
+ ]
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/AboutPlugin.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/AboutPlugin.qml
new file mode 100644
index 0000000..8c869d6
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/AboutPlugin.qml
@@ -0,0 +1,248 @@
+/*
+ SPDX-FileCopyrightText: 2018 Aleix Pol Gonzalez
+ SPDX-FileCopyrightText: 2020 David Redondo
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+
+import org.kde.plasma.plasmoid
+import org.kde.kirigami as Kirigami
+import org.kde.kcmutils as KCM
+
+/**
+ * A copy of Kirigami.AboutPage adapted to KPluginMetadata instead of KAboutData
+ */
+KCM.SimpleKCM {
+ id: page
+ title: i18nc("@title:window About this widget", "About")
+
+ property var metaData: Plasmoid.metaData
+
+ Component {
+ id: personDelegate
+
+ RowLayout {
+ height: implicitHeight + (Kirigami.Units.smallSpacing * 2)
+
+ spacing: Kirigami.Units.smallSpacing * 2
+ Kirigami.Icon {
+ implicitWidth: Kirigami.Units.iconSizes.smallMedium
+ implicitHeight: implicitWidth
+ source: "user"
+ }
+ QQC2.Label {
+ Layout.fillWidth: true
+ text: modelData.name
+ textFormat: Text.PlainText
+ }
+ Row {
+ // Group action buttons together
+ spacing: 0
+ QQC2.Button {
+ visible: modelData.emailAddress
+ width: height
+ icon.name: "mail-sent"
+
+ display: QQC2.AbstractButton.IconOnly
+ text: i18ndc("@action:button icononly for tooltip & accessible", "plasma_shell_org.kde.plasma.desktop", "Send an email to %1", modelData.emailAddress)
+
+ QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
+ QQC2.ToolTip.visible: hovered
+ QQC2.ToolTip.text: text
+
+ onClicked: Qt.openUrlExternally("mailto:%1".arg(modelData.emailAddress))
+ }
+ QQC2.Button {
+ visible: modelData.webAddress
+ width: height
+ icon.name: "globe"
+
+ display: QQC2.AbstractButton.IconOnly
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button icononly for tooltip & accessible %1 is url", "Open website %1", modelData.webAddress)
+
+ QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
+ QQC2.ToolTip.visible: hovered
+ QQC2.ToolTip.text: modelData.webAddress
+
+ onClicked: Qt.openUrlExternally(modelData.webAddress)
+ }
+ }
+ }
+ }
+
+ Component {
+ id: licenseComponent
+
+ Kirigami.OverlaySheet {
+ property alias text: licenseLabel.text
+
+ onClosed: destroy()
+
+ Kirigami.SelectableLabel {
+ id: licenseLabel
+ implicitWidth: Math.max(Kirigami.Units.gridUnit * 25, Math.round(page.width / 2), contentWidth)
+ wrapMode: Text.WordWrap
+ }
+
+ Component.onCompleted: open();
+ }
+ }
+
+ Item {
+ height: childrenRect.height
+
+ ColumnLayout {
+ id: column
+
+ readonly property int headingTopSpacing: Kirigami.Units.smallSpacing
+ readonly property int dataLeftSpacing: Kirigami.Units.smallSpacing
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: Kirigami.Units.largeSpacing
+
+ GridLayout {
+ columns: 2
+ Layout.fillWidth: true
+
+ Kirigami.Icon {
+ Layout.rowSpan: 2
+ Layout.preferredHeight: Kirigami.Units.iconSizes.huge
+ Layout.preferredWidth: height
+ Layout.maximumWidth: page.width / 3;
+ Layout.rightMargin: Kirigami.Units.largeSpacing
+ source: page.metaData.iconName || page.metaData.pluginId
+ fallback: "application-x-plasma"
+ }
+
+ Kirigami.Heading {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignBottom
+ text: page.metaData.name + " " + page.metaData.version
+ textFormat: Text.PlainText
+ }
+
+ Kirigami.Heading {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignTop
+ Layout.maximumWidth: Kirigami.Units.gridUnit * 15
+ level: 3
+ type: Kirigami.Heading.Type.Secondary
+ wrapMode: Text.WordWrap
+ text: page.metaData.description
+ textFormat: Text.PlainText
+ }
+ }
+
+ Kirigami.Separator {
+ Layout.fillWidth: true
+ }
+
+ Kirigami.Heading {
+ Layout.topMargin: column.headingTopSpacing
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Website")
+ textFormat: Text.PlainText
+ }
+ Kirigami.UrlButton {
+ Layout.leftMargin: column.dataLeftSpacing
+ url: page.metaData.website
+ visible: url.length > 0
+ }
+
+ Kirigami.Heading {
+ Layout.topMargin: column.headingTopSpacing
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Get Help")
+ textFormat: Text.PlainText
+ }
+ Kirigami.UrlButton {
+ Layout.leftMargin: column.dataLeftSpacing
+ textFormat: Text.PlainText
+
+ url: page.metaData.bugReportUrl
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button urlbutton", "Report an issue")
+
+ visible: page.metaData.bugReportUrl.length > 0
+ }
+
+ Kirigami.Heading {
+ Layout.topMargin: column.headingTopSpacing
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title license information", "Copyright")
+ textFormat: Text.PlainText
+ }
+
+ ColumnLayout {
+ spacing: Kirigami.Units.smallSpacing
+ Layout.leftMargin: column.dataLeftSpacing
+
+ QQC2.Label {
+ text: page.metaData.copyrightText
+ textFormat: Text.PlainText
+ visible: text.length > 0
+ }
+
+ RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ QQC2.Label {
+ Layout.fillWidth: true
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@label %1 is the short SPDX text for the license", "License: %1", page.metaData.license)
+ textFormat: Text.PlainText
+ }
+
+ QQC2.Button {
+ icon.name: "view-readermode"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Read License")
+ onClicked: {
+ licenseComponent.incubateObject(page.Window.window.contentItem, {
+ "text": page.metaData.licenseText,
+ "title": page.metaData.license,
+ }, Qt.Asynchronous);
+ }
+ }
+ }
+ }
+
+ Kirigami.Heading {
+ Layout.fillWidth: true
+ Layout.topMargin: column.headingTopSpacing
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Authors")
+ textFormat: Text.PlainText
+ visible: page.metaData.authors.length > 0
+ }
+ Repeater {
+ Layout.leftMargin: column.dataLeftSpacing
+ model: page.metaData.authors
+ delegate: personDelegate
+ }
+
+ Kirigami.Heading {
+ Layout.topMargin: column.headingTopSpacing
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Credits")
+ textFormat: Text.PlainText
+ visible: repCredits.count > 0
+ }
+ Repeater {
+ id: repCredits
+ Layout.leftMargin: column.dataLeftSpacing
+ model: page.metaData.otherContributors
+ delegate: personDelegate
+ }
+
+ Kirigami.Heading {
+ Layout.topMargin: column.headingTopSpacing
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Translators")
+ textFormat: Text.PlainText
+ visible: repTranslators.count > 0
+ }
+ Repeater {
+ id: repTranslators
+ Layout.leftMargin: column.dataLeftSpacing
+ model: page.metaData.translators
+ delegate: personDelegate
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/AppletConfiguration.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/AppletConfiguration.qml
new file mode 100644
index 0000000..00af8c3
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/AppletConfiguration.qml
@@ -0,0 +1,483 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+ SPDX-FileCopyrightText: 2020 Nicolas Fella
+ SPDX-FileCopyrightText: 2020 Carl Schwan
+ SPDX-FileCopyrightText: 2022-2023 ivan tkachenko
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+
+import org.kde.kcmutils as KCMUtils
+import org.kde.kirigami as Kirigami
+import org.kde.kitemmodels as KItemModels
+import org.kde.plasma.configuration
+import org.kde.plasma.plasmoid
+
+Rectangle {
+ id: root
+
+ implicitWidth: Kirigami.Units.gridUnit * 45
+ implicitHeight: Kirigami.Units.gridUnit * 35
+
+ Layout.minimumWidth: Kirigami.Units.gridUnit * 30
+ Layout.minimumHeight: Kirigami.Units.gridUnit * 21
+
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+
+ color: Kirigami.Theme.backgroundColor
+
+ property bool isContainment: false
+
+ property ConfigModel globalConfigModel: globalAppletConfigModel
+
+ property url currentSource
+
+ property bool wasConfigurationChangedSignalSent: false
+
+ function closing() {
+ if (applyButton.enabled) {
+ messageDialog.item = null;
+ messageDialog.open();
+ return false;
+ }
+ return true;
+ }
+
+ function saveConfig() {
+ const config = Plasmoid.configuration; // type: KConfigPropertyMap
+
+ // call applet's own config handling first so it can set cfg_ properties if needed
+ if (app.pageStack.currentItem.saveConfig) {
+ app.pageStack.currentItem.saveConfig()
+ }
+
+ config.keys().forEach(key => {
+ const cfgKey = "cfg_" + key;
+ if (cfgKey in app.pageStack.currentItem) {
+ config[key] = app.pageStack.currentItem[cfgKey];
+ }
+ })
+
+ plasmoid.configuration.writeConfig();
+ }
+
+ function isConfigurationChanged() {
+ const config = Plasmoid.configuration;
+ return config.keys().some(key => {
+ const cfgKey = "cfg_" + key
+ if (!app.pageStack.currentItem.hasOwnProperty(cfgKey))
+ return false
+ return config[key] != app.pageStack.currentItem[cfgKey] &&
+ config[key].toString() != app.pageStack.currentItem[cfgKey].toString()
+ })
+ }
+
+ Connections {
+ target: configDialog
+ function onClosing(event) {
+ event.accepted = closing();
+ }
+ }
+
+ ConfigModel {
+ id: globalAppletConfigModel
+ ConfigCategory {
+ name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group for configuration dialog page", "Keyboard Shortcuts")
+ icon: "preferences-desktop-keyboard"
+ source: Qt.resolvedUrl("ConfigurationShortcuts.qml")
+ }
+ }
+
+ KItemModels.KSortFilterProxyModel {
+ id: configDialogFilterModel
+ sourceModel: configDialog.configModel
+ filterRowCallback: (row, parent) => {
+ return sourceModel.data(sourceModel.index(row, 0), ConfigModel.VisibleRole);
+ }
+ }
+
+ function settingValueChanged() {
+ applyButton.enabled = wasConfigurationChangedSignalSent || isConfigurationChanged() || (app?.pageStack?.currentItem?.unsavedChanges ?? false);
+ }
+
+ function pushReplace(item, config) {
+ let page;
+ if (app.pageStack.depth === 0) {
+ page = app.pageStack.push(item, config);
+ } else {
+ page = app.pageStack.replace(item, config);
+ }
+ app.currentConfigPage = page;
+ }
+
+ function open(item) {
+ app.isAboutPage = false;
+ root.currentSource = item.source
+
+ if (item.configUiModule && item.configUiComponent) {
+ root.currentSource = item.configUiModule + item.configUiComponent; // Just for the highlight status
+ const config = Plasmoid.configuration; // type: KConfigPropertyMap
+
+ const props = {
+ "title": item.name,
+ };
+
+ config.keys().forEach(key => {
+ props["cfg_" + key] = config[key];
+ });
+
+ pushReplace(Qt.createComponent(item.configUiModule, item.configUiComponent), props);
+ } else if (item.source) {
+ app.isAboutPage = item.source === Qt.resolvedUrl("AboutPlugin.qml");
+
+ const config = Plasmoid.configuration; // type: KConfigPropertyMap
+
+ const props = { "title": item.name };
+
+ config.keys().forEach(key => {
+ props["cfg_" + key] = config[key];
+ });
+
+ pushReplace(Qt.resolvedUrl(item.source), props);
+ } else {
+ app.pageStack.pop();
+ }
+
+ applyButton.enabled = false
+ }
+
+ Connections {
+ target: app.currentConfigPage
+ ignoreUnknownSignals: true
+
+ // This is an artifact of old internal architecture. If control beyond the automated
+ // monitoring based on cfg_ properties is required, plasmoids should not emit
+ // settingValueChanged() but configurationChanged() to force prompting the user
+ // for saving changes, or use the unsavedChanges property to dynamically indicate
+ // whether saving is needed in the current state).
+ // We keep it around for now as third-party plasmoids might use it (even though they
+ // really shouldn't as it's not documented).
+ // TODO Plasma 7: remove and document in porting guide.
+ function onSettingValueChanged() {
+ wasConfigurationChangedSignalSent = true;
+ }
+
+ function onUnsavedChangesChanged() {
+ root.settingValueChanged()
+ }
+ }
+
+ Connections {
+ target: app.pageStack
+
+ function onCurrentItemChanged() {
+ if (app.pageStack.currentItem !== null) {
+ const config = Plasmoid.configuration; // type: KConfigPropertyMap
+
+ config.keys().forEach(key => {
+ const changedSignal = app.pageStack.currentItem["cfg_" + key + "Changed"];
+ if (changedSignal) {
+ changedSignal.connect(() => root.settingValueChanged());
+ }
+ });
+
+ const configurationChangedSignal = app.pageStack.currentItem.configurationChanged;
+ if (configurationChangedSignal) {
+ configurationChangedSignal.connect(() => {
+ root.wasConfigurationChangedSignalSent = true
+ root.settingValueChanged()
+ });
+ }
+
+ const configurationUnsavedChangesSignal = app.pageStack.currentItem.unsavedChangesChanged
+ if (configurationUnsavedChangesSignal) {
+ configurationUnsavedChangesSignal.connect(() => root.settingValueChanged())
+ }
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ // if we are a containment then the first item will be ConfigurationContainmentAppearance
+ // if the applet does not have own configs then the first item will be Shortcuts
+ if (isContainment || !configDialog.configModel || configDialog.configModel.count === 0) {
+ open(root.globalConfigModel.get(0))
+ } else {
+ open(configDialog.configModel.get(0))
+ }
+ }
+
+ function applicationWindow() {
+ return app;
+ }
+
+
+ QQC2.ScrollView {
+ id: categoriesScroll
+ anchors {
+ left: parent.left
+ top: parent.top
+ bottom: parent.bottom
+ }
+ width: Kirigami.Units.gridUnit * 7
+ contentWidth: availableWidth
+ Kirigami.Theme.colorSet: Kirigami.Theme.View
+ Kirigami.Theme.inherit: false
+ activeFocusOnTab: true
+ focus: true
+ Accessible.role: Accessible.PageTabList
+ background: Rectangle {
+ color: Kirigami.Theme.backgroundColor
+ }
+
+ Keys.onUpPressed: {
+ const buttons = categories.children
+
+ let foundPrevious = false
+ for (let i = buttons.length - 1; i >= 0; --i) {
+ const button = buttons[i];
+ if (!button.hasOwnProperty("highlighted")) {
+ // not a ConfigCategoryDelegate
+ continue;
+ }
+
+ if (foundPrevious) {
+ categories.openCategory(button.item)
+ categoriesScroll.forceActiveFocus(Qt.TabFocusReason)
+ return
+ } else if (button.highlighted) {
+ foundPrevious = true
+ }
+ }
+
+ event.accepted = false
+ }
+
+ Keys.onDownPressed: {
+ const buttons = categories.children
+
+ let foundNext = false
+ for (let i = 0, length = buttons.length; i < length; ++i) {
+ const button = buttons[i];
+ if (!button.hasOwnProperty("highlighted")) {
+ continue;
+ }
+
+ if (foundNext) {
+ categories.openCategory(button.item)
+ categoriesScroll.forceActiveFocus(Qt.TabFocusReason)
+ return
+ } else if (button.highlighted) {
+ foundNext = true
+ }
+ }
+
+ event.accepted = false
+ }
+
+ ColumnLayout {
+ id: categories
+
+ spacing: 0
+ width: categoriesScroll.contentWidth
+ focus: true
+
+ function openCategory(item) {
+ if (applyButton.enabled) {
+ messageDialog.item = item;
+ messageDialog.open();
+ return;
+ }
+ open(item)
+ }
+
+ Component {
+ id: categoryDelegate
+ ConfigCategoryDelegate {
+ id: delegate
+ onActivated: categories.openCategory(model);
+ highlighted: {
+ if (app.pageStack.currentItem) {
+ if (model.configUiModule && model.configUiComponent) {
+ return root.currentSource == (model.configUiModule + model.configUiComponent)
+ } else {
+ return root.currentSource == model.source
+ }
+ }
+ return false
+ }
+ item: model
+ }
+ }
+
+ Repeater {
+ Layout.fillWidth: true
+ model: root.isContainment ? globalConfigModel : undefined
+ delegate: categoryDelegate
+ }
+ Repeater {
+ Layout.fillWidth: true
+ model: configDialogFilterModel
+ delegate: categoryDelegate
+ }
+ Repeater {
+ Layout.fillWidth: true
+ model: !root.isContainment ? globalConfigModel : undefined
+ delegate: categoryDelegate
+ }
+ Repeater {
+ Layout.fillWidth: true
+ model: ConfigModel {
+ ConfigCategory{
+ name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group for About dialog page", "About")
+ icon: "help-about"
+ source: Qt.resolvedUrl("AboutPlugin.qml")
+ }
+ }
+ delegate: categoryDelegate
+ }
+ }
+ }
+
+ Kirigami.Separator {
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: parent.top
+ }
+ z: 1
+ }
+ Kirigami.Separator {
+ id: verticalSeparator
+ anchors {
+ top: parent.top
+ left: categoriesScroll.right
+ bottom: parent.bottom
+ }
+ z: 1
+ }
+
+ Kirigami.ApplicationItem {
+ id: app
+ anchors {
+ top: parent.top
+ left: verticalSeparator.right
+ right: parent.right
+ bottom: parent.bottom
+ }
+
+ pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.Auto
+ wideScreen: true
+ pageStack.globalToolBar.separatorVisible: bottomSeparator.visible
+ pageStack.globalToolBar.colorSet: Kirigami.Theme.Window
+
+ property var currentConfigPage: null
+ property bool isAboutPage: false
+
+ Kirigami.PromptDialog {
+ id: messageDialog
+ property var item
+ title: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:window dialog title", "Apply Settings")
+ subtitle: i18ndc("plasma_shell_org.kde.plasma.desktop", "@label dialog body", "The current page has unsaved changes. Apply the changes or discard them?")
+ standardButtons: Kirigami.Dialog.Apply | Kirigami.Dialog.Discard | Kirigami.Dialog.Cancel
+ onApplied: {
+ applyAction.trigger()
+ discarded();
+ }
+ onDiscarded: {
+ wasConfigurationChangedSignalSent = false;
+ if (item) {
+ root.open(item);
+ messageDialog.close();
+ } else {
+ applyButton.enabled = false;
+ configDialog.close();
+ }
+ }
+ }
+
+ footer: QQC2.Pane {
+
+ padding: Kirigami.Units.largeSpacing
+
+ contentItem: RowLayout {
+ id: buttonsRow
+ spacing: Kirigami.Units.smallSpacing
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ QQC2.Button {
+ icon.name: "dialog-ok"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "OK")
+ onClicked: acceptAction.trigger()
+ }
+ QQC2.Button {
+ id: applyButton
+ enabled: false
+ icon.name: "dialog-ok-apply"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Apply")
+ visible: !app.isAboutPage && app.pageStack.currentItem
+ onClicked: applyAction.trigger()
+ }
+ QQC2.Button {
+ icon.name: "dialog-cancel"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Cancel")
+ onClicked: cancelAction.trigger()
+ visible: !app.isAboutPage
+ KeyNavigation.tab: categories
+ }
+ }
+ background: Item {
+ Kirigami.Separator {
+ id: bottomSeparator
+ visible: (app.pageStack.currentItem
+ && app.pageStack.currentItem.flickable
+ && !(app.pageStack.currentItem.flickable instanceof KCMUtils.GridViewKCM)
+ && !(app.pageStack.currentItem.flickable.atYBeginning
+ && app.pageStack.currentItem.flickable.atYEnd)) ?? false
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: parent.top
+ }
+ }
+ }
+ }
+
+ QQC2.Action {
+ id: acceptAction
+ onTriggered: {
+ applyAction.trigger();
+ configDialog.close();
+ }
+ }
+
+ QQC2.Action {
+ id: applyAction
+ onTriggered: {
+ root.saveConfig()
+ wasConfigurationChangedSignalSent = false
+ applyButton.enabled = false;
+ }
+ }
+
+ QQC2.Action {
+ id: cancelAction
+ onTriggered: {
+ if (root.closing()) {
+ configDialog.close();
+ }
+ }
+ }
+
+ Keys.onReturnPressed: acceptAction.trigger();
+ Keys.onEscapePressed: cancelAction.trigger();
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigCategoryDelegate.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigCategoryDelegate.qml
new file mode 100644
index 0000000..83d0fe5
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigCategoryDelegate.qml
@@ -0,0 +1,72 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+ SPDX-FileCopyrightText: 2020 Carl Schwan
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls as QQC2
+import QtQuick.Window
+
+import org.kde.kirigami as Kirigami
+
+QQC2.ItemDelegate {
+ id: delegate
+
+ signal activated()
+
+//BEGIN properties
+ Layout.fillWidth: true
+ hoverEnabled: true
+
+ Accessible.role: Accessible.PageTab
+ Accessible.name: model.name
+ Accessible.description: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:whatsthis Accessible description for sidebar entries opening configuration page", "Open configuration page")
+ Accessible.onPressAction: delegate.clicked()
+
+ focus: highlighted // need to actually focus highlighted items for the screen reader to see them
+
+ property var item
+//END properties
+
+//BEGIN connections
+ onClicked: {
+ if (highlighted) {
+ return;
+ }
+
+ activated()
+ }
+//END connections
+
+//BEGIN UI components
+ contentItem: ColumnLayout {
+ id: delegateContents
+ spacing: Kirigami.Units.smallSpacing
+
+ Kirigami.Icon {
+ Layout.alignment: Qt.AlignHCenter
+ implicitWidth: Kirigami.Units.iconSizes.medium
+ implicitHeight: Kirigami.Units.iconSizes.medium
+ source: model.icon
+ selected: Window.active && (delegate.highlighted || delegate.pressed)
+ }
+
+ QQC2.Label {
+ id: nameLabel
+ Layout.fillWidth: true
+ Layout.leftMargin: Kirigami.Units.smallSpacing
+ Layout.rightMargin: Kirigami.Units.smallSpacing
+ text: model.name
+ textFormat: Text.PlainText
+ wrapMode: Text.Wrap
+ horizontalAlignment: Text.AlignHCenter
+ color: Window.active && (delegate.highlighted || delegate.pressed) ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
+ font.bold: delegate.highlighted && delegate.parent.activeFocus
+ Accessible.ignored: true
+ }
+ }
+//END UI components
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationContainmentActions.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationContainmentActions.qml
new file mode 100644
index 0000000..5cac407
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationContainmentActions.qml
@@ -0,0 +1,146 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+
+import org.kde.kcmutils as KCM
+
+KCM.SimpleKCM {
+ id: root
+
+ signal configurationChanged
+
+ property var prettyStrings: {
+ "LeftButton": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Left-Button"),
+ "RightButton": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Right-Button"),
+ "MiddleButton": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Middle-Button"),
+ "BackButton": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Back-Button"),
+ "ForwardButton": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Forward-Button"),
+
+ "wheel:Vertical": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Vertical-Scroll"),
+ "wheel:Horizontal": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Horizontal-Scroll"),
+
+ "ShiftModifier": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Shift"),
+ "ControlModifier": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Ctrl"),
+ "AltModifier": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Alt"),
+ "MetaModifier": i18ndc("plasma_shell_org.kde.plasma.desktop", "@label for shortcuts", "Meta")
+ }
+
+ function saveConfig() {
+ configDialog.currentContainmentActionsModel.save();
+ }
+
+ Connections {
+ target: configDialog.currentContainmentActionsModel
+ function onConfigurationChanged() {
+ root.configurationChanged()
+ }
+ }
+
+ GridLayout {
+ id: mainColumn
+ flow: GridLayout.TopToBottom
+ width: parent.width
+
+ Repeater {
+ id: actionsRepeater
+ model: configDialog.currentContainmentActionsModel
+
+ MouseEventInputButton {
+ Layout.column: 0
+ Layout.row: index
+ Layout.fillWidth: true
+ Layout.minimumWidth: implicitWidth
+ defaultText: {
+ var splitAction = model.action.split(';');
+
+ var button = splitAction[0];
+ var modifiers = (splitAction[1] || "").split('|').filter(function (item) {
+ return item !== "NoModifier";
+ });
+
+ var parts = modifiers;
+ modifiers.push(button);
+
+ return parts.map(function (item) {
+ return root.prettyStrings[item] || item;
+ }).join(i18ndc("plasma_shell_org.kde.plasma.desktop", "Concatenation sign for shortcuts, e.g. Ctrl+Shift", "+"));
+ }
+ eventString: model.action
+ onEventStringChanged: {
+ configDialog.currentContainmentActionsModel.update(index, eventString, model.pluginName);
+ }
+ }
+ }
+
+ Repeater {
+ model: configDialog.currentContainmentActionsModel
+
+ QQC2.ComboBox {
+ id: pluginsCombo
+ // "index" argument of onActivated shadows the model index
+ readonly property int pluginIndex: index
+ Layout.fillWidth: true
+ Layout.column: 1
+ Layout.row: index
+ // both MouseEventInputButton and this ComboBox have fillWidth for a uniform layout
+ // however, their implicit sizes is taken into account and they compete against
+ // each other for available space. By setting an insane preferredWidth we give
+ // ComboBox a greater share of the available space
+ Layout.preferredWidth: 9000
+ model: configDialog.containmentActionConfigModel
+ textRole: "name"
+ valueRole: "pluginName"
+ property bool initialized: false
+ Component.onCompleted: {
+ currentIndex = indexOfValue(pluginName)
+ pluginsCombo.initialized = true;
+ }
+ onActivated: {
+ if (initialized) {
+ var newPluginName = currentValue;
+ if (newPluginName !== pluginName) {
+ configDialog.currentContainmentActionsModel.update(pluginIndex, action, newPluginName);
+ }
+ }
+ }
+ }
+ }
+
+ Repeater {
+ model: configDialog.currentContainmentActionsModel
+
+ RowLayout {
+ Layout.column: 2
+ Layout.row: index
+
+ QQC2.Button {
+ icon.name: "configure"
+ enabled: model.hasConfigurationInterface
+ onClicked: {
+ configDialog.currentContainmentActionsModel.showConfiguration(index, this);
+ }
+ }
+ QQC2.Button {
+ icon.name: "list-remove"
+ onClicked: {
+ configDialog.currentContainmentActionsModel.remove(index);
+ }
+ }
+ }
+ }
+
+ MouseEventInputButton {
+ defaultText: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Add Action");
+ icon.name: checked ? "input-mouse-symbolic" : "list-add"
+ onEventStringChanged: {
+ configDialog.currentContainmentActionsModel.append(eventString, "org.kde.contextmenu");
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationContainmentAppearance.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationContainmentAppearance.qml
new file mode 100644
index 0000000..29fa866
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationContainmentAppearance.qml
@@ -0,0 +1,253 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+import QtQml
+
+import org.kde.newstuff as NewStuff
+import org.kde.kirigami as Kirigami
+import org.kde.kcmutils
+import org.kde.plasma.plasmoid
+import org.kde.plasma.configuration
+
+SimpleKCM {
+ id: appearanceRoot
+ signal configurationChanged
+
+ leftPadding: 0 // let wallpaper config touch the edges in case there's a List/GridView'
+ rightPadding: 0
+ bottomPadding: 0
+
+ property int formAlignment: wallpaperComboBox.Kirigami.ScenePosition.x - appearanceRoot.Kirigami.ScenePosition.x + Kirigami.Units.smallSpacing
+ property string originalWallpaper: ""
+ property alias parentLayout: parentLayout
+ property bool unsavedChanges: false
+
+ function saveConfig() {
+ if (main.currentItem.saveConfig) {
+ main.currentItem.saveConfig()
+ }
+ configDialog.currentWallpaper = wallpaperComboBox.currentValue
+ appearanceRoot.originalWallpaper = wallpaperComboBox.currentValue
+ configDialog.wallpaperConfiguration.keys().forEach(key => {
+ if (main.currentItem["cfg_"+key] !== undefined) {
+ configDialog.wallpaperConfiguration[key] = main.currentItem["cfg_"+key]
+ }
+ })
+ configDialog.applyWallpaper()
+ configDialog.containmentPlugin = pluginComboBox.currentValue
+ appearanceRoot.closeContainmentWarning()
+ appearanceRoot.unsavedChanges = false
+ }
+
+ function checkUnsavedChanges() {
+ const wallpaperConfig = configDialog.wallpaperConfiguration
+ appearanceRoot.unsavedChanges = configDialog.currentWallpaper != appearanceRoot.originalWallpaper ||
+ configDialog.containmentPlugin != pluginComboBox.currentValue ||
+ wallpaperConfig.keys().some(key => {
+ const cfgKey = "cfg_" + key
+ if (!(cfgKey in main.currentItem) || key.startsWith("PreviewImage") || key.endsWith("Default")) {
+ return false
+ }
+ return main.currentItem[cfgKey] != wallpaperConfig[key] &&
+ main.currentItem[cfgKey].toString() != wallpaperConfig[key].toString()
+ })
+ }
+
+ function closeContainmentWarning() {
+ if (main.currentItem?.objectName === "switchContainmentWarningItem") {
+ main.pop();
+ categoriesScroll.enabled = true;
+ }
+ }
+
+ ColumnLayout {
+ width: appearanceRoot.availableWidth
+ height: Math.max(implicitHeight, appearanceRoot.availableHeight)
+ spacing: 0 // unless it's 0 there will be an additional gap between two FormLayouts
+
+ Kirigami.InlineMessage {
+ visible: Plasmoid.immutable || animating
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:status inlinemessage", "Layout changes have been restricted by the system administrator")
+ showCloseButton: true
+ Layout.fillWidth: true
+ Layout.leftMargin: Kirigami.Units.smallSpacing
+ Layout.rightMargin: Kirigami.Units.smallSpacing
+ Layout.bottomMargin: Kirigami.Units.smallSpacing * 2 // we need this because ColumnLayout's spacing is 0
+ }
+
+ Kirigami.FormLayout {
+ id: parentLayout // needed for twinFormLayouts to work in wallpaper plugins
+ twinFormLayouts: main.currentItem.formLayout || []
+ Layout.fillWidth: true
+ QQC2.ComboBox {
+ id: pluginComboBox
+ Layout.preferredWidth: Math.max(implicitWidth, wallpaperComboBox.implicitWidth)
+ Kirigami.FormData.label: i18ndc("plasma_shell_org.kde.plasma.desktop", "@label:listbox", "Layout:")
+ enabled: !Plasmoid.immutable
+ model: configDialog.containmentPluginsConfigModel
+ textRole: "name"
+ valueRole: "pluginName"
+ onActivated: {
+ if (configDialog.containmentPlugin !== pluginComboBox.currentValue) {
+ main.push(switchContainmentWarning);
+ categoriesScroll.enabled = false;
+ } else {
+ closeContainmentWarning()
+ }
+ appearanceRoot.checkUnsavedChanges()
+ }
+ Component.onCompleted: {
+ currentIndex = indexOfValue(configDialog.containmentPlugin)
+ activated(currentIndex)
+ }
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ enabled: main.currentItem.objectName !== "switchContainmentWarningItem"
+ Kirigami.FormData.label: i18ndc("plasma_shell_org.kde.plasma.desktop", "@label:listbox", "Wallpaper type:")
+ Kirigami.FormData.buddyFor: wallpaperComboBox
+
+ QQC2.ComboBox {
+ id: wallpaperComboBox
+
+ function selectCurrentWallpaperPlugin() {
+ currentIndex = indexOfValue(configDialog.currentWallpaper)
+ appearanceRoot.originalWallpaper = currentValue
+ activated(currentIndex)
+ }
+
+ Layout.preferredWidth: Math.max(implicitWidth, pluginComboBox.implicitWidth)
+ model: configDialog.wallpaperConfigModel
+ textRole: "name"
+ valueRole: "pluginName"
+ onActivated: {
+ var idx = configDialog.wallpaperConfigModel.index(currentIndex, 0)
+ if (configDialog.currentWallpaper === currentValue && main.sourceFile !== "tbd") {
+ return;
+ }
+ configDialog.currentWallpaper = currentValue
+ main.sourceFile = idx.data(ConfigModel.SourceRole)
+ appearanceRoot.checkUnsavedChanges()
+ }
+ Component.onCompleted: {
+ selectCurrentWallpaperPlugin();
+ }
+
+ Connections {
+ enabled: true
+ target: configDialog.wallpaperConfigModel
+ function onWallpaperPluginsChanged() {
+ wallpaperComboBox.selectCurrentWallpaperPlugin();
+ }
+ }
+ }
+ NewStuff.Button {
+ configFile: "wallpaperplugin.knsrc"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Get New Plugins…")
+ visibleWhenDisabled: true // don't hide on disabled
+ Layout.preferredHeight: wallpaperComboBox.height
+ }
+ }
+ }
+
+ Item {
+ id: emptyConfig
+ }
+
+ QQC2.StackView {
+ id: main
+
+ implicitHeight: main.empty ? 0 : currentItem.implicitHeight
+
+ Layout.fillHeight: true;
+ Layout.fillWidth: true;
+
+ // Bug 360862: if wallpaper has no config, sourceFile will be ""
+ // so we wouldn't load emptyConfig and break all over the place
+ // hence set it to some random value initially
+ property string sourceFile: "tbd"
+
+ onSourceFileChanged: loadSourceFile()
+
+ function loadSourceFile() {
+ const wallpaperConfig = configDialog.wallpaperConfiguration
+ // BUG 407619: wallpaperConfig can be null before calling `ContainmentItem::loadWallpaper()`
+ if (wallpaperConfig && sourceFile) {
+ var props = {
+ "configDialog": configDialog,
+ "wallpaperConfiguration": Qt.binding(() => Plasmoid.wallpaperGraphicsObject.configuration)
+ }
+
+ // Some third-party wallpaper plugins need the config keys to be set initially.
+ // We should not break them within one Plasma major version, but setting everything
+ // will lead to an error message for every unused property (and some, like KConfigXT
+ // default values, are used by almost no plugin configuration). We load the config
+ // page in a temp variable first, then use that to figure out which ones we need to
+ // set initially.
+ // TODO Plasma 7: consider whether we can drop this workaround
+ const temp = Qt.createComponent(Qt.resolvedUrl(sourceFile)).createObject(appearanceRoot, props)
+ wallpaperConfig.keys().forEach(key => {
+ const cfgKey = "cfg_" + key;
+ if (cfgKey in temp) {
+ props[cfgKey] = wallpaperConfig[key]
+ }
+ })
+ temp.destroy()
+
+ var newItem = replace(Qt.resolvedUrl(sourceFile), props)
+
+ wallpaperConfig.keys().forEach(key => {
+ const cfgKey = "cfg_" + key;
+ if (cfgKey in newItem) {
+ let changedSignal = main.currentItem[cfgKey + "Changed"]
+ if (changedSignal) {
+ changedSignal.connect(appearanceRoot.checkUnsavedChanges)
+ }
+ }
+ });
+
+ const configurationChangedSignal = newItem.configurationChanged
+ if (configurationChangedSignal) {
+ configurationChangedSignal.connect(appearanceRoot.configurationChanged)
+ }
+ } else {
+ replace(emptyConfig)
+ }
+ }
+ }
+
+ Kirigami.Separator {
+ Layout.fillWidth: true
+ }
+ }
+
+ Component {
+ id: switchContainmentWarning
+
+ Item {
+ objectName: "switchContainmentWarningItem"
+
+ Kirigami.PlaceholderMessage {
+ id: message
+ width: parent.width - Kirigami.Units.largeSpacing * 8
+ anchors.centerIn: parent
+
+ icon.name: "documentinfo"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info", "Layout changes must be applied before other changes can be made")
+
+ helpfulAction: QQC2.Action {
+ icon.name: "dialog-ok-apply"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Apply Now")
+ onTriggered: appearanceRoot.saveConfig()
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationShortcuts.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationShortcuts.qml
new file mode 100644
index 0000000..df6929e
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ConfigurationShortcuts.qml
@@ -0,0 +1,35 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.kquickcontrols
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.plasmoid
+import org.kde.kcmutils as KCM
+
+KCM.SimpleKCM {
+ id: root
+
+ title: i18nc("@title:window for configuration page", "Shortcuts")
+
+ property bool unsavedChanges: false
+
+ function saveConfig() {
+ Plasmoid.globalShortcut = button.keySequence
+ unsavedChanges = false
+ }
+
+ Kirigami.FormLayout {
+
+ KeySequenceItem {
+ id: button
+ Kirigami.FormData.label: i18nc("@action:button set keyboard shortcut for", "Activate widget as if clicked:")
+ keySequence: Plasmoid.globalShortcut
+ patterns: ShortcutPattern.Modifier | ShortcutPattern.ModifierAndKey
+ onKeySequenceModified: root.unsavedChanges = keySequence !== Plasmoid.globalShortcut
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ContainmentConfiguration.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ContainmentConfiguration.qml
new file mode 100644
index 0000000..8b9dbea
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ContainmentConfiguration.qml
@@ -0,0 +1,38 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.configuration
+
+AppletConfiguration {
+ id: root
+ isContainment: true
+ Layout.minimumWidth: Kirigami.Units.gridUnit * 35
+ Layout.minimumHeight: Kirigami.Units.gridUnit * 30
+ Layout.preferredWidth: Kirigami.Units.gridUnit * 32
+ Layout.preferredHeight: Kirigami.Units.gridUnit * 36
+
+//BEGIN model
+ globalConfigModel: globalContainmentConfigModel
+
+ ConfigModel {
+ id: globalContainmentConfigModel
+ ConfigCategory {
+ name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group for configuration dialog page", "Wallpaper")
+ icon: "preferences-desktop-wallpaper"
+ source: "ConfigurationContainmentAppearance.qml"
+ }
+ ConfigCategory {
+ name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group for configuration dialog page", "Mouse Actions")
+ icon: "preferences-desktop-mouse"
+ source: "ConfigurationContainmentActions.qml"
+ }
+ }
+//END model
+
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/MouseEventInputButton.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/MouseEventInputButton.qml
new file mode 100644
index 0000000..aeb4f83
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/MouseEventInputButton.qml
@@ -0,0 +1,57 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+
+
+QQC2.Button {
+ id: mouseInputButton
+ property string defaultText: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button inactive state for button recording mouse input" ,"Add Action")
+ text: defaultText
+ checkable: true
+ property string eventString
+
+ onCheckedChanged: {
+ if (checked) {
+ text = i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button active state for button recording mouse input", "Input Here");
+ mouseInputArea.enabled = true;
+ }
+ }
+ MouseArea {
+ id: mouseInputArea
+ anchors.fill: parent
+ acceptedButtons: Qt.AllButtons
+ enabled: false
+
+ onClicked: mouse => {
+ var newEventString = configDialog.currentContainmentActionsModel.mouseEventString(mouse.button, mouse.modifiers);
+
+ if (mouseInputButton.eventString === newEventString || !configDialog.currentContainmentActionsModel.isTriggerUsed(newEventString)) {
+ if (mouseInputButton.eventString === newEventString) {
+ // fire changed signal so deleted button can return if needed
+ mouseInputButton.eventStringChanged()
+ } else {
+ mouseInputButton.eventString = newEventString;
+ }
+ mouseInputButton.text = mouseInputButton.defaultText;
+ mouseInputButton.checked = false;
+ enabled = false;
+ }
+ }
+
+ onWheel: wheel => {
+ var newEventString = configDialog.currentContainmentActionsModel.wheelEventString(wheel);
+
+ if (mouseInputButton.eventString === newEventString || !configDialog.currentContainmentActionsModel.isTriggerUsed(newEventString)) {
+ mouseInputButton.eventString = newEventString;
+ mouseInputButton.text = mouseInputButton.defaultText;
+ mouseInputButton.checked = false;
+ enabled = false;
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/PanelConfiguration.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/PanelConfiguration.qml
new file mode 100644
index 0000000..3343177
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/PanelConfiguration.qml
@@ -0,0 +1,762 @@
+/*
+ SPDX-FileCopyrightText: 2023 Niccolò Venerandi
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls as QQC2
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.components as PC3
+import org.kde.plasma.shell.panel as Panel
+import org.kde.kquickcontrols
+import "panelconfiguration"
+
+ColumnLayout {
+ id: dialogRoot
+ spacing: Kirigami.Units.largeSpacing * 2
+
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+
+ signal closeContextMenu
+
+ required property QtObject panelConfiguration
+
+ property bool vertical: (panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge)
+
+ readonly property int headingLevel: 2
+
+ property Item panelRuler: Ruler {
+ id: ruler
+
+ prefix: {
+ switch (panel.location) {
+ case PlasmaCore.Types.TopEdge:
+ return "north"
+ case PlasmaCore.Types.LeftEdge:
+ return "west"
+ case PlasmaCore.Types.RightEdge:
+ return "east"
+ case PlasmaCore.Types.BottomEdge:
+ default:
+ return "south"
+ }
+ }
+ Item {
+ activeFocusOnTab: true
+ onActiveFocusChanged: {
+ if (activeFocus && dialogRoot.Window.window && dialogRoot.Window.window.visible) {
+ dialogRoot.Window.window.requestActivate()
+ }
+ }
+ }
+ // This item is used to "pass" focus to the main window when we're at the last of the control of the ruler
+ Item {
+ parent: dialogRoot.parent // Used to not take space in the ColumnLayout
+ activeFocusOnTab: true
+ onActiveFocusChanged: {
+ let window = dialogRoot.Window.window
+ if (activeFocus && window && window.visible) {
+ window.requestActivate()
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: panel
+ function onOffsetChanged() {
+ ruler.offset = panel.offset
+ }
+ function onMinimumLengthChanged() {
+ ruler.minimumLength = panel.minimumLength
+ }
+ function onMaximumLengthChanged() {
+ ruler.maximumLength = panel.maximumLength
+ }
+ }
+
+ Component.onCompleted: {
+ if (panel.lengthMode === Panel.Global.Custom) {
+ Qt.callLater(()=> {
+ panelConfiguration.panelRulerView.visible = true
+ })
+ }
+ }
+
+
+ PlasmaExtras.PlasmoidHeading {
+ RowLayout {
+ anchors.fill: parent
+ spacing: Kirigami.Units.largeSpacing
+
+ Kirigami.Heading {
+ Layout.leftMargin: Kirigami.Units.smallSpacing
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:window", "Panel Settings")
+ textFormat: Text.PlainText
+ }
+
+ Item { Layout.fillWidth: true }
+
+ PC3.ToolButton {
+ id: addNewButton
+
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button label of button to open a menu that lets you add widgets or spacers", "Add New")
+ icon.name: "list-add-symbolic"
+ down: addMenu.opened
+ Accessible.role: Accessible.ButtonMenu
+
+ onClicked: {
+ if (addMenu.visible) {
+ addMenu.dismiss();
+ } else {
+ addMenu.open();
+ }
+ }
+
+ PC3.Menu {
+ id: addMenu
+ y: addNewButton.height
+
+ PC3.MenuItem {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:menu add a spacer", "Spacer")
+ icon.name: "distribute-horizontal-x"
+
+ onClicked: configDialog.addPanelSpacer()
+ }
+
+ PC3.MenuItem {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:menu add a widget", "Widgets…")
+ icon.name: "view-group-symbolic"
+ onClicked: {
+ configDialog.close()
+ configDialog.showAddWidgetDialog()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ GridLayout {
+ Layout.leftMargin: columnSpacing
+ Layout.rightMargin: columnSpacing
+ Layout.alignment: Qt.AlignHCenter
+ Layout.minimumWidth: (positionRepresentation.implicitWidth + columnSpacing) * columns + columnSpacing
+ rowSpacing: dialogRoot.spacing
+ columnSpacing: Kirigami.Units.smallSpacing
+ rows: 2
+ columns: 3
+ uniformCellWidths: true
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: Kirigami.Units.mediumSpacing
+ Kirigami.Heading {
+ Layout.alignment: Qt.AlignHCenter
+ level: dialogRoot.headingLevel
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Position")
+ textFormat: Text.PlainText
+ }
+ PanelRepresentation {
+ id: positionRepresentation
+ text: (panel.location === PlasmaCore.Types.TopEdge ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@label panel screen edge", "Top") :
+ panel.location === PlasmaCore.Types.RightEdge ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@label panel screen edge", "Right") :
+ panel.location === PlasmaCore.Types.LeftEdge ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@label panel screen edge", "Left") :
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@label panel screen edge", "Bottom"))
+ Layout.alignment: Qt.AlignHCenter
+ alignment: (panel.location === PlasmaCore.Types.TopEdge ? Qt.AlignHCenter | Qt.AlignTop :
+ panel.location === PlasmaCore.Types.RightEdge ? Qt.AlignVCenter | Qt.AlignRight :
+ panel.location === PlasmaCore.Types.LeftEdge ? Qt.AlignVCenter | Qt.AlignLeft :
+ Qt.AlignHCenter | Qt.AlignBottom)
+ isVertical: dialogRoot.vertical
+ mainIconSource: (panel.location === PlasmaCore.Types.TopEdge ? "arrow-up" :
+ panel.location === PlasmaCore.Types.RightEdge ? "arrow-right" :
+ panel.location === PlasmaCore.Types.LeftEdge ? "arrow-left": "arrow-down")
+ onClicked: {
+ setPositionButton.checked = !setPositionButton.checked
+ setPositionButton.forceActiveFocus()
+ }
+ }
+ PC3.Button {
+ id: setPositionButton
+ Layout.minimumHeight: transparencyBox.height
+ Layout.minimumWidth: positionRepresentation.width
+ Layout.alignment: Qt.AlignHCenter
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "action:button", "Set Position…")
+ checkable: true
+
+ function moveTo(newLocation: int, associatedWindow = null) {
+ if (!setPositionButton.checked) {
+ return;
+ }
+ panel.location = newLocation;
+ if (associatedWindow !== null) {
+ panel.screenToFollow = dialogRoot.panelConfiguration.screenFromWindow(associatedWindow);
+ }
+ setPositionButton.checked = false;
+ }
+
+ Keys.onLeftPressed: moveTo(PlasmaCore.Types.LeftEdge)
+ Keys.onRightPressed: moveTo(PlasmaCore.Types.RightEdge)
+ Keys.onUpPressed: moveTo(PlasmaCore.Types.TopEdge)
+ Keys.onDownPressed: moveTo(PlasmaCore.Types.BottomEdge)
+ }
+ }
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: Kirigami.Units.mediumSpacing
+ Kirigami.Heading {
+ Layout.alignment: Qt.AlignHCenter
+ level: dialogRoot.headingLevel
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Alignment")
+ textFormat: Text.PlainText
+ }
+ PanelRepresentation {
+ id: alignmentRepresentation
+ Layout.alignment: Qt.AlignHCenter
+ mainIconSource: {
+ if (dialogRoot.vertical) {
+ if (alignmentBox.previewIndex === 0) {
+ return "align-vertical-top"
+ } else if (alignmentBox.previewIndex === 1) {
+ return "align-vertical-center"
+ } else {
+ return "align-vertical-bottom"
+ }
+ } else {
+ if (alignmentBox.previewIndex === 0) {
+ return "align-horizontal-left"
+ } else if (alignmentBox.previewIndex === 1) {
+ return "align-horizontal-center"
+ } else {
+ return "align-horizontal-right"
+ }
+ }
+ }
+ alignment: {
+ let first, second;
+ if (dialogRoot.vertical) {
+ if (alignmentBox.previewIndex === 0) {
+ first = Qt.AlignTop
+ } else if (alignmentBox.previewIndex === 1) {
+ first = Qt.AlignVCenter
+ } else {
+ first = Qt.AlignBottom
+ }
+ if (panel.location === PlasmaCore.Types.LeftEdge) {
+ second = Qt.AlignLeft
+ } else {
+ second = Qt.AlignRight
+ }
+ } else {
+ if (alignmentBox.previewIndex === 0) {
+ first = Qt.AlignLeft
+ } else if (alignmentBox.previewIndex === 1) {
+ first = Qt.AlignHCenter
+ } else {
+ first = Qt.AlignRight
+ }
+ if (panel.location === PlasmaCore.Types.TopEdge) {
+ second = Qt.AlignTop
+ } else {
+ second = Qt.AlignBottom
+ }
+ }
+ return first | second;
+ }
+ onClicked: alignmentBox.popup.visible = true
+ isVertical: dialogRoot.vertical
+ }
+ PC3.ComboBox {
+ id: alignmentBox
+ property int previewIndex: highlightedIndex > -1 ? highlightedIndex : currentIndex
+ Layout.alignment: Qt.AlignHCenter
+ Layout.minimumWidth: alignmentRepresentation.width
+ model: [
+ dialogRoot.vertical ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Top") : i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Left"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Center"),
+ dialogRoot.vertical ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Bottom") : i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Right")
+ ]
+ currentIndex: (panel.alignment === Qt.AlignLeft ? 0 :
+ panel.alignment === Qt.AlignCenter ? 1 : 2)
+ onActivated: (index) => {
+ if (index === 0) {
+ panel.alignment = Qt.AlignLeft
+ } else if (index === 1) {
+ panel.alignment = Qt.AlignCenter
+ } else {
+ panel.alignment = Qt.AlignRight
+ }
+ }
+ }
+ PC3.ComboBox {
+ model: [alignmentBox.model.reduce((a, b) => a.length > b.length ? a : b)]
+
+ Component.onCompleted: {
+ parent.Layout.minimumWidth = implicitWidth
+ destroy()
+ }
+ }
+ }
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: Kirigami.Units.mediumSpacing
+ Kirigami.Heading {
+ level: dialogRoot.headingLevel
+ Layout.alignment: Qt.AlignHCenter
+ text: dialogRoot.vertical ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group panel height", "Height")
+ : i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group panel width", "Width")
+ textFormat: Text.PlainText
+ }
+ PanelRepresentation {
+ id: lengthRepresentation
+ Layout.alignment: Qt.AlignHCenter
+ mainIconSource: (widthBox.previewIndex === 1 ? "gnumeric-ungroup" :
+ widthBox.previewIndex === 0 ? (dialogRoot.vertical ? "panel-fit-height" : "panel-fit-width") : "kdenlive-custom-effect")
+ isVertical: dialogRoot.vertical
+ alignment: positionRepresentation.alignment
+ fillAvailable: widthBox.previewIndex === 0
+ onClicked: widthBox.popup.visible = true
+ }
+ PC3.ComboBox {
+ id: widthBox
+ property int previewIndex: highlightedIndex > -1 ? highlightedIndex : currentIndex
+ Layout.alignment: Qt.AlignHCenter
+ Layout.minimumWidth: lengthRepresentation.width
+ model: [
+ dialogRoot.vertical ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox panel fills the full height of the display", "Fill height") : i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox panel fills the full width of the display", "Fill width"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox panel is just big enough to fit its content", "Fit content"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox panel size", "Custom")
+ ]
+ currentIndex: (panel.lengthMode === Panel.Global.FillAvailable ? 0 :
+ panel.lengthMode === Panel.Global.FitContent ? 1 : 2)
+ onActivated: (index) => {
+ if (index === 0) {
+ panel.lengthMode = Panel.Global.FillAvailable
+ panelConfiguration.panelRulerView.visible = false
+ } else if (index === 1) {
+ panel.lengthMode = Panel.Global.FitContent
+ panelConfiguration.panelRulerView.visible = false
+ } else {
+ panel.lengthMode = Panel.Global.Custom
+ panelConfiguration.panelRulerView.visible = true
+ }
+ }
+ }
+ PC3.ComboBox {
+ model: [widthBox.model.reduce((a, b) => a.length > b.length ? a : b)]
+
+ Component.onCompleted: {
+ parent.Layout.minimumWidth = implicitWidth
+ destroy()
+ }
+ }
+ }
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: Kirigami.Units.mediumSpacing
+ Kirigami.Heading {
+ Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
+ level: dialogRoot.headingLevel
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Visibility")
+ textFormat: Text.PlainText
+ }
+ PanelRepresentation {
+ id: visibilityRepresentation
+ Layout.alignment: Qt.AlignHCenter
+ sunkenPanel: autoHideBox.previewIndex == 1 || autoHideBox.previewIndex == 2
+ onClicked: autoHideBox.popup.visible = true
+ windowVisible: true
+ panelReservesSpace: autoHideBox.previewIndex == 0
+ isVertical: dialogRoot.vertical
+ alignment: positionRepresentation.alignment
+ }
+ PC3.ComboBox {
+ id: autoHideBox
+ property int previewIndex: popup.visible ? highlightedIndex : currentIndex
+ property int animationIndex: popup.visible ? highlightedIndex : -1
+ model: [
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Always visible"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Auto hide"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Dodge windows"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Windows go below"),
+ ]
+ onAnimationIndexChanged: {
+ if (animationIndex == 0 || animationIndex == 3) {
+ visibilityRepresentation.maximizeWindow()
+ } else if (animationIndex == 1) {
+ visibilityRepresentation.hidePanel()
+ } else if (animationIndex == 2) {
+ visibilityRepresentation.dodgePanel()
+ }
+ }
+ Layout.alignment: Qt.AlignHCenter
+ Layout.minimumWidth: visibilityRepresentation.width
+ currentIndex: {
+ switch (panel.visibilityMode) {
+ case Panel.Global.AutoHide:
+ return 1;
+ case Panel.Global.DodgeWindows:
+ return 2;
+ case Panel.Global.WindowsGoBelow:
+ return 3;
+ case Panel.Global.NormalPanel:
+ default:
+ return 0;
+ }
+ }
+ onActivated: (index) => {
+ switch (index) {
+ case 1:
+ panel.visibilityMode = Panel.Global.AutoHide;
+ break;
+ case 2:
+ panel.visibilityMode = Panel.Global.DodgeWindows;
+ break;
+ case 3:
+ panel.visibilityMode = Panel.Global.WindowsGoBelow;
+ break;
+ case 0:
+ default:
+ panel.visibilityMode = Panel.Global.NormalPanel;
+ break;
+ }
+ }
+ }
+ PC3.ComboBox {
+ model: [autoHideBox.model.reduce((a, b) => a.length > b.length ? a : b)]
+
+ Component.onCompleted: {
+ parent.Layout.minimumWidth = implicitWidth
+ destroy()
+ }
+ }
+ }
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: Kirigami.Units.mediumSpacing
+ Kirigami.Heading {
+ Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
+ level: dialogRoot.headingLevel
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group", "Opacity")
+ textFormat: Text.PlainText
+ }
+ PanelRepresentation {
+ id: opacityRepresentation
+ Layout.alignment: Qt.AlignHCenter
+ adaptivePanel: transparencyBox.previewIndex === 0
+ translucentPanel: transparencyBox.previewIndex === 2
+ onClicked: transparencyBox.popup.visible = true
+ isVertical: dialogRoot.vertical
+ alignment: positionRepresentation.alignment
+ }
+ PC3.ComboBox {
+ id: transparencyBox
+ readonly property int previewIndex: popup.visible ? highlightedIndex : currentIndex
+ model: [
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Adaptive"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Opaque"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox", "Translucent")
+ ]
+ Layout.alignment: Qt.AlignHCenter
+ Layout.minimumWidth: opacityRepresentation.width
+ currentIndex: (panel.opacityMode === Panel.Global.Adaptive ? 0 :
+ panel.opacityMode === Panel.Global.Opaque ? 1 : 2)
+ onActivated: (index) => {
+ if (index === 0) {
+ panel.opacityMode = Panel.Global.Adaptive
+ } else if (index === 1) {
+ panel.opacityMode = Panel.Global.Opaque
+ } else {
+ panel.opacityMode = Panel.Global.Translucent
+ }
+ }
+ }
+ PC3.ComboBox {
+ model: [transparencyBox.model.reduce((a, b) => a.length > b.length ? a : b)]
+
+ Component.onCompleted: {
+ parent.Layout.minimumWidth = implicitWidth
+ destroy()
+ }
+ }
+ }
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: Kirigami.Units.mediumSpacing
+ Kirigami.Heading {
+ level: dialogRoot.headingLevel
+ Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop","@title:group Degree of floatingness of panel and applets", "Floating")
+ textFormat: Text.PlainText
+ }
+ PanelRepresentation {
+ Layout.alignment: Qt.AlignHCenter
+ floatingGap: Kirigami.Units.smallSpacing * (floatingBox.previewIndex === 2)
+ onClicked: floatingBox.popup.visible = true
+ visibleApplet: true
+ floatingApplet: floatingBox.previewIndex !== 0
+ isVertical: dialogRoot.vertical
+ alignment: positionRepresentation.alignment
+ }
+ PC3.ComboBox {
+ id: floatingBox
+ readonly property int previewIndex: popup.visible ? highlightedIndex : currentIndex
+ model: [
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox Option to disable floating panels or applets", "Disabled"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox Option to make only panel applets always float", "Applets only"),
+ i18ndc("plasma_shell_org.kde.plasma.desktop", "@item:inlistbox Option to make panel and applets floating", "Panel and applets")
+ ]
+ Layout.alignment: Qt.AlignHCenter
+ Layout.minimumHeight: transparencyBox.height
+ Layout.minimumWidth: opacityRepresentation.width
+ currentIndex: (panel.floating ? 2 : panel.floatingApplets ? 1 : 0)
+ onActivated: (index) => {
+ if (index === 0) {
+ panel.floating = panel.floatingApplets = false
+ } else if (index === 1) {
+ panel.floating = false
+ panel.floatingApplets = true
+ } else {
+ panel.floating = true
+ }
+ }
+ }
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ Layout.columnSpan: 3
+ spacing: Kirigami.Units.smallSpacing
+ visible: panel.unsupportedConfiguration
+
+ Kirigami.Icon {
+ source: "data-warning-symbolic"
+ Layout.alignment: Qt.AlignVCenter
+ Layout.preferredWidth: Kirigami.Units.iconSizes.medium
+ Layout.preferredHeight: Kirigami.Units.iconSizes.medium
+ }
+
+ PC3.Label {
+ Layout.alignment: Qt.AlignVCenter
+ Layout.fillWidth: true
+ // Popup doesn't have to expand to the implicit size of this label, let it wrap.
+ Layout.preferredWidth: 0
+ text: panel.unsupportedConfigurationDescription
+ wrapMode: Text.Wrap
+ }
+
+ PC3.ToolButton {
+ Layout.alignment: Qt.AlignVCenter
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Revert an unsupported configuration back to the defaults", "Fix it")
+ icon.name: "tools-wizard-symbolic"
+ onClicked: {
+ panel.fixUnsupportedConfiguration();
+ }
+ }
+ }
+ }
+
+ Instantiator {
+ id: dialogInstantiator
+ active: setPositionButton.checked || clonePanelButton.checked
+ asynchronous: true
+ model: Application.screens
+ Item {
+ width: 0
+ height: 0
+ required property var modelData
+
+ component Indicator : PlasmaCore.Dialog {
+ id: root
+ property string iconSource
+ property var onClickedLocation
+ flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.BypassWindowManagerHint
+ location: PlasmaCore.Types.Floating
+ visible: dialogInstantiator.active && (panel.location !== onClickedLocation || modelData.name !== panel.screenToFollow.name)
+
+ x: modelData.virtualX + Kirigami.Units.largeSpacing
+ y: modelData.virtualY + modelData.height / 2 - mainItem.height / 2 - margins.top
+
+ mainItem: PC3.ToolButton {
+ width: Kirigami.Units.iconSizes.enormous
+ height: Kirigami.Units.iconSizes.enormous
+ icon.name: root.iconSource
+
+ onClicked: {
+ if (setPositionButton.checked) {
+ setPositionButton.moveTo(root.onClickedLocation, Window.window)
+ } else if (clonePanelButton.checked) {
+ panel.clonePanelTo(root.onClickedLocation, dialogRoot.panelConfiguration.screenFromWindow(Window.window))
+ clonePanelButton.checked = false
+ }
+ }
+ }
+ }
+
+ Indicator {
+ x: modelData.virtualX + Kirigami.Units.largeSpacing
+ y: modelData.virtualY + modelData.height / 2 - mainItem.height / 2 - margins.top
+ iconSource: "arrow-left"
+ onClickedLocation: PlasmaCore.Types.LeftEdge
+ }
+ Indicator {
+ x: modelData.virtualX + modelData.width - Kirigami.Units.largeSpacing - margins.left - margins.right - mainItem.width
+ y: modelData.virtualY + modelData.height / 2 - mainItem.height / 2 - margins.top
+ iconSource: "arrow-right"
+ onClickedLocation: PlasmaCore.Types.RightEdge
+ }
+ Indicator {
+ x: modelData.virtualX + modelData.width / 2 - mainItem.width / 2 - margins.left
+ y: modelData.virtualY + Kirigami.Units.largeSpacing
+ iconSource: "arrow-up"
+ onClickedLocation: PlasmaCore.Types.TopEdge
+ }
+ Indicator {
+ x: modelData.virtualX + modelData.width / 2 - mainItem.width / 2 - margins.left
+ y: modelData.virtualY + modelData.height - mainItem.height - margins.top - margins.bottom - Kirigami.Units.largeSpacing
+ iconSource: "arrow-down"
+ onClickedLocation: PlasmaCore.Types.BottomEdge
+ }
+ }
+ }
+
+ GridLayout {
+ Layout.alignment: Qt.AlignHCenter
+ rowSpacing: Kirigami.Units.largeSpacing
+ columnSpacing: Kirigami.Units.largeSpacing
+ rows: 2
+ columns: 2
+
+ PC3.Label {
+ id: spinBoxLabel
+ Layout.alignment: Qt.AlignRight
+ wrapMode: Text.Wrap
+
+ text: panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge
+ ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@label:spinbox", "Panel Width:")
+ : i18ndc("plasma_shell_org.kde.plasma.desktop", "@label:spinbox", "Panel Height:")
+ textFormat: Text.PlainText
+ }
+ PC3.SpinBox {
+ id: spinBox
+
+ editable: true
+ focus: !Kirigami.InputMethod.willShowOnActive
+ from: Math.max(20, panel.minThickness) // below this size, the panel is mostly unusable
+ to: panel.location === PlasmaCore.Types.LeftEdge || panel.location === PlasmaCore.Types.RightEdge
+ ? panel.screenToFollow.geometry.width / 2
+ : panel.screenToFollow.geometry.height / 2
+
+ stepSize: 2
+
+ value: panel.thickness
+ onValueModified: {
+ panel.thickness = value
+ }
+ }
+
+ PC3.Label {
+ Layout.alignment: Qt.AlignRight
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group shortcut that moves focus to the panel", "Focus shortcut:")
+ textFormat: Text.PlainText
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+
+ PC3.ToolTip {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip", "Press this keyboard shortcut to move focus to the Panel")
+ visible: mouseArea.containsMouse
+ }
+ }
+ KeySequenceItem {
+ id: button
+
+ Accessible.name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button accessible name", "Focus Shortcut Setter")
+ Accessible.description: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:whatsthis Accessible description for button", "Button to set the shortcut for the panel to gain focus")
+ Accessible.onPressAction: startCapturing()
+
+ keySequence: plasmoid.globalShortcut
+ onCaptureFinished: {
+ plasmoid.globalShortcut = button.keySequence
+ }
+ }
+ }
+
+ PlasmaExtras.PlasmoidHeading {
+ position: PlasmaExtras.PlasmoidHeading.Footer
+ Layout.topMargin: Kirigami.Units.smallSpacing
+ topPadding: Kirigami.Units.smallSpacing * 2
+ leftPadding: Kirigami.Units.smallSpacing
+ rightPadding: Kirigami.Units.smallSpacing
+ bottomPadding: Kirigami.Units.smallSpacing
+
+ Layout.fillWidth: true
+ RowLayout {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.right: parent.right
+ spacing: Kirigami.Units.largeSpacing
+
+ PC3.ToolButton {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Delete the panel", "Delete Panel")
+ icon.name: "delete"
+
+ PC3.ToolTip.text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip for button", "Remove this panel; this action can be undone")
+ PC3.ToolTip.delay: Kirigami.Units.toolTipDelay
+ PC3.ToolTip.visible: hovered
+
+ onClicked: plasmoid.internalAction("remove").trigger()
+ }
+
+ PC3.ToolButton {
+ id: clonePanelButton
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Clone the panel", "Clone Panel")
+ icon.name: "edit-copy-symbolic"
+ checkable: true
+
+ PC3.ToolTip.text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip for button", "Create a new panel with the same settings and applets")
+ PC3.ToolTip.delay: Kirigami.Units.toolTipDelay
+ PC3.ToolTip.visible: hovered
+ }
+
+
+ Item {Layout.fillWidth: true}
+
+ PC3.ToolButton {
+ text: plasmoid.corona.enteredEditModeViaDesktop() ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Close the panel configuration window", "Close") : i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Close the panel configuration window and exit edit mode", "Exit Edit Mode")
+ icon.name: "dialog-ok-symbolic"
+
+ PC3.ToolTip.text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip for button", "Close Panel Settings window and exit Edit Mode")
+ PC3.ToolTip.delay: Kirigami.Units.toolTipDelay
+ PC3.ToolTip.visible: hovered
+
+ onClicked: plasmoid.internalAction("configure").trigger()
+ }
+ }
+ }
+ // This item is used to "pass" focus to the ruler with tab when we're at the last of the control of this window
+ Item {
+ parent: dialogRoot.parent // Used to not take space in the ColumnLayout
+ activeFocusOnTab: true
+ onActiveFocusChanged: {
+ let window = ruler.Window.window
+ if (activeFocus && window && window.visible) {
+ window.requestActivate()
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ShellContainmentConfiguration.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ShellContainmentConfiguration.qml
new file mode 100644
index 0000000..6b468a9
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/ShellContainmentConfiguration.qml
@@ -0,0 +1,85 @@
+/*
+ SPDX-FileCopyrightText: 2021 Cyril Rossi
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+import QtQuick.Window
+
+import org.kde.kirigami as Kirigami
+
+import "shellcontainmentconfiguration"
+
+Kirigami.AbstractApplicationWindow {
+ id: root
+
+ title: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:window", "Manage Panels and Desktops")
+
+ width: Kirigami.Units.gridUnit * 40
+ height: Kirigami.Units.gridUnit * 32
+
+ minimumWidth: Kirigami.Units.gridUnit * 30
+ minimumHeight: Kirigami.Units.gridUnit * 25
+
+ header: QQC2.ToolBar {
+ anchors {
+ left: parent.left
+ right: parent.right
+ }
+ contentItem: QQC2.Label {
+ Layout.fillWidth: parent
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:usagetip", "You can drag Panels and Desktops around to move them to different screens.")
+ textFormat: Text.PlainText
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.WordWrap
+ }
+ }
+
+ footer: QQC2.Control {
+ contentItem: QQC2.DialogButtonBox {
+ QQC2.Button {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Close window", "Close")
+ onClicked: Window.window.close()
+ }
+ }
+ background: Item {
+ // FIXME: automate that somehow?
+ Kirigami.Separator {
+ anchors {
+ left: parent.left
+ top: parent.top
+ right: parent.right
+ }
+ visible: mainPage.flickable.contentHeight > mainPage.flickable.height
+ }
+ }
+ }
+
+ Kirigami.ScrollablePage {
+ id: mainPage
+ anchors.fill: parent
+
+ leftPadding: 0
+ topPadding: 0
+ rightPadding: 0
+ bottomPadding: 0
+
+ Flow {
+ id: mainGrid
+ width: mainPage.flickable.width
+ spacing: 0
+
+ Repeater {
+ id: repeater
+ model: ShellContainmentModel
+
+ delegate: Delegate {
+ viewPort: mainPage
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/PanelRepresentation.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/PanelRepresentation.qml
new file mode 100644
index 0000000..68ab33c
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/PanelRepresentation.qml
@@ -0,0 +1,351 @@
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.components as PC3
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+
+Item {
+ id: root
+
+ property string text
+ property /*Qt::Alignment*/int alignment: Qt.AlignHCenter | Qt.AlignBottom
+ property string tooltip
+
+ property bool isVertical: false
+ property bool isHorizontal: !isVertical
+ property bool checked: false
+ property bool windowVisible: false
+ property bool panelVisible: true
+
+ property bool isTop: !!(alignment & Qt.AlignTop)
+ property bool isBottom: !!(alignment & Qt.AlignBottom)
+ property bool isLeft: !!(alignment & Qt.AlignLeft)
+ property bool isRight: !!(alignment & Qt.AlignRight)
+
+ property bool translucentPanel: false
+ property bool sunkenPanel: false
+ property bool adaptivePanel: false
+ property bool panelReservesSpace: true
+
+ property bool fillAvailable: false
+ property int floatingGap: 0
+ property var mainIconSource: null
+ property int screenHeight: Math.round(screenRect.height / 2)
+
+ property bool visibleApplet: false
+ property bool floatingApplet: false
+
+ readonly property bool iconAndLabelsShouldlookSelected: checked || mouseArea.pressed
+
+ // Layouts automatically mirror on RTL languages, and we use
+ // layouts to position the panel here. As a result, RTL languages
+ // show the panel on the opposite side, which does not match
+ // where the panel actually is. We instead disable layout
+ // mirroring to avoid that.
+ LayoutMirroring.enabled: false
+ LayoutMirroring.childrenInherit: true
+
+ function maximizeWindow() {
+
+ hidePanelLater.stop()
+ hidePanel.stop()
+ showPanel.restart()
+
+ moveWindowOverPanel.stop()
+ resetWindowOverPanel.restart()
+
+ maximizeAnimation.restart()
+ }
+ function hidePanel() {
+
+ hidePanelLater.stop()
+ maximizeAnimation.stop()
+ resetMaximize.restart()
+
+ moveWindowOverPanel.stop()
+ resetWindowOverPanel.restart()
+
+ hidePanel.restart()
+ }
+
+ function dodgePanel() {
+
+ hidePanel.stop()
+ showPanel.restart()
+
+ maximizeAnimation.stop()
+ resetMaximize.restart()
+
+ moveWindowOverPanel.restart()
+ hidePanelLater.restart()
+ }
+
+ Timer {
+ id: hidePanelLater
+ interval: 200
+ onTriggered: hidePanel.restart()
+ running: false
+ }
+
+ signal clicked()
+
+ implicitHeight: mainItem.height
+ implicitWidth: mainItem.width
+
+ PC3.ToolTip {
+ text: root.tooltip
+ visible: mouseArea.containsMouse && text.length > 0
+ }
+
+ PlasmaExtras.Highlight {
+ anchors.fill: parent
+ anchors.margins: -Kirigami.Units.smallSpacing
+ hovered: mouseArea.containsMouse
+ pressed: root.iconAndLabelsShouldlookSelected
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: root.clicked()
+ }
+
+ ColumnLayout {
+ id: mainItem
+ spacing: Kirigami.Units.smallSpacing
+ Rectangle {
+ id: screenRect
+
+ Layout.alignment: Qt.AlignHCenter
+ implicitWidth: Math.round(Math.min(Kirigami.Units.gridUnit * 6, Screen.width * 0.1))
+ implicitHeight: Math.round(Math.min(Kirigami.Units.gridUnit * 4, Screen.width * 0.1))
+ color: Qt.tint(Kirigami.Theme.backgroundColor, Qt.rgba(1, 1, 1, 0.3))
+ border.color: Kirigami.Theme.highlightColor
+ radius: Kirigami.Units.cornerRadius
+ clip: root.sunkenPanel
+
+ RowLayout {
+ anchors.fill: parent
+ z: 1
+
+ Rectangle {
+ id: panelImage
+
+ property real sunkenValue: 0
+
+ Component.onCompleted: {
+ panelImage.sunkenValue = root.sunkenPanel / 2
+ }
+
+ implicitWidth: root.isVertical ? Math.round(parent.width / 6) : Math.round(parent.width * (root.fillAvailable ? 1 : 0.7))
+ implicitHeight: root.isVertical ? Math.round(parent.height * (root.fillAvailable ? 1 : 0.8)) : Math.round(parent.height / 4)
+
+ Layout.alignment: root.alignment
+ Layout.bottomMargin: root.isBottom ? sunkenValue * -Math.round(height) + root.floatingGap : 0
+ Layout.topMargin: root.isTop ? sunkenValue * -Math.round(height) + root.floatingGap : 0
+ Layout.leftMargin: root.isLeft ? sunkenValue * -Math.round(width) + root.floatingGap : 0
+ Layout.rightMargin: root.isRight ? sunkenValue * -Math.round(width) + root.floatingGap : 0
+
+ color: root.translucentPanel ? screenRect.color : Kirigami.Theme.backgroundColor
+ opacity: root.translucentPanel ? 0.8 : 1.0
+ border.color: "transparent"
+ visible: root.panelVisible
+ clip: root.adaptivePanel
+ radius: Kirigami.Units.cornerRadius
+
+ SequentialAnimation on sunkenValue {
+ id: hidePanel
+ running: false
+ NumberAnimation {
+ to: 0
+ duration: Kirigami.Units.shortDuration
+ }
+ NumberAnimation {
+ to: 1
+ duration: Kirigami.Units.veryLongDuration
+ }
+ PauseAnimation {
+ duration: Kirigami.Units.veryLongDuration * 2
+ }
+ NumberAnimation {
+ to: 0.5
+ duration: Kirigami.Units.veryLongDuration
+ }
+ }
+ SequentialAnimation on sunkenValue {
+ id: showPanel
+ running: false
+ NumberAnimation {
+ to: 0
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+
+ Loader {
+ id: horizontalAdaptivePanelLoader
+ active: root.adaptivePanel && root.isHorizontal
+ sourceComponent: Rectangle {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: Math.round(panelImage.width / 3)
+ color: Qt.lighter(screenRect.color)
+ border.color: Kirigami.Theme.highlightColor
+ width: panelImage.width
+ height: Math.round(panelImage.height * 4)
+ radius: Math.round(height / 2)
+ rotation: 45
+ }
+ }
+
+ Loader {
+ id: verticalAdaptivePanelLoader
+ active: root.adaptivePanel && root.isVertical
+ sourceComponent: Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: Math.round(panelImage.height / 4)
+ color: Qt.lighter(screenRect.color)
+ border.color: Kirigami.Theme.highlightColor
+ width: Math.round(panelImage.width * 2)
+ height: panelImage.height
+ radius: Math.round(height / 2)
+ rotation: 45
+ }
+ }
+
+ Rectangle {
+ id: panelBorder
+ anchors.fill: parent
+ color: "transparent"
+ border.color: Kirigami.Theme.highlightColor
+ radius: panelImage.radius
+ }
+ }
+ }
+
+ Rectangle {
+ x: panelImage.x + root.isLeft * panelImage.width - root.isRight * width + root.isVertical * panelSpacing
+ y: panelImage.y + root.isTop * panelImage.height - root.isBottom * height + (root.isHorizontal) * panelSpacing
+ height: Math.round(parent.height / 2)
+ width: Math.round(parent.width / 3)
+ visible: root.visibleApplet
+
+ property int panelSpacing: Kirigami.Units.smallSpacing * (root.floatingApplet ? -1 : 1) * (root.isRight || root.isBottom ? 1 : -1)
+
+ color: window.color
+ radius: 5
+
+ Behavior on y {
+ NumberAnimation {
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+ Behavior on x {
+ NumberAnimation {
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+ }
+
+ Rectangle {
+ id: window
+
+ property real maximized: 0
+ property real windowOverPanel: 0
+
+ width: Math.round(parent.width * (0.4 + 0.6 * maximized) - panelImage.width * root.panelReservesSpace * maximized * root.isVertical)
+ height: Math.round(parent.height * (0.4 + 0.6 * maximized) - panelImage.height * root.panelReservesSpace * maximized * root.isHorizontal)
+ visible: root.windowVisible
+ radius: 5
+ color: Kirigami.Theme.highlightColor
+ border.color: "transparent"
+
+ x: Math.round(screenRect.width / 2 - width / 2) * (1 - maximized) + windowOverPanel * Kirigami.Units.mediumSpacing * 2 * root.isVertical * (root.isLeft ? - 1 : 1) + panelImage.width * maximized * root.isLeft * root.panelReservesSpace
+ y: Math.round(screenRect.height / 2 - height / 2) * (1 - maximized) + windowOverPanel * Kirigami.Units.mediumSpacing * 2 * root.isHorizontal * (root.isTop ? - 1 : 1) + panelImage.height * maximized * root.isTop * root.panelReservesSpace
+ z: 0
+
+ SequentialAnimation on maximized {
+ id: maximizeAnimation
+ running: false
+ NumberAnimation {
+ to: 0
+ duration: Kirigami.Units.shortDuration
+ }
+ NumberAnimation {
+ to: 1
+ duration: Kirigami.Units.longDuration
+ }
+ PauseAnimation {
+ duration: Kirigami.Units.veryLongDuration * 2
+ }
+ NumberAnimation {
+ to: 0
+ duration: Kirigami.Units.longDuration
+ }
+ }
+ NumberAnimation on maximized {
+ id: resetMaximize
+ running: false
+ to: 0
+ duration: Kirigami.Units.shortDuration
+ }
+ SequentialAnimation on windowOverPanel {
+ id: moveWindowOverPanel
+ NumberAnimation {
+ to: 0
+ duration: Kirigami.Units.shortDuration
+ }
+ NumberAnimation {
+ to: 1
+ duration: Kirigami.Units.veryLongDuration
+ }
+ PauseAnimation {
+ duration: Kirigami.Units.veryLongDuration * 2
+ }
+ NumberAnimation {
+ to: 0
+ duration: Kirigami.Units.veryLongDuration
+ }
+ }
+ NumberAnimation on windowOverPanel {
+ id: resetWindowOverPanel
+ running: false
+ to: 0
+ duration: Kirigami.Units.shortDuration
+ }
+
+ Row {
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.margins: Kirigami.Units.smallSpacing
+ spacing: Kirigami.Units.smallSpacing
+ Repeater {
+ model: 3
+ delegate: Rectangle {
+ width: Math.round(Kirigami.Units.gridUnit / 6)
+ height: width
+ radius: Math.round(height / 2)
+ color: Kirigami.Theme.textColor
+ }
+ }
+ }
+ }
+
+ Kirigami.Icon {
+ id: mainIcon
+ visible: valid
+ anchors.centerIn: parent
+ transform: Translate {
+ y: root.isVertical ? 0 : Math.round((mainIcon.y - panelImage.y) / 4)
+ x: root.isVertical ? Math.round((mainIcon.x - panelImage.x) / 4) : 0
+ }
+ height: parent.height / 2
+ source: root.mainIconSource
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/Ruler.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/Ruler.qml
new file mode 100644
index 0000000..fee04af
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/Ruler.qml
@@ -0,0 +1,243 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.kirigami as Kirigami
+import org.kde.ksvg as KSvg
+import org.kde.plasma.shell.panel as Panel
+
+KSvg.FrameSvgItem {
+ id: root
+
+ anchors.fill: parent
+
+ //Those properties get updated by PanelConfiguration.qml whenever a value in the panel changes
+ property alias offset: offsetHandle.value
+ property alias minimumLength: rightMinimumLengthHandle.value
+ property alias maximumLength: rightMaximumLengthHandle.value
+ property bool isHorizontal: root.prefix[0] === 'north' || root.prefix[0] === 'south'
+
+ property string maximumText: (
+ dialogRoot.vertical
+ ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip slider handle", "Drag to change maximum height.")
+ : i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip slider handle", "Drag to change maximum width.")
+ ) + "\n" + i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip slider handle", "Double-click to reset.")
+ property string minimumText: (
+ dialogRoot.vertical
+ ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip slider handle", "Drag to change minimum height.")
+ : i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip slider handle", "Drag to change minimum width.")
+ ) + "\n" + i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip slider handle", "Double-click to reset.")
+
+ imagePath: "widgets/containment-controls"
+ implicitWidth: Math.max(offsetHandle.width, rightMinimumLengthHandle.width + rightMaximumLengthHandle.width)
+ implicitHeight: Math.max(offsetHandle.height, rightMinimumLengthHandle.height + rightMaximumLengthHandle.height)
+
+ onMinimumLengthChanged: rightMinimumLengthHandle.value = leftMinimumLengthHandle.value = minimumLength
+ onMaximumLengthChanged: rightMaximumLengthHandle.value = leftMaximumLengthHandle.value = maximumLength
+
+ /* As offset and length have a different meaning in all alignments, the panel shifts on alignment change.
+ * This could result in wrong panel positions (e.g. panel shifted over monitor border).
+ * The fancy version would be a recalculation of all values, so that the panel stays at it's current position,
+ * but this would be error prone and complicated. As the panel alignment is rarely changed, it's not worth it.
+ * The more easy approach is just setting the panel offset to zero. This makes sure the panel has a valid position and size.
+ */
+ Connections {
+ target: panel
+ function onAlignmentChanged() {
+ offset = 0
+ }
+ }
+
+ Component.onCompleted: {
+ offsetHandle.value = panel.offset
+ rightMinimumLengthHandle.value = panel.minimumLength
+ rightMaximumLengthHandle.value = panel.maximumLength
+ leftMinimumLengthHandle.value = panel.minimumLength
+ leftMaximumLengthHandle.value = panel.maximumLength
+ }
+
+ KSvg.SvgItem {
+ id: centerMark
+ imagePath: "widgets/containment-controls"
+ elementId: dialogRoot.vertical ? "vertical-centerindicator" : "horizontal-centerindicator"
+ visible: panel.alignment === Qt.AlignCenter
+ width: dialogRoot.vertical ? parent.width : naturalSize.width
+ height: dialogRoot.vertical ? naturalSize.height : parent.height
+ anchors.centerIn: parent
+ }
+
+ SliderHandle {
+ id: offsetHandle
+ anchors {
+ right: !root.isHorizontal ? root.right : undefined
+ bottom: root.isHorizontal ? root.bottom : undefined
+ }
+ graphicElementName: "offsetslider"
+ description: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:tooltip slider handle",
+ "Drag to change position on this screen edge.\nDouble-click to reset.")
+ offset: panel.alignment === Qt.AlignCenter ? 0 : (dialogRoot.vertical ? panel.height : panel.width) / 2
+ property int position: (dialogRoot.vertical) ? y + height / 2 : x + width / 2
+ onPositionChanged: {
+ if (!offsetHandle.hasEverBeenMoved) return;
+ let panelLength = dialogRoot.vertical ? panel.height : panel.width
+ let rootLength = dialogRoot.vertical ? root.height : root.width
+ // Snap at the center
+ if (Math.abs(position - rootLength / 2) < 5) {
+ if (panel.alignment !== Qt.AlignCenter) {
+ panel.alignment = Qt.AlignCenter
+ // Coordinate change: since we switch from measuring the min/max
+ // length from the side of the panel to the center of the panel,
+ // we need to double the distance between the min/max indicators
+ // and the panel side.
+ panel.minimumLength += panel.minimumLength - panelLength
+ panel.maximumLength += panel.maximumLength - panelLength
+ }
+ panel.offset = 0
+ } else if (position > rootLength / 2) {
+ if (panel.alignment === Qt.AlignCenter) {
+ // This is the opposite of the previous comment, as we are
+ // cutting in half the distance between the min/max indicators
+ // and the side of the panel.
+ panel.minimumLength -= (panel.minimumLength - panelLength) / 2
+ panel.maximumLength -= (panel.maximumLength - panelLength) / 2
+ }
+ panel.alignment = Qt.AlignRight
+ panel.offset = Math.round(rootLength - position - offset)
+ } else if (position <= rootLength / 2) {
+ if (panel.alignment === Qt.AlignCenter) {
+ panel.minimumLength -= (panel.minimumLength - panelLength) / 2
+ panel.maximumLength -= (panel.maximumLength - panelLength) / 2
+ }
+ panel.alignment = Qt.AlignLeft
+ panel.offset = Math.round(position - offset)
+ }
+ }
+ /* The maximum/minimumPosition values are needed to prevent the user from moving a panel with
+ * center alignment to the left and then drag the position handle to the left.
+ * This would make the panel to go off the monitor:
+ * |<- V -> |
+ * | -> | <- |
+ * ^move this slider to the left
+ */
+ minimumPosition: {
+ var size = dialogRoot.vertical ? height : width
+ switch(panel.alignment){
+ case Qt.AlignLeft:
+ return -size / 2 + offset
+ case Qt.AlignRight:
+ return leftMaximumLengthHandle.value - size / 2 - offset
+ default:
+ return panel.maximumLength / 2 - size / 2
+ }
+ }
+ //Needed for the same reason as above
+ maximumPosition: {
+ var size = dialogRoot.vertical ? height : width
+ var rootSize = dialogRoot.vertical ? root.height : root.width
+ switch(panel.alignment){
+ case Qt.AlignLeft:
+ return rootSize - rightMaximumLengthHandle.value - size / 2 + offset
+ case Qt.AlignRight:
+ return rootSize - size / 2 - offset
+ default:
+ return rootSize - panel.maximumLength / 2 - size / 2
+ }
+ }
+ function defaultPosition(): int /*override*/ {
+ return 0;
+ }
+ }
+
+ /* The maximumPosition value for the right handles and the minimumPosition value for the left handles are
+ * needed to prevent the user from moving a panel with center alignment to the left (right) and then pull one of the
+ * right (left) sliders to the right (left).
+ * Because the left and right sliders are coupled, this would make the left (right) sliders to go off the monitor.
+ *
+ * |<- V -> |
+ * | -> | <- |
+ * ^move this slider to the right
+ *
+ * The other max/min Position values just set a minimum panel size
+ */
+
+ SliderHandle {
+ id: rightMinimumLengthHandle
+ anchors {
+ left: !root.isHorizontal ? root.left : undefined
+ top: root.isHorizontal ? root.top : undefined
+ }
+ description: root.minimumText
+ alignment: panel.alignment | Qt.AlignLeft
+ visible: panel.alignment !== Qt.AlignRight
+ offset: panel.offset
+ graphicElementName: "minslider"
+ onValueChanged: panel.minimumLength = value
+ minimumPosition: offsetHandle.position + Kirigami.Units.gridUnit * 3
+ maximumPosition: {
+ var rootSize = dialogRoot.vertical ? root.height : root.width
+ var size = dialogRoot.vertical ? height : width
+ panel.alignment === Qt.AlignCenter ? Math.min(rootSize - size/2, rootSize + offset * 2 - size/2) : rootSize - size/2
+ }
+ }
+
+ SliderHandle {
+ id: rightMaximumLengthHandle
+ anchors {
+ right: !root.isHorizontal ? root.right : undefined
+ bottom: root.isHorizontal ? root.bottom : undefined
+ }
+ description: root.maximumText
+ alignment: panel.alignment | Qt.AlignLeft
+ visible: panel.alignment !== Qt.AlignRight
+ offset: panel.offset
+ graphicElementName: "maxslider"
+ onValueChanged: panel.maximumLength = value
+ minimumPosition: offsetHandle.position + Kirigami.Units.gridUnit * 3
+ maximumPosition: {
+ var rootSize = dialogRoot.vertical ? root.height : root.width
+ var size = dialogRoot.vertical ? height : width
+ panel.alignment === Qt.AlignCenter ? Math.min(rootSize - size/2, rootSize + offset * 2 - size/2) : rootSize - size/2
+ }
+ }
+
+ SliderHandle {
+ id: leftMinimumLengthHandle
+ anchors {
+ left: !root.isHorizontal ? root.left : undefined
+ top: root.isHorizontal ? root.top : undefined
+ }
+ description: root.minimumText
+ alignment: panel.alignment | Qt.AlignRight
+ visible: panel.alignment !== Qt.AlignLeft
+ offset: panel.offset
+ graphicElementName: "maxslider"
+ onValueChanged: panel.minimumLength = value
+ maximumPosition: offsetHandle.position - Kirigami.Units.gridUnit * 3
+ minimumPosition: {
+ var size = dialogRoot.vertical ? height : width
+ panel.alignment === Qt.AlignCenter ? Math.max(-size/2, offset*2 - size/2) : -size/2
+ }
+ }
+
+ SliderHandle {
+ id: leftMaximumLengthHandle
+ anchors {
+ right: !root.isHorizontal ? root.right : undefined
+ bottom: root.isHorizontal ? root.bottom : undefined
+ }
+ description: root.maximumText
+ alignment: panel.alignment | Qt.AlignRight
+ visible: panel.alignment !== Qt.AlignLeft
+ offset: panel.offset
+ graphicElementName: "minslider"
+ onValueChanged: panel.maximumLength = value
+ maximumPosition: offsetHandle.position - Kirigami.Units.gridUnit * 3
+ minimumPosition: {
+ var size = dialogRoot.vertical ? height : width
+ panel.alignment === Qt.AlignCenter ? Math.max(-size/2, offset*2 - size/2) : -size/2
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/SliderHandle.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/SliderHandle.qml
new file mode 100644
index 0000000..c5c92c4
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/panelconfiguration/SliderHandle.qml
@@ -0,0 +1,236 @@
+/*
+ SPDX-FileCopyrightText: 2013 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+import org.kde.ksvg as KSvg
+import org.kde.plasma.components as PC3
+import org.kde.plasma.shell.panel as Panel
+
+KSvg.SvgItem {
+ id: root
+
+ //Those properties get updated by PanelConfiguration.qml whenever a value changes
+ imagePath: "widgets/containment-controls"
+ elementId: parent.prefix + '-' + graphicElementName
+ width: naturalSize.width
+ height: naturalSize.height
+
+ //value expressed by this slider, this is the distance to offset
+ property int value
+
+ //name of the graphics to load
+ property string graphicElementName
+
+ //where the point "0" is
+ property int offset: 0
+
+ /*handle type: behave in different ways based on the alignment:
+ * alignment === Qt.AlignRight: Panel aligned to right and handle value relative to the right
+ * alignment === Qt.AlignLeft: Panel aligned to left and handle relative to the left
+ * (alignment !== Qt.AlignRight) && (alignment & Qt.AlignRight): Panel aligned to the center and handle right of offset and value doubled
+ * (alignment !== Qt.AlignLeft) && (alignment & Qt.AlignLeft): Panel aligned to the center and handle left of offset and value doubled
+ * else: Panel aligned to center and handle relative to the center
+ * Note that right/left and top/bottom are interchangeable
+ */
+ property int alignment: panel.alignment
+
+ //The maximum/minimum Position (X/Y) the silder can be moved to
+ property int minimumPosition
+ property int maximumPosition
+ //Provide default position for "reset" action.
+ function defaultPosition(): int {
+ var dialogSize, panelSize;
+ if (dialogRoot.vertical) {
+ dialogSize = dialogRoot.height;
+ panelSize = panel.height;
+ } else {
+ dialogSize = dialogRoot.width;
+ panelSize = panel.width;
+ }
+ return (value === panelSize) ? dialogSize : panelSize;
+ }
+
+ // Handle name displayed as a tooltip.
+ property string description
+
+ property bool hasEverBeenMoved: false
+
+ function syncPos() {
+ if (dialogRoot.vertical) {
+ let newY = 0
+ if (alignment === Qt.AlignRight) {
+ newY = root.parent.height - (value + offset + root.height/2)
+ } else if (alignment === Qt.AlignLeft) {
+ newY = value + offset - root.height/2
+ } else {
+ if (root.alignment & Qt.AlignRight) {
+ newY = root.parent.height/2 - value/2 + offset - root.height/2
+ } else if (root.alignment & Qt.AlignLeft) {
+ newY = root.parent.height/2 + value/2 + offset - root.height/2
+ } else {
+ newY = root.parent.height/2 + value + offset -root.height/2
+ }
+ }
+ y = Math.max(-height/2, Math.min(parent.height - height/2, newY))
+ } else {
+ let newX = 0
+ if (alignment === Qt.AlignRight) {
+ newX = root.parent.width - (value + offset + root.width/2)
+ } else if (alignment === Qt.AlignLeft) {
+ newX = value + offset - root.width/2
+ } else {
+ if (root.alignment & Qt.AlignRight) {
+ newX = root.parent.width/2 - value/2 + offset - root.width/2
+ } else if (root.alignment & Qt.AlignLeft) {
+ newX = root.parent.width/2 + value/2 + offset -root.width/2
+ } else {
+ newX = root.parent.width/2 + value + offset -root.width/2
+ }
+ }
+ x = Math.max(-width/2, Math.min(parent.width - width/2, newX))
+ }
+ }
+ onValueChanged: syncPos()
+ onOffsetChanged: syncPos()
+ onAlignmentChanged: syncPos()
+ Connections {
+ target: root.parent
+ function onWidthChanged() {
+ syncPos()
+ }
+ function onHeightChanged() {
+ syncPos()
+ }
+ }
+
+ PC3.ToolTip {
+ text: root.description
+ visible: root.description !== "" && ((area.containsMouse && !area.containsPress) || area.activeFocus)
+ }
+
+ MouseArea {
+ id: area
+ drag {
+ target: parent
+ axis: (dialogRoot.vertical) ? Drag.YAxis : Drag.XAxis
+ minimumX: root.minimumPosition
+ minimumY: root.minimumPosition
+ maximumX: root.maximumPosition
+ maximumY: root.maximumPosition
+ }
+ anchors {
+ fill: parent
+ leftMargin: (dialogRoot.vertical) ? 0 : -Kirigami.Units.gridUnit
+ rightMargin: (dialogRoot.vertical) ? 0 : -Kirigami.Units.gridUnit
+ topMargin: (dialogRoot.vertical) ? -Kirigami.Units.gridUnit : 0
+ bottomMargin: (dialogRoot.vertical) ? -Kirigami.Units.gridUnit : 0
+ }
+
+ readonly property int keyboardMoveStepSize: Math.ceil((root.maximumPosition - root.minimumPosition) / 20)
+
+ activeFocusOnTab: true
+ hoverEnabled: true
+ cursorShape: dialogRoot.vertical ? Qt.SizeVerCursor : Qt.SizeHorCursor
+
+ Accessible.description: root.description
+
+ Keys.onEnterPressed: doubleClicked(null);
+ Keys.onReturnPressed: doubleClicked(null);
+ Keys.onSpacePressed: doubleClicked(null);
+
+ // BEGIN Arrow keys
+ Keys.onUpPressed: if (dialogRoot.vertical) {
+ root.y = Math.max(root.minimumPosition, root.y - ((event.modifiers & Qt.ShiftModifier) ? 1 : keyboardMoveStepSize));
+ changePosition();
+ } else {
+ event.accepted = false;
+ }
+ Keys.onDownPressed: if (dialogRoot.vertical) {
+ root.y = Math.min(root.maximumPosition, root.y + ((event.modifiers & Qt.ShiftModifier) ? 1 : keyboardMoveStepSize));
+ changePosition();
+ } else {
+ event.accepted = false;
+ }
+ Keys.onLeftPressed: if (!dialogRoot.vertical) {
+ root.x = Math.max(root.minimumPosition, root.x - ((event.modifiers & Qt.ShiftModifier) ? 1 : keyboardMoveStepSize));
+ changePosition();
+ } else {
+ event.accepted = false;
+ }
+ Keys.onRightPressed: if (!dialogRoot.vertical) {
+ root.x = Math.min(root.maximumPosition, root.x + ((event.modifiers & Qt.ShiftModifier) ? 1 : keyboardMoveStepSize));
+ changePosition();
+ } else {
+ event.accepted = false;
+ }
+ // END Arrow keys
+
+ onPositionChanged: {
+ if (!drag.active) {
+ return;
+ }
+ changePosition();
+ }
+ onDoubleClicked: {
+ root.value = root.defaultPosition();
+ }
+
+ function changePosition() {
+ root.hasEverBeenMoved = true
+ if (dialogRoot.vertical) {
+ if (root.alignment === Qt.AlignRight) {
+ root.value = root.parent.height - (root.y + root.offset + root.height/2)
+ } else if (root.alignment === Qt.AlignLeft) {
+ root.value = root.y - root.offset + root.height/2
+ //Center
+ } else {
+ if (root.alignment & Qt.AlignRight) {
+ root.value = (root.parent.height/2 - root.y + root.offset)*2 - root.height
+ } else if (root.alignment & Qt.AlignLeft) {
+ root.value = (root.y - root.offset - root.parent.height/2)*2 + root.height
+ } else {
+ var value = root.y - root.parent.height/2 - root.offset + root.height/2
+ //Snap
+ if (Math.abs(value) < 5) {
+ root.value = 0
+ } else {
+ root.value = value
+ }
+ }
+ }
+ } else {
+ if (root.alignment === Qt.AlignRight) {
+ root.value = root.parent.width - (root.x + root.offset + root.width/2)
+ } else if (root.alignment === Qt.AlignLeft) {
+ root.value = root.x - root.offset + root.width/2
+ //Center
+ } else {
+ if (root.alignment & Qt.AlignRight) {
+ root.value = (root.parent.width/2 - root.x + root.offset)*2 - root.width
+ } else if (root.alignment & Qt.AlignLeft) {
+ root.value = (root.x - root.offset - root.parent.width/2)*2 + root.width
+ } else {
+ var value = root.x - root.parent.width/2 - root.offset + root.width/2
+ //Snap
+ if (Math.abs(value) < 5) {
+ root.value = 0
+ } else {
+ root.value = value
+ }
+ }
+ }
+ }
+ }
+
+ PlasmaExtras.Highlight {
+ anchors.fill: parent
+ visible: parent.activeFocus
+ hovered: true
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/shellcontainmentconfiguration/Delegate.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/shellcontainmentconfiguration/Delegate.qml
new file mode 100644
index 0000000..9da4bf0
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/configuration/shellcontainmentconfiguration/Delegate.qml
@@ -0,0 +1,284 @@
+/*
+ SPDX-FileCopyrightText: 2021 Cyril Rossi
+ SPDX-FileCopyrightText: 2022 Marco Martin
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+import QtQuick.Window
+
+import org.kde.kirigami as Kirigami
+
+QQC2.Control {
+ id: delegate
+ property Item viewPort
+ readonly property string screenName: model.screenName
+ readonly property int screenId: model.screenId
+ property bool containsDrag
+ property alias contentsLayout: contentsLayout
+
+ width: Math.min(Kirigami.Units.gridUnit * 25, Math.floor(viewPort.width / Math.min(repeater.count, Math.floor(viewPort.width / (Kirigami.Units.gridUnit * 12)))))
+
+ contentItem: ColumnLayout {
+ id: contentsLayout
+ width: Math.min(parent.width, Kirigami.Units.gridUnit * 15)
+
+ Rectangle {
+ id: screenRect
+ Layout.fillWidth: true
+ Layout.preferredHeight: width / 1.6
+ color: Kirigami.Theme.backgroundColor
+ border.color: Kirigami.Theme.textColor
+ Rectangle {
+ anchors.fill: parent
+ z: 9
+ color: "black"
+ opacity: delegate.containsDrag ? 0.3 : 0
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+
+ Repeater {
+ id: containmentRepeater
+ model: containments
+
+ Rectangle {
+ id: contRect
+ property real homeX
+ property real homeY
+ property string oldState
+ readonly property int edgeDistance: {
+ return (state === "left" || state === "right" ? width : height) * model.edgePosition;
+ }
+
+ width: moveButton.width
+ height: moveButton.height
+ border.color: Kirigami.Theme.textColor
+ color: Kirigami.Theme.backgroundColor
+ state: model.edge
+ z: state === "floating" ? 0 : 1
+ visible: !model.isDestroyed
+
+ HoverHandler {
+ cursorShape: Qt.OpenHandCursor
+ }
+ DragHandler {
+ id: dragHandler
+ property QQC2.Control targetDelegate
+
+ cursorShape: Qt.ClosedHandCursor
+ onActiveChanged: {
+ if (active) {
+ delegate.z = 1;
+ } else {
+ if (targetDelegate) {
+ resetAnim.restart();
+ containmentRepeater.model.moveContainementToScreen(model.containmentId, targetDelegate.screenId)
+ targetDelegate.containsDrag = false;
+ targetDelegate = null;
+ } else {
+ resetAnim.restart();
+ }
+ }
+ }
+ onTranslationChanged: {
+ if (!active) {
+ if (targetDelegate) {
+ targetDelegate.containsDrag = false;
+ targetDelegate = null;
+ }
+ return;
+ }
+ let pos = contRect.mapToItem(delegate.parent, dragHandler.centroid.position.x, dragHandler.centroid.position.y);
+ let otherDelegate = delegate.parent.childAt(pos.x, pos.y);
+ if (targetDelegate && targetDelegate !== otherDelegate) {
+ targetDelegate.containsDrag = false;
+ }
+ if (!otherDelegate || otherDelegate === delegate) {
+ targetDelegate = null;
+ } else if (otherDelegate && otherDelegate !== delegate
+ && otherDelegate.hasOwnProperty("screenId")
+ && otherDelegate.hasOwnProperty("containsDrag")) {
+ targetDelegate = otherDelegate;
+ targetDelegate.containsDrag = true;
+ }
+ }
+ }
+ SequentialAnimation {
+ id: resetAnim
+ property var targetDelegatePos: dragHandler.targetDelegate
+ ? dragHandler.targetDelegate.contentsLayout.mapToItem(delegate.contentsLayout, 0, 0)
+ : Qt.point(0, 0)
+ ParallelAnimation {
+ XAnimator {
+ target: contRect
+ from: contRect.x
+ to: contRect.homeX + resetAnim.targetDelegatePos.x
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ YAnimator {
+ target: contRect
+ from: contRect.y
+ to: contRect.homeY + resetAnim.targetDelegatePos.y
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ PropertyAction {
+ target: delegate
+ property: "z"
+ value: 0
+ }
+ }
+
+ Image {
+ id: containmentImage
+ anchors {
+ fill: parent
+ margins: 1
+ }
+ // It needs to reload the image from disk when the file changes
+ cache: false
+ source: model.imageSource
+ fillMode: model.edge == "floating" ? Image.PreserveAspectCrop : Image.PreserveAspectFit
+ }
+
+ QQC2.Button {
+ id: moveButton
+ icon.name: "open-menu-symbolic"
+ visible: contextMenuRepeater.anyActionAvailable || removeItem.itemVisible
+ checked: contextMenu.visible
+ anchors {
+ right: parent.right
+ top: parent.top
+ topMargin: model.edge == "floating"
+ ? model.panelCountAtTop * moveButton.height + Kirigami.Units.largeSpacing
+ : 0
+ rightMargin: model.edge == "floating"
+ ? (moveButton.LayoutMirroring.enabled ? model.panelCountAtLeft : model.panelCountAtRight) * moveButton.height + Kirigami.Units.largeSpacing
+ : 0
+ }
+ onClicked: {
+ contextMenu.open()
+ }
+
+ QQC2.Menu {
+ id: contextMenu
+ y: moveButton.height
+ Repeater {
+ id: contextMenuRepeater
+ model: ShellContainmentModel
+
+ // There will always be at least one hidden action for the
+ // current screen; if there's any other, then we should
+ // display them.
+ property bool anyActionAvailable: count > 1
+
+ QQC2.MenuItem {
+ text: edge == "floating"
+ ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Swap with Desktop on Screen %1", model.screenName)
+ : i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Move to Screen %1", model.screenName)
+ visible: model.screenName !== delegate.screenName
+ height: visible ? implicitHeight : 0
+ onTriggered: {
+ containmentRepeater.model.moveContainementToScreen(containmentId, screenId)
+ }
+ }
+ }
+ QQC2.MenuSeparator {
+ visible: removeItem.visible && contextMenuRepeater.anyActionAvailable
+ }
+ QQC2.MenuItem {
+ id: removeItem
+ text: contRect.state === "floating"
+ ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Remove Desktop")
+ : i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Remove Panel")
+ icon.name: "edit-delete"
+ onTriggered: {
+ if (contRect.state === "floating") {
+ ShellContainmentModel.remove(screenId);
+ } else {
+ containments.remove(containmentId);
+ }
+ }
+ // We read this variable elsewhere to know if this item
+ // would be visible if the context menu were to be shown.
+ property bool itemVisible: contRect.state !== "floating" || !model.active
+ visible: itemVisible
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "floating"
+ PropertyChanges {
+ target: contRect;
+ width: screenRect.width
+ height: screenRect.height
+ color: "transparent"
+ }
+ },
+ State {
+ name: "top"
+ PropertyChanges {
+ target: contRect;
+ width: screenRect.width
+ y: homeY
+ homeX: 0
+ homeY: contRect.edgeDistance
+ }
+ },
+ State {
+ name: "right"
+ PropertyChanges {
+ target: contRect;
+ x: homeX
+ homeX: screenRect.width - contRect.width - contRect.edgeDistance;
+ height: screenRect.height
+ homeY: 0
+ }
+ },
+ State {
+ name: "bottom"
+ PropertyChanges {
+ target: contRect;
+ y: homeY
+ homeX: 0
+ homeY: screenRect.height - contRect.height - contRect.edgeDistance;
+ width: screenRect.width
+ }
+ },
+ State {
+ name: "left"
+ PropertyChanges {
+ target: contRect;
+ height: screenRect.height
+ x: homeX
+ homeX: contRect.edgeDistance
+ homeY: 0
+ }
+ }
+ ]
+ }
+ }
+ }
+ QQC2.Label {
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.WordWrap
+ text: model.isPrimary
+ ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@info % is screen name", "%1 (primary)", model.screenName)
+ : model.screenName
+ textFormat: Text.PlainText
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/defaults b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/defaults
new file mode 100644
index 0000000..63c6b2b
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/defaults
@@ -0,0 +1,14 @@
+[Desktop]
+Containment=org.kde.plasma.folder
+ToolBox=
+RuntimePlatform=Desktop
+
+[Desktop][ContainmentActions]
+RightButton;NoModifier=org.kde.contextmenu
+MiddleButton;NoModifier=org.kde.paste
+
+[Panel]
+Containment=org.kde.panel
+ToolBox=org.kde.paneltoolbox
+[Panel][ContainmentActions]
+RightButton;NoModifier=org.kde.contextmenu
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/AppletAlternatives.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/AppletAlternatives.qml
new file mode 100644
index 0000000..7bc0a6b
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/AppletAlternatives.qml
@@ -0,0 +1,211 @@
+/*
+ SPDX-FileCopyrightText: 2014 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Layouts
+import QtQuick.Window
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.components as PlasmaComponents3
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.plasma.plasmoid
+import org.kde.kirigami as Kirigami
+
+import org.kde.plasma.private.shell
+import org.kde.plasma.shell
+
+PlasmaCore.Dialog {
+ id: dialog
+
+ required property AlternativesHelper alternativesHelper
+
+ visualParent: alternativesHelper.applet
+ location: alternativesHelper.applet.Plasmoid.location
+ hideOnWindowDeactivate: true
+ backgroundHints: (alternativesHelper.applet.Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentPrefersOpaqueBackground) ? PlasmaCore.Dialog.SolidBackground : PlasmaCore.Dialog.StandardBackground
+
+ Component.onCompleted: {
+ flags = flags | Qt.WindowStaysOnTopHint;
+ dialog.show();
+ }
+
+ ColumnLayout {
+ id: root
+
+ signal configurationChanged
+
+ Layout.minimumWidth: Kirigami.Units.gridUnit * 20
+ Layout.minimumHeight: Math.min(Screen.height - Kirigami.Units.gridUnit * 10, implicitHeight)
+
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+
+ property string currentPlugin: ""
+
+ Shortcut {
+ sequence: "Escape"
+ onActivated: dialog.close()
+ }
+ Shortcut {
+ sequence: "Return"
+ onActivated: root.savePluginAndClose()
+ }
+ Shortcut {
+ sequence: "Enter"
+ onActivated: root.savePluginAndClose()
+ }
+
+
+ WidgetExplorer {
+ id: widgetExplorer
+ provides: dialog.alternativesHelper.appletProvides
+ }
+
+ PlasmaExtras.PlasmoidHeading {
+ Kirigami.Heading {
+ id: heading
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:window for widget alternatives explorer", "Alternative Widgets")
+ textFormat: Text.PlainText
+ }
+ }
+
+ // This timer checks with a short delay whether a new item in the list has been hovered by the cursor.
+ // If not, then the cursor has left the view and thus no item should be selected.
+ Timer {
+ id: resetCurrentIndex
+ property string oldPlugin
+ interval: 100
+ onTriggered: {
+ if (root.currentPlugin === oldPlugin) {
+ mainList.currentIndex = -1
+ root.currentPlugin = ""
+ }
+ }
+ }
+
+ function savePluginAndClose() {
+ dialog.alternativesHelper.loadAlternative(currentPlugin);
+ dialog.close();
+ }
+
+ PlasmaComponents3.ScrollView {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ Layout.preferredHeight: mainList.contentHeight
+
+ focus: true
+
+ ListView {
+ id: mainList
+
+ focus: dialog.visible
+ model: widgetExplorer.widgetsModel
+ boundsBehavior: Flickable.StopAtBounds
+ highlight: PlasmaExtras.Highlight {
+ pressed: mainList.currentItem && mainList.currentItem.pressed
+ }
+ highlightMoveDuration : 0
+ highlightResizeDuration: 0
+
+ height: contentHeight+Kirigami.Units.smallSpacing
+
+ delegate: PlasmaComponents3.ItemDelegate {
+ id: listItem
+
+ implicitHeight: contentLayout.implicitHeight + Kirigami.Units.smallSpacing * 2
+ width: ListView.view.width
+
+ Accessible.name: model.name
+ Accessible.description: model.description
+
+ onHoveredChanged: {
+ if (hovered) {
+ resetCurrentIndex.stop()
+ mainList.currentIndex = index
+ } else {
+ resetCurrentIndex.oldPlugin = model.pluginName
+ resetCurrentIndex.restart()
+ }
+ }
+
+ Connections {
+ target: mainList
+ function onCurrentIndexChanged() {
+ if (mainList.currentIndex === index) {
+ root.currentPlugin = model.pluginName
+ }
+ }
+ }
+
+ onClicked: root.savePluginAndClose()
+
+ Component.onCompleted: {
+ if (model.pluginName === dialog.alternativesHelper.currentPlugin) {
+ root.currentPlugin = model.pluginName
+ setAsCurrent.restart()
+ }
+ }
+
+ // we don't want to select any entry by default
+ // this cannot be set in Component.onCompleted
+ Timer {
+ id: setAsCurrent
+ interval: 100
+ onTriggered: {
+ mainList.currentIndex = index
+ }
+ }
+
+ contentItem: RowLayout {
+ id: contentLayout
+ spacing: Kirigami.Units.largeSpacing
+
+ Kirigami.Icon {
+ implicitWidth: Kirigami.Units.iconSizes.huge
+ implicitHeight: Kirigami.Units.iconSizes.huge
+ source: model.decoration
+ }
+
+ ColumnLayout {
+ id: labelLayout
+
+ readonly property color textColor: listItem.pressed ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
+
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ spacing: 0 // The labels bring their own bottom margins
+
+ Kirigami.Heading {
+ level: 4
+ Layout.fillWidth: true
+ text: model.name
+ textFormat: Text.PlainText
+ elide: Text.ElideRight
+ type: model.pluginName === dialog.alternativesHelper.currentPlugin ? PlasmaExtras.Heading.Type.Primary : PlasmaExtras.Heading.Type.Normal
+ color: labelLayout.textColor
+ }
+
+ PlasmaComponents3.Label {
+ Layout.fillWidth: true
+ text: model.description
+ textFormat: Text.PlainText
+ font.pointSize: Kirigami.Theme.smallFont.pointSize
+ font.family: Kirigami.Theme.smallFont.family
+ font.bold: model.pluginName === dialog.alternativesHelper.currentPlugin
+ opacity: 0.75
+ maximumLineCount: 2
+ wrapMode: Text.WordWrap
+ elide: Text.ElideRight
+ color: labelLayout.textColor
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/AppletDelegate.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/AppletDelegate.qml
new file mode 100644
index 0000000..30bed28
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/AppletDelegate.qml
@@ -0,0 +1,315 @@
+/*
+ SPDX-FileCopyrightText: 2011 Marco Martin
+ SPDX-FileCopyrightText: 2015 Kai Uwe Broulik
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.components as PlasmaComponents
+import org.kde.plasma.core as PlasmaCore
+import org.kde.kwindowsystem
+import org.kde.kirigami as Kirigami
+import org.kde.graphicaleffects as KGraphicalEffects
+
+Item {
+ id: delegate
+
+ readonly property string pluginName: model.pluginName
+ readonly property bool pendingUninstall: pendingUninstallTimer.applets.indexOf(pluginName) > -1
+ readonly property bool pressed: tapHandler.pressed
+ readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
+
+ width: list.cellWidth
+ height: list.cellHeight
+
+ Accessible.name: i18nc("@action:button accessible only, %1 is widget name", "Add %1", model.name) + (model.isSupported ? "" : unsupportedTooltip.mainText)
+ Accessible.description: (model.isSupported ? "" : model.unsupportedMessage) + model.description + (overlayedBadge.visible ? countLabel.Accessible.name : "")
+ Accessible.role: Accessible.Button
+
+ HoverHandler {
+ id: hoverHandler
+ onHoveredChanged: if (hovered) delegate.GridView.view.currentIndex = index
+ }
+
+ TapHandler {
+ id: tapHandler
+ enabled: !delegate.pendingUninstall && model.isSupported
+ onTapped: widgetExplorer.addApplet(delegate.pluginName)
+ }
+
+ PlasmaCore.ToolTipArea {
+ id: unsupportedTooltip
+ anchors.fill: parent
+ visible: !model.isSupported
+ mainText: i18nc("@info:tooltip", "Unsupported Widget")
+ subText: model.unsupportedMessage
+ }
+
+ // Avoid repositioning delegate item after dragFinished
+ Item {
+ anchors.fill: parent
+ enabled: model.isSupported
+
+ Drag.dragType: Drag.Automatic
+ Drag.supportedActions: Qt.MoveAction | Qt.LinkAction
+ Drag.mimeData: {
+ "text/x-plasmoidservicename" : delegate.pluginName,
+ }
+ Drag.onDragStarted: {
+ KWindowSystem.showingDesktop = true;
+ main.draggingWidget = true;
+ delegate.forceActiveFocus()
+ }
+ Drag.onDragFinished: {
+ main.draggingWidget = false;
+ }
+
+ DragHandler {
+ id: dragHandler
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
+ enabled: !delegate.pendingUninstall && model.isSupported
+
+ onActiveChanged: if (active) {
+ iconContainer.grabToImage(function(result) {
+ if (!dragHandler.active) {
+ return;
+ }
+ parent.Drag.imageSource = result.url;
+ parent.Drag.active = dragHandler.active;
+ }, Qt.size(Kirigami.Units.iconSizes.huge, Kirigami.Units.iconSizes.huge));
+ } else {
+ parent.Drag.active = false;
+ parent.Drag.imageSource = "";
+ }
+ }
+
+
+ DragHandler {
+ id: touchDragHandler
+ acceptedDevices: PointerDevice.Stylus | PointerDevice.TouchScreen
+ enabled: dragHandler.enabled
+ yAxis.enabled: false
+
+ onActiveChanged: if (active) {
+ iconContainer.grabToImage(function(result) {
+ if (!touchDragHandler.active) {
+ return;
+ }
+ parent.Drag.imageSource = result.url;
+ parent.Drag.active = touchDragHandler.active;
+ }, Qt.size(Kirigami.Units.iconSizes.huge, Kirigami.Units.iconSizes.huge));
+ } else {
+ parent.Drag.active = false;
+ parent.Drag.imageSource = "";
+ }
+ }
+
+ }
+
+ ColumnLayout {
+ id: mainLayout
+
+ readonly property color textColor: tapHandler.pressed ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
+
+ spacing: Kirigami.Units.smallSpacing
+ anchors {
+ left: parent.left
+ right: parent.right
+ //bottom: parent.bottom
+ margins: Kirigami.Units.smallSpacing * 2
+ rightMargin: Kirigami.Units.smallSpacing * 2 // don't cram the text to the border too much
+ top: parent.top
+ }
+
+ Item {
+ id: iconContainer
+ width: Kirigami.Units.iconSizes.enormous
+ height: width
+ Layout.alignment: Qt.AlignHCenter
+ opacity: delegate.pendingUninstall ? 0.6 : 1
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ Item {
+ id: iconWidget
+ anchors.fill: parent
+ Kirigami.Icon {
+ anchors.fill: parent
+ source: model.decoration
+ visible: model.screenshot === ""
+ selected: tapHandler.pressed
+ enabled: model.isSupported
+ }
+ Image {
+ width: Kirigami.Units.iconSizes.enormous
+ height: width
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectFit
+ source: model.screenshot
+ }
+ }
+
+ Item {
+ id: badgeMask
+ anchors.fill: parent
+
+ Rectangle {
+ x: Math.round(-Kirigami.Units.smallSpacing * 1.5 / 2)
+ y: x
+ width: overlayedBadge.width + Math.round(Kirigami.Units.smallSpacing * 1.5)
+ height: overlayedBadge.height + Math.round(Kirigami.Units.smallSpacing * 1.5)
+ radius: height
+ visible: (running && delegate.GridView.isCurrentItem) ?? false
+ }
+ }
+
+ KGraphicalEffects.BadgeEffect {
+ anchors.fill: parent
+ source: ShaderEffectSource {
+ sourceItem: iconWidget
+ hideSource: !softwareRendering
+ live: false
+ }
+ mask: ShaderEffectSource {
+ id: maskShaderSource
+ sourceItem: badgeMask
+ hideSource: true
+ live: false
+ }
+ }
+
+ Rectangle {
+ id: overlayedBadge
+ width: countLabel.width + height
+ height: Math.round(Kirigami.Units.iconSizes.sizeForLabels * 1.3)
+ radius: height
+ color: (running && delegate.GridView.isCurrentItem) ? Kirigami.Theme.highlightColor : Kirigami.Theme.positiveTextColor
+ visible: ((running && delegate.GridView.isCurrentItem) || model.recent) ?? false
+ onVisibleChanged: maskShaderSource.scheduleUpdate()
+
+ PlasmaComponents.Label {
+ id: countLabel
+ height: parent.height
+ verticalAlignment: Text.AlignVCenter
+ anchors.centerIn: parent
+ text: (running && delegate.GridView.isCurrentItem) ? running : i18ndc("plasma_shell_org.kde.plasma.desktop", "Text displayed on top of newly installed widgets", "New!")
+ Accessible.name: running
+ ? i18ncp("@info:other accessible for badge showing applet count", "%1 widget active", "%1 widgets active", running)
+ : i18nc(" @info:other accessible for badge indicating new widget", "Recently installed")
+ textFormat: Text.PlainText
+ }
+ }
+
+
+ PlasmaComponents.ToolButton {
+ id: uninstallButton
+ anchors {
+ top: parent.top
+ right: parent.right
+ }
+ text: delegate.pendingUninstall ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button tooltip and accessible cancel uninstall widget", "Cancel Uninstallation")
+ : i18ndc("plasma_shell_org.kde.plasma.desktop","@action:button tooltip and accessible uninstall widget", "Mark for Uninstallation")
+ icon.name: delegate.pendingUninstall ? "edit-undo" : "edit-delete"
+ display: PlasmaComponents.AbstractButton.IconOnly
+ Accessible.description: delegate.pendingUninstall
+ ? i18nc("@action:button accessible only, %1 is widget name", "Cancel pending uninstallation for widget %1", model.name)
+ : i18nc("@action:button accessible only, %1 is widget name", "Mark widget %1 for uninstallation. Requires confirmation", model.name)
+ // we don't really "undo" anything but we'll pretend to the user that we do
+ PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay
+ PlasmaComponents.ToolTip.visible: hovered
+ PlasmaComponents.ToolTip.text: text
+ flat: false
+ visible: (model.local && delegate.GridView.isCurrentItem && !dragHandler.active && !touchDragHandler.active) ?? false
+
+ onHoveredChanged: {
+ if (hovered) {
+ // hovering the uninstall button triggers onExited of the main mousearea
+ delegate.GridView.view.currentIndex = index
+ }
+ }
+
+ onClicked: {
+ let pending = pendingUninstallTimer.applets
+ if (delegate.pendingUninstall) {
+ let index = pending.indexOf(pluginName)
+ if (index > -1) {
+ pending.splice(index, 1)
+ }
+ } else {
+ pending.push(pluginName)
+ }
+ pendingUninstallTimer.applets = pending
+
+ if (pending.length) {
+ pendingUninstallTimer.restart()
+ } else {
+ pendingUninstallTimer.stop()
+ }
+ }
+ }
+
+ PlasmaComponents.ToolButton {
+ id: removeInstancesButton
+ anchors {
+ top: parent.top
+ right: uninstallButton.visible ? uninstallButton.left : parent.right
+ rightMargin: uninstallButton.visible ? Kirigami.Units.smallSpacing : 0
+ }
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Remove all instances")
+ display: PlasmaComponents.AbstractButton.IconOnly
+ icon.name: "edit-clear-all"
+ Accessible.description: i18ncp("@action:button accessible description, %1 number of instances %2 is widget name",
+ "Remove running instance of widget %2",
+ "Remove all %1 running instances of widget %2", running ,model.name)
+
+ // we don't really "undo" anything but we'll pretend to the user that we do
+ PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay
+ PlasmaComponents.ToolTip.visible: hovered
+ PlasmaComponents.ToolTip.text: text
+ flat: false
+ visible: (running && delegate.GridView.isCurrentItem && !dragHandler.active) ?? false
+
+ onHoveredChanged: {
+ if (hovered) {
+ // hovering the uninstall button triggers onExited of the main mousearea
+ delegate.GridView.view.currentIndex = index
+ }
+ }
+
+ onClicked: widgetExplorer.removeAllInstances(pluginName)
+ }
+ }
+ Kirigami.Heading {
+ id: heading
+ Layout.fillWidth: true
+ level: 4
+ text: model.name
+ textFormat: Text.PlainText
+ elide: Text.ElideRight
+ wrapMode: Text.WordWrap
+ maximumLineCount: 3
+ lineHeight: 0.95
+ horizontalAlignment: Text.AlignHCenter
+ color: mainLayout.textColor
+ }
+ PlasmaComponents.Label {
+ Layout.fillWidth: true
+ // otherwise causes binding loop due to the way the Plasma sets the height
+ text: model.description
+ textFormat: Text.PlainText
+ font: Kirigami.Theme.smallFont
+ wrapMode: Text.WordWrap
+ elide: Text.ElideRight
+ maximumLineCount: 5 - heading.lineCount
+ horizontalAlignment: Text.AlignHCenter
+ color: mainLayout.textColor
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/WidgetExplorer.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/WidgetExplorer.qml
new file mode 100644
index 0000000..0ce36c7
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/explorer/WidgetExplorer.qml
@@ -0,0 +1,392 @@
+/*
+ SPDX-FileCopyrightText: 2011 Marco Martin
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Controls as QQC2
+
+import org.kde.plasma.components as PC3
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kquickcontrolsaddons
+import org.kde.kwindowsystem
+import org.kde.kirigami as Kirigami
+
+import QtQuick.Window
+import QtQuick.Layouts
+
+import org.kde.plasma.private.shell
+
+PC3.Page {
+ id: main
+
+ width: Math.max(heading.paintedWidth, Kirigami.Units.iconSizes.enormous * 3 + Kirigami.Units.smallSpacing * 4 + Kirigami.Units.gridUnit * 5)
+ height: 800//Screen.height
+
+ opacity: draggingWidget ? 0.3 : 1
+
+ readonly property int contentMargins: Kirigami.Units.largeSpacing
+
+ property QtObject containment
+
+ property PlasmaCore.Dialog sidePanel
+
+ //external drop events can cause a raise event causing us to lose focus and
+ //therefore get deleted whilst we are still in a drag exec()
+ //this is a clue to the owning dialog that hideOnWindowDeactivate should be deleted
+ //See https://bugs.kde.org/show_bug.cgi?id=332733
+ property bool preventWindowHide: draggingWidget || categoriesDialog.status !== PlasmaExtras.Menu.Closed
+ || getWidgetsDialog.status !== PlasmaExtras.Menu.Closed
+
+ // We might've lost focus during the widget drag and drop or whilst using
+ // the "get widgets" dialog; however we prevented the sidebar to hide.
+ // This might get the sidebar stuck, since we only hide when losing focus.
+ // To avoid this we reclaim focus as soon as the drag and drop is done,
+ // or the get widgets window is closed.
+ onPreventWindowHideChanged: {
+ if (!preventWindowHide && !sidePanel.active) {
+ sidePanel.requestActivate()
+ }
+ }
+
+ property bool outputOnly: draggingWidget
+
+ property Item categoryButton
+
+ property bool draggingWidget: false
+
+ signal closed()
+
+ onClosed: {
+ // If was called from a panel, open the panel config
+ if (root.widgetExplorer.containment &&
+ root.widgetExplorer.containment.containmentType == 1 &&
+ !root.widgetExplorer.containment.userConfiguring) {
+ root.widgetExplorer.containment.internalAction("configure").trigger()
+ }
+ }
+
+ onVisibleChanged: {
+ if (!visible) {
+ KWindowSystem.showingDesktop = false
+ }
+ }
+
+ Component.onCompleted: {
+ if (!root.widgetExplorer) {
+ root.widgetExplorer = widgetExplorerComponent.createObject(root)
+ }
+ root.widgetExplorer.containment = main.containment
+ }
+
+ Component.onDestruction: {
+ if (pendingUninstallTimer.running) {
+ // we're not being destroyed so at least reset the filters
+ widgetExplorer.widgetsModel.filterQuery = ""
+ widgetExplorer.widgetsModel.filterType = ""
+ widgetExplorer.widgetsModel.searchTerm = ""
+ } else {
+ root.widgetExplorer.destroy()
+ root.widgetExplorer = null
+ }
+ }
+
+ function addCurrentApplet() {
+ var pluginName = list.currentItem ? list.currentItem.pluginName : ""
+ if (pluginName) {
+ widgetExplorer.addApplet(pluginName)
+ }
+ }
+
+ QQC2.Action {
+ shortcut: "Escape"
+ onTriggered: {
+ if (searchInput.length > 0) {
+ searchInput.text = ""
+ } else {
+ main.closed()
+ }
+ }
+ }
+
+ QQC2.Action {
+ shortcut: "Enter"
+ onTriggered: addCurrentApplet()
+ }
+ QQC2.Action {
+ shortcut: "Return"
+ onTriggered: addCurrentApplet()
+ }
+
+ Component {
+ id: widgetExplorerComponent
+
+ WidgetExplorer {
+ //view: desktop
+ onShouldClose: main.closed();
+ }
+ }
+
+ PlasmaExtras.ModelContextMenu {
+ id: categoriesDialog
+ visualParent: categoryButton
+ // model set on first invocation
+
+ onClicked: model => {
+ list.contentX = 0
+ list.contentY = 0
+ categoryButton.text = (model.filterData ? model.display : i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button like listbox, switches category to all widgets", "All Widgets"))
+ widgetExplorer.widgetsModel.filterQuery = model.filterData
+ widgetExplorer.widgetsModel.filterType = model.filterType
+ }
+ }
+
+ PlasmaExtras.ModelContextMenu {
+ id: getWidgetsDialog
+ visualParent: getWidgetsButton
+ placement: PlasmaExtras.Menu.TopPosedLeftAlignedPopup
+ // model set on first invocation
+ onClicked: model.trigger()
+ }
+
+ header: PlasmaExtras.PlasmoidHeading {
+ // Subtract page's own margins since we touch the top, left, and right
+ topPadding: - main.sidePanel.margins.top
+ leftPadding: main.contentMargins - main.sidePanel.margins.left
+ rightPadding: main.contentMargins - main.sidePanel.margins.right
+ bottomPadding: main.contentMargins
+
+ contentItem: ColumnLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+ Kirigami.Heading {
+ id: heading
+ level: 1
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@title:group for widget grid", "Widgets")
+ textFormat: Text.PlainText
+ elide: Text.ElideRight
+
+ Layout.fillWidth: true
+ }
+ PC3.ToolButton {
+ id: getWidgetsButton
+ icon.name: "get-hot-new-stuff"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button The word 'new' refers to widgets", "Get New…")
+ Accessible.name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Get New Widgets…")
+
+
+ KeyNavigation.right: closeButton
+ KeyNavigation.down: searchInput
+
+ onClicked: {
+ getWidgetsDialog.model = widgetExplorer.widgetsMenuActions
+ getWidgetsDialog.openRelative()
+ }
+ }
+ PC3.ToolButton {
+ id: closeButton
+ text: i18nc("@action:button accessible for close button", "Close Widget Explorer")
+ icon.name: "window-close"
+ display: PC3.AbstractButton.IconOnly
+
+ KeyNavigation.down: categoryButton
+
+ onClicked: main.closed()
+ }
+ }
+
+ RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+
+ PlasmaExtras.SearchField {
+ id: searchInput
+ Layout.fillWidth: true
+ Accessible.name: i18nc("@label:textbox accessible", "Search through widgets")
+
+ KeyNavigation.down: list
+ KeyNavigation.right: categoryButton
+
+ onTextChanged: {
+ list.positionViewAtBeginning()
+ list.currentIndex = -1
+ widgetExplorer.widgetsModel.searchTerm = text
+ }
+
+ Component.onCompleted: if (!Kirigami.InputMethod.willShowOnActive) { forceActiveFocus() }
+ }
+ PC3.ToolButton {
+ id: categoryButton
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button like listbox, switches category to all widgets", "All Widgets")
+ icon.name: "view-filter"
+
+ Accessible.role: Accessible.ButtonMenu
+ down: categoriesDialog.status == PlasmaExtras.ModelContextMenu.Open || pressed
+
+ KeyNavigation.down: list
+
+ onClicked: {
+ categoriesDialog.model = widgetExplorer.filterModel
+ categoriesDialog.open(0, categoryButton.height)
+ }
+
+ PC3.ToolTip {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button tooltip only", "Categories")
+ }
+ }
+ }
+ }
+ }
+
+ footer: PlasmaExtras.PlasmoidHeading {
+ id: footerContainer
+
+ // Subtract page's own margins since we touch the left, right, and bottom
+ topPadding: main.contentMargins
+ leftPadding: main.contentMargins - main.sidePanel.margins.left
+ rightPadding: main.contentMargins - main.sidePanel.margins.right
+ bottomPadding: main.contentMargins - main.sidePanel.margins.bottom
+
+ position: PC3.ToolBar.Footer
+ visible: pendingUninstallTimer.applets.length > 0
+
+ contentItem: PC3.Button {
+ id: uninstallButton
+ icon.name: "delete"
+ text: i18ndcp("plasma_shell_org.kde.plasma.desktop", "@action:button uninstall widgets in widget explorer", "Uninstall (%1 Widget)", "Uninstall (%1 Widgets)", pendingUninstallTimer.applets.length)
+ onClicked: pendingUninstallTimer.uninstall()
+ }
+ }
+
+ Timer {
+ id: setModelTimer
+ interval: 20
+ running: true
+ onTriggered: list.model = widgetExplorer.widgetsModel
+ }
+
+ PC3.ScrollView {
+ id: scrollView
+ anchors {
+ fill: parent
+ // Subtract page's own margins since we touch the left, right, and sometimes bottom
+ topMargin: -1 // account for PlasmoidHeading's pixel
+ leftMargin: - main.sidePanel.margins.left
+ rightMargin: - main.sidePanel.margins.right
+ bottomMargin: footerContainer.visible ? 0 : - main.sidePanel.margins.bottom
+ }
+
+ // The scrollbar changing visibility can lead to the content size changing due to word wrap
+ // A delayed binding gives some extra time, it'll come to a stop as there's only one scroll bar
+ property bool scrollBarVisible
+ Binding on scrollBarVisible {
+ value: list.contentHeight > scrollView.height
+ delayed: true
+ }
+
+ PC3.ScrollBar.horizontal.policy: PC3.ScrollBar.AlwaysOff
+ PC3.ScrollBar.vertical.visible: scrollBarVisible
+
+ // hide the flickering by fading in nicely
+ opacity: setModelTimer.running ? 0 : 1
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ GridView {
+ id: list
+
+ readonly property int effectiveWidth: width
+ - leftMargin
+ - rightMargin
+
+ // model set delayed by Timer above
+
+ topMargin: main.contentMargins
+ leftMargin: main.contentMargins
+ rightMargin: main.contentMargins
+ bottomMargin: main.contentMargins
+
+ activeFocusOnTab: true
+ cellWidth: Math.floor(effectiveWidth / 3)
+ cellHeight: Kirigami.Units.iconSizes.enormous + Kirigami.Units.smallSpacing * 4 + headingFontMetrics.height * 3 * referenceHeading.lineHeight + descriptionFontMetrics.height * 2
+
+ // This element is used as a reference to size the
+ // cellHeight and should be kept in sync with the
+ // heading within the AppletDelegate.
+ Kirigami.Heading {
+ id: referenceHeading
+ visible: false
+ level: 4
+ lineHeight: 0.95
+ }
+ FontMetrics {
+ id: headingFontMetrics
+ font: referenceHeading.font
+ }
+ FontMetrics {
+ id: descriptionFontMetrics
+ font: Kirigami.Theme.smallFont
+ }
+
+ delegate: AppletDelegate {}
+ highlight: PlasmaExtras.Highlight {
+ pressed: list.currentItem && list.currentItem.pressed
+ }
+ highlightMoveDuration: 0
+ //highlightResizeDuration: 0
+
+ //slide in to view from the left
+ add: Transition {
+ // Work around https://bugreports.qt.io/browse/QTBUG-127709
+ enabled: Kirigami.Units.shortDuration > 0
+ NumberAnimation {
+ properties: "x"
+ from: -list.width
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+
+ //slide out of view to the right
+ remove: Transition {
+ // Work around https://bugreports.qt.io/browse/QTBUG-127709
+ enabled: Kirigami.Units.shortDuration > 0
+ NumberAnimation {
+ properties: "x"
+ to: list.width
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+
+ //if we are adding other items into the view use the same animation as normal adding
+ //this makes everything slide in together
+ //if we make it move everything ends up weird
+ addDisplaced: list.add
+
+ //moved due to filtering
+ displaced: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ duration: Kirigami.Units.shortDuration
+ }
+ }
+
+ KeyNavigation.up: searchInput
+ KeyNavigation.down: uninstallButton
+ }
+ }
+
+ PlasmaExtras.PlaceholderMessage {
+ anchors.centerIn: parent
+ width: parent.width - (Kirigami.Units.gridUnit * 4)
+ iconName: "edit-none"
+ text: searchInput.text.length > 0 ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@info placeholdermessage", "No widgets matched the search terms") : i18ndc("plasma_shell_org.kde.plasma.desktop", "@info placeholdermessage", "No widgets available")
+ visible: list.count == 0 && !setModelTimer.running
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockOsd.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockOsd.qml
new file mode 100644
index 0000000..4629c10
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockOsd.qml
@@ -0,0 +1,72 @@
+/*
+ SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import org.kde.ksvg as KSvg
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.workspace.osd
+
+KSvg.FrameSvgItem {
+ id: osd
+
+ property alias timeout: osdItem.timeout
+ property alias osdValue: osdItem.osdValue
+ property alias osdMaxValue: osdItem.osdMaxValue
+ property alias icon: osdItem.icon
+ property alias showingProgress: osdItem.showingProgress
+
+ objectName: "onScreenDisplay"
+ visible: false
+ width: osdItem.width + margins.left + margins.right
+ height: osdItem.height + margins.top + margins.bottom
+ imagePath: "dialogs/background"
+
+ Kirigami.Theme.inherit: false
+ Kirigami.Theme.colorSet: Kirigami.Theme.Window
+
+ function show() {
+ osd.visible = true;
+ hideAnimation.restart();
+ }
+
+ // avoid leaking ColorScope of lock screen theme into the OSD "popup"
+ Item {
+ width: osdItem.width
+ height: osdItem.height
+ anchors.centerIn: parent
+
+ OsdItem {
+ id: osdItem
+ }
+ }
+
+ SequentialAnimation {
+ id: hideAnimation
+ ScriptAction {
+ // prevent opacity layering of ProgressBar.
+ script: osd.layer.enabled = true
+ }
+ // prevent press and hold from flickering
+ PauseAnimation { duration: osd.timeout }
+ NumberAnimation {
+ target: osd
+ property: "opacity"
+ from: 1
+ to: 0
+ duration: Kirigami.Units.shortDuration
+ easing.type: Easing.InQuad
+ }
+ ScriptAction {
+ script: {
+ osd.visible = false;
+ osd.opacity = 1;
+ osd.icon = "";
+ osd.osdValue = 0;
+ osd.layer.enabled = false;
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockScreen.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockScreen.qml
new file mode 100644
index 0000000..8924a4c
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockScreen.qml
@@ -0,0 +1,34 @@
+/*
+ SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+
+Item {
+ id: root
+ property bool debug: false
+ property string notification
+ signal clearPassword()
+ signal notificationRepeated()
+
+ // These are magical properties that kscreenlocker looks for
+ property bool viewVisible: false
+ property bool suspendToRamSupported: false
+ property bool suspendToDiskSupported: false
+
+ // These are magical signals that kscreenlocker looks for
+ signal suspendToDisk()
+ signal suspendToRam()
+
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+
+ implicitWidth: 800
+ implicitHeight: 600
+
+ LockScreenUi {
+ anchors.fill: parent
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockScreenUi.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockScreenUi.qml
new file mode 100644
index 0000000..e5cba30
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/LockScreenUi.qml
@@ -0,0 +1,427 @@
+/*
+ SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQml
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Qt5Compat.GraphicalEffects
+
+import org.kde.plasma.components as PlasmaComponents3
+import org.kde.plasma.workspace.components as PW
+import org.kde.plasma.private.keyboardindicator as KeyboardIndicator
+import org.kde.kirigami as Kirigami
+import org.kde.kscreenlocker as ScreenLocker
+
+import org.kde.plasma.private.sessions
+import org.kde.breeze.components
+
+Item {
+ id: lockScreenUi
+
+ // If we're using software rendering, draw outlines instead of shadows
+ // See https://bugs.kde.org/show_bug.cgi?id=398317
+ readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
+
+ function handleMessage(msg) {
+ if (!root.notification) {
+ root.notification += msg;
+ } else if (root.notification.includes(msg)) {
+ root.notificationRepeated();
+ } else {
+ root.notification += "\n" + msg
+ }
+ }
+
+ Kirigami.Theme.inherit: false
+ Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
+
+ Connections {
+ target: authenticator
+ function onFailed(kind) {
+ if (kind != 0) { // if this is coming from the noninteractive authenticators
+ return;
+ }
+ const msg = i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:status", "Unlocking failed");
+ lockScreenUi.handleMessage(msg);
+ graceLockTimer.restart();
+ notificationRemoveTimer.restart();
+ rejectPasswordAnimation.start();
+ }
+
+ function onSucceeded() {
+ if (authenticator.hadPrompt) {
+ Qt.quit();
+ } else {
+ mainStack.replace(null, Qt.resolvedUrl("NoPasswordUnlock.qml"),
+ {
+ userListModel: users
+ },
+ StackView.Immediate,
+ );
+ mainStack.forceActiveFocus();
+ }
+ }
+
+ function onInfoMessageChanged() {
+ lockScreenUi.handleMessage(authenticator.infoMessage);
+ }
+
+ function onErrorMessageChanged() {
+ lockScreenUi.handleMessage(authenticator.errorMessage);
+ }
+
+ function onPromptChanged(msg) {
+ lockScreenUi.handleMessage(authenticator.prompt);
+ }
+ function onPromptForSecretChanged(msg) {
+ mainBlock.showPassword = false;
+ mainBlock.mainPasswordBox.forceActiveFocus();
+ }
+ }
+
+ SessionManagement {
+ id: sessionManagement
+ }
+
+ KeyboardIndicator.KeyState {
+ id: capsLockState
+ key: Qt.Key_CapsLock
+ }
+
+ Connections {
+ target: sessionManagement
+ function onAboutToSuspend() {
+ root.clearPassword();
+ }
+ }
+
+ RejectPasswordAnimation {
+ id: rejectPasswordAnimation
+ target: mainBlock
+ }
+
+ MouseArea {
+ id: lockScreenRoot
+
+ property bool uiVisible: false
+ property bool seenPositionChange: false
+ property bool blockUI: containsMouse && (mainStack.depth > 1 || mainBlock.mainPasswordBox.text.length > 0 || inputPanel.keyboardActive)
+
+ x: parent.x
+ y: parent.y
+ width: parent.width
+ height: parent.height
+ hoverEnabled: true
+ cursorShape: uiVisible ? Qt.ArrowCursor : Qt.BlankCursor
+ drag.filterChildren: true
+ onPressed: uiVisible = true;
+ onPositionChanged: {
+ uiVisible = seenPositionChange;
+ seenPositionChange = true;
+ }
+ onUiVisibleChanged: {
+ if (uiVisible) {
+ Window.window.requestActivate();
+ }
+
+ if (blockUI) {
+ fadeoutTimer.running = false;
+ } else if (uiVisible) {
+ fadeoutTimer.restart();
+ }
+ authenticator.startAuthenticating();
+ }
+ onBlockUIChanged: {
+ if (blockUI) {
+ fadeoutTimer.running = false;
+ uiVisible = true;
+ } else {
+ fadeoutTimer.restart();
+ }
+ }
+ onExited: {
+ uiVisible = false;
+ }
+ Keys.onEscapePressed: {
+ // If the escape key is pressed, kscreenlocker will turn off the screen.
+ // We do not want to show the password prompt in this case.
+ if (uiVisible) {
+ uiVisible = false;
+ if (inputPanel.keyboardActive) {
+ inputPanel.showHide();
+ }
+ root.clearPassword();
+ }
+ }
+ Keys.onPressed: event => {
+ uiVisible = true;
+ event.accepted = false;
+ }
+ Timer {
+ id: fadeoutTimer
+ interval: 10000
+ onTriggered: {
+ if (!lockScreenRoot.blockUI) {
+ mainBlock.mainPasswordBox.showPassword = false;
+ lockScreenRoot.uiVisible = false;
+ }
+ }
+ }
+ Timer {
+ id: notificationRemoveTimer
+ interval: 3000
+ onTriggered: root.notification = ""
+ }
+ Timer {
+ id: graceLockTimer
+ interval: 3000
+ onTriggered: {
+ root.clearPassword();
+ authenticator.startAuthenticating();
+ }
+ }
+
+ PropertyAnimation {
+ id: launchAnimation
+ target: lockScreenRoot
+ property: "opacity"
+ from: 0
+ to: 1
+ duration: Kirigami.Units.veryLongDuration * 2
+ }
+
+ Component.onCompleted: launchAnimation.start();
+
+ WallpaperFader {
+ anchors.fill: parent
+ state: lockScreenRoot.uiVisible ? "on" : "off"
+ source: wallpaper
+ mainStack: mainStack
+ footer: footer
+ clock: clock
+ alwaysShowClock: config.alwaysShowClock && !config.hideClockWhenIdle
+ }
+
+ DropShadow {
+ id: clockShadow
+ anchors.fill: clock
+ source: clock
+ visible: !lockScreenUi.softwareRendering && config.alwaysShowClock
+ radius: 7
+ verticalOffset: 0.8
+ samples: 15
+ spread: 0.2
+ color : Qt.rgba(0, 0, 0, 0.7)
+ opacity: lockScreenRoot.uiVisible ? 0 : 1
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: Kirigami.Units.veryLongDuration * 2
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+
+ Clock {
+ id: clock
+ property Item shadow: clockShadow
+ visible: y > 0 && config.alwaysShowClock
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: (mainBlock.userList.y + mainStack.y)/2 - height/2
+ Layout.alignment: Qt.AlignBaseline
+ }
+
+ ListModel {
+ id: users
+
+ Component.onCompleted: {
+ users.append({
+ name: kscreenlocker_userName,
+ realName: kscreenlocker_userName,
+ icon: kscreenlocker_userImage !== ""
+ ? "file://" + kscreenlocker_userImage.split("/").map(encodeURIComponent).join("/")
+ : "",
+ })
+ }
+ }
+
+ StackView {
+ id: mainStack
+ anchors {
+ left: parent.left
+ right: parent.right
+ }
+ height: lockScreenRoot.height + Kirigami.Units.gridUnit * 3
+ focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it
+
+ // this isn't implicit, otherwise items still get processed for the scenegraph
+ visible: opacity > 0
+
+ initialItem: MainBlock {
+ id: mainBlock
+ lockScreenUiVisible: lockScreenRoot.uiVisible
+
+ showUserList: userList.y + mainStack.y > 0
+
+ enabled: !graceLockTimer.running
+
+ StackView.onStatusChanged: {
+ // prepare for presenting again to the user
+ if (StackView.status === StackView.Activating) {
+ mainPasswordBox.clear();
+ mainPasswordBox.focus = true;
+ root.notification = "";
+ }
+ }
+ userListModel: users
+
+
+ notificationMessage: {
+ const parts = [];
+ if (capsLockState.locked) {
+ parts.push(i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:status", "Caps Lock is on"));
+ }
+ if (root.notification) {
+ parts.push(root.notification);
+ }
+ return parts.join(" • ");
+ }
+
+ onPasswordResult: password => {
+ authenticator.respond(password)
+ }
+
+ actionItems: [
+ ActionButton {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Slee&p")
+ icon.name: "system-suspend"
+ onClicked: root.suspendToRam()
+ visible: root.suspendToRamSupported
+ },
+ ActionButton {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "&Hibernate")
+ icon.name: "system-suspend-hibernate"
+ onClicked: root.suspendToDisk()
+ visible: root.suspendToDiskSupported
+ },
+ ActionButton {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Switch &User")
+ icon.name: "system-switch-user"
+ onClicked: {
+ sessionManagement.switchUser();
+ }
+ visible: sessionManagement.canSwitchUser
+ }
+ ]
+
+ Loader {
+ Layout.topMargin: Kirigami.Units.smallSpacing // some distance to the password field
+ Layout.fillWidth: true
+ Layout.preferredHeight: item ? item.implicitHeight : 0
+ active: config.showMediaControls
+ source: "MediaControls.qml"
+ }
+ }
+ }
+
+ VirtualKeyboardLoader {
+ id: inputPanel
+
+ z: 1
+
+ screenRoot: lockScreenRoot
+ mainStack: mainStack
+ mainBlock: mainBlock
+ passwordField: mainBlock.mainPasswordBox
+ }
+
+ Loader {
+ z: 2
+ active: root.viewVisible
+ source: "LockOsd.qml"
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ bottom: parent.bottom
+ bottomMargin: Kirigami.Units.gridUnit
+ }
+ }
+
+ // Note: Containment masks stretch clickable area of their buttons to
+ // the screen edges, essentially making them adhere to Fitts's law.
+ // Due to virtual keyboard button having an icon, buttons may have
+ // different heights, so fillHeight is required.
+ //
+ // Note for contributors: Keep this in sync with SDDM Main.qml footer.
+ RowLayout {
+ id: footer
+ anchors {
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ margins: Kirigami.Units.smallSpacing
+ }
+ spacing: Kirigami.Units.smallSpacing
+
+ PlasmaComponents3.ToolButton {
+ id: virtualKeyboardButton
+
+ focusPolicy: Qt.TabFocus
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "Button to show/hide virtual keyboard", "Virtual Keyboard")
+ icon.name: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off"
+ onClicked: {
+ // Otherwise the password field loses focus and virtual keyboard
+ // keystrokes get eaten
+ mainBlock.mainPasswordBox.forceActiveFocus();
+ inputPanel.showHide()
+ }
+
+ visible: inputPanel.status === Loader.Ready
+
+ Layout.fillHeight: true
+ containmentMask: Item {
+ parent: virtualKeyboardButton
+ anchors.fill: parent
+ anchors.leftMargin: -footer.anchors.margins
+ anchors.bottomMargin: -footer.anchors.margins
+ }
+ }
+
+ PlasmaComponents3.ToolButton {
+ id: keyboardButton
+
+ focusPolicy: Qt.TabFocus
+ Accessible.description: i18ndc("plasma_shell_org.kde.plasma.desktop", "Button to change keyboard layout", "Switch layout")
+ icon.name: "input-keyboard"
+
+ PW.KeyboardLayoutSwitcher {
+ id: keyboardLayoutSwitcher
+
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton
+ }
+
+ text: keyboardLayoutSwitcher.layoutNames.longName
+ onClicked: keyboardLayoutSwitcher.keyboardLayout.switchToNextLayout()
+
+ visible: keyboardLayoutSwitcher.hasMultipleKeyboardLayouts
+
+ Layout.fillHeight: true
+ containmentMask: Item {
+ parent: keyboardButton
+ anchors.fill: parent
+ anchors.leftMargin: virtualKeyboardButton.visible ? 0 : -footer.anchors.margins
+ anchors.bottomMargin: -footer.anchors.margins
+ }
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Battery {}
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/MainBlock.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/MainBlock.qml
new file mode 100644
index 0000000..5dab857
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/MainBlock.qml
@@ -0,0 +1,169 @@
+/*
+ SPDX-FileCopyrightText: 2016 David Edmundson
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+import QtQuick
+
+import QtQuick.Layouts
+import QtQuick.Controls as QQC2
+
+import org.kde.plasma.components as PlasmaComponents3
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+import org.kde.kscreenlocker as ScreenLocker
+
+import org.kde.breeze.components
+
+SessionManagementScreen {
+ id: sessionManager
+
+ readonly property alias mainPasswordBox: passwordBox
+ property bool lockScreenUiVisible: false
+ property alias showPassword: passwordBox.showPassword
+
+ //the y position that should be ensured visible when the on screen keyboard is visible
+ property int visibleBoundary: mapFromItem(loginButton, 0, 0).y
+ onHeightChanged: visibleBoundary = mapFromItem(loginButton, 0, 0).y + loginButton.height + Kirigami.Units.smallSpacing
+ /*
+ * Login has been requested with the following username and password
+ * If username field is visible, it will be taken from that, otherwise from the "name" property of the currentIndex
+ */
+ signal passwordResult(string password)
+
+ onUserSelected: {
+ const nextControl = (passwordBox.visible ? passwordBox : loginButton);
+ // Don't startLogin() here, because the signal is connected to the
+ // Escape key as well, for which it wouldn't make sense to trigger
+ // login. Using TabFocusReason, so that the loginButton gets the
+ // visual highlight.
+ nextControl.forceActiveFocus(Qt.TabFocusReason);
+ }
+
+ function startLogin() {
+ const password = passwordBox.text
+
+ // This is partly because it looks nicer, but more importantly it
+ // works round a Qt bug that can trigger if the app is closed with a
+ // TextField focused.
+ //
+ // See https://bugreports.qt.io/browse/QTBUG-55460
+ loginButton.forceActiveFocus();
+ passwordResult(password);
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ PlasmaExtras.PasswordField {
+ id: passwordBox
+ font.pointSize: Kirigami.Theme.defaultFont.pointSize + 1
+ Layout.fillWidth: true
+ text: PasswordSync.password
+
+ placeholderText: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:placeholder in text field", "Password")
+ focus: true
+ enabled: !authenticator.graceLocked
+
+ // In Qt this is implicitly active based on focus rather than visibility
+ // in any other application having a focussed invisible object would be weird
+ // but here we are using to wake out of screensaver mode
+ // We need to explicitly disable cursor flashing to avoid unnecessary renders
+ cursorVisible: visible
+
+ onAccepted: {
+ if (sessionManager.lockScreenUiVisible) {
+ sessionManager.startLogin();
+ }
+ }
+
+ //if empty and left or right is pressed change selection in user switch
+ //this cannot be in keys.onLeftPressed as then it doesn't reach the password box
+ Keys.onPressed: event => {
+ if (event.key === Qt.Key_Left && !text) {
+ sessionManager.userList.decrementCurrentIndex();
+ event.accepted = true
+ }
+ if (event.key === Qt.Key_Right && !text) {
+ sessionManager.userList.incrementCurrentIndex();
+ event.accepted = true
+ }
+ }
+
+ Connections {
+ target: root
+ function onClearPassword() {
+ passwordBox.forceActiveFocus()
+ passwordBox.text = "";
+ passwordBox.text = Qt.binding(() => PasswordSync.password);
+ }
+ function onNotificationRepeated() {
+ sessionManager.playHighlightAnimation();
+ }
+ }
+ }
+ Binding {
+ target: PasswordSync
+ property: "password"
+ value: passwordBox.text
+ }
+
+ PlasmaComponents3.Button {
+ id: loginButton
+ Accessible.name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button accessible only", "Unlock")
+ Layout.preferredHeight: passwordBox.implicitHeight
+ Layout.preferredWidth: loginButton.Layout.preferredHeight
+
+ icon.name: LayoutMirroring.enabled ? "go-previous" : "go-next"
+
+ onClicked: sessionManager.startLogin()
+ Keys.onEnterPressed: clicked()
+ Keys.onReturnPressed: clicked()
+ }
+ }
+
+ component FailableLabel : PlasmaComponents3.Label {
+ id: _failableLabel
+ required property int kind
+ required property string label
+
+ visible: authenticator.authenticatorTypes & kind
+ text: label
+ textFormat: Text.PlainText
+ horizontalAlignment: Text.AlignHCenter
+ Layout.fillWidth: true
+
+ RejectPasswordAnimation {
+ id: _rejectAnimation
+ target: _failableLabel
+ onFinished: _timer.restart()
+ }
+
+ Connections {
+ target: authenticator
+ function onNoninteractiveError(kind, authenticator) {
+ if (kind & _failableLabel.kind) {
+ _failableLabel.text = Qt.binding(() => authenticator.errorMessage)
+ _rejectAnimation.start()
+ }
+ }
+ }
+ Timer {
+ id: _timer
+ interval: Kirigami.Units.humanMoment
+ onTriggered: {
+ _failableLabel.text = Qt.binding(() => _failableLabel.label)
+ }
+ }
+ }
+
+ FailableLabel {
+ kind: ScreenLocker.Authenticator.Fingerprint
+ label: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:usagetip", "(or scan your fingerprint on the reader)")
+ }
+ FailableLabel {
+ kind: ScreenLocker.Authenticator.Smartcard
+ label: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:usagetip", "(or scan your smartcard)")
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/MediaControls.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/MediaControls.qml
new file mode 100644
index 0000000..13bc14f
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/MediaControls.qml
@@ -0,0 +1,118 @@
+/*
+ SPDX-FileCopyrightText: 2016 Kai Uwe Broulik
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Layouts
+
+import org.kde.plasma.components as PlasmaComponents3
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.private.mpris as Mpris
+
+Item {
+ visible: instantiator.count > 0
+ implicitHeight: Kirigami.Units.gridUnit * 3
+ implicitWidth: Kirigami.Units.gridUnit * 16
+
+ Repeater {
+ id: instantiator
+ model: Mpris.MultiplexerModel { }
+
+ RowLayout {
+ id: controlsRow
+
+ anchors.fill: parent
+ spacing: 0
+ enabled: model.canControl
+
+ Image {
+ id: albumArt
+ Layout.preferredWidth: height
+ Layout.fillHeight: true
+ visible: status === Image.Loading || status === Image.Ready
+ asynchronous: true
+ fillMode: Image.PreserveAspectFit
+ source: model.artUrl
+ sourceSize.height: height * Screen.devicePixelRatio
+ }
+
+ Item { // spacer
+ implicitWidth: Kirigami.Units.smallSpacing
+ implicitHeight: 1
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+ spacing: 0
+
+ PlasmaComponents3.Label {
+ Layout.fillWidth: true
+ elide: Text.ElideRight
+ font.pointSize: Kirigami.Theme.defaultFont.pointSize + 1
+ maximumLineCount: 1
+ text: model.track.length > 0
+ ? model.track
+ : (model.playbackStatus > Mpris.PlaybackStatus.Stopped
+ ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:status", "No title")
+ : i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:status", "No media playing"))
+ textFormat: Text.PlainText
+ wrapMode: Text.NoWrap
+ }
+
+ PlasmaExtras.DescriptiveLabel {
+ Layout.fillWidth: true
+ wrapMode: Text.NoWrap
+ elide: Text.ElideRight
+ // if no artist is given, show player name instead
+ text: model.artist || model.identity
+ textFormat: Text.PlainText
+ font.pointSize: Kirigami.Theme.smallFont.pointSize + 1
+ maximumLineCount: 1
+ }
+ }
+
+ PlasmaComponents3.ToolButton {
+ Layout.preferredHeight: Kirigami.Units.gridUnit * 2
+ Layout.preferredWidth: Layout.preferredHeight
+ visible: model.canGoBack || model.canGoNext
+ enabled: model.canGoPrevious
+ focusPolicy: Qt.TabFocus
+ icon.name: LayoutMirroring.enabled ? "media-skip-forward" : "media-skip-backward"
+ onClicked: {
+ fadeoutTimer.running = false
+ model.container.Previous()
+ }
+ Accessible.name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Accessible only", "Previous track")
+ }
+
+ PlasmaComponents3.ToolButton {
+ Layout.fillHeight: true
+ Layout.preferredWidth: height // make this button bigger
+ focusPolicy: Qt.TabFocus
+ icon.name: model.playbackStatus === Mpris.PlaybackStatus.Playing ? "media-playback-pause" : "media-playback-start"
+ onClicked: {
+ fadeoutTimer.running = false
+ model.container.PlayPause()
+ }
+ Accessible.name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Accessible only", "Play or Pause media")
+ }
+
+ PlasmaComponents3.ToolButton {
+ Layout.preferredHeight: Kirigami.Units.gridUnit * 2
+ Layout.preferredWidth: Layout.preferredHeight
+ visible: model.canGoBack || model.canGoNext
+ enabled: model.canGoNext
+ focusPolicy: Qt.TabFocus
+ icon.name: LayoutMirroring.enabled ? "media-skip-backward" : "media-skip-forward"
+ Accessible.name: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button Accessible only", "Next track")
+ onClicked: {
+ fadeoutTimer.running = false
+ model.container.Next()
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/NoPasswordUnlock.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/NoPasswordUnlock.qml
new file mode 100644
index 0000000..3a339f3
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/NoPasswordUnlock.qml
@@ -0,0 +1,27 @@
+/*
+ SPDX-FileCopyrightText: 2022 David Edmundson
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+import QtQuick
+
+import org.kde.plasma.components as PlasmaComponents3
+
+import org.kde.breeze.components
+
+SessionManagementScreen {
+ focus: true
+ PlasmaComponents3.Button {
+ id: loginButton
+ focus: true
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button no-password unlock", "Unlock")
+ icon.name: "unlock"
+ onClicked: Qt.quit();
+ Keys.onEnterPressed: clicked()
+ Keys.onReturnPressed: clicked()
+ }
+
+ Component.onCompleted: {
+ forceActiveFocus();
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/PasswordSync.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/PasswordSync.qml
new file mode 100644
index 0000000..e57b4e0
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/PasswordSync.qml
@@ -0,0 +1,13 @@
+/*
+ SPDX-FileCopyrightText: 2025 Yifan Zhu
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+pragma Singleton
+
+import QtQuick
+
+QtObject {
+ property string password
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/config.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/config.qml
new file mode 100644
index 0000000..0ac9414
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/config.qml
@@ -0,0 +1,79 @@
+import QtQuick
+import QtQuick.Controls as QQC2
+import org.kde.kirigami as Kirigami
+import org.kde.kcmutils as KCM
+
+Kirigami.FormLayout {
+ id: configForm
+
+ // TODO Plasma 7: Make this an enum.
+ property bool cfg_alwaysShowClock
+ property bool cfg_hideClockWhenIdle
+ property bool cfg_alwaysShowClockDefault: true
+ property bool cfg_hideClockWhenIdleDefault: false
+
+ property alias cfg_showMediaControls: showMediaControls.checked
+ property bool cfg_showMediaControlsDefault: false
+
+ twinFormLayouts: parentLayout
+
+ QQC2.RadioButton {
+ Kirigami.FormData.label: i18ndc("plasma_shell_org.kde.plasma.desktop",
+ "@title: group",
+ "Show clock:")
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@option:radio Clock always shown", "Always")
+ Accessible.name: i18nc("@option:radio", "Always show clock")
+ checked: configForm.cfg_alwaysShowClock && !configForm.cfg_hideClockWhenIdle
+ onToggled: {
+ configForm.cfg_alwaysShowClock = true;
+ configForm.cfg_hideClockWhenIdle = false;
+ }
+
+ KCM.SettingHighlighter {
+ id: clockAlwaysHighlighter
+ highlight: configForm.cfg_alwaysShowClock != configForm.cfg_alwaysShowClockDefault
+ || configForm.cfg_hideClockWhenIdle != configForm.cfg_hideClockWhenIdleDefault
+ }
+ }
+
+ QQC2.RadioButton {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@option:radio Clock shown only while unlock prompt is visible", "On unlocking prompt")
+ Accessible.name: i18nc("@option:radio", "Show clock only on unlocking prompt")
+ checked: configForm.cfg_alwaysShowClock && configForm.cfg_hideClockWhenIdle
+ onToggled: {
+ configForm.cfg_alwaysShowClock = true;
+ configForm.cfg_hideClockWhenIdle = true;
+ }
+
+ KCM.SettingHighlighter {
+ highlight: clockAlwaysHighlighter.highlight
+ }
+ }
+
+ QQC2.RadioButton {
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@option:radio Clock never shown", "Never")
+ Accessible.name: i18nc("@option:radio", "Never show clock")
+ checked: !configForm.cfg_alwaysShowClock
+ onToggled: {
+ configForm.cfg_alwaysShowClock = false;
+ }
+
+ KCM.SettingHighlighter {
+ highlight: clockAlwaysHighlighter.highlight
+ }
+ }
+
+ QQC2.CheckBox {
+ id: showMediaControls
+ Kirigami.FormData.label: i18ndc("plasma_shell_org.kde.plasma.desktop",
+ "@title: group UI controls for playback of multimedia content",
+ "Media controls:")
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop",
+ "@option:check",
+ "Show under unlocking prompt")
+
+ KCM.SettingHighlighter {
+ highlight: configForm.cfg_showMediaControlsDefault != configForm.cfg_showMediaControls
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/config.xml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/config.xml
new file mode 100644
index 0000000..be15773
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/config.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+ true
+
+
+
+ false
+
+
+
+ true
+
+
+
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/qmldir b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/qmldir
new file mode 100644
index 0000000..759d12d
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/lockscreen/qmldir
@@ -0,0 +1,4 @@
+# SPDX-FileCopyrightText: 2025 Yifan Zhu
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+singleton PasswordSync 1.0 PasswordSync.qml
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/main.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/main.js
new file mode 100644
index 0000000..e62f467
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/main.js
@@ -0,0 +1,9 @@
+
+loadTemplate("org.kde.plasma.desktop.defaultPanel")
+
+var desktopsArray = desktopsForActivity(currentActivity());
+for( var j = 0; j < desktopsArray.length; j++) {
+ desktopsArray[j].wallpaperPlugin = 'org.kde.image';
+ //var clock = desktopsArray[j].addWidget("org.kde.plasma.analogclock");
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/00-start-here-2.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/00-start-here-2.js
new file mode 100644
index 0000000..c0a49fe
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/00-start-here-2.js
@@ -0,0 +1,51 @@
+/*
+ 00-start-here-kde-fedora.js - Set launcher icon to start-here-kde-fedora
+ Copyright (C) 2010 Kevin Kofler
+ Copyright (C) 2010 Rex Dieter
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+ Portions lifted from 01-kubuntu-10.04.js:
+ Harald Sitter, apachelogger@ubuntu.com 2010-04-02
+ Jonathan Riddell, jriddell@ubuntu.com 2010-02-18
+ Copyright Canonical Ltd, may be copied under the GNU GPL 2 or later
+*/
+
+launcherFound = false;
+
+pids = panelIds;
+for (i = 0; i < pids.length; ++i) {
+ p = panelById(pids[i]);
+ if (!p) continue;
+ ids = p.widgetIds;
+ for (j = 0; j < ids.length; ++j) {
+ w = p.widgetById(ids[j]);
+ if (!w) continue;
+ if ( w.type != "org.kde.plasma.kickoff" &&
+ w.type != "org.kde.plasma.kicker" &&
+ w.type != "org.kde.plasma.kickerdash" )
+ continue;
+ launcherFound = true;
+ if ( w.readConfig("icon", "start-here-kde") == "start-here-kde-fedora" ) {
+ w.currentConfigGroup = ["General"];
+ w.writeConfig("icon", "start-here");
+ }
+ break;
+ }
+ if (launcherFound) break;
+}
+if (!launcherFound)
+ print("No launcher found");
+
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/bazzite-pins.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/bazzite-pins.js
new file mode 100644
index 0000000..43429fc
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/bazzite-pins.js
@@ -0,0 +1,31 @@
+const allPanels = panels();
+
+for (let i = 0; i < allPanels.length; ++i) {
+ const panel = allPanels[i];
+ const widgets = panel.widgets();
+
+ for (let j = 0; j < widgets.length; ++j) {
+ const widget = widgets[j];
+
+ if (widget.type === "org.kde.plasma.icontasks") {
+ widget.currentConfigGroup = ["General"];
+
+ // Read the current launchers value
+ const currentLaunchers = widget.readConfig("launchers", "");
+
+ // Only set our default if launchers is empty
+ if (!currentLaunchers || currentLaunchers.trim() === "") {
+ widget.writeConfig("launchers", [
+ "preferred://browser",
+ "applications:steam.desktop",
+ "applications:net.lutris.Lutris.desktop",
+ "applications:org.kde.konsole.desktop",
+ "applications:io.github.kolunmi.Bazaar.desktop",
+ "preferred://filemanager"
+ ]);
+ widget.reloadConfig();
+ }
+ }
+ }
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/containmentactions_middlebutton.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/containmentactions_middlebutton.js
new file mode 100644
index 0000000..36626e7
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/containmentactions_middlebutton.js
@@ -0,0 +1,15 @@
+// MidButton got deprecated and doesn't really work anymore as a stringified enum value
+// for the middle button Qt::MouseButton, we need to update our config to "MiddleButton"
+var plasmaConfig = ConfigFile("plasma-org.kde.plasma.desktop-appletsrc", "ActionPlugins");
+
+for (let i in plasmaConfig.groupList) {
+ let subGroup = ConfigFile(plasmaConfig, plasmaConfig.groupList[i])
+
+ for (let j in subGroup.keyList) {
+ let key = subGroup.keyList[j];
+ if (key.indexOf("MidButton") !== -1) {
+ subGroup.writeEntry(key.replace("MidButton", "MiddleButton"), subGroup.readEntry(key));
+ subGroup.deleteEntry(key);
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_font_settings.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_font_settings.js
new file mode 100644
index 0000000..09a32e1
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_font_settings.js
@@ -0,0 +1,53 @@
+/*
+ SPDX-FileCopyrightText: 2022 Jin Liu
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+/*
+ Plasma 5.26 introduced a new config entry autoFontAndSize which defaults to true.
+ This means if the user customized font before (fontFamily, boldText, italicText),
+ in 5.26 these settings are ignored.
+
+ So we need to set autoFontAndSize=false if:
+ 1. Any of these 3 old entries above is set.
+ 2. No new entries introduced in 5.26 (autoFontAndSize, fontSize, fontWeight, fontStyleName)
+ are set, so this is a config from 5.25.
+
+ And fontWeight should be set to 75 (Font.Bold) if boldText==true.
+
+ See https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/1809
+*/
+
+const containments = desktops().concat(panels());
+for (var i in containments) {
+ var cont = containments[i];
+ const widgets = cont.widgets();
+ for (var j in widgets) {
+ var widget = widgets[j];
+
+ if (widget.type == "org.kde.plasma.digitalclock") {
+ widget.currentConfigGroup = new Array('Appearance')
+ if ((widget.readConfig("fontFamily", "").length > 0
+ || widget.readConfig("boldText", false)
+ || widget.readConfig("italicText", false))
+ &&
+ (widget.readConfig("autoFontAndSize", true)
+ && widget.readConfig("fontSize", 10) === 10
+ && widget.readConfig("fontWeight", 50) === 50
+ && widget.readConfig("fontStyleName", "").length === 0)) {
+ widget.writeConfig("autoFontAndSize", false)
+ if (widget.readConfig("boldText", false)) {
+ widget.writeConfig("fontWeight", 75)
+ }
+ // Set the font size to the largest value (72) in the font dialog,
+ // so the font autofits the panel when the panel height is less
+ // than 72pt. This should keep 5.25's autosize behavior for custom
+ // font.
+ // For panels taller than 72pt, with custom font set in 5.25, the
+ // digital clock's look may still change, though.
+ widget.writeConfig("fontSize", 72)
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_showseconds_setting.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_showseconds_setting.js
new file mode 100644
index 0000000..67b9279
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_showseconds_setting.js
@@ -0,0 +1,21 @@
+/*
+ SPDX-FileCopyrightText: 2023 Fushan Wen
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+/**
+ @c showSeconds option now supports showing seconds only in the tooltip.
+
+ @see https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/2232
+ @since 6.0
+*/
+
+const containments = desktops().concat(panels());
+
+containments.forEach(containment => containment.widgets("org.kde.plasma.digitalclock").forEach(widget => {
+ widget.currentConfigGroup = ["Appearance"];
+ if (widget.readConfig("showSeconds", false /* Default: never show seconds */) === true /* Changed by the user */) {
+ widget.writeConfig("showSeconds", 2 /* Always show seconds */);
+ }
+}));
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_rename_timezonedisplay_key.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_rename_timezonedisplay_key.js
new file mode 100644
index 0000000..eb682e7
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_rename_timezonedisplay_key.js
@@ -0,0 +1,23 @@
+// Find all digital clock applets in all containments and change
+// displayTimezoneAsCode=false
+// to
+// displayTimezoneFormat=FullText
+// See https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/751
+
+var containments = desktops().concat(panels());
+for (var i in containments) {
+ var cont = containments[i];
+
+ for (var j in cont.widgetIds) {
+ var widget = cont.widgetById(cont.widgetIds[j]);
+
+ if (widget.type == "org.kde.plasma.digitalclock") {
+ widget.currentConfigGroup = new Array('Appearance')
+ if (widget.readConfig("displayTimezoneAsCode", true) == false) {
+ widget.writeConfig("displayTimezoneFormat", "FullText")
+ // Work around not being able to delete config file keys using widget interface
+ widget.writeConfig("displayTimezoneAsCode", "")
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/folderview_fix_recursive_screenmapping.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/folderview_fix_recursive_screenmapping.js
new file mode 100644
index 0000000..e8e600d
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/folderview_fix_recursive_screenmapping.js
@@ -0,0 +1,109 @@
+/* vim:set foldmethod=marker:
+
+ SPDX-FileCopyrightText: 2023 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+function filterDisabled(entries) {
+ let filteredEntries = [];
+
+ // 0 = screen, 1 = activity, 2 = how many entries, 3 = desktop entry
+ let state = 0;
+ let entriesForCurrentScreen = 0;
+
+ let currentScreen = -1;
+ let currentActivity = "";
+ let currentEntrtriesNumber = 0;
+ let currentEntry = 0;
+ let currentEntries = [];
+
+ for (let e of entries) {
+ switch (state) {
+ case 0: // Screen
+ currentScreen = e;
+ state = 1;
+ break;
+ case 1: // Activity
+ currentActivity = e;
+ state = 2;
+ break;
+ case 2: // Entries number
+ currentEntrtriesNumber = Number(e);
+ state = 3;
+ break;
+ case 3: // Desktop file
+ if (e.indexOf("desktop:/") !== 0) { // User has a folderview not in desktop:/
+ currentEntries.push(e);
+ currentEntry++;
+ } else {
+ let count = (e.match(/\//g) || []).length;
+ if (count == 1) {
+ currentEntries.push(e);
+ currentEntry++;
+ } else {
+ currentEntrtriesNumber--;
+ }
+ }
+
+ if (currentEntry === currentEntrtriesNumber) {
+ state = 0;
+ if (currentEntries.length > 0) {
+ filteredEntries = filteredEntries.concat([currentScreen, currentActivity, currentEntrtriesNumber]);
+ filteredEntries = filteredEntries.concat(currentEntries);
+ currentEntries = [];
+ }
+ }
+ break;
+ }
+
+ }
+ return filteredEntries;
+}
+
+function filterEnabled(entries) {
+ let filteredEntries = [];
+
+ // 0 = desktop entry, 1 = screen 2 = activity
+ let state = 0;
+ let shouldDrop = false; //true when this entry should be dropped
+
+ for (let e of entries) {
+ switch (state) {
+ case 0: // Desktop file
+ if (e.indexOf("desktop:/") !== 0) { // User has a folderview not in desktop:/
+ filteredEntries.push(e);
+ shouldDrop = false;
+ } else {
+ let count = (e.match(/\//g) || []).length;
+ if (count == 1) {
+ filteredEntries.push(e);
+ shouldDrop = false;
+ } else {
+ shouldDrop = true;
+ }
+ }
+ break;
+ case 1: // Screen
+ case 2: // Activity
+ if (!shouldDrop) {
+ filteredEntries.push(e);
+ }
+ }
+ state = (state + 1) % 3;
+ }
+ return filteredEntries;
+}
+
+const config = ConfigFile('plasma-org.kde.plasma.desktop-appletsrc');
+config.group = 'ScreenMapping';
+
+let entries = config.readEntry("itemsOnDisabledScreens").split(",");
+let filteredEntries = filterDisabled(entries);
+
+config.writeEntry("itemsOnDisabledScreens", filteredEntries.join(","));
+
+entries = config.readEntry("screenMapping").split(",");
+filteredEntries = filterEnabled(entries);
+
+config.writeEntry("screenMapping", filteredEntries.join(","));
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_migrateiconsetting.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_migrateiconsetting.js
new file mode 100644
index 0000000..8861d9d
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_migrateiconsetting.js
@@ -0,0 +1,33 @@
+// Find all Keyboard Layout applets in all containments and change
+// showFlag=true
+// to
+// displayStyle=Flag
+// See https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/1131
+
+const containments = desktops().concat(panels());
+for (var i in containments) {
+ forEachWidgetInContainment(containments[i]);
+}
+
+function forEachWidgetInContainment(containment) {
+ const widgets = containment.widgets();
+ for (var i in widgets) {
+ const widget = widgets[i];
+ switch(widget.type) {
+ case "org.kde.plasma.systemtray":
+ systemtrayId = widget.readConfig("SystrayContainmentId");
+ if (systemtrayId) {
+ forEachWidgetInContainment(desktopById(systemtrayId))
+ }
+ break;
+ case "org.kde.plasma.keyboardlayout":
+ widget.currentConfigGroup = new Array('General')
+ if (widget.readConfig("showFlag", false) == true) {
+ widget.writeConfig("displayStyle", "Flag")
+ // Work around not being able to delete config file keys using widget interface
+ widget.writeConfig("showFlag", "")
+ }
+ break;
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_remove_shortcut.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_remove_shortcut.js
new file mode 100644
index 0000000..f3d0868
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_remove_shortcut.js
@@ -0,0 +1,25 @@
+const containments = desktops().concat(panels());
+for (var i in containments) {
+ forEachWidgetInContainment(containments[i]);
+}
+
+function forEachWidgetInContainment(containment) {
+ const widgets = containment.widgets();
+ for (var i in widgets) {
+ const widget = widgets[i];
+ switch(widget.type) {
+ case "org.kde.plasma.systemtray":
+ systemtrayId = widget.readConfig("SystrayContainmentId");
+ if (systemtrayId) {
+ forEachWidgetInContainment(desktopById(systemtrayId))
+ }
+ break;
+ case "org.kde.plasma.keyboardlayout":
+ if (widget.globalShortcut) {
+ print("Shortcut to remove: " + widget.globalShortcut);
+ widget.globalShortcut = "";
+ }
+ break;
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/klipper_clear_config.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/klipper_clear_config.js
new file mode 100644
index 0000000..9ee8bdf
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/klipper_clear_config.js
@@ -0,0 +1,14 @@
+/*
+ Previously, Klipper "clear history" dialog used to not ask again even if user answered No.
+ This was changed so that only a Yes answer will lead to no more asking, by using warningContinueCancel instead of questionYesNo.
+ Now the behaviour of previous config value really_clear_history has inverted: true/undefined => ask again; false => don't ask.
+ This update script migrates old configs to use the new config value, renamed to klipperClearHistoryAskAgain.
+*/
+
+config = ConfigFile("plasmashellrc", "Notification Messages");
+oldVal = config.readEntry("really_clear_history");
+if (oldVal === "true") {
+ // Clear and don't ask again -- preserve this choice
+ config.writeEntry("klipperClearHistoryAskAgain", false)
+}
+config.deleteEntry("really_clear_history");
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/maintain_existing_desktop_icon_sizes.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/maintain_existing_desktop_icon_sizes.js
new file mode 100644
index 0000000..f11633b
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/maintain_existing_desktop_icon_sizes.js
@@ -0,0 +1,46 @@
+// This script updates users' Folder View icon sizes following a change in what
+// they mean in https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/111
+
+var allDesktops = desktops();
+
+for (var i = 0; i < allDesktops.length; ++i) {
+ var desktop = allDesktops[i];
+ desktop.currentConfigGroup = ["General"];
+
+ var currentIconSize = desktop.readConfig("iconSize");
+
+ // Don't do anything if there is no value in the config file, since in this
+ // case, no change is needed because the new default works properly
+ if (currentIconSize) {
+ currentIconSize = parseInt(currentIconSize);
+
+ // No change needed for iconSize=0 or 5
+ if (currentIconSize != 0 && currentIconSize != 5) {
+ print("Current icon size is " + currentIconSize);
+ var newIconSize = 3;
+
+ switch(currentIconSize) {
+ case 1:
+ newIconSize = 0;
+ break;
+ case 2:
+ newIconSize = 1;
+ break;
+ case 3:
+ newIconSize = 2;
+ break;
+ case 4:
+ newIconSize = 3;
+ break;
+ // We should never reach here, but in case we do anyway, reset to
+ // the default value
+ default:
+ break;
+ }
+
+ desktop.writeConfig("iconSize", newIconSize);
+ desktop.reloadConfig()
+ }
+ }
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/mediaframe_migrate_useBackground_setting.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/mediaframe_migrate_useBackground_setting.js
new file mode 100644
index 0000000..5206509
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/mediaframe_migrate_useBackground_setting.js
@@ -0,0 +1,23 @@
+/*
+ SPDX-FileCopyrightText: 2022 Fushan Wen
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+/**
+ The Media Frame widget removes the useBackground option and uses ConfigurableBackground
+ hint to support toggling the background directly from the widget toolbar.
+
+ The option only applies to media frame widgets on desktop.
+
+ @see https://invent.kde.org/plasma/kdeplasma-addons/-/merge_requests/238
+ @since 5.27
+*/
+desktops().forEach(containment => containment.widgets("org.kde.plasma.mediaframe").forEach(widget => {
+ widget.currentConfigGroup = ["General"];
+ if (widget.readConfig("useBackground", true /* Default */) === false /* Changed by the user */) {
+ widget.writeConfig("useBackground", "");
+ widget.currentConfigGroup = []; // Root Configuration
+ widget.writeConfig("UserBackgroundHints", "NoBackground");
+ }
+}));
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/migrate_font_weights.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/migrate_font_weights.js
new file mode 100644
index 0000000..b2ccad0
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/migrate_font_weights.js
@@ -0,0 +1,44 @@
+/*
+ SPDX-FileCopyrightText: 2023 Akseli Lahtinen
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+// Find all depicted widgets and migrate their font weights from qt5 to qt6 style
+
+var containments = desktops().concat(panels());
+for (var c in containments) {
+ const cont = containments[c];
+ const widgets = cont.widgets();
+ for (var w in widgets) {
+ var widget = widgets[w];
+ switch(widget.type) {
+ case "org.kde.plasma.digitalclock":
+ widget.currentConfigGroup = ['Appearance'];
+ // Use "normal" weight as default if weight is not set
+ const oldFontWeight = widget.readConfig("fontWeight", 400);
+ const newFontWeight = migrateFontWeight(Number(oldFontWeight));
+ widget.writeConfig("fontWeight", newFontWeight);
+ break;
+ }
+ }
+}
+
+function migrateFontWeight(oldWeight) {
+ // Takes old weight (Qt5 weight) and returns the Qt6 equivalent
+ // Qt5 font weights: https://doc.qt.io/qt-5/qfont.html#Weight-enum
+ // Qt6 font weights: https://doc.qt.io/qt-6/qfont.html#Weight-enum
+ var newWeight = 400;
+ if (oldWeight === 0) { newWeight = 100; }
+ else if (oldWeight === 12) { newWeight = 200; }
+ else if (oldWeight === 25) { newWeight = 300; }
+ else if (oldWeight === 50) { newWeight = 400; }
+ else if (oldWeight === 57) { newWeight = 500; }
+ else if (oldWeight === 63) { newWeight = 600; }
+ else if (oldWeight === 75) { newWeight = 700; }
+ else if (oldWeight === 81) { newWeight = 800; }
+ else if (oldWeight === 87) { newWeight = 900; }
+
+ return newWeight;
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/move_desktop_layout_config.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/move_desktop_layout_config.js
new file mode 100644
index 0000000..45d404d
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/move_desktop_layout_config.js
@@ -0,0 +1,10 @@
+var allDesktops = desktops();
+
+for (var i = 0; i < allDesktops.length; ++i) {
+ var desktop = allDesktops[i];
+ desktop.currentConfigGroup = ["General"];
+ var serializedItems = desktop.readConfig("ItemsGeometries");
+ desktop.currentConfigGroup = [];
+ desktop.writeConfig("ItemGeometriesHorizontal", serializedItems);
+ desktop.reloadConfig()
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/no_middle_click_paste_on_panels.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/no_middle_click_paste_on_panels.js
new file mode 100644
index 0000000..1e3ad03
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/no_middle_click_paste_on_panels.js
@@ -0,0 +1,26 @@
+// In the past, panels were configured to add a note on middle-click. This was changed,
+// but the "MiddleButton;NoModifier=org.kde.paste" action was never removed from the
+// config file, so some people still got this undesirable behavior with no GIU method
+// to change it.
+//
+// This script removes it.
+
+var plasmaConfig = ConfigFile("plasma-org.kde.plasma.desktop-appletsrc", "ActionPlugins");
+
+for (let i in plasmaConfig.groupList) {
+ let subSubGroupKeys = [];
+ let subGroup = ConfigFile(plasmaConfig, plasmaConfig.groupList[i]);
+ for (let j in subGroup.groupList) {
+ let subSubGroup = ConfigFile(subGroup, subGroup.groupList[j]);
+ subSubGroupKeys = subSubGroup.keyList;
+ }
+ if (subSubGroupKeys.indexOf("_sep1") === -1) {
+ print("Containment " + i + " Does not have a _sep1 item; it must be a panel.\n");
+ // No _sep1 item; this must be a panel
+ let mmbAction = subGroup.readEntry("MiddleButton;NoModifier");
+ if (mmbAction === "org.kde.paste") {
+ print("Panel " + i + " Seems to have a middle-click paste action defined; deleting it!");
+ subGroup.deleteEntry("MiddleButton;NoModifier");
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/systemloadviewer_systemmonitor.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/systemloadviewer_systemmonitor.js
new file mode 100644
index 0000000..f401a21
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/systemloadviewer_systemmonitor.js
@@ -0,0 +1,39 @@
+
+function swapWidget(cont, oldWidget, newType, geometry) {
+ oldWidget.remove();
+ cont.addWidget(newType, geometry.x, geometry.y, geometry.width, geometry.height);
+}
+
+var containments = desktops().concat(panels());
+
+for (var i in containments) {
+ var cont = containments[i];
+
+ for (var j in cont.widgetIds) {
+ var widget = cont.widgetById(cont.widgetIds[j]);
+
+ let newType = ""
+ if (widget.type == "org.kde.plasma.systemloadviewer") {
+ let geometry = widget.geometry;
+ geometry.width = geometry.width/3
+
+ widget.remove();
+ cont.addWidget("org.kde.plasma.systemmonitor.cpuusage", geometry.x, geometry.y, geometry.width, geometry.height);
+ geometry.x += geometry.width;
+ cont.addWidget("org.kde.plasma.systemmonitor.memoryusage", geometry.x, geometry.y, geometry.width, geometry.height);
+ geometry.x += geometry.width;
+
+ let swapWidget = cont.addWidget("org.kde.plasma.systemmonitor", geometry.x, geometry.y, geometry.width, geometry.height);
+ swapWidget.currentConfigGroup = ["Appearance"];
+ swapWidget.writeConfig("title", "Swap");
+ swapWidget.currentConfigGroup = ["Sensors"];
+ swapWidget.writeConfig("highPrioritySensorIds", "[\"mem/swap/used\",\"mem/swap/free\"]");
+ swapWidget.writeConfig("totalSensors", "[\"mem/swap/used\"]");
+ swapWidget.currentConfigGroup = ["SensorColors"];
+ swapWidget.writeConfig("mem/swap/free", "230,230,230");
+
+ swapWidget.reloadconfiguration();
+ }
+ }
+}
+
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/taskmanager_configUpdate_wheelEnabled.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/taskmanager_configUpdate_wheelEnabled.js
new file mode 100644
index 0000000..c110cdf
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/taskmanager_configUpdate_wheelEnabled.js
@@ -0,0 +1,17 @@
+// Update all applets with wheelEnabled=true to wheelEnabled=AllTask
+
+var containments = desktops().concat(panels());
+
+containments.forEach(function(cont) {
+
+ cont.widgetIds.forEach(function(id) {
+ var widget = cont.widgetById(id);
+
+ widget.currentConfigGroup = new Array("General");
+
+ if (widget.readConfig("wheelEnabled", false) === true) {
+ widget.writeConfig("wheelEnabled", "AllTask");
+ widget.reloadConfig();
+ }
+ });
+});
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/unlock_widgets.js b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/unlock_widgets.js
new file mode 100644
index 0000000..c332270
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/unlock_widgets.js
@@ -0,0 +1,2 @@
+
+__AppInterface.locked = false;
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/Desktop.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/Desktop.qml
new file mode 100644
index 0000000..7276bb4
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/Desktop.qml
@@ -0,0 +1,419 @@
+/*
+ SPDX-FileCopyrightText: 2012 Marco Martin
+ SPDX-FileCopyrightText: 2014 David Edmundson
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.kwindowsystem
+import org.kde.plasma.activityswitcher as ActivitySwitcher
+import "../activitymanager"
+import "../explorer"
+import org.kde.kirigami as Kirigami
+
+Item {
+ id: root
+
+ property Item containment
+
+ property QtObject widgetExplorer
+
+ Connections {
+ target: ActivitySwitcher.Backend
+ function onShouldShowSwitcherChanged(): void {
+ if (ActivitySwitcher.Backend.shouldShowSwitcher) {
+ if (sidePanelStack.state !== "activityManager") {
+ root.toggleActivityManager();
+ }
+
+ } else {
+ if (sidePanelStack.state === "activityManager") {
+ root.toggleActivityManager();
+ }
+
+ }
+ }
+ }
+
+ function toggleWidgetExplorer(containment) {
+
+ if (sidePanelStack.state === "widgetExplorer") {
+ sidePanelStack.state = "closed";
+ } else {
+ sidePanelStack.state = "widgetExplorer";
+ sidePanelStack.setSource(Qt.resolvedUrl("../explorer/WidgetExplorer.qml"), {
+ containment,
+ sidePanel,
+ });
+ }
+ }
+
+ function toggleActivityManager() {
+ if (sidePanelStack.state === "activityManager") {
+ sidePanelStack.state = "closed";
+ } else {
+ sidePanelStack.state = "activityManager";
+ sidePanelStack.setSource(Qt.resolvedUrl("../activitymanager/ActivityManager.qml"));
+ }
+ }
+
+
+ readonly property rect editModeRect: {
+ if (!containment) {
+ return Qt.rect(0,0,0,0);
+ }
+ let screenRect = desktop.strictAvailableScreenRect;
+ let panelConfigRect = Qt.rect(0,0,0,0);
+
+ if (containment.plasmoid.corona.panelBeingConfigured
+ && containment.plasmoid.corona.panelBeingConfigured.screenToFollow === desktop.screenToFollow) {
+ panelConfigRect = containment.plasmoid.corona.panelBeingConfigured.relativeConfigRect;
+ }
+
+ if (panelConfigRect.width <= 0) {
+ ; // Do nothing
+ } else if (panelConfigRect.x > width - (panelConfigRect.x + panelConfigRect.width)) {
+ screenRect = Qt.rect(screenRect.x, screenRect.y, panelConfigRect.x - screenRect.x, screenRect.height);
+ } else {
+ const diff = Math.max(0, panelConfigRect.x + panelConfigRect.width - screenRect.x);
+ screenRect = Qt.rect(Math.max(screenRect.x, panelConfigRect.x + panelConfigRect.width), screenRect.y, screenRect.width - diff, screenRect.height);
+ }
+
+ if (sidePanel.visible) {
+ if (sidePanel.sideBarOnRightEdge) {
+ screenRect = Qt.rect(screenRect.x, screenRect.y, screenRect.width - sidePanel.width, screenRect.height);
+ } else {
+ screenRect = Qt.rect(screenRect.x + sidePanel.width, screenRect.y, screenRect.width - sidePanel.width, screenRect.height);
+ }
+ }
+ return screenRect;
+ }
+
+ MouseArea {
+ id: desktopMouseArea
+ anchors.fill: parent
+ onClicked: containment.plasmoid.corona.editMode = false
+ }
+
+ MouseArea {
+ id: containmentParent
+ x: editModeLoader.item ? editModeLoader.item.centerX - width / 2 : 0
+ y: editModeLoader.item ? editModeLoader.item.centerY - height / 2 : 0
+ width: root.width
+ height: root.height
+ readonly property real extraScale: desktop.configuredPanel || sidePanel.visible ? 0.95 : 0.9
+ property real scaleFactor: Math.min(editModeRect.width / root.width, editModeRect.height / root.height) * extraScale
+ scale: containment?.plasmoid.corona.editMode ? scaleFactor : 1
+ }
+
+ Loader {
+ id: editModeLoader
+ anchors.fill: parent
+ sourceComponent: DesktopEditMode {}
+ active: containment?.plasmoid.corona.editMode || editModeUiTimer.running
+ Timer {
+ id: editModeUiTimer
+ property bool editMode: containment?.plasmoid.corona.editMode ?? false
+ onEditModeChanged: restart()
+ interval: 200
+ }
+ }
+
+ Loader {
+ id: wallpaperColors
+
+ active: root.containment && root.containment.wallpaper && desktop.usedInAccentColor
+ asynchronous: true
+
+ sourceComponent: Kirigami.ImageColors {
+ id: imageColors
+ source: root.containment.wallpaper
+
+ readonly property color backgroundColor: Kirigami.Theme.backgroundColor
+ readonly property color textColor: Kirigami.Theme.textColor
+
+ // Ignore the initial dominant color
+ onPaletteChanged: {
+ if (!Qt.colorEqual(root.containment.wallpaper.accentColor, "transparent")) {
+ desktop.accentColor = root.containment.wallpaper.accentColor;
+ }
+ if (this.palette.length === 0) {
+ desktop.accentColor = "transparent";
+ } else {
+ desktop.accentColor = this.dominant;
+ }
+ }
+
+ Kirigami.Theme.inherit: false
+ Kirigami.Theme.backgroundColor: backgroundColor
+ Kirigami.Theme.textColor: textColor
+
+ onBackgroundColorChanged: Qt.callLater(update)
+ onTextColorChanged: Qt.callLater(update)
+
+ readonly property Connections __repaintConnection: Connections {
+ target: root.containment.wallpaper
+ function onAccentColorChanged() {
+ if (Qt.colorEqual(root.containment.wallpaper.accentColor, "transparent")) {
+ imageColors.update();
+ } else {
+ imageColors.paletteChanged();
+ }
+ }
+ }
+ }
+ }
+
+ Timer {
+ id: pendingUninstallTimer
+ // keeps track of the applets the user wants to uninstall
+ property list applets: []
+ function uninstall() {
+ for (const applet of applets) {
+ widgetExplorer.uninstall(applet);
+ }
+ applets = [];
+
+ if (sidePanelStack.state !== "widgetExplorer" && widgetExplorer) {
+ widgetExplorer.destroy();
+ widgetExplorer = null;
+ }
+ }
+
+ interval: 60000 // one minute
+ onTriggered: uninstall()
+ }
+
+ PlasmaCore.Dialog {
+ id: sidePanel
+
+ // If we are currently in edit mode, all panels are being shown
+ // and we use the strictAvailableScreenRect, which accounts for all
+ // of them. If we're not configuring anything, we instead use the
+ // entire screen rect, without fear of overlapping panels.
+ property var referenceRect: containment?.plasmoid.corona.editMode ? desktop.strictAvailableScreenRect : Qt.rect(0, 0, desktop.screenGeometry.width, desktop.screenGeometry.height)
+
+
+ readonly property bool sideBarOnRightEdge: {
+ if (!sidePanelStack.active) {
+ return false;
+ }
+
+ const item = sidePanelStack.item;
+ if (!item) {
+ return false;
+ }
+
+ const rightEdgeParent = (item.containment
+ && item.containment !== containment.plasmoid
+ && item.containment.location == PlasmaCore.Types.RightEdge);
+
+ return rightEdgeParent || Application.layoutDirection === Qt.RightToLeft;
+ }
+
+ location: sideBarOnRightEdge ? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge
+ type: PlasmaCore.Dialog.Dock
+ flags: Qt.WindowStaysOnTopHint
+
+ hideOnWindowDeactivate: true
+
+ x: {
+ let result = desktop.x;
+ if (!containment) {
+ return result;
+ }
+
+ const rect = referenceRect;
+ result += rect.x;
+
+ if (sideBarOnRightEdge) {
+ result += rect.width - sidePanel.width;
+ }
+
+ return result;
+ }
+ y: desktop.y + (containment ? referenceRect.y : 0)
+
+ onVisibleChanged: {
+ if (!visible) {
+ sidePanelStack.state = "closed";
+ ActivitySwitcher.Backend.shouldShowSwitcher = false;
+ }
+ }
+
+ mainItem: Loader {
+ id: sidePanelStack
+ asynchronous: true
+ width: item ? item.width : 0
+ height: containment ? sidePanel.referenceRect.height - sidePanel.margins.top - sidePanel.margins.bottom : 1000
+ state: "closed"
+
+ function bindingWithItem(callback: var, defaults: var): var {
+ return Qt.binding(() => {
+ const item = this.item;
+ return item !== null ? callback(item) : defaults;
+ });
+ }
+
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+
+ onLoaded: {
+ if (item) {
+ item.closed.connect(() => {
+ state = "closed";
+ });
+
+ switch (state) {
+ case "activityManager":
+ item.showSwitcherOnly = ActivitySwitcher.Backend.shouldShowSwitcher;
+ sidePanel.hideOnWindowDeactivate = bindingWithItem(
+ item => !ActivitySwitcher.Backend.shouldShowSwitcher && !item.showingDialog,
+ false,
+ );
+ item.forceActiveFocus();
+ break;
+ case "widgetExplorer":
+ sidePanel.hideOnWindowDeactivate = bindingWithItem(item => !item.preventWindowHide, false);
+ sidePanel.opacity = bindingWithItem(item => item.opacity, 1);
+ sidePanel.outputOnly = bindingWithItem(item => item.outputOnly, false);
+ break;
+ default:
+ sidePanel.hideOnWindowDeactivate = true;
+ break;
+ }
+ }
+ sidePanel.visible = true;
+ if (KWindowSystem.isPlatformX11) {
+ KX11Extras.forceActiveWindow(sidePanel);
+ }
+ }
+ onStateChanged: {
+ if (state === "closed") {
+ sidePanel.visible = false;
+ source = ""; //unload all elements
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: desktop
+ function onStrictAvailableScreenRectChanged() {
+ if (sidePanel.visible) {
+ sidePanel.requestActivate();
+ }
+ }
+ }
+
+ onContainmentChanged: {
+ if (containment === null) {
+ return;
+ }
+
+ containment.parent = containmentParent
+
+ if (switchAnim.running) {
+ //If the animation was still running, stop it and reset
+ //everything so that a consistent state can be kept
+ switchAnim.running = false;
+ internal.newContainment.visible = false;
+ internal.oldContainment.visible = false;
+ internal.oldContainment = null;
+ }
+
+ internal.newContainment = containment;
+ containment.visible = true;
+
+ if (internal.oldContainment !== null && internal.oldContainment !== containment) {
+ switchAnim.running = true;
+ } else {
+ containment.anchors.left = containmentParent.left;
+ containment.anchors.top = containmentParent.top;
+ containment.anchors.right = containmentParent.right;
+ containment.anchors.bottom = containmentParent.bottom;
+ if (internal.oldContainment) {
+ internal.oldContainment.visible = false;
+ }
+ internal.oldContainment = containment;
+ }
+ }
+
+ //some properties that shouldn't be accessible from elsewhere
+ QtObject {
+ id: internal
+
+ property Item oldContainment: null
+ property Item newContainment: null
+ }
+
+ SequentialAnimation {
+ id: switchAnim
+ ScriptAction {
+ script: {
+ if (containment) {
+ containment.z = 1;
+ containment.x = root.width;
+ }
+ if (internal.oldContainment) {
+ internal.oldContainment.z = 0;
+ internal.oldContainment.x = 0;
+ }
+ }
+ }
+ ParallelAnimation {
+ NumberAnimation {
+ target: internal.oldContainment
+ properties: "x"
+ to: internal.newContainment != null ? -root.width : 0
+ duration: Kirigami.Units.veryLongDuration
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ target: internal.newContainment
+ properties: "x"
+ to: 0
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ ScriptAction {
+ script: {
+ if (internal.oldContainment) {
+ internal.oldContainment.visible = false;
+ }
+ if (containment) {
+ internal.oldContainment = containment;
+ }
+ }
+ }
+ }
+
+ Loader {
+ id: previewBannerLoader
+
+ function shouldBeActive(): bool {
+ // Loader::active is true by default at the time of creation, so
+ // it shouldn't be used in other bindings as a guard.
+ return root.containment !== null && (desktop.showPreviewBanner ?? false);
+ }
+
+ readonly property point pos: root.containment?.plasmoid.availableScreenRegion, shouldBeActive() && item !== null
+ ? root.containment.adjustToAvailableScreenRegion(
+ root.containment.width + root.containment.x - item.width - Kirigami.Units.largeSpacing,
+ root.containment.height + root.containment.y - item.height - Kirigami.Units.largeSpacing,
+ item.width + Kirigami.Units.largeSpacing,
+ item.height + Kirigami.Units.largeSpacing)
+ : Qt.point(0, 0)
+
+ x: pos.x
+ y: pos.y
+ z: (root.containment?.z ?? 0) + 1
+ active: shouldBeActive()
+ visible: active
+ source: "PreviewBanner.qml"
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/DesktopEditMode.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/DesktopEditMode.qml
new file mode 100644
index 0000000..befb229
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/DesktopEditMode.qml
@@ -0,0 +1,183 @@
+/*
+ SPDX-FileCopyrightText: 2024 Marco Martin
+ SPDX-FileCopyrightText: 2014 David Edmundson
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Effects
+import QtQuick.Layouts
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.plasma.components as PC
+import org.kde.kirigami as Kirigami
+
+import org.kde.kcmutils as KCM
+
+Item {
+ id: editModeItem
+ property real centerX: Math.round(editModeUi.x + editModeUi.width/2)
+ property real centerY: Math.round(editModeUi.y + editModeUi.height/2)
+ property real roundedRootWidth: Math.round(root.width)
+ property real roundedRootHeight: Math.round(root.height)
+
+ property bool open: false
+ Component.onCompleted: {
+ open = Qt.binding(() => {return containment.plasmoid.corona.editMode})
+ }
+
+ // Those 2 elements have the same parameters as the overview effect
+ MultiEffect {
+ source: containment
+ anchors.fill: parent
+ blurEnabled: true
+ blurMax: 64
+ blur: 1.0
+ }
+ Rectangle {
+ anchors.fill: parent
+ color: Kirigami.Theme.backgroundColor
+ opacity: 0.7
+ }
+
+ Item {
+ id: editModeUi
+ visible: editModeItem.open || xAnim.running
+ x: Math.round(editModeItem.open ? editModeRect.x + editModeRect.width/2 - zoomedWidth/2 : 0)
+ y: Math.round(editModeItem.open ? editModeRect.y + editModeRect.height/2 - zoomedHeight/2 + toolBar.height/2 : 0)
+ width: editModeItem.open ? zoomedWidth : editModeItem.roundedRootWidth
+ height: editModeItem.open ? zoomedHeight : editModeItem.roundedRootHeight
+ property real zoomedWidth: Math.round(root.width * containmentParent.scaleFactor)
+ property real zoomedHeight: Math.round(root.height * containmentParent.scaleFactor)
+
+ Kirigami.ShadowedRectangle {
+ color: Kirigami.Theme.backgroundColor
+ width: Math.round(parent.width)
+ height: Math.round(parent.height + toolBar.height + Kirigami.Units.largeSpacing)
+ y: - toolBar.height - Kirigami.Units.largeSpacing
+
+ radius: editModeItem.open ? Kirigami.Units.cornerRadius : 0
+ Behavior on radius {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ shadow {
+ size: Kirigami.Units.gridUnit * 2
+ color: Qt.rgba(0, 0, 0, 0.3)
+ yOffset: 3
+ }
+ RowLayout {
+ id: toolBar
+ LayoutMirroring.enabled: Application.layoutDirection === Qt.RightToLeft
+ LayoutMirroring.childrenInherit: true
+ spacing: Kirigami.Units.smallSpacing
+ anchors {
+ left: parent.left
+ top: parent.top
+ right: parent.right
+ margins: Kirigami.Units.smallSpacing
+ }
+ Flow {
+ Layout.fillWidth: true
+ Layout.minimumHeight: implicitHeight
+ spacing: Kirigami.Units.smallSpacing
+ PC.ToolButton {
+ id: addWidgetButton
+ property QtObject qAction: containment?.plasmoid.internalAction("add widgets") || null
+ text: qAction?.text
+ icon.name: "view-group-symbolic"
+ onClicked: qAction.trigger()
+ }
+
+ PC.ToolButton {
+ id: addPanelButton
+ height: addWidgetButton.height
+ property QtObject qAction: containment?.plasmoid.corona.action("add panel") || null
+ text: qAction?.text
+ icon.name: "list-add"
+ Accessible.role: Accessible.ButtonMenu
+ onClicked: containment.plasmoid.corona.showAddPanelContextMenu(mapToGlobal(0, height))
+ }
+
+ PC.ToolButton {
+ id: manageContainmentsButton
+ property QtObject qAction: containment?.plasmoid.corona.action("manage-containments") || null
+ text: qAction?.text
+ visible: qAction?.visible || false
+ icon.name: "configure-symbolic"
+ onClicked: qAction.trigger()
+ }
+ }
+
+ PC.ToolButton {
+ Layout.alignment: Qt.AlignTop
+
+ visible: Kirigami.Settings.hasTransientTouchInput || Kirigami.Settings.tabletMode
+
+ icon.name: "overflow-menu"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "More")
+
+ onClicked: {
+ containment.openContextMenu(mapToGlobal(0, height));
+ }
+ }
+ PC.ToolButton {
+ Layout.alignment: Qt.AlignTop
+ icon.name: "dialog-ok-symbolic"
+ text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Exit Edit Mode")
+ onClicked: containment.plasmoid.corona.editMode = false
+ }
+ }
+ }
+
+ Behavior on x {
+ NumberAnimation {
+ id: xAnim
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ Behavior on y {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ Behavior on width {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ Behavior on height {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ MultiEffect {
+ anchors.fill: parent
+ source: containment
+ layer.enabled: true
+ layer.smooth: true
+ layer.effect: Kirigami.ShadowedTexture {
+ width: editModeItem.roundedRootWidth
+ height: editModeItem.roundedRootHeight
+ color: "transparent"
+
+ radius: editModeItem.open ? Kirigami.Units.cornerRadius : 0
+ Behavior on radius {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/Panel.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/Panel.qml
new file mode 100644
index 0000000..bd57d91
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/Panel.qml
@@ -0,0 +1,375 @@
+/*
+ SPDX-FileCopyrightText: 2012 Marco Martin
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Layouts
+import QtQml
+
+import org.kde.plasma.core as PlasmaCore
+import org.kde.ksvg as KSvg
+import org.kde.taskmanager as TaskManager
+import org.kde.kwindowsystem
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.shell.panel as Panel
+
+import org.kde.plasma.plasmoid
+
+Item {
+ id: root
+
+ property Item containment
+
+ property bool floatingPrefix: floatingPanelSvg.usedPrefix === "floating"
+ readonly property bool verticalPanel: containment?.plasmoid?.formFactor === PlasmaCore.Types.Vertical
+
+ readonly property real spacingAtMinSize: Math.floor(Math.max(1, panel.thickness - Kirigami.Units.iconSizes.smallMedium)/2)
+ KSvg.FrameSvgItem {
+ id: thickPanelSvg
+ visible: false
+ prefix: 'thick'
+ imagePath: "widgets/panel-background"
+ }
+ KSvg.FrameSvgItem {
+ id: floatingPanelSvg
+ visible: false
+ prefix: ['floating', '']
+ imagePath: "widgets/panel-background"
+ }
+
+ readonly property bool rightEdge: containment?.plasmoid?.location === PlasmaCore.Types.RightEdge
+ readonly property bool bottomEdge: containment?.plasmoid?.location === PlasmaCore.Types.BottomEdge
+
+ readonly property int bottomFloatingPadding: Math.round(fixedBottomFloatingPadding * floatingness)
+ readonly property int leftFloatingPadding: Math.round(fixedLeftFloatingPadding * floatingness)
+ readonly property int rightFloatingPadding: Math.round(fixedRightFloatingPadding * floatingness)
+ readonly property int topFloatingPadding: Math.round(fixedTopFloatingPadding * floatingness)
+
+
+ // NOTE: Many of the properties in this file are accessed directly in C++ PanelView!
+ // If you change these, make sure to also correct the related code in panelview.cpp.
+ readonly property int fixedBottomFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.bottom : 8)
+ readonly property int fixedLeftFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.left : 8)
+ readonly property int fixedRightFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.right : 8)
+ readonly property int fixedTopFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.top : 8)
+
+ readonly property int topPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.top + Kirigami.Units.smallSpacing, spacingAtMinSize));
+ readonly property int bottomPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.bottom + Kirigami.Units.smallSpacing, spacingAtMinSize));
+ readonly property int leftPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.left + Kirigami.Units.smallSpacing, spacingAtMinSize));
+ readonly property int rightPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.right + Kirigami.Units.smallSpacing, spacingAtMinSize));
+
+ readonly property int minPanelHeight: translucentItem.minimumDrawingHeight
+ readonly property int minPanelWidth: translucentItem.minimumDrawingWidth
+
+ // This value is read from panelview.cpp which needs it to decide which border should be enabled
+ property real topShadowMargin: -floatingTranslucentItem.y
+ property real leftShadowMargin: -floatingTranslucentItem.x
+ property real rightShadowMargin: -(width - floatingTranslucentItem.width - floatingTranslucentItem.x)
+ property real bottomShadowMargin: -(height - floatingTranslucentItem.height - floatingTranslucentItem.y)
+
+ property var panelMask: floatingness === 0 ? (panelOpacity === 1 ? opaqueItem.mask : translucentItem.mask) : (panelOpacity === 1 ? floatingOpaqueItem.mask : floatingTranslucentItem.mask)
+
+ // The point is read from panelview.cpp and is used as an offset for the mask
+ readonly property point floatingTranslucentItemOffset: Qt.point(floatingTranslucentItem.x, floatingTranslucentItem.y)
+
+ TaskManager.VirtualDesktopInfo {
+ id: virtualDesktopInfo
+ }
+
+ TaskManager.ActivityInfo {
+ id: activityInfo
+ }
+
+ // We need to have a little gap between the raw visibleWindowsModel count
+ // and actually determining if a window is touching.
+ // This is because certain dialog windows start off with a position of (screenwidth/2, screenheight/2)
+ // and they register as "touching" in the split-second before KWin can place them correctly.
+ // This avoids the panel flashing if it is auto-hide etc and such a window is shown.
+ // Examples of such windows: properties of a file on desktop, or portal "open with" dialog
+ property bool touchingWindow: false
+ property bool touchingWindowDirect: visibleWindowsModel.count > 0
+ property bool showingDesktop: KWindowSystem.showingDesktop
+ Timer {
+ id: touchingWindowDebounceTimer
+ interval: 10 // ms, I find that this value is enough while not causing unresponsiveness while dragging windows close
+ onTriggered: root.touchingWindow = !KWindowSystem.showingDesktop && root.touchingWindowDirect
+ }
+ onTouchingWindowDirectChanged: touchingWindowDebounceTimer.start()
+ onShowingDesktopChanged: touchingWindowDebounceTimer.start()
+
+ TaskManager.TasksModel {
+ id: visibleWindowsModel
+ filterByVirtualDesktop: true
+ filterByActivity: true
+ filterByScreen: false
+ filterByRegion: TaskManager.RegionFilterMode.Intersect
+ filterHidden: true
+ filterMinimized: true
+
+ screenGeometry: panel.screenGeometry
+ virtualDesktop: virtualDesktopInfo.currentDesktop
+ activity: activityInfo.currentActivity
+
+ groupMode: TaskManager.TasksModel.GroupDisabled
+
+ Binding on regionGeometry {
+ delayed: true
+ value: panel.width, panel.height, panel.x, panel.y, panel.dogdeGeometryByDistance(panel.visibilityMode === Panel.Global.DodgeWindows ? -1 : 1) // +1 is for overlap detection, -1 is for snapping to panel
+ }
+ }
+
+ Connections {
+ target: root.containment?.plasmoid ?? null
+ function onActivated() {
+ if (root.containment.plasmoid.status === PlasmaCore.Types.AcceptingInputStatus) {
+ root.containment.plasmoid.status = PlasmaCore.Types.PassiveStatus;
+ } else {
+ root.containment.plasmoid.status = PlasmaCore.Types.AcceptingInputStatus;
+ }
+ }
+ }
+
+ // Floatingness is a value in [0, 1] that's multiplied to the floating margin; 0: not floating, 1: floating, between 0 and 1: animation between the two states
+ readonly property int floatingnessAnimationDuration: Kirigami.Units.longDuration
+ property double floatingnessTarget: 0.0 // The animation is handled in panelview.cpp for efficiency
+ property double floatingness: 0.0
+
+ // PanelOpacity is a value in [0, 1] that's used as the opacity of the opaque elements over the transparent ones; values between 0 and 1 are used for animations
+ property double panelOpacity
+ Behavior on panelOpacity {
+ NumberAnimation {
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.OutCubic
+ }
+ }
+
+ KSvg.FrameSvgItem {
+ id: translucentItem
+ visible: root.floatingness === 0 && root.panelOpacity !== 1
+ enabledBorders: panel.enabledBorders
+ anchors.fill: floatingTranslucentItem
+ imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "widgets/panel-background"
+ }
+ KSvg.FrameSvgItem {
+ id: floatingTranslucentItem
+ visible: root.floatingness !== 0 && root.panelOpacity !== 1
+ x: root.rightEdge ? root.fixedLeftFloatingPadding + root.fixedRightFloatingPadding * (1 - root.floatingness) : root.leftFloatingPadding
+ y: root.bottomEdge ? root.fixedTopFloatingPadding + root.fixedBottomFloatingPadding * (1 - root.floatingness) : root.topFloatingPadding
+ width: root.verticalPanel ? panel.thickness : parent.width - root.leftFloatingPadding - root.rightFloatingPadding
+ height: root.verticalPanel ? parent.height - root.topFloatingPadding - root.bottomFloatingPadding : panel.thickness
+
+ imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "widgets/panel-background"
+ }
+ KSvg.FrameSvgItem {
+ id: floatingOpaqueItem
+ visible: root.floatingness !== 0 && root.panelOpacity !== 0
+ opacity: root.panelOpacity
+ anchors.fill: floatingTranslucentItem
+ imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
+ }
+ KSvg.FrameSvgItem {
+ id: opaqueItem
+ visible: root.panelOpacity !== 0 && root.floatingness === 0
+ opacity: root.panelOpacity
+ enabledBorders: panel.enabledBorders
+ anchors.fill: floatingTranslucentItem
+ imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
+ }
+
+ Keys.onEscapePressed: {
+ root.parent.focus = false
+ }
+
+ property bool isOpaque: panel.opacityMode === Panel.Global.Opaque
+ property bool isTransparent: panel.opacityMode === Panel.Global.Translucent
+ property bool isAdaptive: panel.opacityMode === Panel.Global.Adaptive
+ property bool floating: panel.floating
+ property bool hasCompositing: KWindowSystem.isPlatformX11 ? KX11Extras.compositingActive : true
+ property var stateTriggers: [floating, touchingWindow, isOpaque, isAdaptive, isTransparent, hasCompositing, containment, panel.floatingApplets]
+ onStateTriggersChanged: {
+ let opaqueApplets = false
+ let floatingApplets = false
+ if ((!floating || touchingWindow) && (isOpaque || (touchingWindow && isAdaptive))) {
+ panelOpacity = 1
+ opaqueApplets = true
+ floatingnessTarget = 0
+ floatingApplets = (panel.floatingApplets && !floating)
+ } else if ((!floating || touchingWindow) && (isTransparent || (!touchingWindow && isAdaptive))) {
+ panelOpacity = 0
+ floatingnessTarget = 0
+ floatingApplets = (panel.floatingApplets && !floating)
+ } else if ((floating && !touchingWindow) && (isTransparent || isAdaptive)) {
+ panelOpacity = 0
+ floatingnessTarget = 1
+ floatingApplets = true
+ } else if (floating && !touchingWindow && isOpaque) {
+ panelOpacity = 1
+ opaqueApplets = true
+ floatingnessTarget = 1
+ floatingApplets = true
+ }
+
+ // Exceptions: panels with not NormalPanel visibilityMode
+ // should never de-float, and we should not have transparent
+ // panels when on X11 with compositing not active.
+ if (panel.visibilityMode != Panel.Global.NormalPanel && floating) {
+ floatingnessTarget = 1
+ floatingApplets = true
+ }
+ if (!KWindowSystem.isPlatformWayland && !KX11Extras.compositingActive) {
+ opaqueApplets = false
+ panelOpacity = 0
+ }
+
+ // Not using panelOpacity to check as it has a NumberAnimation, and it will thus
+ // be still read as the initial value here, before the animation starts.
+ if (containment) {
+ if (opaqueApplets) {
+ containment.plasmoid.containmentDisplayHints |= PlasmaCore.Types.ContainmentPrefersOpaqueBackground
+ } else {
+ containment.plasmoid.containmentDisplayHints &= ~PlasmaCore.Types.ContainmentPrefersOpaqueBackground
+ }
+ if (floatingApplets) {
+ containment.plasmoid.containmentDisplayHints |= PlasmaCore.Types.ContainmentPrefersFloatingApplets
+ } else {
+ containment.plasmoid.containmentDisplayHints &= ~PlasmaCore.Types.ContainmentPrefersFloatingApplets
+ }
+ }
+ }
+
+ function adjustPrefix() {
+ if (!containment) {
+ return "";
+ }
+ var pre;
+ switch (containment.plasmoid.location) {
+ case PlasmaCore.Types.LeftEdge:
+ pre = "west";
+ break;
+ case PlasmaCore.Types.TopEdge:
+ pre = "north";
+ break;
+ case PlasmaCore.Types.RightEdge:
+ pre = "east";
+ break;
+ case PlasmaCore.Types.BottomEdge:
+ pre = "south";
+ break;
+ default:
+ pre = "";
+ break;
+ }
+ translucentItem.prefix = opaqueItem.prefix = floatingTranslucentItem.prefix = floatingOpaqueItem.prefix = [pre, ""];
+ }
+
+ onContainmentChanged: {
+ if (!containment) {
+ return;
+ }
+ containment.parent = containmentParent;
+ containment.visible = true;
+ containment.anchors.fill = containmentParent;
+ containment.plasmoid.locationChanged.connect(adjustPrefix);
+ adjustPrefix();
+ }
+
+ Binding {
+ target: panel
+ property: "length"
+ when: containment
+ value: {
+ if (!containment) {
+ return;
+ }
+ if (root.verticalPanel) {
+ if (containment.Layout.fillHeight) {
+ if (panel.lengthMode == Panel.Global.Custom) {
+ return panel.maximumHeight
+ } else {
+ return panel.screenGeometry.height
+ }
+ }
+ return containment.Layout.preferredHeight
+ } else {
+ if (containment.Layout.fillWidth) {
+ if (panel.lengthMode == Panel.Global.Custom) {
+ return panel.maximumWidth
+ } else {
+ return panel.screenGeometry.width
+ }
+ }
+ return containment.Layout.preferredWidth
+ }
+ }
+ restoreMode: Binding.RestoreBinding
+ }
+
+ Binding {
+ target: panel
+ property: "backgroundHints"
+ when: containment
+ value: {
+ if (!containment) {
+ return;
+ }
+
+ return containment.plasmoid.backgroundHints;
+ }
+ restoreMode: Binding.RestoreBinding
+ }
+
+ KSvg.FrameSvgItem {
+
+ Accessible.name: i18nc("@info:whatsthis Accessible name", "Panel Focus Indicator")
+
+ x: root.verticalPanel || !panel.activeFocusItem
+ ? translucentItem.x
+ : Math.max(panel.activeFocusItem.Kirigami.ScenePosition.x, panel.activeFocusItem.Kirigami.ScenePosition.x)
+ y: root.verticalPanel && panel.activeFocusItem
+ ? Math.max(panel.activeFocusItem.Kirigami.ScenePosition.y, panel.activeFocusItem.Kirigami.ScenePosition.y)
+ : translucentItem.y
+
+ width: panel.activeFocusItem
+ ? (root.verticalPanel ? translucentItem.width : Math.min(panel.activeFocusItem.width, panel.activeFocusItem.width))
+ : 0
+ height: panel.activeFocusItem
+ ? (root.verticalPanel ? Math.min(panel.activeFocusItem.height, panel.activeFocusItem.height) : translucentItem.height)
+ : 0
+
+ visible: panel.active && panel.activeFocusItem
+
+ imagePath: "widgets/tabbar"
+ prefix: {
+ if (!root.containment) {
+ return "";
+ }
+ var prefix = ""
+ switch (root.containment.plasmoid.location) {
+ case PlasmaCore.Types.LeftEdge:
+ prefix = "west-active-tab";
+ break;
+ case PlasmaCore.Types.TopEdge:
+ prefix = "north-active-tab";
+ break;
+ case PlasmaCore.Types.RightEdge:
+ prefix = "east-active-tab";
+ break;
+ default:
+ prefix = "south-active-tab";
+ }
+ if (!hasElementPrefix(prefix)) {
+ prefix = "active-tab";
+ }
+ return prefix;
+ }
+ }
+ Item {
+ id: containmentParent
+ anchors.centerIn: root.isOpaque ? floatingOpaqueItem : floatingTranslucentItem
+ width: root.verticalPanel ? panel.thickness : root.width - root.fixedLeftFloatingPadding - root.fixedRightFloatingPadding
+ height: root.verticalPanel ? root.height - root.fixedBottomFloatingPadding - root.fixedTopFloatingPadding : panel.thickness
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/PreviewBanner.qml b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/PreviewBanner.qml
new file mode 100644
index 0000000..980e217
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/contents/views/PreviewBanner.qml
@@ -0,0 +1,48 @@
+/*
+ SPDX-FileCopyrightText: 2023 Fushan Wen
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+import QtQuick
+
+import org.kde.plasma.extras as PlasmaExtras
+import org.kde.kirigami as Kirigami
+
+Item {
+ // Using childrenRect.width causes a binding loop since we can only get the
+ // actual width, not the implicitWidth--which is what we would want
+ width: Math.max(title.implicitWidth, subtitle.implicitWidth)
+ height: childrenRect.height
+
+ HoverHandler {
+ cursorShape: Qt.PointingHandCursor
+ }
+
+ TapHandler {
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onTapped: desktop.showPreviewBannerMenu(mapToGlobal(point.position))
+ }
+
+ PlasmaExtras.ShadowedLabel {
+ id: title
+ anchors {
+ top: parent.top
+ right: parent.right
+ }
+ z: 2
+ text: desktop.previewBannerTitle
+ // Emulate the size of a level 1 heading
+ font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 1.35)
+ }
+
+ PlasmaExtras.ShadowedLabel {
+ id: subtitle
+ anchors {
+ top: title.bottom
+ right: parent.right
+ }
+ z: 2
+ text: desktop.previewBannerText
+ }
+}
diff --git a/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/metadata.json b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/metadata.json
new file mode 100644
index 0000000..f48567d
--- /dev/null
+++ b/files/system/usr/share/plasma/shells/org.kde.plasma.desktop/metadata.json
@@ -0,0 +1,212 @@
+{
+ "KPackageStructure": "Plasma/Shell",
+ "KPlugin": {
+ "Authors": [
+ {
+ "Email": "mart@kde.org",
+ "Name": "Marco Martin",
+ "Name[ar]": "ماركو مارتن",
+ "Name[ast]": "Marco Martin",
+ "Name[az]": "Marco Martin",
+ "Name[be]": "Marco Martin",
+ "Name[bg]": "Marco Martin",
+ "Name[ca@valencia]": "Marco Martin",
+ "Name[ca]": "Marco Martin",
+ "Name[cs]": "Marco Martin",
+ "Name[da]": "Marco Martin",
+ "Name[de]": "Marco Martin",
+ "Name[el]": "Marco Martin",
+ "Name[en_GB]": "Marco Martin",
+ "Name[eo]": "Marco Martin",
+ "Name[es]": "Marco Martin",
+ "Name[et]": "Marco Martin",
+ "Name[eu]": "Marco Martin",
+ "Name[fi]": "Marco Martin",
+ "Name[fr]": "Marco Martin",
+ "Name[ga]": "Marco Martin",
+ "Name[gl]": "Marco Martin",
+ "Name[he]": "מרקו מרטין",
+ "Name[hu]": "Marco Martin",
+ "Name[ia]": "Marco Martin",
+ "Name[id]": "Marco Martin",
+ "Name[ie]": "Marco Martin",
+ "Name[is]": "Marco Martin",
+ "Name[it]": "Marco Martin",
+ "Name[ja]": "Marco Martin",
+ "Name[ka]": "მაკრო მარტინი",
+ "Name[ko]": "Marco Martin",
+ "Name[lt]": "Marco Martin",
+ "Name[lv]": "Marco Martin",
+ "Name[nb]": "Marco Martin",
+ "Name[nl]": "Marco Martin",
+ "Name[nn]": "Marco Martin",
+ "Name[pl]": "Marco Martin",
+ "Name[pt]": "Marco Martin",
+ "Name[pt_BR]": "Marco Martin",
+ "Name[ro]": "Marco Martin",
+ "Name[ru]": "Marco Martin",
+ "Name[sa]": "मार्को मार्टिन्",
+ "Name[sk]": "Marco Martin",
+ "Name[sl]": "Marco Martin",
+ "Name[sv]": "Marco Martin",
+ "Name[ta]": "மார்க்கோ மார்ட்டின்",
+ "Name[tr]": "Marco Martin",
+ "Name[uk]": "Marco Martin",
+ "Name[vi]": "Marco Martin",
+ "Name[zh_CN]": "Marco Martin",
+ "Name[zh_TW]": "Marco Martin"
+ }
+ ],
+ "Category": "",
+ "Description": "Desktop view furniture",
+ "Description[ar]": "إعداد عرض مساحة العمل ",
+ "Description[az]": "İş masası görünüşü tərkibləri",
+ "Description[be]": "Выгляд працоўнага стала",
+ "Description[bg]": "Компоненти на работния плот",
+ "Description[ca@valencia]": "Accessori de vista de l'escriptori",
+ "Description[ca]": "Accessori de vista de l'escriptori",
+ "Description[cs]": "Zobrazení plochy",
+ "Description[da]": "Møbler til skrivebordsvisning",
+ "Description[de]": "Einrichtung der Ansicht einer Arbeitsfläche",
+ "Description[el]": "Παρουσίαση της επιφάνειας εργασίας",
+ "Description[en_GB]": "Desktop view furniture",
+ "Description[eo]": "Labortabla vidigilaro",
+ "Description[es]": "Accesorio de vista del escritorio",
+ "Description[et]": "Töölauavaate sisustus",
+ "Description[eu]": "Mahaigain ikuspegi osagarria",
+ "Description[fi]": "Työpöydän sisustus",
+ "Description[fr]": "Aménagement du bureau",
+ "Description[ga]": "Troscán radhairc deisce",
+ "Description[gl]": "Contidos da vista do escritorio.",
+ "Description[he]": "ריהוט תצוגת שולחן עבודה",
+ "Description[hu]": "Munkaasztal nézet bútor",
+ "Description[ia]": "Vista de accessorio de Scriptorio",
+ "Description[id]": "Furnitur tampilan desktop",
+ "Description[is]": "Skjáborðsinnréttingar",
+ "Description[it]": "Componenti della vista del desktop",
+ "Description[ja]": "デスクトップビュー",
+ "Description[ka]": "სამუშაო მაგიდის მორთულობის ჩვენება",
+ "Description[ko]": "바탕 화면 보기 부속 프로그램",
+ "Description[lt]": "Darbalaukio rodinio baldai",
+ "Description[lv]": "Darbvirsmas skata elementi",
+ "Description[nb]": "Skrivebordsvisningmøbler",
+ "Description[nl]": "Meubilair voor weergave op het bureaublad",
+ "Description[nn]": "Skrivebordsvisingmøblar",
+ "Description[pa]": "ਡੈਸਕਟਾਪ ਵੇਖਣ ਫਰਨੀਚਰ",
+ "Description[pl]": "Widok umeblowania pulpitu",
+ "Description[pt]": "Disposição do ecrã",
+ "Description[pt_BR]": "Acessório de visualização da área de trabalho",
+ "Description[ro]": "Mobilier pentru vizualizarea biroului",
+ "Description[ru]": "Компоненты пользовательского интерфейса Plasma",
+ "Description[sa]": "डेस्कटॉप दृश्य फर्निचर",
+ "Description[sk]": "Zobrazenie plochy nábytok",
+ "Description[sl]": "Pohištvo prikaza namizja",
+ "Description[sv]": "Visa skrivbordsmöbler",
+ "Description[ta]": "பணிமேடை பிளாஸ்மாய்டுகள்",
+ "Description[tr]": "Masaüstü görünümü mobilyası",
+ "Description[uk]": "Компоненти для перегляду стільниці",
+ "Description[vi]": "Đồ đạc trong khung xem bàn làm việc",
+ "Description[zh_CN]": "桌面视图小工具",
+ "Description[zh_TW]": "桌面檢視設備",
+ "Icon": "user-desktop",
+ "Id": "org.kde.plasma.desktop",
+ "License": "GPL-2.0+",
+ "Name": "Desktop",
+ "Name[af]": "Werkskerm",
+ "Name[ar]": "سطح المكتب",
+ "Name[ast]": "Escritoriu",
+ "Name[az]": "İş masası",
+ "Name[be@latin]": "Rabočy stoł",
+ "Name[be]": "Працоўны стол",
+ "Name[bg]": "Работен плот",
+ "Name[bn]": "ডেস্কটপ",
+ "Name[bn_IN]": "ডেস্কটপ",
+ "Name[br]": "Gorretaol",
+ "Name[bs]": "Radna površina",
+ "Name[ca@valencia]": "Escriptori",
+ "Name[ca]": "Escriptori",
+ "Name[cs]": "Pracovní plocha",
+ "Name[csb]": "Pùlt",
+ "Name[cy]": "Penbwrdd",
+ "Name[da]": "Skrivebord",
+ "Name[de]": "Arbeitsfläche",
+ "Name[el]": "Επιφάνεια εργασίας",
+ "Name[en_GB]": "Desktop",
+ "Name[eo]": "Labortablo",
+ "Name[es]": "Escritorio",
+ "Name[et]": "Töölaud",
+ "Name[eu]": "Mahaigaina",
+ "Name[fa]": "رومیزی",
+ "Name[fi]": "Työpöytä",
+ "Name[fr]": "Bureau",
+ "Name[fy]": "Buroblêd",
+ "Name[ga]": "Deasc",
+ "Name[gl]": "Escritorio",
+ "Name[gu]": "ડેસ્કટોપ",
+ "Name[he]": "שולחן עבודה",
+ "Name[hi]": "डेस्कटॉप",
+ "Name[hne]": "डेस्कटाप",
+ "Name[hr]": "Radna površina",
+ "Name[hsb]": "Dźěłowy powjerch",
+ "Name[hu]": "Munkaasztal",
+ "Name[ia]": "Scriptorio",
+ "Name[id]": "Desktop",
+ "Name[ie]": "Pupitre",
+ "Name[is]": "Skjáborð",
+ "Name[it]": "Desktop",
+ "Name[ja]": "デスクトップ",
+ "Name[ka]": "სამუშაო მაგიდა",
+ "Name[kk]": "Жұмыс үстелі",
+ "Name[kn]": "ಗಣಕತೆರೆ",
+ "Name[ko]": "바탕 화면",
+ "Name[ku]": "Sermasê",
+ "Name[lt]": "Darbalaukis",
+ "Name[lv]": "Darbvirsma",
+ "Name[mai]": "डेस्कटाप",
+ "Name[mk]": "Работна површина",
+ "Name[ml]": "പണിയിടം",
+ "Name[mr]": "डेस्कटॉप",
+ "Name[ms]": "Ruang Kerja",
+ "Name[nb]": "Skrivebord",
+ "Name[nds]": "Schriefdisch",
+ "Name[ne]": "डेस्कटप",
+ "Name[nl]": "Bureaublad",
+ "Name[nn]": "Skrivebord",
+ "Name[oc]": "Burèu",
+ "Name[or]": "ଡ଼େସ୍କଟପ",
+ "Name[pa]": "ਡੈਸਕਟਾਪ",
+ "Name[pl]": "Pulpit",
+ "Name[pt]": "Ambiente de Trabalho",
+ "Name[pt_BR]": "Área de trabalho",
+ "Name[ro]": "Birou",
+ "Name[ru]": "Рабочий стол",
+ "Name[sa]": "डेस्कटॉप",
+ "Name[se]": "Čállinbeavdi",
+ "Name[si]": "වැඩතලය",
+ "Name[sk]": "Plocha",
+ "Name[sl]": "Namizje",
+ "Name[sr@ijekavian]": "Површ",
+ "Name[sr@ijekavianlatin]": "Površ",
+ "Name[sr@latin]": "Površ",
+ "Name[sr]": "Површ",
+ "Name[sv]": "Skrivbord",
+ "Name[ta]": "பணிமேடை",
+ "Name[te]": "రంగస్ఠలం",
+ "Name[tg]": "Мизи корӣ",
+ "Name[th]": "พื้นที่ทำงาน",
+ "Name[tr]": "Masaüstü",
+ "Name[uk]": "Стільниця",
+ "Name[uz@cyrillic]": "Иш столи",
+ "Name[uz]": "Ish stoli",
+ "Name[vi]": "Bàn làm việc",
+ "Name[wa]": "Sicribanne",
+ "Name[xh]": "Desktop",
+ "Name[zh_CN]": "桌面",
+ "Name[zh_TW]": "桌面",
+ "Version": "",
+ "Website": "https://www.kde.org/plasma-desktop"
+ },
+ "Keywords": "",
+ "X-KDE-ParentApp": "org.kde.plasmashell",
+ "X-Plasma-APIVersion": "2"
+}
diff --git a/files/system/usr/share/wallpapers/jumping-jax--TfwQjOWEp8-unsplash.jpg b/files/system/usr/share/wallpapers/Miasma-Audio.jpg
similarity index 100%
rename from files/system/usr/share/wallpapers/jumping-jax--TfwQjOWEp8-unsplash.jpg
rename to files/system/usr/share/wallpapers/Miasma-Audio.jpg
diff --git a/files/system/usr/share/wallpapers/Miasma-Blue-Purple.jpg b/files/system/usr/share/wallpapers/Miasma-Blue-Purple.jpg
new file mode 100644
index 0000000..03f66fd
Binary files /dev/null and b/files/system/usr/share/wallpapers/Miasma-Blue-Purple.jpg differ
diff --git a/files/system/usr/share/wallpapers/blueredwave.jpg b/files/system/usr/share/wallpapers/Miasma-Blueredwave.jpg
similarity index 100%
rename from files/system/usr/share/wallpapers/blueredwave.jpg
rename to files/system/usr/share/wallpapers/Miasma-Blueredwave.jpg
diff --git a/files/system/usr/share/wallpapers/yassine-ait-tahit-uBqd-tGQI8o-unsplash.jpg b/files/system/usr/share/wallpapers/Miasma-Light.jpg
similarity index 100%
rename from files/system/usr/share/wallpapers/yassine-ait-tahit-uBqd-tGQI8o-unsplash.jpg
rename to files/system/usr/share/wallpapers/Miasma-Light.jpg
diff --git a/files/system/usr/share/wallpapers/boliviainteligente-1f5tMsTQGD8-unsplash.jpg b/files/system/usr/share/wallpapers/Miasma-Lines.jpg
similarity index 100%
rename from files/system/usr/share/wallpapers/boliviainteligente-1f5tMsTQGD8-unsplash.jpg
rename to files/system/usr/share/wallpapers/Miasma-Lines.jpg
diff --git a/files/system/usr/share/wallpapers/dmitry-dreyer-O_7jOtM_Hg0-unsplash.jpg b/files/system/usr/share/wallpapers/Miasma-Purple.jpg
similarity index 100%
rename from files/system/usr/share/wallpapers/dmitry-dreyer-O_7jOtM_Hg0-unsplash.jpg
rename to files/system/usr/share/wallpapers/Miasma-Purple.jpg
diff --git a/files/system/usr/share/wallpapers/blackwave.jpg b/files/system/usr/share/wallpapers/blackwave.jpg
deleted file mode 100644
index 5faa5d3..0000000
Binary files a/files/system/usr/share/wallpapers/blackwave.jpg and /dev/null differ
diff --git a/files/system/usr/share/wallpapers/bluewave.jpg b/files/system/usr/share/wallpapers/bluewave.jpg
deleted file mode 100644
index 67dadcf..0000000
Binary files a/files/system/usr/share/wallpapers/bluewave.jpg and /dev/null differ
diff --git a/files/system/usr/share/wallpapers/default.jpg b/files/system/usr/share/wallpapers/default.jpg
deleted file mode 100644
index 651ae67..0000000
Binary files a/files/system/usr/share/wallpapers/default.jpg and /dev/null differ
diff --git a/files/system/usr/share/wallpapers/dima-solomin-4fLZjleexow-unsplash.jpg b/files/system/usr/share/wallpapers/dima-solomin-4fLZjleexow-unsplash.jpg
deleted file mode 100644
index 5f81e4a..0000000
Binary files a/files/system/usr/share/wallpapers/dima-solomin-4fLZjleexow-unsplash.jpg and /dev/null differ
diff --git a/files/system/usr/share/wallpapers/martin-martz-JfwQ36wG7Uo-unsplash.jpg b/files/system/usr/share/wallpapers/martin-martz-JfwQ36wG7Uo-unsplash.jpg
deleted file mode 100644
index 490db04..0000000
Binary files a/files/system/usr/share/wallpapers/martin-martz-JfwQ36wG7Uo-unsplash.jpg and /dev/null differ
diff --git a/files/system/usr/share/wallpapers/miasma-default.jxl b/files/system/usr/share/wallpapers/miasma-default.jxl
new file mode 100644
index 0000000..e0411ad
Binary files /dev/null and b/files/system/usr/share/wallpapers/miasma-default.jxl differ