plasmoides KDE Store/GitHub (gnome-pager, kMenu, kvitals, windowtitle, claude, launchpad)

This commit is contained in:
Josevi
2026-07-08 20:47:59 +02:00
parent ca606377ee
commit dd3b0f6ae8
136 changed files with 20239 additions and 0 deletions
@@ -0,0 +1,523 @@
/*
SPDX-FileCopyrightText: 2015 Eike Hein <hein@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import Qt5Compat.GraphicalEffects
// Deliberately imported after QtQuick to avoid missing restoreMode property in Binding. Fix in Qt 6.
import QtQml 2.15
import org.kde.kquickcontrolsaddons 2.0
import org.kde.kwindowsystem 1.0
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.core as PlasmaCore
import org.kde.ksvg 1.0 as KSvg
import org.kde.plasma.private.shell 2.0
import org.kde.kirigami 2.20 as Kirigami
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.private.kicker 0.1 as Kicker
import QtQuick.Controls
import QtQuick
import Qt5Compat.GraphicalEffects
import "code/tools.js" as Tools
Kicker.DashboardWindow {
id: root
property bool smallScreen: ((Math.floor(width / Kirigami.Units.iconSizes.huge) <= 22) || (Math.floor(height / Kirigami.Units.iconSizes.huge) <= 14))
property int iconSize:{ switch(Plasmoid.configuration.appsIconSize){
case 0: return Kirigami.Units.iconSizes.smallMedium;
case 1: return Kirigami.Units.iconSizes.medium;
case 2: return Kirigami.Units.iconSizes.large;
case 3: return Kirigami.Units.iconSizes.huge;
case 4: return Kirigami.Units.iconSizes.large * 2;
case 5: return Kirigami.Units.iconSizes.enormous;
default: return 64
}
}
property int favsIconSize:{ switch(Plasmoid.configuration.favsIconSize){
case 0: return Kirigami.Units.iconSizes.smallMedium;
case 1: return Kirigami.Units.iconSizes.medium;
case 2: return Kirigami.Units.iconSizes.large;
case 3: return Kirigami.Units.iconSizes.huge;
case 4: return Kirigami.Units.iconSizes.enormous;
default: return 64
}
}
property int systemIconSize:{ switch(Plasmoid.configuration.systemIconSize){
case 0: return Kirigami.Units.iconSizes.smallMedium;
case 1: return Kirigami.Units.iconSizes.medium;
case 2: return Kirigami.Units.iconSizes.large;
case 3: return Kirigami.Units.iconSizes.huge;
case 4: return Kirigami.Units.iconSizes.enormous;
default: return 64
}
}
property int cellSize: iconSize + (2 * Kirigami.Units.iconSizes.sizeForLabels)
+ (2 * Kirigami.Units.largeSpacing)
+ (2 * Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom,
highlightItemSvg.margins.left + highlightItemSvg.margins.right))
//property int columns: Math.floor(width*0.7/root.cellSize)// Math.floor(((smallScreen ? 85 : 80)/100) * Math.ceil(width / cellSize))
property int columns: Math.floor(((smallScreen ? 85 : 80)/100) * Math.ceil(width / cellSize))
property bool searching: searchField.text !== ""
property int favoritesRows: Math.floor(height*0.4/cellSize)
//keyEventProxy: searchField
backgroundColor: "transparent"
onKeyEscapePressed: {
if (searching) {
searchField.clear();
} else {
root.toggle();
}
}
onVisibleChanged: {
if(visible){
animatorMainColumn.start()
}else{
rootItem.opacity = 0
}
reset();
}
onSearchingChanged: {
if (!searching) {
//mainView.currentIndex = 1
mainView.pop()
reset();
} else {
mainView.push(runnerComponent)
//mainView.currentIndex = 0
}
}
function colorWithAlpha(color: color, alpha: real): color {
return Qt.rgba(color.r, color.g, color.b, alpha)
}
function reset() {
allAppsGrid.model = rootModel.modelForRow(2)
globalFavoritesGrid.model = globalFavorites
allAppsGrid.currentIndex = -1
globalFavoritesGrid.currentIndex = -1;
systemFavoritesGrid.currentIndex = -1;
allAppsGrid.forceLayout()
searchField.clear();
searchField.focus = true
}
mainItem: MouseArea {
id: rootItem
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
Rectangle{
anchors.fill: parent
color: Kirigami.Theme.backgroundColor
opacity: 0.4
}
Connections {
target: kicker
function onReset() {
if (!root.searching) {
//filterList.applyFilter();
//funnelModel.reset();
}
}
function onDragSourceChanged() {
if (!kicker.dragSource) {
// FIXME TODO HACK: Reset all views post-DND to work around
// mouse grab bug despite QQuickWindow::mouseGrabberItem==0x0.
// Needs a more involved hunt through Qt Quick sources later since
// it's not happening with near-identical code in the menu repr.
rootModel.refresh();
}
}
}
Connections {
target: Plasmoid
function onUserConfiguringChanged() {
if (Plasmoid.userConfiguring) {
root.hide()
}
}
}
PlasmaExtras.Menu {
id: contextMenu
PlasmaExtras.MenuItem {
action: Plasmoid.internalAction("configure")
}
}
Kirigami.Heading {
id: dummyHeading
visible: false
width: 0
level: 1
}
TextMetrics {
id: headingMetrics
font: dummyHeading.font
}
Kicker.FunnelModel {
id: funnelModel
onSourceModelChanged: {
if (mainColumn.visible) {
mainGrid.currentIndex = -1;
mainGrid.forceLayout();
}
}
}
Kicker.ContainmentInterface {
id: containmentInterface
}
TextField{
id: searchField
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: mainView.top
anchors.bottomMargin: Kirigami.Units.largeSpacing * 6
//focus: true
width: Kirigami.Units.gridUnit * 13
topPadding: Kirigami.Units.largeSpacing
bottomPadding: Kirigami.Units.largeSpacing
placeholderText: i18nc("@info:placeholder as in, 'start typing to initiate a search'", "Search")
horizontalAlignment: TextInput.AlignHCenter
wrapMode: Text.NoWrap
font.pointSize: Kirigami.Theme.defaultFont.pointSize + 0.5
onTextChanged: {
runnerModel.query = searchField.text;
}
function clear() {
text = "";
}
background: Rectangle {
color: colorWithAlpha(Kirigami.Theme.backgroundColor,0.7)
radius: 100
border.width: 1
border.color: colorWithAlpha(Kirigami.Theme.textColor,0.05)
}
function appendText(newText) {
if (!root.visible) {
return;
}
focus = true;
text = text + newText;
}
function backspace() {
if (!root.visible) {
return;
}
focus = true;
text = text.slice(0, -1);
}
function updateSelection() {
if (!searchField.selectedText) {
return;
}
var delta = text.lastIndexOf(searchField.text, text.length - 2);
searchHeading.select(searchField.selectionStart + delta, searchField.selectionEnd + delta);
}
Keys.onPressed: event => {
if (event.key === Qt.Key_Down || event.key === Qt.Key_Tab) {
event.accepted = true;
if(root.searching){
mainView.currentItem.tryActivate(0,0)
mainView.currentItem.forceActiveFocus()
}
else{
allAppsGrid.tryActivate(0,0)
allAppsGrid.forceActiveFocus()
}
}
}
}
OpacityAnimator{ id: animatorMainColumn ;from: 0; to: 1 ; target: rootItem;}
StackView {
id: mainView
width: (root.columns * root.cellSize) + Kirigami.Units.gridUnit
height: Math.ceil(root.height*0.7/root.cellSize) * root.cellSize
anchors{
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
initialItem: Column {
id: allAppsColumn
clip: true
spacing: Kirigami.Units.largeSpacing * 2
ItemGridView {
id: allAppsGrid
width: parent.width
height: Math.ceil(root.height*0.7/cellHeight) * cellHeight
cellWidth: root.cellSize
cellHeight: root.cellSize
iconSize: root.iconSize
dropEnabled: false
onKeyNavDown: {
allAppsGrid.focus = false
globalFavoritesGrid.tryActivate(0,0)
globalFavoritesGrid.forceActiveFocus()
}
onKeyNavUp: {
allAppsGrid.focus = false
searchField.focus = true
}
Keys.onPressed: event => {
if (event.key === Qt.Key_Tab) {
event.accepted = true;
allAppsGrid.focus = false
globalFavoritesGrid.tryActivate(0,0)
globalFavoritesGrid.forceActiveFocus()
}
}
}
}
pushEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 0
to:1
duration: 200
}
}
pushExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:0
duration: 200
}
}
popEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 0
to:1
duration: 200
}
}
popExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:0
duration: 200
}
}
}
Component {
id: runnerComponent
ItemGridView {
id: runnerGrid
anchors.horizontalCenter: mainView.horizontalCenter
width: mainView.width/2
clip: true
height: mainView.height
grabFocus: true
cellWidth: root.cellSize
cellHeight: root.cellSize
iconSize: root.iconSize
model: runnerModel.count > 0 ? runnerModel.modelForRow(0) : undefined
onKeyNavDown: {
runnerGrid.focus = false
globalFavoritesGrid.tryActivate(0,0)
globalFavoritesGrid.forceActiveFocus()
}
onKeyNavUp: {
runnerGrid.focus = false
searchField.focus = true
}
Keys.onPressed: event => {
if (event.key === Qt.Key_Tab) {
event.accepted = true;
runnerGrid.focus = false
globalFavoritesGrid.tryActivate(0,0)
globalFavoritesGrid.forceActiveFocus()
}
}
}
}
Rectangle{
anchors.centerIn: globalFavoritesGrid
height: globalFavoritesGrid.height + Kirigami.Units.largeSpacing
width: globalFavoritesGrid.width + Kirigami.Units.largeSpacing
color: Kirigami.Theme.backgroundColor
radius: 10
opacity: 0.6
z:1
}
ItemGridView {
id: globalFavoritesGrid
width: globalFavoritesGrid.model ? Math.min(Math.floor((root.width*0.85)/cellWidth)*cellWidth,globalFavoritesGrid.model.count*cellWidth) : 0
iconSize: root.favsIconSize
cellHeight: iconSize + Kirigami.Units.largeSpacing
cellWidth: cellHeight + Kirigami.Units.largeSpacing
clip: true
z:2
verticalScrollBarPolicy: PlasmaComponents.ScrollBar.AlwaysOff
height: cellHeight
anchors.bottom: parent.bottom
anchors.bottomMargin: Kirigami.Units.largeSpacing
anchors.horizontalCenter: parent.horizontalCenter
showLabels: false
dropEnabled: true
dragEnabled: true
onKeyNavUp: {
if(root.searching){
globalFavoritesGrid.focus = false
//runnerGrid.tryActivate(0,0)
//runnerGrid.forceActiveFocus()
mainView.currentItem.tryActivate(0,0)
mainView.currentItem.forceActiveFocus()
}
else{
globalFavoritesGrid.focus = false
allAppsGrid.tryActivate(0,0)
allAppsGrid.forceActiveFocus()
}
}
Keys.onPressed: event => {
if (event.key === Qt.Key_Tab) {
event.accepted = true;
globalFavoritesGrid.focus = false
systemFavoritesGrid.tryActivate(0,0)
systemFavoritesGrid.forceActiveFocus()
}
}
}
ItemGridView {
id: systemFavoritesGrid
anchors.top: parent.top
anchors.right: parent.right
clip: true
width: cellWidth
height: systemFavoritesGrid.model ? systemFavoritesGrid.model.count * cellHeight : 0
cellWidth: iconSize + Kirigami.Units.largeSpacing * 2
cellHeight: cellWidth
iconSize: root.systemIconSize
z:5
showLabels: false
model: systemFavorites
dragEnabled: false
dropEnabled: false
Keys.onPressed: event => {
if (event.key === Qt.Key_Tab) {
event.accepted = true;
systemFavoritesGrid.focus = false
searchField.focus = true
}
}
}
onPressed: mouse => {
if (mouse.button === Qt.RightButton) {
contextMenu.open(mouse.x, mouse.y);
}
}
onClicked: mouse => {
if (mouse.button === Qt.LeftButton) {
root.toggle();
}
}
Keys.onPressed: (event)=> {
if(event.modifiers & Qt.ControlModifier ||event.modifiers & Qt.ShiftModifier){
searchField.focus = true;
return
}
if (event.key === Qt.Key_Escape) {
event.accepted = true;
if (root.searching) {
reset();
} else {
root.visible = false;
}
return;
}
if (searchField.focus) {
return;
}
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
searchField.backspace();
} else if (event.text !== "") {
event.accepted = true;
searchField.appendText(event.text);
}
//searchField.focus = true
}
}
Component.onCompleted: {
rootModel.refresh();
searchField.forceActiveFocus()
}
}